你觉得 Kubernetes 是不是太复杂了?认为学习它是在浪费时间?经验告诉我,你并不孤单!见鬼,我有提供Kubernetes 培训[2]给了人们,所以我非常清楚学习是有曲线的。一开始它可能看起来很复杂,因为你显然需要学习各种各样的抽象概念和对象。但是,如果你把这些都看一遍,看看 Kubernetes 会给你什么,你会发现它们都设计得很好。这是有道理的。我是不是生活在某种幸福的 Kubernetes 涅槃状态的泡泡里?也许。但这是一个很好的泡泡,所以拿起一杯咖啡,加入我!
那些不了解 Kubernetes 的人注定要重新发明它,很糟糕地
我发现Henry Spencer[3]关于 UNIX 的名言也适用于 Kubernetes。因为尽管我同意 Kubernetes 中的概念需要学习曲线,但如果你试图在“更简单”的系统中实现所有这些特性,你不应该低估你所面临的学习曲线。
我最近和一些朋友出去玩,回忆起我们只使用配置管理系统,并在裸机上运行应用程序的美好时光。这些应用程序被勤奋地打包成 Debian 包,通过 Ansible 安装,这也是我们管理它们的方式。Nagios(喜欢 Munin 的家伙被我们其他人忽略了)用于监视我们的系统,当然日志只在磁盘上存储。审核谁在系统中做了什么从来都不是我们真正想过的。我们都只是登陆然后随便做。当然,所有这些都很有效。直到问题出现。
不管出于什么原因,当问题出现时,我们会有很多事情要做来修复它。物理硬件是否已经死了?是操作系统升级搞砸了吗?如果你在这个领域呆了一分钟以上,你就会知道出错的可能性是无限的。所以我们必须在其他地方启动软件。迁移数据,要么将数据从一个地方复制到另一个地方,要么将硬盘驱动器实际连接到另一台(未死的)机器。
这些都是手工完成的吗?是的,大部分!至少一次。当我们厌倦了手工操作时,我们会尝试使用脚本实现自动化。无尽的脚本。要我说,是脆弱的。不过,他们大部分时间都能完成自己的工作。虽然很有趣,但也很乏味。在多台机器上运行软件需要我们进行规划。在发生错误时动态地重新调度?不成!
Kubernetes 做对了部署和编排
Kubernetes 的核心是分布式键值存储和一组控制循环,这些控制循环可以在集群中的多台机器上自动部署。就是这样。分布式键值存储是容错的,因为只要剩余的成员占多数,它就可以承受成员的损失。控制循环连续运行,并确保如果发生错误,有一个简单的修复,他们只需修复它。
假设一台机器死了。Kubernetes 在几秒钟内就注意到了这一点,并将应用程序组件部署到其他地方。然后,它修改自己的覆盖网络,使流量仍然可以流向被替换的组件。它还检查组件是否已经正确启动,并在让流量到达组件之前接受流量。
最重要的是,如果它理解你的负载需要它,它还能够在更多的集群中扩展你的应用程序组件。老实说,一个人做这些事简直是一场噩梦:我知道自己的局限性。所以你可以批评 Kubernetes 的复杂性,但它解决的任务也很复杂。
那次我拼凑了一个像 Kubernetes 那样的烂平台,以及它为什么这么烂
我曾经做过一份很烂的 Kubernetes。是的,它很糟糕。让我来告诉你这个故事。那是 2014 年。Kubernetes 刚要出柜,但是在直接贡献者之外,谁知道呢?和其他 DevOps 用户一样,我也被 Docker 容器深深吸引。所有依赖打包成一个包,我可以直接交付到生产?哇!
但是在集群中的许多机器上运行是很痛苦的。Docker 试图通过笨拙的 Docker Swarm 项目来解决这个问题,该项目现在处于生命支持或死亡状态。我一点都不关心它,甚至都不去检查它是哪一个。这就是死亡的程度。至少对我来说是这样。但没有死的是一头美丽的野兽,名叫 CoreOS。CoreOS 是一个专注于运行容器的 Linux 发行版。它的特点是 etcd,分布式键值存储,是现代 Kubernetes 的大脑。它与一个名为“fleet”的组件一起,创建了一个基于 systemd 的分布式 init 系统。以至于如何运行容器是通过编写 systemd 单元文件来定义的。这是非常灵活的,让你可以轻松地描述组件之间的依赖关系。你也可以将应用程序配置存储在 etcd 中!只要把它推到那里,它就可以从任何地方读取!最后,一个让你运行集群容器化应用程序的工具!但是配置的变化呢?我找到了 Kelsey Hightower 开发的一个工具,叫做"confd",它可以帮助你在 etcd 中的数据发生变化时做出反应。所以我所要做的就是在 etcd 中更新配置,这将自动触发组件重启。我在 LinkedIn 上写了一篇关于这个系统的博客[4],以及我如何使用它来安装 WordPress。不要到访那个链接。
那么,到底哪里糟糕呢?当然,数据管理。我必须自己建立一个网络文件系统,并让它在主机访问容器中运行,这些容器可以通过 systemd 单元文件将 GlusterFS 文件系统挂载到 CoreOS 主机。然后在我的 WordPress systemd 单元文件中引用这个特定的挂载目录。所有相互依赖的组件(哦,哇,有好几个!)必须引用彼此的 systemd 单位。它能工作吗?可以。但这是一场噩梦。我花了很长时间才安排好。维护它也是一团糟。我不认为我做了什么明智的日志记录。审计呢?我想我当时的字典里连这个词都没有。我很有信心,我可以在一个下午基于 Kubernetes 实现相同的系统。记住,我是个知道自己能力有限的人。所以,我认为这完全是 Kubernetes 有多优秀的一个标志。
Kubernetes 如何帮助部署和操作应用程序
如果我使用 Kubernetes 来实现 WordPress 设置会有什么不同?首先,通过选择如何运行各种组件,我清楚地与 Kubernetes 沟通了我的意图。
WordPress 想要使用的数据库?这是需要持久存储的东西,我希望它具有稳定的网络地址和主机名,因为这使它们集群变得非常简单。这将在一个带有持久化卷的 StatefulSet 中运行。如果一个实例崩溃,它将被重新创建,但以一种其他实例无法察觉的方式。像 memcached 这样的缓存层,根据定义,它只是内存中的临时存储?将其部署为 Deployment 没有问题,因为我只关心 Kubernetes 是否会在某个地方重新创建它。
我想把应用程序暴露到互联网上,这样访问者就可以看到它。而且因为 WordPress 喜欢使用“本地”文件系统,所以如果我有多个应用服务器,它就必须有一个网络文件系统的支持。但我不需要这些有稳定的网络地址之类的,所以 Deployment 就可以了,但我必须确保它们都附加的持久卷是一个允许多个写入器的卷。它还需要有一个 Service 和该 Service 前面的一个 Ingress。Ingress 指示 Ingress Controller 只监听 HTTPS 流量,它也可以为我做 SSL 终止。哦,通过 cert-manager,它也会为我做所有 Let’s Encrypt 的加密魔法等等。如你所见,只要知道我需要使用哪个 Kubernetes 对象,就可以为我解决很多问题。不再有只有我能理解的定制和定制脚本。
除此之外,现在所有优秀的软件都知道如何在 Kubernetes 中部署,比如 Helm charts,甚至 Kubernetes Operators,用组件构建应用变得容易多了。在我们有 Kubernetes 之前,我们必须自己弄清楚运行时环境之间的各种差异。
总结
Kubernetes 是不可避免的。这不仅仅是因为谷歌想通过标准化应用程序的部署方式来挖走 AWS 云客户。而是因为我们都厌倦了自己处理低级别的事情,不得不开始处理困难的操作任务:自动故障转移、滚动部署、重新调度等等。
参考资料
[1]
Elastisys 博客: https://elastisys.com/why-kubernetes-was-inevitable/
[2]
Kubernetes 培训: https://elastisys.com/training/
[3]
Henry Spencer: https://en.wikipedia.org/wiki/Henry_Spencer
[4]
博客: https://www.linkedin.com/pulse/automation-scalable-wordpress-using-docker-coreos-etcd-lars-larsson/