使用 Kubernetes 控制容器混乱

7 位读者喜欢这篇文章。
How Kubernetes is helping Docker blossom

Maersk Line。CC SA-BY 4.0

您已经切换到 Linux 容器。现在您正在尝试弄清楚如何在生产环境中运行容器,并且您正面临一些在开发过程中没有出现的问题。您需要的不只是几个精心准备的 Dockerfile 才能转移到生产环境。您需要的是某种东西来管理您的所有容器:一个容器编排系统

问题

让我们来看一个相对简单的应用程序,一个使用 PHP 和 MySQL 的简单数据库驱动的 Web 应用程序。您对解决方案的初步尝试可能是将所有 HTTP 职责(如提供 API 和前端用户界面 (UI))拆分到一个容器中,并将所有后端存储拆分到第二个容器中。

现在您有了看起来像这两张图片的的东西

PHP frontend Dockerfile

 

MySQL backend Dockerfile

如果您需要扩展此架构,这非常容易,您可以添加更多前端容器的副本。接下来的两张图片显示了一个前端带一个后端,以及多个前端带一个后端

Single frontend and a single backend

Multiple frontends and a single backend

现在有人跳出来告诉您,这不是好的微服务架构。他们是对的,因为您确实需要进一步拆分职责。从同一个容器中提供 PHP 驱动的 API 和 HTML/JS/CSS UI 不是最佳实践。最好将它们拆分成两个容器

  • PHP 和 NGINX 提供 API
  • NGINX 提供 HTML/JS/CSS

PHP services Dockerfile

NGINX frontend Dockerfile

另一个人跳出来指出,让 MySQL 持久数据存储在临时容器上运行是次优的,因为当容器关闭时,您会丢失数据。为了解决这个问题,您可以向容器添加一个持久存储卷,该卷位于容器外部。运行 MySQL 的容器可以关闭,而不会带走您的数据。

MySQL backend with persistent disk Dockerfile

现在您可以扩展您的容器解决方案并使用更多容器来处理更大的负载。

Multiple containers for frontend, service, and backend layers

现在您有了一个很棒的容器解决方案,能够处理大量流量,但它是基于一个谎言。好吧,谎言可能有点不公平,所以我们说它是基于一个抽象。容器仍然在资源有限的机器上运行,所以我们希望这项工作在多台机器之间分配。如果其中一台机器宕机,您需要移动容器怎么办?

Expanded deployment on additional hardware

现在,您为您的设置增加了很多复杂性,但您仍然需要维护单个机器、处理正常运行时间以及移动资源等底层复杂性。

解决方案:容器编排

您会希望拥有某种系统来管理您需要运行容器的所有裸机或虚拟机。您也会希望该系统能够管理您的容器,在底层机器上启动它们,确保它们被分配,并保持它们的健康。我在这里描述的被称为容器编排系统。并且,Kubernetes 就是这样一个系统。

在讨论容器和 Kubernetes 时,有两个概念非常重要。

临时计算

服务器宕机。堆栈溢出。当您每天处理数百万个请求时,就会发生百万分之一的问题。与其试图追逐难以捉摸的九个 9,不如设计您的应用程序来处理进程宕机的情况。因此,您应该预期在容器中运行的任何东西都会消失,并被该容器的另一个新版本取代。

有很多用于此的比喻,但最常见的是“宠物与牲畜”。宠物是您像对待家里的狗、猫、兔子或迷你猪一样对待的服务器。您给它们命名,您像对待个体一样照顾它们,当它们在半夜生病时,您会悉心照料它们直到康复。您不希望容器是这种情况。相反,您希望服务器可以像对待牲畜一样对待:大量运行它们,不要费心起个别名称,如果一个在半夜生病了,您就做成汉堡。(实际上,不要吃生病的牛。那样您会感染不治之症——不如做一件皮大衣。)

期望状态

期望状态与我们所说的命令式风格指令相反,命令式风格指令只是脚本的另一种说法。当我们编写脚本时,事情之所以发生是因为我们列出了具体的步骤并等待它们完成。通过脚本,您可以创建新的

  • 带有代码更新的镜像
  • SQL 数据库
  • API 服务器
  • 前端服务器

如果您的过程中的某个步骤失败,则该过程将停止,并且您的应用程序不会启动。如果这些机器中的一台在启动后宕机,则必须有人或某物重新启动它。

期望状态,或声明式,而是说:“描述您想要的设置,系统将使其发生。” 因此,您不必写出步骤,而是说

  • 我想要 1 个数据库副本。
  • 我想要 2 个 API 服务器副本。
  • 我想要 3 个前端服务器副本。

声明式系统确保您始终运行着那么多副本。如果一个副本宕机,它会重新启动另一个副本。如果运行的副本太多,它会杀死多余的副本。现在您必须稍微更改您的应用程序。如果 API 服务器在 SQL 数据库之前启动,您可能会遇到 SQL 连接错误。您需要确保向系统添加渐进式重试。但是这些更改很简单,并且在许多情况下已经是最佳实践。

用于编排的 Kubernetes

Kubernetes 是一个开源容器编排系统,它使用期望状态理念运行您的所有应用程序容器。Kubernetes 由 Google 创建,旨在捕捉我们的工程师在过去 10 年中构建我们自己的容器编排系统(我们称之为 Borg)时获得的经验。它不是该系统的端口或转换。相反,它是从头开始的全新尝试,旨在第一次就把事情做好,并分享我们的经验。它受益于与 Red Hat、CoreOS、IBM、Mesosphere 和 Microsoft 的合作。

Kubernetes 有很多组件使其工作。让我们探索一些更重要的组件。

容器

容器是 Kubernetes 中的亚原子组件,这意味着您永远不会只运行一个容器,因为它们必须在称为Pod的控制结构内运行。但是您可以完全按照在 Docker 中所做的方式运行基于 Dockerfile 的 Docker 镜像。我经常有 Makefile 在 Docker 中运行容器进行开发,然后在 Kubernetes 中启动进行生产。

Pod

Pod 是 Kubernetes 的原子单元。Kubernetes 的其他组件启动一个或多个 Pod,或将一个或多个 Pod 连接到网络。Pod 由一个或多个容器组成。在同一 Pod 中运行的容器共享磁盘、localhost、安全上下文和一些其他属性。

部署

部署是运行一个或多个 Pod 的控制结构。Pod 本身没有期望状态的概念。部署通过创建副本集来管理一组 Pod 的期望状态。例如,如果您需要三个此 Pod,则始终有三个 Pod 正在运行。部署还管理 Pod 的更新。

服务

服务将临时 Pod 连接到需要长时间运行的内部或外部进程,例如 API 端点或 MySQL 主机。假设您有三个 Pod 运行 Web 服务器容器,并且您需要一种方法将来自公共互联网的请求路由到您的容器。您可以通过设置使用负载均衡器将来自公共 IP 地址的请求路由到一个容器的服务来做到这一点。给 Pod 添加一个标签,例如“web server”,然后在服务定义中说:“使用任何标记为web server的容器来服务端口 80”。然后 Kubernetes 将使用公共负载均衡器来分配所选容器之间的流量。这也可以私下完成,用于您只想向 Kubernetes 应用程序的其他部分公开的主机,例如数据库服务器。

总结

总而言之,要在 Kubernetes 上提供一个简单的 Web 前端,您需要

  • 配置 Docker 镜像。
  • 配置引用该镜像的部署。
  • 运行部署以基于该镜像启动 Pod 的副本集。
  • 配置引用 Pod 的服务。
  • 使用公共负载均衡器运行服务。

Kubernetes 绝不是此处所述问题的唯一解决方案。Docker Swarm、Amazon Container Service 和 Mesosphere 都是替代方案。Kubernetes 拥有活跃的开源贡献者社区、强大的架构、在许多商业云上运行的能力,并且它可以在裸机上运行。我邀请您查看该项目,看看它是否对您有意义。

我将在 2016 年都柏林 DrupalCon 上就此发表演讲

User profile image.
Terry Ryan 是 Google Cloud Platform 团队的开发者布道师。他拥有 15 年的 Web 工作经验 - 包括前端和后端。在为 Google 和 Adobe 等技术公司工作之前,他曾在沃顿商学院担任将开发与系统管理相结合的职位。

评论已关闭。

Creative Commons License本作品根据 Creative Commons Attribution-Share Alike 4.0 International License 获得许可。
© . All rights reserved.