在生产中部署容器的更好方法

在单个容器主机上部署容器

几乎所有容器运行时都设计为在单个容器主机上运行容器 ; 容器共享主机操作系统内核和特性,如cgroups,命名空间,chroot,SELinux和seccomp等,以提供隔离和安全性。因此,一组给定的容器可能需要在单个容器主机上运行。目前,当前可用的容器运行时都没有提供将多个容器主机集成在一起以共享工作负载的机制,除非使用容器集群管理器。下图说明了如何使用单个容器主机将部署在一组VM上的软件解决方案移动到容器化环境中:




radware负载均衡原理 rancher负载均衡_应用程序


此部署模型简单易用,易于设置且易于使用。它非常适合在开发人员计算机上设置开发环境。但是,当将软件解决方案移至开发环境之外并在QA、性能测试、预生产环境和生产环境中部署时,由于容器部署在单个容器主机上,因此可能需要进行以下限制:

  • 单点故障:由于如果主机在某个时刻出现故障,所有容器都在单个主机上运行,则所有容器也会失败。结果,在容器上运行的整个软件系统将变得不可用。
  • 资源限制:由于只有一个容器主机可用,容器在某些时候会达到它的资源(CPU,内存,磁盘)限制。之后,除非主机垂直缩放,否则系统将无法向上扩展。
  • 没有自动修复和自动缩放功能:目前,没有任何容器运行时为容器提供自动修复和自动缩放功能。因此,可能需要由人工管理或使用其他软件组件自动管理。
  • 有限的容器编排功能:在部署复合应用程序时,容器可能需要某种级别的编排功能来进行容器分组,容器集群分组,处理依赖关系,运行状况检查等。Docker已经使用Docker Compose为此提供了解决方案,但即使使用自己的容器集群管理器Docker Swarm ,它也有一些限制。
  • 有限的服务发现功能:复合应用程序的组件可能需要使用某种机制相互交互。最简单的方法是使用域名来发现他们的依赖。Docker Compose用Docker-links解决了这个问题; 它的作用是,如果容器A依赖于容器B,当启动容器A时,我们可以指定一个到容器B的链接。然后Docker在容器A中生成一个指向容器B的IP地址的/etc/hosts条目。这适用于1:1场景,但可能不适用于1:M用例。

在容器主机集合上部署容器

解决上述问题最简单的方法可能是使用容器主机的集合。请参考下图:


radware负载均衡原理 rancher负载均衡_集群管理_02


这种方法可能看起来简单直接,但可能会产生以下影响;

  • 独立操作的容器主机:即使使用了容器主机的集合,它们也不会相互了解分配工作负载。
  • 容器管理开销:需要手动与系统交互并在容器主机之间分配容器以确保每个应用程序组件的高可用性,这称为容器调度。在现实生活中,对于不可变的,短暂的容器来说,这可能是不实际的。可能需要一种编程方法来安排容器,自动修复和自动缩放它们。
  • 断开连接的桥接容器网络:由于每个容器主机都有自己的容器桥接网络,容器IP地址将由容器主机租用。因此,容器IP地址将在主机之间重复。更重要的是,容器之间不会有直接路由。在部署需要在应用程序组件容器之间进行内部路由的复合应用程序时,这可能会成为问题。
  • 没有动态负载平衡:让我们假设容器使用主机端口公开其端口。给定的应用程序组件容器可以在多个容器主机中使用。在这种情况下,需要通过指向容器主机IP和主机端口根据容器可用性手动配置负载平衡器。

在Container Cluster Manager上部署应用程序


radware负载均衡原理 rancher负载均衡_集群管理_03


上图说明了容器集群管理器的参考体系结构。在这种方法中,使用容器主机集合的第二种方法中确定的几乎所有问题都是通过以编程方式管理容器主机群集和在其上运行的容器群集来解决的:

  • Scheduler

调度程序是容器集群管理器的大脑。它通过分析每个主机的资源利用率来监视整个容器集群,并采取容器调度决策来优化资源使用和容器的高可用性。

  • Agent

代理程序组件在每个容器主机中运行,以提供主机管理功能并将资源使用情况统计信息发送给计划程序。每当调度程序想要在主机中创建或终止容器实例时,它就会与相关代理进行通信,并让它执行容器管理命令。

  • Overlay Network

Overlay Network可以使用诸如Flannel,Open VSwitch或Weave的软件定义网络(SDN)框架来实现。使用此类解决方案的主要优点是容器集群中的所有容器都将连接到具有容器到容器路由的单个网络。更重要的是,容器将获得SDN租用的容器主机上的唯一IP地址,并且如果需要,将能够与容器主机群集的物理网络集成。

  • DNS

DNS是容器集群管理系统的另一个关键要素。它主要有两个目的;

容器和容器集群提供域名。例如,如果应用程序服务器部署在一组容器上,则每个容器和容器集群可能都需要可访问性的域名。 使用DNS循环进行服务发现,如果不需要应用层路由,则DNS服务器可用于OSI模型的网络层的循环负载平衡。

  • 负载均衡器

容器集群管理器可以动态配置第三方负载均衡器,例如Nginx,haproxy,用于为应用层的容器提供负载均衡。如果UI组件需要会话亲和性,这适用于路由HTTP流量。此外,它还提供了在暴露众所周知的HTTP端口(如80,443)的同时执行基于主机名的路由的能力,而无需暴露动态主机端口。

Container Cluster Manager中必需的主要功能

容器集群管理器需要以下主要功能,以便在生产中部署复合,复杂的应用程序;

  • 容器组:通过使用Linux命名空间共享磁盘,进程,用户等将一组容器组合在一起。
  • 容器集群管理:
  • 应用健康检查:
  • 自动愈合:
  • 水平自动调节:
  • 域名命名和服务发现:域命名和服务发现对于在容器上部署复合应用程序非常重要。
  • 动态负载均衡:容器集群管理器需要动态配置负载均衡器作为容器端口,主机端口可以根据部署在运行时更改。
  • 日志访问中心:在容器本身上访问数百个容器的日志几乎是不可能的。因此,集群管理器需要提供从中央位置访问日志的机制。
  • 多租户:多租户可能是与多个租户共享单个容器集群管理器实例的必要条件。
  • 身份和授权:集群管理器和部署在顶部的应用程序都需要身份和授权管理。
  • 存储系统:需要持久存储的应用程序需要使用卷装入,以避免在重新启动容器时丢失写入磁盘的数据。

结论

总之,容器可以在单个容器主机上运行,同时多了一些限制:单点故障,资源限制,没有自动修复和自动扩展,有限的容器编排功能,有限的服务发现功能等。从积极的一面来看,它将减少设置容器集群管理器的开销。Docker解决了使用Docker Compose在单个容器主机上部署复合应用程序的问题。它也适用于Docker拥有的容器集群管理器Docker Swarm,但有一些限制。因此,生产级复合应用程序部署可能需要容器集群管理器,它可以处理复杂的部署要求,例如容器分组,容器集群管理,应用程序运行状况检查,自动修复,水平自动扩展,域命名,服务发现,动态负载平衡,集中日志访问,多租户,身份,授权,安装存储系统等

参考

[1] Docker, What is Docker?: https://www.docker.com/what-docker

[2] Docker Docs, Docker Compose: https://docs.docker.com/compose/

[3] Docker Docs, Docker Swarm: https://docs.docker.com/swarm/overview/

[4] Kubernetes Docs, What is Kubernetes: http://kubernetes.io/docs/whatisk8s/

[5] Kubernetes Github Repository, Kubernetes Architecture: https://github.com/kubernetes/kubernetes/blob/release-1.2/docs/design/architecture.md

[6] Apache Mesos Docs, Mesos Architecture: http://mesos.apache.org/documentation/latest/architecture/