微服务架构日益成熟,不但得到了初创公司和创新型公司的认可,一些传统企业也在逐步接受微服务架构。我们仍然在学习如何利用其在扩展性,易于维护和构建等方面的优势。当然我们也必须承担微服务增加的成本,比如从SOA架构的迁移,编排,备份,以及对技能提升的需求等等。
一个典型的微服务架构可能是这样的:
- Touchbase,一个Node.js写的应用作为技术栈的核心;
- Nginx,作为Touchbase节点的负载均衡;
- Couchbase,作为数据层;
- Consul,服务发现;
- Containerbuddy,服务发现;
- CloudFlare-watcher,DNS更新;
- CloudFlare DNS,DNS服务;
每个组件可能都有备选方案,可以替换,只要改 docker-compose.yml文件就可以。
为什么Docker很适合这样的架构呢?以下将分别从Docker的优缺点以及在生产环境中使用Docker可能会遇到的挑战来进行分析,首先让我们来看Docker带来的优势。
优势
1隔离,抽象,可移植性
容器是操作系统内存中的应用隔离,我们并不知道这些相关的服务是不是运行在同一个机器上,通过容器抽象来共享主机的操作系统资源。得益于Docker,我们可以从头建立一个分布式应用,根据应用的需求定制环境,并复用在所有Docker主机上。还可以省去不重要安装,环境依赖,将环境改变控制在容器内,从而保持操作系统的『纯净』。
2轻量级
Docker轻量级,开销很少,这使得它成为一个开发immutable infrastructure的绝佳工具,并且所有组件都很容易被替代。使用Docker 可以在同一台主机上运行更多的服务和应用,不会产生性能损失和额外的容量。
3版本化的镜像
Docker通过Docker镜像来交付环境,你可以用Docker的强大的tag机制指定你的镜像的版本。这意味着你可以版本化你的整个微服务环境,不管你的应用s用是Java、Python、Ruby还是其它完全独立于主机操作系统的语言写的,都可以拥有一个同质的打包系统。
4可复用
Docker组件是可以重用的。之前精心设计的镜像,可以通过base imge被重用,并且不需要从零开始构建。
5可测试
Dockerfile描述了Docker的环境,以及能够使我们的应用运行于其上的必要的步骤。每次Docker构建的过程,都是对这个步骤的测试,测试其能否为我们的应用程序执行创建一个完美的运行环境。
6DevOps的思维方式
得益于上述几点,开发团队更容易从传统思维过渡到DevOps的思维方式,关注完整的软件交付生命周期。Docker可以将IT运维部门从一个繁忙的、简易的交付批准/拒绝导向的团队,变成一个有效率的,交付授权的部门,而且开发人员可以在容器内定制自己的运行环境,同时不会影响其他应用。
如此强大的工具!我们为什么不马上开始开发几十或者上百个微服务?好吧,因为所有事物都有两面性。Docker真的是很灵活的工具,但与传统的,基于虚拟机的解决方案非常不同。
缺陷
1编排
最大的挑战是容器的生命周期管理。传统的虚拟机启动缓慢,在运行时将其状态保存进虚拟机镜像,下一次重启时使用这个改变了的镜像来继续运行。它在硬件资源上有显著的开销,模块化程度更低,需要复制镜像来扩大规模。
Docker对于分层,只读的镜像采取了不同的策略,对于给定的容器只存储变化的部分,这种方式好坏参半。好是因为我们可以从同一个Docker镜像中快速做出多个实例(即使在多台主机上),其启动和开销是最小的。这些属性使Docker成为了一个出色的immutable infrastructure的工具,但是在Docker中运行有状态的服务,就需要在写dockerfiles和管理持久化数据时做一些额外的处理。
2持久化
默认情况下,Docker不会在容器中存储持久化数据。它只存储镜像和容器实例之间的差异。如果你删除一个容器,你会失去所有数据。为了保持数据独立于容器生命周期,你应该定义数据卷。
您有2个选择可以将数据持久化为卷:主机卷或容器卷。主机端是一个与容器共享的Docker主机上的物理文件夹。容器卷是一个主机上隔离的,私有的空间,并且多个容器共享。管理卷比简单的虚拟机数据持久化更为复杂。
3调度
在云中的调度,比一个单一的主机环境更有挑战性。如何分配任务和应该安排多少实例?如何追踪云来扩展任务的生命周期。在Docker容器中使用配置文件是困难的,尤其是在分布式的环境中。调度一个镜像作为容器可靠地运行,我们需要一个分布式的调度平台例如: ApacheMesos的Chronos或者你可以使用SystemdTimers。无论你选择哪种方式,都要跟踪容器的运行状态等相关细节,并且它应该是系统容错和默认重启的。
4Docker不是虚拟机
Docker的设计初衷是为应用提供隔离的环境,并跟踪文件系统的变化,独立于主机操作系统的配置。对于长时间运行和复杂的进程也不是那么合适,但我也不那么保守地建议一个应用对应一个容器。现实生活不同于纸上谈兵,不是吗?
5安全性
在公有的服务器上运行Docker容器,与他人共享有一些安全风险,我们需要非常仔细地设计我们的Docker基础架构。生态系统发展这么快,你应该投入时间研究最新的安全工具,以防止来自容器的安全威胁。
6成熟度
Docker此刻(在推出1.8版本后)还是不成熟的。Docker compose不能在多主机状态下编排,Docker swarm本身距离商用状态还有很长的路要走,网络模式也在试验中。完全基于Docker的组件还不能建立一个完整的生产环境,但第三方供应商如SaltStack, Kubernetes, ApacheMesos或stackengine、tutum等云基础供应商正在非常好地弥补这些缺口。
挑战
以上从个人观点阐述了Docker的一些优点和缺点,就让我们看看当我们实践的时候会遇到的挑战和需要注意的地方。
1版本/标签
Docker镜像可以由三个要素来描述:namespace,名称和标签。namespace是您在公共hub中的用户名或私有库的名称。你可以用它来区分镜像的功能,比如dev,int,prod;镜像名称(hub称其为库)是你artifact的名称;标签是描述镜像版本的一个很好的机制,但你应该尽量不用lastest标签。
2构建自动化
基础镜像的手动更新是不可靠的,有风险的。也应测试基础镜像并且标记lastest标签,以保证基础镜像的最新版本。
3Rollback and roll forward
在最新的版本发生任何问题的情况下,明确的镜像版本使rollback变得容易;还可以通过roll forward触发通过修正的提交。你也可以使用分层释放/修复和立即改变一组运行实例。
4使用域
Docker不仅可以为你的应用程序提供一个灵活的运行环境,而且你可以建立一整个交付管道,它包括CI / CD服务器和他们的附属机器,根据需求来动态分配现有的资源。