@jaga_prasanna: https://x.com/jaga_prasanna/status/2079614504451838426
摘要
一个教育性的推文串,使用像亚马逊仓库和巡航控制这样易于理解的类比来解释Kubernetes的核心概念,分解了组件和期望状态机制。
查看缓存全文
缓存时间: 2026/07/22 14:31
给讨厌Kubernetes的人看的Kubernetes
整个行业长期以来把Kubernetes集群设计搞得极其复杂,因为它有海量组件,各种东西协同工作。但说实话,核心思想并没有那么复杂。
让我证明给你看!
先忘掉Kubernetes一秒钟
想象你经营着一个亚马逊仓库。每天成千上万的订单涌进来。仓库里有打包机器人在干活——拣货、装箱、发货!
问题在于:你不需要站在仓库地板上挨个告诉每个机器人做什么。你不会走到机器人跟前说
“嘿,把这个订单打包。” 规模一大,这得疯掉。
相反,你有一个系统。你只需说:
“我需要地板上一直有5个打包机器人在运行。”
就这些。这就是你的全部工作。你定义了你想要什么,从那一刻起,仓库负责一切:
- 它会激活5个机器人。
- 如果其中一个崩溃了?系统不会只说**“好吧,现在我们有4个了”**,它会立刻启动一个替换的。
- 如果仓库的整个区域离线了?系统会把这些机器人转移到另一个区域。
- 你从不需要直接碰任何一个机器人。你只是告诉系统你想要什么,它就像变魔术一样持续实现它。
这就是Kubernetes!这就是整个思想。你告诉它期望的状态,它持续把实际状态推向它。Kubernetes里的每一个组件都是为了这个循环而存在的。现在让我们把仓库的每个部分映射到实际的Kubernetes组件。
快速备忘单:把仓库角色映射到Kubernetes组件,便于你理解:
下面是全景概览:控制办公室、仓库区域、机器人、路由。
如果看起来很多,别担心,我们会逐项拆解!保证你以后再也不回头看Kubernetes!哈哈!
在深入每个组件之前,我们先问问自己:
什么是期望状态?
这是Kubernetes里最重要的概念。你懂了它,就懂了全部。
想想你车里的定速巡航。
你设到70英里/小时。那是你的期望状态。你不会每5秒手动踩油门和刹车。车帮你做。如果上坡掉到65英里/小时,它会加油。如果下坡到了75英里/小时,它会刹车。你一次设定好目标,系统就不断努力维持它。
Kubernetes完全一样。
你不需要写脚本来手动启动容器、监控健康状况、崩溃了重启。你只需写一个配置文件(你的期望状态),里面说:
> 我要我的Web应用运行5个副本
你把文件交给Kubernetes。从那一刻起,Kubernetes就像定速巡航一样工作。如果容器崩溃,它会启动一个新的。如果服务器宕机,它会把你的应用移到健康的服务器。你一次设定目标,Kubernetes不断努力维持它。这就是全部游戏。
把操作员映射到Kube组件:
让我们分解仓库中的每一个角色。一旦你明白每个人做什么,整个事情就通了。
kube-apiserver — 前台
这是仓库唯一的入口。没有人直接跟其他人说话——不是楼层经理、不是调度器、不是区域主管。每一个指令、每一个状态更新、每一个问题都首先经过前台。
- 你想部署5个机器人?你跟前台说。
- 调度器想把机器人分配到2号区域? 它跟前台说。
- 区域主管想报告一个机器人崩溃了?它跟前台说。
kube-apiserver 也不会盲目接受请求。它先验证它们,就像前台查你的工牌。它通过三道门才继续:
- 认证: 你是谁?你甚至被允许在这里吗?
- 授权: 你被允许做什么?你确实能创建机器人,还是只能查看?
- 准入控制: 这个请求合理吗?有没有策略说不允许你这么做?
只有通过了这三道,请求才被真正处理。“Kubernetes中一切都流经这个组件。如果apiserver宕机,整个仓库会失明并瘫痪。”
etcd — 仓库数据库
这是整个仓库的唯一真相来源。每个机器人的IP地址、每个区域分配、每个配置细节、每个期望状态——都存储在这里。
把它想象成仓库的主库存系统。如果不在etcd里,仓库就不知道它。楼层经理查它。调度器查它。区域主管通过前台向它汇报。
重要的是,只有kube-apiserver直接与etcd通信。没有其他组件碰它。一切都通过前台,前台读写数据库。
如果etcd宕机而且你没有备份?你实际上失去了仓库的整个状态。这就是为什么在生产中,你总是以集群方式运行etcd——多个副本,这样如果一个宕了,其他仍有数据。
kube-controller-manager — 楼层经理
这是真正让事情发生的人。楼层经理不装箱子。他不分配区域。他的全部工作就是坐在那里,通过前台观察数据库,一遍又一遍地问同一个问题:
实际状态是否匹配期望状态?
如果你说想要5个机器人,但只有4个在运行,楼层经理会发现这一点并告诉前台:
“嘿,我们还需要一个机器人,创建它。” 但问题是——controller manager 不仅仅是一个控制器。它其实是一个进程内运行的多个控制器集合:
- Deployment Controller: 监视你的Deployments。如果你说想要5个副本,它会创建一个ReplicaSet来实现。
- ReplicaSet Controller: 监视ReplicaSets,确保正确数量的Pod存在。太少了?创建更多。太多了?杀掉一些。
- Node Controller: 跟踪哪些区域(Nodes)在线。如果一个区域离线,它会标记它,并开始移动在那里运行的机器人。
- Job Controller: 处理一次性任务。比如“打包这个订单然后停止。“
每个控制器运行自己的循环:监视 → 比较 → 行动。这就是整个模式。它们监视状态,与期望状态比较,并在出现差异时采取行动。
kube-scheduler — 区域分配器
当楼层经理创建一个新的机器人(Pod)时,那个机器人不会立刻知道它该去哪个区域(Node)。它只是处于“Pending“状态,基本上就是:
我存在了,但我还没有家!
这就是调度器派上用场的地方。kube-scheduler通过前台监视这些无家可归的Pod,并找出分配它们的最佳区域。
它不是随便选的。实际上经过一个过程:
- 过滤: 排除那些不能处理机器人的区域(比如节点没有足够的容量来容纳机器人)。
- 评分: 然后,对通过过滤的区域进行评分。哪个区域有最多的空闲资源?哪个能更好地平衡负载?哪个已经拥有机器人所需的依赖?
- 绑定: 选择得分最高的区域并报告给前台。
一旦绑定完成,该节点上的区域主管(kubelet)就会接手并实际启动机器人。
kubelet — 区域主管
每个仓库区域(Node)都有自己的主管——kubelet。这是运行在每个工作节点上的代理。它不在控制办公室运行。它就在车间地板上,就在那个区域里。
kubelet的工作很简单:
- 监视前台: 查看已分配到其区域的Pod。
- 启动机器人: 通过告诉容器运行时拉取镜像并运行容器。
- 保持它活着: 运行健康检查,如果容器崩溃则重启,确保一切按预期运行。
- 汇报: 向前台报告状态更新。“机器人A在运行。机器人B刚崩溃了。正在重启。”
kubelet也负责处理存活探针和就绪探针。如果一个机器人说它活着但实际没有响应工作?kubelet会发现并重启它。
kube-proxy — 传送带路由器
这是使Services工作的组件。还记得那个客户订单柜台吗?就是那个有永久IP地址、把订单路由到正确机器人的?
kube-proxy就是那个在每个区域实际设置路由规则的组件。它在每个节点上运行,维护网络规则,这些规则说:
“如果有请求到达10.96.0.1:80(Service IP),把它重定向到这些pod(机器人)IP之一:10.244.1.5、10.244.2.8或10.244.1.6。”
当一个机器人死掉,新机器人启动并获得不同IP时,kube-proxy自动更新其路由表。客户永远不会注意到。他们持续访问同一个柜台IP,流量持续流向健康的机器人。
它基本上就像每个节点上的负载均衡器,确保流量到达它应该去的地方!
容器运行时 — 机器人激活器
当kubelet说“启动这个机器人“时,它自己不做。它调用容器运行时——这是实际拉取容器镜像并运行它的引擎。
kubelet说“用这个软件激活机器人A“,容器运行时下载代码,设置隔离环境,然后启动它。
过去默认是docker,但Kubernetes已经远离它了。运行时只需支持CRI(容器运行时接口),kubelet就能与它工作。
Pod — 机器人
Pod是Kubernetes中最小的可部署单元。它是实际做真正工作的机器人——装箱子、服务请求、运行你的应用代码。
Pod基本上是一个或多个容器的包装器。大多数情况下,它只是一个容器,一个机器人做一项工作——但有时你有sidecar容器,比如日志代理或代理,与主应用程序一起运行在同一个Pod内。
关于Pod的关键点是它们都是临时的。它们不是要永远存在的。如果一个Pod崩溃,Kubernetes不会修复它,它会杀死它并启动一个新的。这就是为什么你永远不要直接依赖Pod的IP地址。你总是通过Service来访问。
把它们放在一起——一个部署如何流经仓库
现在你知道了每一个组件,让我们看着它们一起工作。这是当你告诉仓库**“我需要5个打包机器人”**时发生的事情:
你通过kube-apiserver将机器人的配置和IP地址存储在名为etcd的数据库中。kube-controller-manager监视这些数据变化并触发pod的创建。kube-scheduler接收这些pod并将它们分配到有容量的区域。该区域上的kubelet通过容器运行时启动机器人。完成!
在我们深入之前,先澄清一个主要的混淆点:管理集群(控制平面)与路由应用流量(数据平面)不是一回事。
我们刚才介绍的涉及API服务器、etcd、调度器和控制器的工作流负责管理集群状态和工作负载,例如创建Pod并决定它们在哪里运行。
普通的用户请求进入应用程序不会经过etcd、调度器或API服务器——相反,控制平面向kube-proxy和Ingress或Gateway控制器等组件提供路由配置,这些组件配置数据平面。
实际的应用程序流量然后流经配置好的网络路径——例如Service、Ingress、Gateway或负载均衡器——到达后端Pod之一。
引导流量:我们如何与机器人通信?
好了,现在车间里有5个机器人在运行。但问题是——它们的IP地址一直在变。如果一个机器人没电了,系统用一个新机器人替换它,新机器人获得一个完全不同的IP。
如果一个客户想发送订单来打包,不能指望他们跟踪每个机器人的确切IP地址——它们都是临时的。来来回回!
所以仓库设置了一个客户订单柜台——一个固定地址的永久台位。客户总是去同一个柜台,柜台决定把订单发送给哪个机器人。
在Kubernetes中,这被称为Service!
- 永久柜台: 订单柜台一直在同一个位置。一个稳定的IP。一个稳定的DNS名称。总是可达。
- 自动路由: 客户在柜台放下请求。kube-proxy自动将其路由到当前活跃且健康的机器人。
- 解耦: 客户不知道有多少个机器人,不知道它们的IP,也不关心。Service处理一切。
标签、选择器、EndpointSlice
我们知道每次机器人重启时,它会被分配新的IP地址。你可能会问:如果客户订单柜台有永久IP,当有成千上万个机器人不断启动、停止或崩溃时,它怎么处理?
它使用三个概念协同工作:
- 标签 & 选择器(徽章): 每个机器人都戴着一个徽章(比如 app: packing-robot)。订单柜台配置了一个选择器,它说:只将订单路由给戴着
**app: packing-robot**徽章的机器人。 - Endpoints(主卷轴): 这是包含匹配的、健康的机器人实际IP地址的列表。每次机器人启动或停止,这个列表都会被更新,以便流量去正确的地方。
- EndpointSlices(可扩展的剪贴板纸): 不是有一个包含所有10000个IP地址的巨大卷轴,而是仓库将列表分成小剪贴板纸(Slice),每张通常最多包含100个IP。
问题来了: 在一个有10000个机器人的巨大仓库里,如果你每次一个机器人下线都必须重写一个10000行的主卷轴并复印给每个区域主管,你会造成巨大的负载。你的复印机会烧毁的。
在Kubernetes中,这就是旧的Endpoints系统发生的情况。如果一个集群有成千上万个Pod,一个Pod状态的变化需要把整个巨大的列表发送到每个节点的kube-proxy。
EndpointSlices解决了这个问题:把巨大的列表分成多个小块。如果一个机器人崩溃了,经理只更新那一张100行的小纸片并发送出去,其余部分不变。
到目前为止,我们探索了如何部署集群,但等等——
这是生产环境中外部流量实际到达Pod的方式吗?
既然我们理解了通过Service和kube-proxy内部流量如何流动,那么从公共互联网来的外部流量是如何真正到达生产环境中的Pod的呢?
1. Service IP(ClusterIP)是仅限内部的
标准的Service IP(ClusterIP)是虚拟的,只存在于集群内部网络中。如果公共互联网上的客户试图连接到10.96.0.1,请求哪里也去不了,因为公共互联网路由器没有私有集群IP范围的路由记录。
2. 生产环境外部流量实际如何进入
为了允许外部流量进入集群,生产环境设置使用云负载均衡器结合Ingress Controller(如NGINX、Envoy或Traefik):
Ingress Controller完全绕过kube-proxy处理外部入站流量。它直接将请求路由到目标Pod IP(Pod级负载均衡),以消除双重路由开销和延迟惩罚。
相似文章
@BenjDicken: 对Kubernetes的精彩介绍。没有它,需要处理100种复杂性和边缘情况。有了它,你就有…
一条推文强调了对Kubernetes的精彩介绍,并引用了Fatih Arslan关于控制理论和反馈循环的文章,这些理论用于构建能够自我修复、弹性伸缩、可扩展数千个数据库的系统。
@devops_nk:有人构建了一个完全在你的浏览器中运行的Kubernetes。这可能是学习Kubernetes的最简单方式。- 无需Do…
一位开发者通过将核心组件重写为TypeScript,并在AI辅助下进行代码转换,将Kubernetes移植到浏览器中完全运行。该工具无需安装,专为学习、教学和面试准备而设计。
求职面试教会我的 Kubernetes 知识
一位求职者发现,小型初创公司采用 Kubernetes 并非出于技术可扩展性,而是为了组织层面的好处,如一致性、共享知识和可追溯性。这篇文章反思了 Kubernetes 对小型团队的非技术优势。
Kubernetes In Anger
一份全面指南,介绍在生产环境中调试和管理 Amazon EKS 集群,重点关注常见故障模式、事件响应和安全升级。涵盖 EKS 与标准 Kubernetes 的关键差异。
@ghumare64: https://x.com/ghumare64/status/2052825541057626258
一个X帖子认为生产级AI代理需要运维支撑框架(运维手册、权限、日志、回滚、验证),而不仅仅是更好的提示词。作者引用了DevOps演进历程,指出提示词提供建议而运维手册提供控制,代理系统需要平台工程解决方案来实现权限、状态管理、验证、可观测性和回滚能力。