为什么 Kubernetes 如此难?
介绍
Kubernetes (k8s) 在过去几年里风靡一时,因为应用程序编排已成为运行容器的生产工作负载的必备条件。“容器化”应用程序相对简单,大多数称职的 DevOps 工程师都能创建一些 Dockerfile,并在流水线中构建可运行的镜像。但是,该在哪里“运行”Docker 容器?部署哪些版本?所有容器如何相互通信?这时,编排就派上用场了,大型供应商也为此提出了一些解决方案。截至撰写本文时,主要有两种方案可供选择:亚马逊网络服务 (AWS) 的弹性容器服务 (ECS) 和所有基础设施即服务 (IaaS) 提供商(甚至包括 AWS)都提供的 Kubernetes。
希望编排能够让公司快速轻松地将容器化应用程序交付到测试和集成环境中。理想的情况是它“立即生效”,也就是说,你只需弹指一挥,等待几分钟就能看到应用程序运行起来。理想情况下,你只需要指定运行应用程序所需的最少信息:名称、框架、依赖项等等,最好是从现有的配置文件中读取。无论如何,这就是我们的希望。
显然,从标题来看,我们关注的是 Kubernetes,主要是因为它随处可用,而且主要的原因是唯一的其他选择是 ECS,这恰恰证明了我们的观点:Kubernetes 难以使用,因为 AWS 提出了他们自己的解决方案,据说更容易使用。但是,为什么它这么难用?让你的应用程序在 Kubernetes 中运行起来合理需要多长时间?为什么它并没有更容易?
Kubernetes 基础设施很难
尽管大多数公司不会自己搭建 Kubernetes 集群,但我们始终从基础设施入手。如果您打算使用托管基础设施服务,K8s 将是首选。我相信有些人会在笔记本电脑上启动minikube,然后对自己说:“哇,这太简单了!我自己也能做!!” 这让我想起有些人会在笔记本电脑上启动Elasticsearch容器,然后说:“哇,我们应该在我们的网站里实现这个!!” 六个月或一年后,生产环境上线,简单的“我们可以自己做”变成了“真希望我们不用再做了”。
如果您真的要构建自己的 Kubernetes 集群,则需要在您选择的 IaaS 裸机或虚拟机 (VM) 上构建所有控制平面服务器和服务,然后使用一些复杂的网络配置将它们绑定在一起,以分离控制平面流量和容器流量。您需要配置并运行所有控制平面软件,并使它们相互通信、稳定运行并得到适当的监控。相反,您需要编排用于编排应用程序的容器,但无需进行大量的编排!在 Windows 上运行 minikube 或 Docker Desktop 时呈现的华丽景象掩盖了使用容器运行容器编排系统的所有初衷。
我们甚至还没有讨论设置入口(通常只是 nginx 实例)和位于控制平面堆栈顶部或旁边的负载均衡器的复杂性。很多时候,你会觉得自己只是为了运行你的基础设施而创建了一整套基础设施(这并不罕见,但绝对没有比自己尝试编排更好的感觉)。我们还没有讨论需要设置基于角色的身份验证控制和网络策略来支持在一个集群中运行多个应用程序或堆栈。配置点和服务器端设置的数量开始迅速增加,我们甚至还没有开始编排应用程序,而这正是我们应该设置的编排系统的全部意义所在。
假设你真的踏入了波涛汹涌、冰冷刺骨的北大西洋深海,建造了一艘足以投入生产的船只,能够将容器编排到实际的应用程序中。回顾日历,距离你开始已经过去了六个月或一年,而你现在才部署一个控制平面,上面写着“Hello World!”。你以为自己成功了,正准备庆祝一番,这时你查看了网站的发布页面,发现现在有新版本的 Kubernetes 需要部署了!
我听到了你们说的话:“我们large company
拥有全世界最优秀的lots of
DevOps 工程师,我们可以处理所有繁重的工作,而你们只是个爱抱怨、爱嫉妒的小孩子。” Datadog和Ticketmaster ,我懂你们。(顺便说一句,你们对嫉妒的指责或许是对的。在我的好朋友 Justin Dean 的主题演讲结束时,他展示了所有团队成员的幻灯片,我的照片本应放在那里——但我两年前就离开了团队。)对于其他人来说,我们都决定不再花六个月或一年的时间来构建我们的控制平面,启动我们的 IaaS 提供商的托管服务,然后祈祷一切顺利。top decile
K8s YAML 不是标记语言
如果您跳过前文,直接启动一个托管的 Kubernetes 集群,那么您仍然需要经历一段漫长而乏味的旅程,涉足令人困惑的 YAML 深海。YAML 之于文本,就如同詹姆斯·乔伊斯的《芬尼根的守灵夜》之于英语。如果您闭上一只眼睛,只用左手小指和右手拇指跟着盲文走,双脚摆出芭蕾舞的第五式,然后低声背诵二战密码,您就会发现 YAML 非常容易理解。一旦掌握了它,就像在几厘米厚的冰面上骑自行车穿越结冰的湖面,狂狼在后面追赶您一样轻松。这就像在黄金走私日试图闯入诺克斯堡举行的“远古外星人”鸡尾酒会一样容易。
瞧,其实没那么难,对吧?假设有个人在街上向你走来。他是一位 K8S 专家,准备向你演示部署一个“Hello World” Web 服务有多么简单。对话如下:
Him: “kind: Deployment”
You: “Oh, I see. Yes, I like it.”
Him: “apiVersion: apps/v1beta1.”
You: “Uh, okay. Isn’t v1beta1 out of date? You can use v1 as of k8s 1.9.
It’s actually removed in 1.16, but I wonder how many people have never
updated.”
Him: “Start over.”
You: “Wat.”
Him: “kind: Deployment”
You: “Stop with the Kinds everywhere!”
Him: “apiVersion: apps/v1”
You: “This again.”
Him: “spec:”
You: “Huh??”
Him: “selector:”
You: “No.”
Him: “matchLabels:”
You: “Wat.”
Him: “app: nginx”
You: “That’s nearly the first thing I’ve understood about this so far.”
Him: “spec:”
You: “Again?”
Him: “containers:”
You: “Okay, now we’re getting somewhere.”
Him: “image: nginx:1.14.2”
You: “Hmm.”
Him: “ports:”
You: “Aiiiiieeee.”
Him: “containerPort: 80”
You: “I’m going home. I quit. There must be a devops job I can get where
I work on [Gatsby blogs](https://www.gatsbyjs.com/ "Gatsby nodejs frontend")
all day.”
这只是尝试阅读和理解文件。尝试阅读两个 k8s yaml 示例,然后自己从头开始生成一个。更好的是,每天尝试一个Code Kata练习,编写可工作且可部署到 Kubernetes 的配置。
我赌你。
复制粘贴不是代码
我仍然对上一节的内容窃喜。我不得不笑,因为这是我日常生活中每天都要面对的痛苦,直面这种痛苦就像站在高速公路上基努·里维斯驾驶的公交车前一样。唯一让我继续埋头苦干的原因是,我意识到使用 NodeJs 会更糟糕。问题是 Kubernetes 文档已经相当不错了。你复制粘贴一些 hello world 示例,输出看起来好像可以正常工作。你开始熟练使用 kubectl 了。你可以在 YAML 中看到模糊的形状和轮廓。你开始对自己可能能够做一些有用的事情充满信心。
“我们试试把应用迁移到 Kubernetes 上!”你从浴缸里出来,浑身湿透,只裹着一条毛巾,就像阿基米德在锡拉丘兹的街道上飞奔一样,对着空中大喊。“我们只需要从这里复制粘贴一些代码,然后把它们放到那里,我们的应用很快就能运行起来了,”你气喘吁吁地向同事解释道。“能用吗?!”他们兴奋地问。“还没用到。我的意思是,不能。我需要缩进这部分代码,并删除一个规范中没有用到的部分。然后我需要决定是使用部署还是守护进程集,不过快完成了。我发誓!”
首先,穿上衣服。我完全赞成一边洗澡一边思考 Kubernetes YAML 文件,但之后你需要穿好衣服。另外,如果你把 Macbook Air 掉进浴缸里,结果可能会很惊人。我知道。其次,给你出个谜语:你认为需要多少个 YAML 文件来运行和部署你的应用程序?幸好有些人有十个手指和十个脚趾,因为这可能就是你需要的数目。它们都相关但又不完全相关。如果你喜欢冒险和容易上当受骗,你可以复制粘贴部分内容,但你不知道这些部分是否兼容。只有四个必填字段,全都是乱码,所有内容都在下面spec:
(包括spec:
)。大多数部分都是重复的,但只是略有重复。它们在微观上有所不同,但在宏观上却很重要。
复制粘贴是一门奇妙的艺术,我个人的整个成年职业生涯都是如此。我欣然承认,我人生的全部产出就像从 Stack Overflow 和文档示例中剪下来的勒索信。但要把这些脆弱的文本拼凑在一起,去做一件本应非常简单明了的事情,却既繁琐又容易出错,而且需要反复试验。更好的做法是,表达出你想要的东西,并能够实际生成可执行的代码,从而产生你想要的结果:也就是让你的应用程序运行起来。
所有关于 YAML 的抱怨听起来挺有意思,但实际上它恰恰反映了问题的症结:Kubernetes 如此难用,是因为它的界面必须完全僵化。Kubernetes 的配置并非生机勃勃、巍峨雄伟的树木,而是一堆枯死的碎木。它们甚至比碎木更糟糕,就像整片石化森林,如同堆积如山的岩石,上面印刻着数千年年轮的痕迹,并保存了数百万年。
不,它们比石化木森林还要糟糕!Kubernetes 清单就像 21 世纪的穿孔卡片。每个 YAML 都像是在切碎的木卡片上戳了一堆孔,我们既看不懂也读不懂,我们盲目地把它们塞进命令里kubectl apply -f
,希望它们顺序正确,没有在任何地方犯任何孔洞错误。然后,就像过去的机器一样,我们试图通过查看闪烁的指示灯和模糊的纸带输出来洞察正在发生的事情,希望从中获得一些见解。
就像试图在自动钢琴上重现莫扎特或贝多芬的作品一样,它既繁琐费力,又容易出错,最终也难以实现。同样,k8s 的清单也永远被冻结在时间中,无法以富有表现力的方式书写,只能无限重复v1beta1
相同的旋律。尽管v1
已经发布两年了,人们仍然在使用,是因为自那以后再也没有人生成新的 k8s 配置。
医生,治愈你自己;或者调试你自己很难
K8s 的一大优点在于,一旦出错,无人知晓。我部署了一些东西,然后又在别的地方忙活了几个小时,回来后才发现部署悄无声息地失败了,却没有任何通知通知我,这样的场景我数不清有多少次了。错误信息总是出现在某个地方:是在部署日志还是 Pod 日志里?是 Ingress 还是 Ingress 部署在运行?在十几个或几十个Kind
s 文件中,日志条目出现在哪个位置?而根本原因往往是一些不相关的问题:一个错误且不可见的空格,没有使用双引号(应该使用双引号),没有使用单引号(应该使用单引号),或者缩进的末尾部分来自三周前的复制粘贴问题。
当然,有一些工具、技术和监控工具可以提供帮助;就像伊隆·马斯克的火星探测器MVP 一样:“它有效吗?”“绝对有效!!一千次,是的!”“它能做什么?”“几乎任何你想要的东西!”你必须知道要寻找什么以及在哪里寻找它,然后你必须知道如何弄清楚该如何处理它,然后你必须弄清楚在十个或几十个文件中哪一行或哪几行需要修复,然后你必须知道如何修复它。
Kubernetes 的另一大优势在于,它完全属于你。听着:老兄,老兄,伙计,你选择了这条路。你复制粘贴了“代码”。文档示例也能正常工作。我可以在笔记本电脑上运行“Hello World!”,所以这显然全都怪你。你才是那个裹着毛巾浑身湿透、在办公室里跑来跑去喊着“Kubernetes!”的人。如果希波克拉底誓言是“不伤害”,那么 DevOps 誓言或许就是“不要做比被解雇更严重的伤害”。
K8s 的最后一个优点是,有无数的人和公司声称自己知道发生了什么、该怎么做,而且他们很乐意收你的钱来证明这些说法是真是假。Kubernetes
在搜索引擎里输入关键词,你会看到所有弹出的广告。这篇文章既是问题的一部分,也是解决方案的一部分,所以请继续阅读。
最终的解决方案
有几种方法可以使 Kubernetes 更易于使用:
- 不要使用 K8S:快跑,为你的生命尖叫
- 训练你的所有人去解决这个问题(完成后再回来找我;我可能还活着。也可能不活着。)
- 为你的团队雇佣更多的人来解决这个问题(我有空,联系我吧。哈哈,开玩笑的。)
- 雇佣别人为你做这件事
- 等待更长时间才能看到结果,用更少的钱做更多的事情,最终选择一些不那么糟糕的事情
- 找到一个解决方案,将你的应用程序部署到合适的环境中,然后专注于你的实际业务,无论你实际从事什么业务。自动化工具和服务可以帮助你运行应用程序,而无需投入上述工作。这项工作必须有人去做,但最好不是你。
在Release,我们孜孜不倦地致力于将您的应用程序融入精心编排的人性化界面。我们编写软件来处理所有复杂性、困难和压力,以便其他人无需承担(除非他们愿意!)。我们打造驱动 Kubernetes 的引擎,并为客户提供可用于开展业务的解决方案。
鏂囩珷鏉ユ簮锛�https://dev.to/rwilsonrelease/why-is-kubernetes-so-hard-i42