Johnny[2] 和 Mat[3] 与 Kris Nova[4] 和 Joe Beda[5] 一起探讨了 Kubernetes 和云原生。他们讨论了 Kubernetes 推动的“云原生”应用的兴起、使用 Kubernetes 的合适场合、运行如此大型的开源项目所面临的挑战、Kubernetes 的可扩展性以及 Kubernetes 如何融入更大的云原生世界。
过程中为符合中文惯用表达有适当删改, 版权归原作者所有.
图片
Johnny Boursiquot: 大家好,欢迎收听 Go Time。这是一个多元化的讨论节目,邀请特别嘉宾一起探讨 Go 语言及其相关领域的各种话题,包括云基础设施、分布式系统、微服务、无服务器架构,今天特别要讨论的是非常流行且开源的容器编排平台 Kubernetes。
我是 Johnny Boursiquot,今天和我一起的嘉宾阵容非常强大,正如 Mat Ryer 常说的那样。今天我们请到了 Mat 本人,还有另外两位对 Kubernetes 非常了解的嘉宾。请欢迎 Joe Beda,前 Heptio(译者注: 现已被VMware收购) 的 CTO,现在是 VMware 的一员;以及 Kris Nova,一位杰出的作者,同时也是 Kubernetes 的全能专家。大家好!
Joe Beda: 大家好,大家好!
Kris Nova: 嗨!
Johnny Boursiquot: 大家好!
Mat Ryer: 很高兴今天能请到你们上节目。这将是一次非常有趣的讨论……我知道很多听众对 Kubernetes 很了解,或者至少我认为他们很了解 Kubernetes,但我想我们还是需要先统一一下基本概念。这是我们节目中经常做的事情---
让那些刚接触 Go 的人、刚加入社区的人和那些已经深入了解 Kubernetes 背后有大量 Go 代码的人都能有所收获。
让我们从基本问题开始,先弄清楚什么是容器编排,Kubernetes 在这个体系中扮演什么角色。
Joe Beda: Nova,你想先来解释一下,还是我先来做一个简短的 "什么是 Kubernetes" 五分钟快速介绍?
Kris Nova: 我想听你先做五分钟的 Kubernetes 介绍,然后我可以再补充。
Joe Beda: 好的,你可以指出我哪里讲错了。
Kris Nova: [笑]
Joe Beda: 假设大家对容器有一定的基础了解---
为了统一认识,容器的基本概念是将一个程序及其所有依赖项打包成一个东西,并使你可以在不同的机器上以可预测的方式运行它。所以这实际上是关于程序的可移植性。我认为 Go 语言开发者已经很幸运了,因为 Go 是静态链接的,你可以把一个 Go 二进制文件拿到任何地方运行……但如果你试试用 Ruby 应用、PHP 应用、Python 应用或 Node.js 应用来做这件事,就会发现并不是所有的东西都像 Go 一样自包含。因此,将这些东西打包成容器是一个很好的选择。 (译者注: "Go 是静态链接"这种说法实际是不准确的)
显然,Docker 让容器变得非常易用且易于访问,但最早的 Docker 只在单机上运行,而我们在 Google 构建类似系统的经验表明,当你开始考虑跨多台机器的容器可移植性时,事情变得更有趣。
因此,Kubernetes 的作用就是,你告诉它你想运行什么---
"我想运行这个容器镜像的十个副本",镜像就是那个东西---
然后它决定在何处运行这些东西,并确保它们一直在运行。
然后你会遇到一系列其他问题---
网络应该如何配置,存储应该如何处理,容器如何互相发现,如何管理指向这些容器的负载均衡器等。所以,Kubernetes 解决了分配程序到计算机后衍生出的许多问题。
从编排的角度来看,这就是 Kubernetes 的作用。与此同时,我们实际上构建了一个通用的分布式系统内核,不仅可以描述如何运行容器,还可以描述你想运行哪些容器,如何升级它们,而且我们还使其具有可扩展性,这也是目前 Kubernetes 生态系统中许多有趣的地方。
Kris Nova: 对,然后我想补充一下---
你说得非常棒,一如既往……我唯一想强调的是,在过去四五年中,我们构建 API 的重要性。正如你所说,Joe,它有点像分布式系统的内核,但真正的价值在于我们终于能够在整个行业中标准化。我们第一次看到大家聚集在一起,以相同的方式定义他们的应用程序、网络和存储……这是云原生生态系统中一个非常强大的原语。
Johnny Boursiquot: 对,关于这个云原生术语……
Joe Beda: 如果你愿意,我可以为你定义一下……
Johnny Boursiquot: 请说。
Joe Beda: 好的,我想很多人都会对云原生的定义有所不同……Nova 也写了一本关于这个的书,她可能是专家,但既然现在是我在说话,我就先讲完……[笑] 抱歉,Nova。 在我看来,云的本质就是运行在别人的基础设施上;它是 API 驱动的,自助服务的,并且具有弹性。因此,从开发者的角度来看,云通常意味着不需要与销售人员沟通的一种服务。你可以直接使用信用卡进行操作并开始使用。这非常强大。
我认为你还可以将这种 API 驱动的自助服务应用到企业内部,虽然可能是另一个部门在提供服务……但如果做得好,应用开发者仍然拥有自助的体验。对我来说,云原生是指工具、文化和流程,用来充分利用这种能力。
如何真正利用这种 API 驱动的自助服务,并将其反馈到软件构建的过程中。你是如何定义的,Nova?
Kris Nova: 再次强调,你又抢了我所有的好句子。你对云的定义确实很好,作为一种一等原语。不过当我想到云原生时,我认为云是一回事,但原生(native)是另一回事,而这往往被忽视了……也就是在第一天,当你走到白板前,打开终端,或者在你写代码的地方,设计系统的地方---
在第一天就考虑到它是在云上运行的。所以现在我们看到很多应用程序的迁移,或者将现有的遗留应用程序移到云上……在我看来,这只是将遗留系统移到云上运行,并不是真正的云原生应用程序。云原生是从一开始就以云为中心来设计应用程序。
Mat Ryer: 那么这个项目是如何开始的呢?Joe,它是从你在 Google 的工作中产生的吗?然后这个开源项目就由此衍生出来了吗?
Joe Beda: 我最初启动了 Google Compute Engine,这是一个在 Google 上运行虚拟机的奇怪项目,因为几乎没有人使用虚拟机……而这个项目的作用其实是建立 GCP 的基础设施云。你看看任何主要的云平台,虚拟机都是其基础服务之一,其他所有东西都是基于它构建的。
在 Google 内部,几乎没人用虚拟机,因为他们使用了一个叫做 Borg 的系统。它有点像 Kubernetes;容器的概念,打包成镜像的方式---
这些东西都有些不同……但总体的理念是一样的:你描述你的程序,然后有一个系统来调度和运行它。这个理念在 Google 内部已经验证了十年。因此,我们了解了这种方式对开发者的好处以及它所能带来的效率。
所以我们当时的处境是这样的---
我们有几件事想通过 Kubernetes 来做。首先是改变游戏规则,因为我们在与其他云平台竞争。像 Amazon 这样的公司已经占据了市场的主导地位,因此我们可以直接在虚拟机方面与它们竞争,或者我们可以尝试让开发者以不同的方式编写程序,以充分发挥 Google 云的优势。
其次,我们希望将内部员工开发与外部客户开发的方式逐渐统一起来,这样内部员工使用的系统体验会与外部客户的体验更接近(如果不是完全相同的话)。
我们也知道,如果没有开源,这些东西就不会产生影响。从一开始我们就认为开源是绝对必要的,并且我们真正承诺要做到开放---
从第一天起,我们就说“你可以在 Amazon 上运行这个”,这让很多人感到惊讶……我们还做了其他一些事情,比如引入了很多来自 Red Hat 的优秀人才。Red Hat 是我们早期的一个重要合作伙伴,帮助扩展了 Kubernetes 的应用场景和思维方式……所以这就是事情的开始。
Mat Ryer: 这是一个非常有趣的故事。这个问题本身也非常有趣……我以前是 App Engine 的用户,虽然从外面看不太清楚内部是如何运作的,但我现在能看到使用 App Engine 与之前的差异,我只能想象在底层发生了什么变化……估计和 Kubernetes 和容器有关。因为从 App Engine 的角度来看,部署现在感觉更加自然。是这样的吗?这个项目发生了类似的事情吗?
Joe Beda: 我认为 App Engine 本身也经历了演变,我不想替那个团队发言……但 GCE 和 App Engine 之间总是有点紧张关系,我认为这种紧张关系也适用于 Kubernetes 和 App Engine。
上周我在 SpringOne[6] 平台会议上做了一个演讲(译者注: 是VMWare组织的一个Spring开发者、应用程序架构师的社区Conf),我谈到了一点关于基础设施即服务(IaaS)和平台即服务(PaaS)之间的哲学差异。基础设施即服务基本上是一组构建块,是一组乐高积木,可以用来构建各种不同的东西。这不仅适用于虚拟机,我认为 Kubernetes 也仍然属于这种工具箱级别的东西……而平台即服务则更像是一个框架,其中有一些推荐的模式,如果你不遵循这些模式,那么使用起来就会更加困难,甚至无法完成你想做的事情。虽然这种方式通常效率很高,但有时也会带来限制。
我认为我们期待的是进入一个两者之间的界限不那么明显的世界,这两种解决问题的方式可以更好地结合起来。
Johnny Boursiquot: 在我脑海中,我试图想象在组织中,谁的角色会负责这个问题?基本上,我应该把 Kubernetes 看作是一个用于部署应用程序的工具,还是一个用于构建部署平台的工具?它是一个平台构建器,还是一个实际的平台?
Joe Beda: 我认为---
我也很想听听 Nova 的看法……但我认为目前 Kubernetes 大致有三类用户。我们发现有平台团队,我认为最具前瞻性的组织会将平台视为一种内部产品。如何提供一个平台,让他们能够扩展,向内部团队提供更多的服务选项,并在某种程度上提供类似于云的体验,但在更大的组织限制范围内。这是在企业中我们常常看到的情况。
然后是应用程序运营者和开发者,应用程序运营者在 Kubernetes 之上运行应用……有时人们也会同时扮演这两种角色,就像 DevOps 的方式一样。
我还认为,平台运营者通常会选择使用 Kubernetes 的原始形式,但他们也会利用扩展性和其他系统,构建出一种推荐的使用 Kubernetes 的方式,这样会更容易使用……随着时间的推移,这种推荐的体验会越来越像 PaaS,开发者可以直接上手,完成工作;运维的角色会减少很多繁琐的工作,开发者的体验会更像“我写代码,我发布,它就能运行”的方式。
Kris Nova: 补充一下---
我们在《云原生基础设施》这本书中也谈到了这个问题---
我认为还有第四类角色。我认为书中提到的“基础设施工程师”就是这个角色。实际上,这些人就像 Joe 和我一样,负责在幕后编写管理基础设施的软件。这些人是 Kubernetes 的贡献者,编写operator软件的人,编写准入控制器实现的人……我认为这是一个非常新的工程角色,直到我们开始拥有一个 Joe 喜欢称为“平台之平台”的东西之前,我们还没有看到过这种角色。
Johnny Boursiquot: 顺着这个思路---
这让我想起了我之前在 Twitter 上看到的一些内容---
这些角色对经验的要求非常高,因此很难让一个初级开发者加入这些团队并有效地做出贡献。进入这些角色的门槛是否太高了?我看到很多招聘广告,要求非常多,“你需要这个经验,你需要那个经验……”从我的角度来看,似乎进入这些角色的门槛非常高……从你的经验来看,这是事实吗?
Kris Nova: 我的看法是,这取决于你的团队有多成熟。如果我们已经有基础设施工程师和平台团队到位,并且已经有系统可以构建应用程序镜像并推送到生产环境,那么进入的门槛会比较低。这只需要你选择一种你擅长的语言编写应用程序,然后让现有系统处理剩下的事情。
但是,建立这些系统是一个完全不同的故事,这就是我们看到的高进入门槛的地方,尤其是当人们必须回答“我们如何开始为构建流水线的各个阶段以及推送到生产环境实施解决方案?”时。
Joe Beda: 是的,这里的确有很多东西需要学习。如果我们把 Kubernetes 称为一个分布式系统内核,那么那些扩展它的人、深入研究它的人---
在某种程度上,他们就是内核工程师。而要成为一个 Linux 内核的专家,深入了解 Linux 内核的方方面面并不容易,对吧?
我的一个观察是,虽然这些东西是新的,但如果我们看看 AWS,它的服务菜单也不容易理解。需要掌握的内容很多,要真正熟练使用 AWS 需要花费几个月的时间。这也是他们推出 Lightsail 的原因。(译者注: AWS推出的一项基于云端的轻量级计算服务,旨在使用户能够轻松快速地建立虚拟专用服务器(VPS),提供简便、经济实惠的云计算解决方案) 我认为,对于任何高级云系统来说,都会有这样一条学习曲线。
我还认为,我们看到的现象是,学习 Linux 的曲线也是如此,但它已经成为了行业中的一种共享知识,大家一起学习,随着时间的推移,它逐渐成为了行业中的背景噪声。我认为云计算也是如此,熟悉 Amazon (的云服务) 某种程度上也已经几乎成为了默认要求,成为了背景噪声……我认为如果 Kubernetes 继续保持它的增长轨迹,并成为一种更普遍的底层技术,那么熟悉或至少具备 Kubernetes 的工作知识将成为我们行业中默认的技能之一。
Mat Ryer: 说到开源团队,这个项目最初是如何开始的?我想它和大多数项目一样,应该有一个较小的范围吧?我不确定。它是如何演变的?有什么惊喜,或者你看到的有趣的事情是什么?
Kris Nova: 对我来说,最有趣的事情之一就是让 Kubernetes 运行起来……Joe 写了一本关于这个的书。但我注意到,无论是在开源社区还是在商业企业中,从零开始运行 Kubernetes 对很多人来说一直是一个难点(译者注: 结合语境,把a high point of friction翻译为 “难点”)。回头看,这也是我最初被 Kubernetes 吸引的原因之一,我对我们已经走了这么远感到惊讶,但我们在这方面仍然没有一个非常好的解决方案。
我认为我们正在取得进展,比如 Cluster API 项目[7]和 Kubeadm 工具[8],但即便如此,我认为关于如何从零开始运行 Kubernetes,至今仍有很多问题需要解答。
Joe Beda: 是的,我觉得这也是我最惊讶的地方。早期在 Kubernetes 项目中,我写了很多 Bash 脚本,用于在 GCP 和其他环境中部署 Kubernetes---
这些脚本并没有很好地适应时间的变化……[笑] 我甚至写了一种方法来在 Bash 中导出堆栈跟踪;对此我既感到害怕又有点自豪。所以我们并没有真正重视集群本身的生命周期管理,包括运行它的环境类型、如何构建能够跨所有这些环境扩展的部署系统……因为在主要的公共云提供商上启动一个集群,和在裸机上,或者用树莓派启动集群,是完全不同的体验。
我认为 Kubernetes 的一个优势在于它的可扩展性---
从零售商在每个商店中使用它, 像 Chick-fil-A 就是一个例子(译者注: Chick-fil-A是一家总部位于美国乔治亚州的美式连锁快餐店,以鸡肉三明治为主要特色),他们用 Kubernetes 来管理店内系统,比如售货点系统、数字标牌等),到像 CERN(译者注: 欧洲核子研究组织) 的粒子加速器这样的大型设施,他们基本上是用它来做数据分析。所以这种可扩展性非常强大,但这也意味着你在管理生命周期时会遇到不同的挑战,而我们在项目早期显然低估了这种复杂性。
Johnny Boursiquot: 在行业会议上,你可能听到有人说“我们要用 Kubernetes 来实现跨云部署。这将成为我们在所有云之上的基础,这样我们就有自由在不同云之间切换,甚至同时使用多个云。”你认为这是明智之举吗?企业和开发团队应该在这一高层构建,而不充分利用任何一个云的特定优势吗?
Joe Beda: 我的看法是,对于很多公司来说,多云战略是有意义的。首先,如果你是一家初创公司,你的首要任务是证明自己对世界有价值,而不是破产---
无论如何,尽一切办法证明你的价值主张是正确的。但是对于更成熟的公司来说,这更多的是风险管理问题。这些公司认为依赖单一供应商有风险,如果有办法降低这种风险,那就值得尝试,而 Kubernetes 是实现这一目标的技术之一。
另外,它还能很好地分离操作角色。你可以有专门的团队来管理 Kubernetes,无论是在 X、Y 或 Z 基础设施上运行 Kubernetes,还是使用某些服务来处理其中的一部分工作。最终你会在应用层面上获得一定的通用性。
当然,我们可能无法屏蔽底层平台的每一个细节,有时你需要利用底层平台的一些特定特性。但如果我们可以减少那些不必要的差异,就能让应用团队的技能更具可移植性,甚至让应用程序本身更加可移植。
另外,我们看到的一点是,这种做法可以在企业和其供应商之间形成杠杆作用。比如你是亚马逊的一个大客户,正在谈折扣……[笑] 如果你完全依赖某些原生服务,你的议价能力就会减弱,除非你有可信的“迁移”威胁。也就是说,你可以对他们说:“我们可以在两个月内从基础设施 A 迁移到 B。” 这时,你和供应商之间的谈判就会更加平衡。
Kris Nova: 接着 Joe 刚才的话题,我觉得在跨云定义应用、网络、存储等抽象层次时,我们经历了一段非常有趣的思维过程。例如,当我们在设计 Cluster API 时,无论你多么通用化,总会遇到某些特定于云的配置。因此,这是一项艰巨的任务,首先要搞清楚哪些是通用部分,然后尽量减少为特定云设计的配置量。
如果你看看我们在 Cluster API 中如何使用 provider config,你会发现我们开始为特定云的部分进行版本管理,同时仍然保持一个通用的配置超集。这是基于我们在设计 Kops[9](译者注: Kops(Kubernetes Operations)是一个用于管理和部署 Kubernetes 集群的工具。它主要用于在云环境中(如 AWS、GCE 和其他云提供商)创建、管理和维护 Kubernetes 集群) 和 Kubicorn[10] (译者注: Kubicorn 是一个用于管理和部署 Kubernetes 集群的开源工具。它的目标是提供一种简单而灵活的方式来创建和管理 Kubernetes 集群,特别是在云环境中. 项目几乎不维护了)时学到的经验教训,我们试图让它尽可能通用……但最终我们发现无法完全做到通用化。
因此,如果你有机会读我的书,我们会谈到如何有效地使用软件来管理 Kubernetes 集群的生命周期。而 Kubernetes 最根本的原则之一就是声明式的本质。换句话说,你定义了目标或期望的状态,然后我们会随着时间推移去协调那个状态。Cluster API 只是在遵循这个原理,并将其应用到基础设施管理上。
你首先声明 Kubernetes 集群的样子,然后我们会去协调并使其成真。这在管理集群生命周期时很有帮助,因为如果我们想对集群进行变更、扩展、升级或进行某种方式的调整,我们都在遵循相同的声明式原则,背后会有某种机制自动执行这些操作。
Joe Beda: 我会这么说:我们基本上是在用 Kubernetes 已经在大规模环境中验证过的模式来管理 Kubernetes 本身。
Johnny Boursiquot: 这很有道理。
Mat Ryer: 听起来像《盗梦空间》啊。 [笑]
Joe Beda: 是的,Cluster API 项目的标志是一堆叠起来的海龟,因为这就是“海龟叠叠乐”的概念。(译者注: 一款流行的益智类游戏,通常以小海龟为主题, 游戏的主要目标是通过叠放海龟来形成稳定的结构,玩家需要运用一定的策略和技巧来完成任务)
Mat Ryer: 哈哈,没错。
Johnny Boursiquot: [笑] 真有趣。我们来自 GoTime FM Slack 频道的一个问题……对于正在收听的朋友们---
是的,我们录制时会实时接受问题,这是你们的机会。有人在频道里问道:“Kubicorn 还活着吗?还是已经被 Kubeadm 和 Kops 取代了?”
Kris Nova: 这是一个好问题。我知道有些人---
包括我自己---
时不时还会用 Kubicorn。我认为它从未打算成为可用于企业级规模管理 Kubernetes 集群的生产就绪工具。我觉得它是一次很好的思维练习,可能我从中获得的最大价值是它是第一个基于 Kubeadm 构建的开源 Kubernetes 管理工具……而这一点至今依然存在。如果你看看 Kubicorn 的工作原理,它现在相对静态,因为我们可以在运行时直接使用由上游推送的最新 Kubeadm 版本。所以我认为,Kubicorn 只是一个自动化使用 Kubeadm 而不是管理集群的工具。
通过 Kubicorn、Kops 和 Kubeadm,我们学到了很多东西,而 Cluster API 是将这些经验教训整合起来的很好的体现。所以,虽然它不再有所增长,但我不会说它已经完全消亡了。
Mat Ryer: 有趣的是,我注意到我们已经提到了几次这个主题---
我对此非常感兴趣,就是这些理念和项目必须不断演进。你谈到了低估了向不同目标部署的复杂性,而这是一个很好的例子。如果在一开始就认识到这些复杂性,可能你根本不会开始这些项目,然而这些项目最终却变得如此庞大、强大且功能齐全。所以这个理念是说,你不能在真空中设计这些东西。你必须先构建它,让它被使用,进入现实世界,软件才能变得更好、更成熟。你同意这一点吗?
Joe Beda: 是的,我觉得---
有几点要说……我认为我们在开始时确实对 Kubernetes 的增长方向有一个相对清晰的愿景,这是基于我们在 Borg 上的经验。但确实有些地方我们一开始简化了,只为了启动项目。你需要先开始做这些事情。
随着项目的成长,我们也扩展了范围。大约三、三年半前,我们意识到,随着 Kubernetes 添加的功能越来越多……首先,我们无法跟上所有人的想法;其次,我们可能会犯错,因此我们需要一种实验机制。所以我们开始在 Kubernetes 中创建可扩展性机制,我觉得这真的将 Kubernetes 从一个仅用于容器编排的工具,转变为真正的---
当我们从技术上谈论平台时,它确实是平台的基础。通过这样做,它让我们能够保持 Kubernetes 的范围适当。
Kubernetes 生态系统中的很多事情并不属于 Kubernetes 项目本身,我认为这是其成功的一个重要部分---
能够让一个繁荣的生态系统蓬勃发展,在 Kubernetes 之上做有趣的事情,而不需要与核心 Kubernetes 开发者打交道。这极大地推动了项目和整个生态系统的发展。现在所有关于如何在 Kubernetes 之上部署应用程序并提供分布式管理的讨论,正是围绕这一点展开的。
Mat Ryer: 你刚才谈到这个问题---
那么 Kubernetes 是如何实现可扩展的?有哪些扩展方式呢?
Joe Beda: Kubernetes 有一堆内置对象,你可以向它发出请求。例如,你可以说“我想要一个 pod”,它本质上是一个容器组,Kubernetes 会负责选择运行它的机器,然后启动它。你还可以说“我想要一个副本集”,这意味着“我想要这个特定模板的多个副本,我需要十个。”Kubernetes 会确保你有十个副本。接着你还可以说“我想要一个部署对象,这是一个版本管理的方式。”所以你可以进行版本升级等操作。我们为 Kubernetes 构建了一层又一层的对象系统。
最核心的扩展性功能是所谓的 自定义资源定义(CRDs)。它允许你在 Kubernetes 中创建新的对象,扩展 Kubernetes 的模式,以便你可以将自己的东西引入。如果你不喜欢 Kubernetes 中的部署方式,因为它无法按照你想要的方式进行蓝绿部署,你可以编写一个与部署对象类似的对象,称之为蓝绿部署,它可以实现你想要的逻辑。
这实际上是扩展了 Kubernetes 的模式,然后运行一段代码,执行之前 Nova 提到的协调循环,这是 Kubernetes 实现分布式系统的核心。
令人兴奋的是,大家不仅将这一模式应用于更领域特定的问题上。例如,你可以管理 MySQL 实例或 Kafka 实例的部署,而不仅仅是应用程序的部署。我们开始看到大家将操作知识转化为代码,并在 Kubernetes 上运行这些代码。这样你就可以用 Kubernetes 来创建一个类似 Amazon RDS 的系统,既可以描述你想要的东西,也可以实现如何运行这个 RDS 类似系统的逻辑。
同时我们还看到人们将这种控制模式应用到其他领域,不仅仅是运行 Kubernetes 上的东西,还可以用于配置硬件负载均衡器、在特定云中配置服务等。我还听说有人在企业内部创建了一个自定义资源定义,用于描述团队及其成员……一旦你定义了这个,它就会自动为你创建 Bitbucket 仓库、Slack 频道,并设置 CI/CD 系统,所有这些都是基于你声明的团队文档。这就是 Kubernetes 赋予我们的分布式系统内核的强大力量,它为 Kubernetes 注入了第二波活力。
Kris Nova: 当我和 Kubernetes 新手交谈时,试图向他们解释 Joe 刚才提到的 CRD 的强大之处,我通常会先定义 CRD 中的两个重要元素,这在 Kubernetes 的每个对象中都能看到:一个是 spec,它是你想要的定义;另一个是 status,它是对象当前的实时状态。正是因为我们同时拥有这两者,协调这一原理才能发挥作用,这也是我们能够构建复杂的协调循环、控制器和运算符的原因,无论我们想要做什么,作为软件工程师都可以做到这一点。我认为很多人没有意识到 Kubernetes 在定义这些运算符和控制器时赋予我们的强大能力和智慧。
Johnny Boursiquot: 嗯,我想他们现在肯定会关注这个了……[笑]
Joe Beda: 我会说的是,编写这些控制器实际上比应该的要难……这是目前的一个活跃探索领域,人们正在研究如何让 Kubernetes 更易于使用,也更容易编程。我们还有很长的路要走,才能让这些东西更加可消费,更容易使用。
我想推荐一本书。这不是我的书,也不是 Kris 的书,而是由 Stefan Schimanski 和 Michael Hausenblas 编写的《Programming Kubernetes》[11]。我手里有一本……如果你想了解如何使用 Go 编写 Kubernetes 代码并开始做一些 CRD 和控制器循环的开发,这是一本很好的入门书。这是一本 O'Reilly 出版的书。
Mat Ryer: 谢谢。
Johnny Boursiquot: 很棒。
Kris Nova: 是的,我觉得还需要指出的是,这个领域也有很多工具。我们从一个原型开始,有一个名为 operator framework[12] 的解决方案,它来自 Red Hat 和 Core OS 的开发者。我们还有一个开源的上游项目 Kubebuilder[13]……所以我们正在寻找构建控制器和运算符的框架,但这仍然是一个不断迭代和完善的过程,我们还没有完全到达目标。
Joe Beda: 说到 Go,我认为现在 Go 是编写这些东西的首选语言……所以,这就是了。 [笑声]
Mat Ryer: 是的,我本来想问这个问题……如果你看 github.com/kubernetes/kubernetes 仓库,我猜这是 Kubernetes 的主代码库……
Joe Beda: 我们叫它 KK。 [笑] Kubernetes/Kubernetes。
Mat Ryer: 好的!我们不会再嵌套了。
Joe Beda: 哈哈。 [笑声]
Mat Ryer: 我注意到在语言构成中,超过 90% 是 Go。那为什么一开始 Kubernetes 选择了 Go 作为开发语言呢?
Joe Beda: 嗯,我想剩下的 10% 大概是 Bash,那都是我的错,抱歉…… [笑声] 我们选择 Go 的第一个原因是 Docker 是其中一个关键因素,而 Docker 当时也是现在也是用 Go 编写的。这对我们有很大的影响。我实际上坚持使用 Go,因为另一位创始人 Brendan Burns 的最初 Kubernetes 原型是用 Java 编写的。我们同时也受到了 Mesosphere 的影响,它是一个较早的系统;Mesosphere 也使用了一些不同的扩展和编程理念,但本质上它是一个庞大的 C++ 代码库。
(译者注: 现在该公司叫D2iQ,Mesos背后的公司,可参考 曾经 Mesos 背后的公司,如今在干嘛?[14])
因此,我在考虑“我们是要像 Mesos 那样做 C++ 吗?还是要像 Apache Hadoop 那样用 Java?又或者我们要看看社区、代码质量以及 Docker 生态系统中的互动性?”我认为 Go 是一个很好的选择,它既足够系统级别,又不像 C++ 那么难以接近,同时比 C++ 更加高效。因为要找到新的贡献者,并让他们在一个庞大的 C++ 代码库中快速上手,这非常困难。尽管有人批评 Kubernetes 是“Java 开发者用 Go 写的”,但我觉得 Go 作为一个易于接近的系统级语言,最终是 Kubernetes 的正确选择。
Kris Nova: 如果你对那些批评 Kubernetes 是基于面向对象的 Go 系统感兴趣,我去年在 FOSDEM 上做了一场演讲,叫《You Can't Have a Cluster \[BLEEP\] Without a Cluster》[15]。在那次演讲中我提到了许多 Go 编程语言中的反模式,这些模式可能源自传统的面向对象思维。不想太多批评你和 Brendan,Joe……
Joe Beda: 是的,你知道,社区发展得太快了,很多人加入项目时并不了解 Go……这在一定程度上推动了 Go 的发展,但也意味着他们可能是有经验的程序员,但不一定擅长 Go……所以这就是我们看到的结果。我敢打赌,很多代码库看起来都很相似,基于相同的动态。
Kris Nova: 但它是一个成功的模式,对我们而言是有效的。再次回到那个随时间演变的教训,我们是如何走到今天的,并不是一开始就决定要以这种方式构建系统的。真的很有趣。
Johnny Boursiquot: 让我真正感受到 Kubernetes 价值的一个方面是,它最初的讨论总是围绕着“我们在虚拟机之上进行容器编排,Kubernetes 为你提供了这种抽象,赋予你 pod 这个概念。”因此,你可以更高层次地处理部署,而不必直接处理虚拟机。那么现在“无服务器”---
我做了个引号---
已经成为一种趋势,尽管我们都知道这更多是个市场术语,但支持 Kubernetes 上的无服务器确实是件事,对吧?通过 virtual-kubelet 项目[16],这变得可能。
从这个角度来看,你认为 Kubernetes 是否会成为下一代部署模式的平台?从虚拟机到容器,再到函数即服务……无论下一步是什么,Kubernetes 是否有能力通过其扩展性来应对?
Joe Beda: 我希望如此,但我无法预测未来……首先我们要认识到,作为开发者和工程师,我们总有一种“唯一正确的方式”的心态。所以我们看到新技术时,它们很吸引人,大家都为之兴奋……但实际上,随着时间的推移,我们只会增加技术层面,而不会移除旧的东西。比如主机业务对 IBM 来说仍是一个增长业务。所以虚拟机不会很快消失。
我认为我们可以把它视为一个光谱,并为不同的场景提供合适的工具。没有哪种应用程序是完全无服务器的、容器化的或虚拟机的。你可以说,“我会用函数即服务平台来处理大部分工作,但我有一个需要用容器的机器学习模型,此外,我可能还需要运行一个遗留的单体架构。”这可以是一个应用程序使用的多种技术组合。我觉得这就是我们更常见的场景,新技术不会完全取代旧的东西。希望 Kubernetes 能够足够灵活,成为下一代技术的良好起点。
Mat Ryer: 是的,Jon Calhoun曾告诉我,很多人会把Kubernetes的代码库当作模式和示例的参考。他提到了一些编写代码时需要不同思维方式的地方......显然,这里面有很多好的示例,Jon也说这些是被广泛使用的。那么,关于代码组织是否还有其他具体的地方呢?
Jon提到的其中一件事是Kubernetes必须迅速演变,你无法从一开始就设计出一个干净、完美的设计;每个人的代码都会自然演变,我认为这本身就是一个很好的教训。那么,关于代码结构或者这个项目,或者Go开发者从Kubernetes代码库中可以汲取到的东西,还有什么值得注意的吗?
Kris Nova: 我认为Kubernetes代码库在我看来,可能是使用Go接口的最佳示例之一。 特别是当你在看Go中一些不太常规的原则时,比如组合(composition)和嵌入(embedding),我们在使用ObjectMeta时做得很好,ObjectMeta[17]嵌入在每个Kubernetes对象中。这是一个很好的例子,展示了我们如何定义通用部分,然后将它们分享给包含其他特定部分的对象中。
所以我认为这多少暗示了面向对象(OO)风格的思维模式,但这些是Go的一级特性,而我认为Kubernetes在巧妙利用这些特性方面做得非常出色。
Joe Beda: 我是看到了问题......[笑声] 我认为Kubernetes经历了从一个单一代码库到尝试拆分的过程......现在它算是半拆分状态,我甚至不想描述当前的状态,这个拆分的过程是痛苦的。所以我认为这里可能有一些值得汲取的教训,比如单一代码库的利与弊。
不过,我认为我们做对的一件事是,我们希望Kubernetes成为一个结构良好的分布式系统。所以我们并没有一开始就创建一个单一的二进制文件,而是将不同的功能拆分成不同的二进制文件,并让它们通过基本上所有人都能访问的相同API进行通信。
所以从结构上看,创建多个可以通过网络通信的二进制文件,并坚持没有私有接口的原则---
这是一个值得汲取的教训。也许这不完全是Go的事情,但当你开始构建分布式系统时,创建正确的机制来帮助保持架构的整洁度是非常重要的。
Mat Ryer: 我猜,你们也是在不断自我验证的过程中?
Kris Nova: 是的,完全正确。我们完全是在使用自己的客户端。如果你查看Go中的官方客户端,看看人们如何构建与Kubernetes交互的Go程序,它实际上就是我们在Kubernetes内部使用的相同的源代码。所以我们实际上是在运行我们建议大家用来解决自己问题的代码......我认为这是一个非常好的模式。
Mat Ryer: 是的,我同意这个观点。即便是它被频繁使用的事实,你也能发现其中的任何问题......但是我们在Machine Box也注意到了一些其他有趣的副作用,Machine Box也是类似的情况---
我们使用SDK,我们有一个用于Machine Box API的Go SDK,并在我们的集成测试中使用它。所以我们尽可能多地将测试整合到一起,以同时测试尽可能多的内容。但它确实提供了一定的稳定性,这真的很有趣。
Johnny Boursiquot: John在频道里问到,Kubernetes作为一个开源项目,是否迫使你们在代码结构、组织方式和包管理上走上一条特定的道路......如果这是一个私有代码库或私有项目,你们会做得不同吗?
Joe Beda: 从代码结构上讲,我不认为我们会有很大的不同。我确实认为,社区的扩展和代码是共同演变的,这是一个有趣的现象。随着项目的增长,我们需要有方法来管理谁负责、谁决定功能、如何推动项目前进......我认为Kubernetes现在所使用的是我们称之为开放治理的模式,基本上是由一群公开的人员决定项目的未来,而不是由某个公司控制。我认为在代码结构的某些地方,我们确实看到了这种演变。
Kubernetes的可扩展性机制确实适合这种开源的“让事情变得广泛”的模式......如果没有开源的角度,我们可能不会在可扩展性上投入这么多。
我觉得我们几乎“打破”了GitHub项目的规模和工作流......Kubernetes社区开发了一个叫Prow的系统,基本上是GitHub的自动化工具。几乎没有人真正拥有Kubernetes GitHub组织的管理员权限。相反,一切都是通过/test、/approve或/lgtm命令来完成的,然后Prow机器人会处理这些内容。所以我们能够在此基础上构建一个更丰富的所有权模型和权限模型。这些东西都是用Go编写的。但这不是代码本身的问题,而是社区和代码处理流程的一部分。
Kris Nova: 关于Kubernetes的快速迭代速度,有很多值得一提的地方。我们已经提到过几次,作为一个开源项目,它的进展非常迅速,我认为这可以从Kubernetes K/K代码库中反映出来,看看我们在其中有多少二进制文件,以及我们引入了多少依赖项。虽然我不想在Go Time节目中提起依赖管理问题......但我认为它发展得很快,因此我们看到了代码库呈现出一种独特的形态,这在其他情况下可能不会出现。
Johnny Boursiquot: 说到治理和公司对项目的影响,每当一个流行的开源项目---
或者说支持这些项目的组织---
被收购时,总会有一种膝跳反应式的担忧,人们会想,“哦,看来我们的项目完了。现在我们将开始看到对某一家公司有利的东西,而对其他公司不利。”从外界来看,Kubernetes似乎没有受到Heptio被VMware收购的影响......但我也很好奇,从你的角度来看,自从收购以来,有没有哪些优势对Kubernetes有益?
Joe Beda: 我首先要说的是,Heptio确实为Kubernetes做出了贡献,但我们并不是最大的贡献者。我认为我们可能在公司规模上做得超出预期,但我们参与的池子非常大。
我认为我的联合创始人在Google时做得很好的一件事就是启动了云原生计算基金会(CNCF),并把大家聚集在一起。我的联合创始人Craig McLuckie是Heptio的共同创始人。这最终成为了一个中立的厂商平台,用来托管Kubernetes。CNCF和Linux基金会有它们的优缺点......这是另一个可以在喝酒时讨论的话题。但总的来说,让这个项目不被任何一个公司拥有,是项目成功的关键之一,也让它能够继续发展,无论是Heptio还是其他任何公司。
至于Heptio加入VMware的事情,我认为我们能够激活VMware内部的很多人,带更多的人进入社区,真正开始弥补我们通过客户视角看到的一些空白。我们确实非常注重确保我们为项目投入的比从中获取的更多。
Kris Nova: 回到之前关于治理的讨论,我认为Kubernetes是第一个成功完成CNCF毕业流程的项目,设定了基调和参考架构。如果你看像Joe提到的Prow工具,它现在已经是一个开源工具,你可以引入它进行使用。你会看到CNCF生态系统中很多项目都在使用它。我们在本地的Falco项目中也在使用它,我知道还有很多其他项目也在使用它。同样,我们要感谢Kubernetes,因为它是第一个通过CNCF毕业流程的项目,设定了很多后续流程的标准。
Johnny Boursiquot: 非常酷。随着时间的推移,我很好奇接下来Kubernetes的重大步骤或改进是什么?你们认为代码库会变得更加稳定,还是还有很多大块的功能需要完成,以使平台更加完善?
Kris Nova: 我有个答案,当然我有些偏见。如果你看看我们作为社区已经解决的问题---
我们已经解决了存储问题,并迭代了几次;我们也完成了网络问题,完成了计算问题,甚至包括我们如何定义应用程序以及如何管理状态的方式都已经有了进展......但如果你看看安全问题,目前还没有一个好的解决方案。我认为这是Kubernetes需要解决的最后一个领域。
关于在Kubernetes中运行应用程序并保持其安全,甚至是保持整个Kubernetes集群的安全,有很多已知的问题。所以在我看来,这是在生态系统中存在的一个比较大的问题,正如Joe之前提到的那样。
Joe Beda: 需要澄清的是,这些问题是可以解决的。我认为只是目前还不够简单或直观,或者说没有达到一键式的便捷程度。我认为在安全性方面,随着时间的推移,Kubernetes将成为安全最佳实践的标杆,因为你能获得大量关于运行程序、它们如何运行、是谁决定运行这些程序、谁采取了哪些操作的数据。这些数据在传统的DevOps环境中往往是看不到的。但我认为我们看到了这种潜力;不过我们还没有完全实现这一点。所以我完全同意Kris的看法。
我们在Kubernetes核心项目中经常谈论的一件事情是,让Kubernetes变得“无趣”。好的基础设施应该是无趣的。我记得Brad Fitzpatrick曾经在谈论某个Go的版本发布时说,“这个Go版本没有什么特别的地方,这其实是一件好事。”Go从那时起变得更有趣了,但曾经有一个时期,Go本身非常稳定,以至于发布说明只是“我们改进了垃圾回收器,并提高了性能,但从用户的角度来看,几乎没有什么变化。”
我们也希望Kubernetes能够到达这个阶段,核心部分非常无趣,所有有趣的事情都发生在核心之外。我认为我们正在朝这个方向前进。所以我觉得这对我们来说是一个好地方,能够让生态系统中的事情变得更有趣,而不是核心项目本身。
Kris Nova: 我第一次听到有人用“无趣”来形容软件的时候,好像是Rob Pike在Go刚推出时的某个早期演讲中提到的。
Mat Ryer: 是的。我有个快速问题,如果我写k8s……
Joe Beda: 哈哈哈!
Mat Ryer: ……我是让自己难堪了吗?这是“潮”还是“不潮”啊?我不确定,这还流行吗,还是……
Joe Beda: 还流行啊。
Mat Ryer: 还流行啊。
Joe Beda: 对于那些不清楚的人来说---
这就像我们写国际化或本地化一样,i...
Johnny Boursiquot: i18n...
Joe Beda: i18n,类似的东西。或者Andreessen Horowitz的a16z……[笑声] 这是同样的逻辑,k和s之间有8个字母。但我们还有一个优势,那就是你可以把它叫做“kates”。因此很多人在读它时,不叫Kube或Kubernetes,而是叫kates。我不知道是谁开始这么叫的......这既酷,因为它是一个简写,但它也增加了Kubernetes世界的新手学习的难度,因为又多了一个术语。人们会想,“好吧,我知道Kubernetes,但我看到k8s......这到底是怎么回事啊?!”
Mat Ryer: 是的。
Kris Nova: 我喜欢它的原因是,它让我在Twitter上谈论Kubernetes时可以最少化字符数。
Johnny Boursiquot: 这确实有帮助。说到更多术语......是“kube cuttle”,还是“kube control”?[笑声]
Joe Beda: “Queue Beck tall”!
Johnny Boursiquot: [笑声]
Joe Beda: 这就像是I/O控制,你是说“I/O控制”还是“eye octal”(ioctl)?我们经常在这些发音上争论不休。我们在Heptio有一位员工,现在在VMware---
她坚持把Kubernetes错误发音成Kapernikes(Copernicus) [笑声] 这成了我们团队的一个游戏,看看谁能找到最糟糕的发音。
Johnny Boursiquot: 太棒了。
Mat Ryer: 最后一个问题,Nova......K/K代码库有85,000多个提交记录。你最喜欢哪个?可以直接给个简短的哈希值。
Kris Nova: 我最喜欢的提交记录......让我们称之为Joe的提交吧。Joe是第一个在开源代码库中提交代码的人,如果没有他的提交,我想我们现在都不会在这里。
Mat Ryer: 这是个好答案。
Johnny Boursiquot: 答案揭晓。
Joe Beda: 我必须反驳一下......在我们把代码库移到GitHub之前,我们其实有一个内部代码库。我只是做了一些清理工作,准备发布代码......[笑声] 所以我不能说那都是我写的代码。我只是负责在我们准备发布时整理了代码。
Mat Ryer: 我认为GitHub的历史不会骗人,它在法庭上也是可以接受的证据。
Johnny Boursiquot: [笑声] 你知道你可以修改那个历史记录,对吧?我只是说一下。
Mat Ryer: 真的可以吗?
Johnny Boursiquot: [笑声] 好吧。我觉得这是我参与过的最有趣的一期节目之一,因为我对基础设施充满了热情,作为一个SRE,知道无趣的技术才是我们想要的让我感到安心......因为当我值班时,我不希望有有趣的事情发生,所以......[笑声] 知道项目的方向真是太棒了,今天能有你们来节目真是太好了。
Joe,你经常主持TGI Kubernetes直播,我们经常看你偶尔遇到点小麻烦,但大多数时候你都能顺利完成任务,还有社区的帮助......
Joe Beda: 是的,我想我们已经做了90多期了。我们每周五都会直播......Nova在她还在Heptio工作时也主持了很多期。我知道她现在也在计划在Twitch上做一些自己的直播。
Johnny Boursiquot: 嗯,期待你的直播,Nova。
Kris Nova: 是的,我们已经做了第一次直播,正在努力完善。我想我们会更多地聚焦于Kubernetes和其他容器编排,拓宽一些话题范围......当然,我们是一家安全公司,所以肯定会有很多安全相关的讨论。
Mat Ryer: 太好了,我们也很期待观看......
Kris Nova: 是的,我想“观看”是个合适的词。
Mat Ryer: 谢谢你。 [笑声] 我只是确认一下。
Johnny Boursiquot: 等待确认......[笑声]
Joe Beda: 有趣的是,YouTube/Twitch的直播和播客有着不同的感觉,我认为它们的消费方式也不一样......所以看到不同的媒介找到自己的方式很有趣。
Kris Nova: 是的,当你开始直播时,总有那么一瞬间,你会意识到自己已经在一个小房间里,一个人对着空气说了30分钟......[笑声] 很容易陷入这种自说自话的状态。
Johnny Boursiquot: 太棒了。非常感谢你们来参加我们的节目,感谢所有现场收听的听众,感谢你们在频道里提问。如果你们之后再听到这期节目,希望你们也会喜欢。
Reference
[1] Kubernetes and Cloud Native: https://changelog.com/gotime/105
[2] Johnny: https://github.com/jboursiquot
[3] Mat: https://github.com/matryer
[4] Kris Nova: https://github.com/krisnova
[5] Joe Beda: https://github.com/jbeda
[6] SpringOne: https://springone.io/
[7] Cluster API 项目: https://github.com/kubernetes-sigs/cluster-api
[8] Kubeadm 工具: https://github.com/kubernetes/kubeadm
[9] Kops: https://github.com/kubernetes/kops
[10] Kubicorn: https://github.com/kubicorn/kubicorn
[11] 《Programming Kubernetes》: https://book.douban.com/subject/33393681/
[12] operator framework: https://github.com/operator-framework
[13] Kubebuilder: https://github.com/kubernetes-sigs/kubebuilder
[14] 曾经 Mesos 背后的公司,如今在干嘛?: https://2d2d.io/s1/mesos/
[15] 《You Can't Have a Cluster [BLEEP] Without a Cluster》: https://www.youtube.com/watch?v=CLVIbCs2VJY
[16] virtual-kubelet 项目: https://github.com/virtual-kubelet/virtual-kubelet
[17] ObjectMeta: https://kubernetes.io/zh-cn/docs/reference/kubernetes-api/common-definitions/object-meta/