1.2 容器集群与分布式服务
1.2.1 微服务架构
近年来容器技术的繁荣同样得益于大规模分布式软件架构的推波助澜。随着现代软件规模不断扩大,单纯地增加节点内存和运算能力已经不足以应对业务请求的需要,由于能够利用服务数量的横向扩展来获得更好的业务性能和承载量,分布式架构成为了许多企业选择的探索方向。
微服务架构(Microservices Architecture)是在Martin Fowler和James Lewis合著的一篇博客里正式提出的一种软件架构形式,它是分布式架构在互联网时代发展过程中的全新诠释。微服务架构提倡将应用分割成一系列细小的服务,每个服务专注于单一业务功能,运行于独立的进程中,服务之间边界清晰,采用轻量级通信机制(如HTTP/REST)相互沟通,配合起来又能实现完整的应用,满足业务和用户的需求。
康威定律(Conway's law)指出:“任何设计系统的组织,最终产生的设计等同于组织之内、之间的沟通结构”。在传统软件开发项目中,通常将开发者按技能分为前端层、中间层、数据层。这种项目设计架构的分层结构对应了不同团队的人员组织结构:前端对应的角色为网页开发和设计人员;中间层对应的角色为服务端业务和开发人员;数据层对应着DBA等角色。所有的软件层需要最终被集成在一起,才能成为一个可部署的整体。而微服务架构的开发模式则将项目按业务能力划分为不同的服务,每个服务都要求在对应业务领域的全栈(从前端到后端)软件中实现,从界面到数据存储再到外部沟通协作等。这样,原本单一的服务就按照功能边界被分解成一系列独立、专注的微服务。每个微服务对应传统项目中的一个组件,但是可以独立编译、测试和部署。
相较于分层架构的项目,微服务架构具备以下优势。
1.复杂度可控
在将项目分解的同时,微服务架构规避了复杂度无止境积累的恶性趋势。每一个微服务专注于单一功能,并通过定义良好的接口来清晰地表述服务边界。由于体积小、复杂度低,每个微服务可由一个小规模开发团队完全掌控,易于保持高可维护性和开发效率。
2.独立部署
由于微服务具备独立的运行进程,所以每个微服务也可以独立部署。当某个微服务发生变更时无须编译、部署整个项目。由微服务组成的项目相当于具备一系列可并行的发布流程,使得发布更加高效,同时可降低对生产环境所造成的风险,最终实现缩短项目交付周期。这十分契合互联网SaaS类型服务每天都要发布很多次的常态需求。
3.技术选型灵活
微服务架构中的技术选型是去中心化的。每个团队可以根据自身服务的需求和行业发展的现状,自由选择最适合的技术栈。由于每个微服务相对简单,因此对技术栈进行升级时所面临的风险较低,甚至可以完全重构一个微服务。这使得对于特定领域的功能,可以充分利用该领域中最好的框架或编程语言来解决问题,而不受系统中其他服务的技术选型制约。
4.容错和故障隔离
当某一组件发生故障时,在单一进程的传统架构下,故障很有可能在进程内扩散,形成系统全局性的不可用。在微服务架构下,故障会被隔离在单个服务中。若设计良好,其他服务可通过重试、平稳退化等机制实现系统层面的容错。
5.灵活的扩展性
分层开发的整体系统并非一定不能进行横向扩展,只是对于大型系统而言,以整个系统为单位进行复制扩展的代价相对较高。事实上系统中网络流量和计算资源的需求差异往往是与业务功能挂钩的,例如报表计算的业务可能需要大量CPU,而购票的业务系统则需要更多的入口带宽,此时微服务架构的灵活性就体现出来了,因为每个服务可以根据实际需求独立进行扩展。
然而,这样的架构要是在早些年提出来,也许还要面临着项目运维的极大挑战。微服务架构项目中的每个独立服务团队都是自己构建、发布和维护自己的分布式微服务应用的,出于技术栈和工具选择的差异,完整部署这样一套系统就需要所有服务团队集体参与,因为很难有人能够熟悉每一个微服务的部署细节。容器技术则为微服务理念提供了统一的打包、部署和状态监控的方式,成为这个架构实施不至于失控的十分关键的环节。
微服务架构本质上是一种分布式的系统,在部署结构上与集群关系十分紧密。容器技术在集群上的运用已经比较成熟,特别是在服务调度和资源分配方面,这使得服务在设计完成后能够独立、快速地完成上线。
1.2.2 容器集群生态圈
容器集群技术的发展并不是孤立的单点,而是伴随着虚拟化技术、容器引擎、编排技术、操作系统、容器仓库、监控技术等周边技术链的共同繁荣。
图1-5是容器集群所处的完整生态。
图1-5 容器集群生态圈
1.容器引擎
容器引擎是容器集群生态圈的核心部分,它是与内核Namespace和CGroup等功能直接交互,并提供相应API使得外部能够与之集成的工具或服务。Docker无疑是目前为止设计最成功、使用最广泛的容器引擎之一。在1.12版本以后,Docker的容器化功能实际上已经由独立的项目RunC来实现,但Docker项目依然作为一种集成完备的容器引擎工具得到许多用户的喜爱。下面列举一些开源的容器引擎。
·Docker:https://www.docker.com。
·Rkt:https://coreos.com/rkt。
·Pouch:https://github.com/alibaba/pouch。
·Systemd-nspawn:https://www.freedesktop.org/wiki/Software/systemd。
·Hyper:http://hyper.sh。
·Garden:https://github.com/cloudfoundry/garden。
·LXC:https://linuxcontainers.org。
·Photon:https://github.com/vmware/photon。
·Jetpack:https://github.com/3ofcoins/jetpack。
·Kurma:https://github.com/apcera/kurma。
·Vagga:https://github.com/tailhook/vagga。
2.监控和数据收集
由于容器基于内核的特殊隔离方式,其对容器性能和状态的监控与虚拟机存在一些差别。传统的虚拟机监控工具,例如Nagios和Zabbix等,对容器监控的原生支持并不完善。而以下一些新启动的开源项目对这种场景具有更友好的体验。
·cAdvisor:https://github.com/google/cadvisor。
·Sysdig:http://sysdig.org。
·Prometheus:https://prometheus.io。
·TICK-Stack:https://influxdata.com。
·Docker-Alertd:https://github.com/deltaskelta/docker-alertd。
·Grafana:https://grafana.com。
其中的TICK-Stack指的是Influxdata推出的Telegraf、InfluxDB、Chronograf、Kapacitor四款开源工具,不过自TICK-Stack推出1.0版本以后,这些工具分别提供了开源版本和企业版本,后者增加了例如高可用、云端存储等企业级功能。
3.容器管理和界面工具
可视化是用户友好性十分重要的一种体现,Shipyard和Decking是Docker早期十分受欢迎的可视化工具,之后Docker又收购了Kitematic作为官方的容器管理UI。但随着容器应用集群化,早期的UI工具不再流行,一些针对特定集群平台定制的新型管理UI开始出现。例如Kubernetes官方推出的Dashboard项目可用于可视化地管理集群,Cockpit则是红帽公司推出的Kubernetes集群管理界面。以下是一些开源的容器管理UI项目。
·Kitematic:https://kitematic.com。
·DockerUI:https://github.com/crosbymichael/dockerui。
·Panamax:http://panamax.io。
·Rapid Dashboard:https://github.com/ozlerhakan/rapid。
·Cockpit:http://cockpit-project.org。
·Portainer:https://www.portainer.io。
·Shipyard:http://shipyard-project.com。
·Seagull:https://github.com/tobegit3hub/seagull。
·Dockeron:https://github.com/dockeron/dockeron。
·DockStation:https://dockstation.io。
4.基础设施集成
容器集群的实施是需要以硬件基础设施作为依托的,有些辅助工具能够简化这个过程。这些项目往往与具体的底层平台相关,如下所示。
·Nova-docker:https://github.com/stackforge/nova-docker。
·Magnum:https://github.com/openstack/magnum。
·Machine:https://docs.docker.com/machine。
·Boot2Docker:https://github.com/boot2docker/boot2docker。
·Clocker:https://github.com/brooklyncentral/clocker。
·MaestroNG:https://github.com/signalfuse/maestro-ng。
Nova-docker和Magnum都是在OpenStack中集成容器集群的项目。不过目前OpenStack官方正在尝试通过让Kubernetes直接创建虚拟机的方式来统一它在IaaS层和CaaS层的差异,其中的Nova-docker已经被废弃了。Machine是Docker公司推出的基础设施管理工具。Boot2Docker曾经是在Windows和Mac上使用Docker的官方方案,但随着Docker 1.12版本发布了多种操作系统的发行版后,已经不再被推荐使用了。
5.编排和调度
编排和调度是容器集群的基本功能,因此选择编排和调度工具实际上就是在选择容器集群的方案。以下是一些开源的容器任务编排调度工具。
·SwarmKit:https://github.com/docker/swarmkit。
·Kubernetes:http://kubernetes.io。
·Marathon:https://github.com/mesosphere/marathon。
·Rancher:http://www.rancher.com。
·Nomad:https://github.com/hashicorp/nomad。
·OpenShift:https://www.openshift.com。
·Crane:https://github.com/michaelsauter/crane。
·Nebula:https://github.com/nebula-orchestrator。
·GearD:http://openshift.github.io/geard。
其中的OpenShift主要是指其3.0之后的发行版(早期版本未开源),它是红帽公司基于Kubernetes二次开发的集持续集成和交付于一体的容器集群方案,它具有开源和商业两个版本。
6.容器镜像仓库
镜像仓库是基于容器的、在软件发布流程中必要的组成部分,Docker开源了其镜像仓库的最小实现,但对于企业级应用来说,它缺少了高可用、权限控制、管理界面等必要功能。Docker Hub和国内的许多容器云平台都提供了公有云的企业级仓库服务,社区中也有一些容器仓库的开源实现,如下所示。
·Repository:https://github.com/docker/distribution。
·Nexus:http://www.sonatype.org/nexus。
·Habor:http://vmware.github.io/harbor。
·Portus:https://github.com/SUSE/Portus。
·Docker Registry UI:https://github.com/atcol/docker-registry-ui。
其中的Nexus是一种通用的软件包仓库解决方案,支持包括Maven、NPM、PIP、RPM等许多主流打包格式的分发和管理,它在3.0以后的版本才开始支持作为Docker镜像仓库。Habor是VMware推出的企业级开源Docker仓库解决方案。
7.服务发现和容器域名服务
服务发现和域名服务实际上是微服务架构和容器集群的调度工具所需的组件,它们在容器集群中十分常见,也是这个生态圈中举足轻重的一部分,以下是其中一些在实际工程中被提及较多的工具。
·Etcd:https://github.com/coreos/etcd。
·Consul:http://www.consul.io。
·ZooKeeper:https:// ZooKeeper.apache.org。
·Eureka:https://github.com/Netflix/eureka。
·Traefik:https://traefik.io。
·Muguet:https://github.com/mattallty/muguet。
·Registrator:https://github.com/gliderlabs/registrator。
·SkyDNS:https://github.com/skynetservices/skydns。
8.容器日志收集处理
和容器集群的监控类似,收集容器中的服务运行日志,与在虚拟机中的实现同样存在许多差异。目前Docker已经内置支持的日志收集工具包括Splunk、Fluentd、Graylog和AWS、GCE等主流云丁商的日志平台。一些过去用于虚拟机的日志收集器,比如LogStash或Flume,同样能够使用容器中的服务,只是它们都不再是首选的方案。但Elastic公司新推出的Beats项目同样值得关注。以下是其中一些工具的链接。
·Splunk:https://www.splunk.com。
·Fluentd:https://www.fluentd.org。
·ElasticSearch:https://www.elastic.co/products/elasticsearch。
·Kibana:https://www.elastic.co/products/kibana。
·Beats: https://www.elastic.co/products/beats。
·LogStash:https://www.elastic.co/products/logstash。
·Flume:https://flume.apache.org。
ElasticSearch和Kibana是开源日志索引和展示的主流选择,因此也属于与日志相关的工具。值得指出的是,Splunk并不是开源或免费的,但它在企业级日志处理方案中的应用十分广泛。
9.与容器相关的系统发行版
有些Linux发行版是为容器运行而优化的,Atomic和ClearLinux系统都属于此类。另一些Linux发行版在设计之初就充分地将容器机制融入了系统的架构理念,例如CoreOS。有的系统甚至将Docker作为系统的核心服务来管理其他用户进程,例如RancherOS和Hyper容器引擎所使用的操作系统。类似的项目还有许多,它们都是架设容器集群时十分称手的基础设施,如下所示。
·Container Linux:http://coreos.com。
·Project Atomic:http://www.projectatomic.io。
·RancherOS:http://rancher.com/rancher-os。
·ClearLinux:https://clearlinux.org。
·Photon OS:https://vmware.github.io/photon。
·CargoOS:https://cargos.io。
·SmartOS:https://www.joyent.com/smartos。
第8章将进一步介绍Container Linux和RancherOS这两个操作系统的细节。
10.容器平台
容器平台是大规模容器运用的产物,它通常会与持续集成、持续交付的工具结合,连接上层应用服务和底层基础设施,帮助使用者快速实现从代码提交到产品上线全过程的端到端交付过程。这些平台继承并发扬了PaaS(Platform as a Service)服务的定位,并由此衍生出CaaS(Container as a Service,容器即服务)的概念。以下是其中一些相关的开源项目。
·Deis:https://deis.com。
·Flynn:http://flynn.io。
·Dokku:https://github.com/progrium/dokku。
·Fabric8:http://fabric8.io。
·Kel:http://www.kelproject.com。
·Nanobox:https://nanobox.io。
·Tsuru:https://tsuru.io。
除了这些开源的容器平台服务实现之外,互联网上还有许多在线按资源使用量付费的CaaS平台,它们也是整个容器集群生态的一部分。
11.容器网络
容器技术在解决环境隔离和配额问题的同时,也引入了网络层面的复杂性。由于使用了Network Namespace,每个容器都可以获得独立的IP地址,这对于单个主机的情况并无大碍,但对于容器集群的情况,IP地址的分配和互联就成为了新的问题。因此在设计容器集群时,通常需要针对网络的连接方式加以特殊考虑。常用的开源方案有以下这些。
·Libnetwork:https://github.com/docker/libnetwork。
·Flannel:https://github.com/coreos/flannel。
·Calico:http://www.projectcalico.org。
·Weave:https://github.com/zettio/weave。
·Romana:http://romana.io。
·Canal:https://github.com/projectcalico/canal。
·Open vSwitch:http://openvswitch.org。
·Pipework:https://github.com/jpetazzo/pipework。
这些网络方案大多采用了七层网络的Overlay Network方式,也就是在容器之间通信的网络包上封装了用于路由寻址的额外包头,这种方式会导致网络通信效率的下降,具体影响程度与所封装的额外数据大小有关。而Calico采用修改每个主机节点上的IPtables和路由表规则来实现容器间数据路由和访问控制,属于三层网络的方式,这种方案在节点规模不太大(最多几百个节点)时的效率优势十分明显,是一种比较受推荐的容器网络工具。除了这些较常用的方案,一些条件允许的企业也会结合MacVLAN等二层网络方案实现容器的互联,以获得更好的网络性能。
12.容器安全
容器安全性问题的根源在于容器和宿主机共用内核,因此受攻击的可能性特别大。另外,如果容器里的应用导致Linux内核崩溃,整个宿主机系统都会崩溃,这一点与虚拟机是不同的。此外,镜像的安全性也是容器安全的一部分,如何保障用户下载的镜像是可信的、未被篡改过的,以及如何保证镜像中不会意外包含具有大量漏洞的老旧软件,都是需要考虑的问题。目前这些安全课题主要在一些企业级应用中引起较多重视,下面是一些相关的开源工具和项目。
·Notary:https://github.com/docker/notary。
·Clair:https://github.com/coreos/clair。
·AppArmor:https://en.wikipedia.org/wiki/AppArmor。
·SELinux:https://selinuxproject.org。
·Twistlock:https://www.twistlock.com。
·OpenSCAP:https://github.com/OpenSCAP/container-compliance。
13.容器数据持久化
容器是一种不可变的基础设施,容器的数据应该通过Volume的方式保存到外部的介质上,容器持久化存储本质上就是要解决如何简便地将外部存储挂载到容器中使用的问题。Docker在其1.9版本后提供了存储的插件,这也为许多存储方案提供了便利,以下列举几个例子。
·Flocker:https://github.com/clusterhq/flocker。
·Convoy:https://github.com/rancher/convoy。
·REX-Ray:https://github.com/codedellemc/rexray。
·Netshare:https://github.com/ContainX/docker-volume-netshare。
·OpenStorage:https://github.com/libopenstorage/openstorage。
其中的Ceph是通用的网络存储工具,它对容器化存储具有良好的支持。
14.容器相关开发流程工具
容器的镜像可以被看作一种新型的应用打包方式,因此容器常常与软件的开发和持续集成、持续交付流程相结合,提供在不同环境中的一致性部署能力。以下是一些利用容器改善软件开发和交付的工具或平台。
·Drone.io:https://drone.io。
·Shippable:http://shippable.com。
·Cyclone:https://github.com/caicloud/cyclone。
·Screwdriver:http://screwdriver.cd。
·WatchTower:https://github.com/v2tec/watchtower。
·Wercker:http://wercker.com。
·Totem:http://totem.github.io