引言
大家好,我是Prism,本篇为大家带来深入浅出k8S技术原理。
我们从 K8S 最核心的设计哲学出发,逐步扩展到它的架构、网络、存储、安全、生态乃至未来的演进。这是一篇长文,但它将系统地带你“看穿”K8S 这个庞大而精妙的“自动化帝国”。
目录
· 开篇:K8S 帝国的"治国之道"
· 第一部分:帝国的"地基"
· 第二部分:帝国"核心架构"
· 第三部分:帝国"核心积木"
· 第四部分:帝国"地下管网"
· 第五部分:帝国"中央账本"的奥秘
· 第六部分:帝国"永久仓库"
· 第七部分:帝国的"迎宾大道"
· 第八部分:帝国的"底层黑魔法"
· 第九部分:帝国的"内部安全局"
· 第十部分:帝国的"蓝图档案室"
· 第十一部分:帝国的"中央情报局"
· 第十二部分:帝国的"终极授权"
· 第十三部分:帝国的"终极形态"
· 总结:K8S 帝国
开篇:K8S 帝国的“治国之道” (核心哲学)
在深入技术之前,我们必须理解 K8S 的核心设计哲学:声明式 API (Declarative API)。
想象一下,你是一个庞大“连锁餐厅帝国”的 CEO。
- 你的应用 (Container Image):是标准化的“料理包”,封装了菜品和做法。
- 容器 (Container):是“厨师”+“料理包”,一个正在工作的最小单元。
在 K8S 出现之前,你是“命令式”(Imperative) 管理:
你(保姆式 CEO)打电话给A店经理:“你加一个厨师。”(过一会儿)“快!去A店看看那个新厨师怎么摸鱼了!赶紧换掉!”
而 K8S 让你成为“声明式”(Declarative) 管理:
你(甩手掌柜 CEO)只撰写一份“帝国蓝图”(YAML 文件) 并下达给中央系统:“我不管你怎么做,我的帝国全境必须始终保持有 100 份宫保鸡丁在售卖状态。”
你把这个“蓝图”交给 K8S,K8S 这个中央系统就会进入一个永恒的“调谐循环” (Reconciliation Loop):
- Observe (观察):从“中央账本”读取“期望状态”(要 100 份)。
- Compare (比较):从“中央账本”读取“实际状态”(现在只有 98 份在卖)。
- Act (行动):发现不一致!马上行动:下令新开 2 份。
- Repeat (重复):永不停止地重复 1-2-3 步。
K8S 所有的“自愈”、“扩容”、“滚动更新”都源于这个简单的循环。
第一部分:帝国的“地基” (Linux 内核魔法)
K8S 本身并不“创造”容器,它能“管”容器,是站在了 Linux 内核的肩膀上。
Namespaces (命名空间) - “VR眼镜” (隔离)
- 原理:这是 K8S 实现“隔离”的基石。Linux 命名空间让一个进程“以为”它自己独占了整个操作系统。
- 比喻:给餐厅的每个厨师(进程)一个“VR 眼镜”。
PIDNamespace:厨师 A 戴上眼镜,发现进程列表里只有他自己(PID 1)。NETNamespace:厨师 A 以为自己独占了所有网络端口(比如 80 端口)。MNTNamespace:厨师 A 以为自己看到了根目录/,但这只是一个“假”的目录。
Cgroups (Control Groups) - “资源配给” (限制)
- 原理:如果 Namespaces 是“隔离”,Cgroups 就是“限制”。它负责控制一个进程组能使用多少系统资源。
- 比喻:中央厨房给每个厨师(进程组)下发了配额:“你今天最多只能用 10 度电 (CPU) 和 50 斤食材 (Memory)。”
- K8S 如何使用:这就是你在
Pod定义中写的resources: { limits: { cpu: "1", memory: "2Gi" } }的底层实现。
第二部分:帝国“核心架构” (Control Plane & Worker Nodes)
K8S 集群分为两个主要部分:控制平面(总部)和数据平面(分店)。
A. 控制平面 (Control Plane) - 总部决策层
这是集群的“大脑”,负责做所有决策,它们自己不炒菜。
etcd:唯一事实来源 (The Single Source of Truth)- 比喻:帝国唯一且不可篡改的“中央账本”。
- 原理:一个高可用的、分布式的键值数据库。它存储了两样东西:1. 你的“期望状态”(YAML 蓝图);2. “实际状态”(全帝国现在到底啥样)。
etcd挂了,K8S 就“失忆”了。
kube-apiserver:帝国的“总机”和“前台”- 比喻:这是整个帝国的唯一入口。
- 原理:你(用
kubectl)、分店经理(kubelet)、监工(controller)……所有人都只和apiserver对话。它负责:- 认证:查身份证,你是谁?
- 授权:查权限,你能干啥?
- 准入:你干的这事合规吗?
- 最后:把合法的数据写入
etcd(记账)。
kube-scheduler:首席“排班经理”- 比喻:一个非常专一的“调度官”。
- 原理:它只干一件事:给新创建的
Pod(新厨师)找一个最合适的Node(分店)。它不断地看“账本”,一旦发现有“新厨师”但还没分配分店,它就开始计算(比如 A 店资源不足,B 店有 GPU 要求),最后在账本上更新:“这个 Pod 分配给 C 店”。
kube-controller-manager:帝国的“监工部门”- 比喻:这是一群永不疲倦的“经理”,核心驱动力。
- 原理:它就是“调谐循环”的执行者。它由一堆“控制器”组成:
ReplicaSet Controller(副本经理):他不断地对比“期望 100 份,实际 98 份?”,他立刻通过apiserver下单:“再来 2 份!”Node Controller(节点经理):他不断地检查“分店”的心跳:“C 店怎么 5 分钟没联系我了?”,他立刻在账本上把 C 店标记为“不健康”。(然后“副本经理”就会接管,把 C 店的订单重新分配到别的店)。
B. 数据平面 (Data Plane) - 分店执行层 (Worker Node)
这是真正干活(炒菜)的地方,你的应用(Pods)就运行在这里。
kubelet:“分店经理”- 比喻:安装在每个 Node(分店)上的代理,它是总部安插在分店的“领班”。
- 原理:它只和“总部 (
apiserver)”直接对话。它不断地看“账本”,检查有没有“分配给本店”的新订单(Pods)。如果有,它就指挥“厨房员工”干活。它还负责监控本店厨师(Pods)的健康状况,并上报给总部。
Container Runtime(容器运行时):“厨房员工”- 比喻:真正负责运行容器(炒菜)的软件,比如
containerd。 - 原理:
kubelet(经理)下达指令:“启动宫保鸡丁容器!”,containerd(员工)就去仓库拿出“料理包”(Image),并使用Namespaces和Cgroups把它运行起来。
- 比喻:真正负责运行容器(炒菜)的软件,比如
kube-proxy:“智能服务员” + “内部网管”- 比喻:K8S 服务发现和负载均衡的实现者。
- 原理:厨师(Pod)是会“挂掉”和“重启”的,IP 会变。那顾客(其他应用)怎么才能稳定地“点到菜”?
kube-proxy负责在每个分店(Node)上设置智能网络规则(比如iptables或IPVS),提供一个稳定的“点餐专线”。
第三部分:帝国“核心积木” (K8S 抽象概念)
理解了架构,我们来看看 K8S 给你的“工具”(你 YAML 里写的那些东西):
Pod(豆荚):- 这是 K8S 部署和调度的最小单元。
- 重点:一个
Pod不是一个容器。它是一个“厨房工作站”,里面可以包含一个或多个紧密相关的厨师(容器)。比如一个 Web 应用厨师 + 一个日志收集助手(Sidecar)。它们共享同一个网络命名空间(能用localhost互相访问)。
Deployment(部署):- “无状态”应用的“老板指令”。
- 你用它来告诉 K8S:“我想要那个‘宫保鸡丁’应用(
Pod模板),保持 100 个副本(replicas),并且更新的时候要用‘滚动更新’(rollingUpdate)策略。” Deployment会创建ReplicaSet(副本集控制器),ReplicaSet再去创建Pod。
Service(服务):- K8S 的“网络灵魂”。
- 问题:
Pod是“短命”的,IP 会变。 - 解决:
Service登场!它会创建一个稳定不变的虚拟 IP(ClusterIP)(比如“宫保鸡丁点餐专线”)。你(或你的其他应用)只需要访问这个“专线 IP”,kube-proxy就会自动帮你把流量负载均衡地转发到它后面某个健康的“厨师”(Pod) 那里。
ConfigMap/Secret(配置与机密):- 解耦工具。你总不能把数据库密码(
Secret)或应用配置(ConfigMap)直接写死在“料理包”(Image)里。你把它们作为“外挂 U 盘”在Pod启动时“挂载”进去。
- 解耦工具。你总不能把数据库密码(
第四部分:帝国“地下管网” (深入网络原理)
这是 K8S 最复杂但也是最关键的底层原理。
K8S 网络模型有三条铁律:
- 所有
Pod都有一个唯一的、全集群可见的 IP 地址。 - 所有
Pod都可以不通过 NAT(网络地址转换)直接访问其他Pod(Pod-to-Pod)。 - 所有
Node都可以不通过 NAT 直接访问所有Pod(Node-to-Pod)。
K8S 是如何做到的?答案是:它自己不做,它交给 CNI。
- CNI (Container Network Interface):容器网络接口
- 比喻:K8S(餐厅帝国)只负责制定“管道标准”,但它把“铺设管道”这个脏活外包给了专业的“管道公司”(如 Flannel, Calico)。
- 原理:
kubelet创建Pod(的 Network Namespace)后,会调用一个网络插件:“喂,给这个Pod插上网线,并分配一个 IP”。
扩展 1:CNI 插件的“武功流派” (Overlay vs. BGP)
Flannel (VXLAN)模式 (隧道模式 - 易用)- 比喻:“包中包”快递。
- 原理:把
Pod A发给Pod B的原始数据包(“货物”)封装(Encapsulate)在一个新的 UDP 包(“快递盒”)里。这个“快递盒”的地址是Node A到Node B。 - 优点:简单。它“隐藏”了 Pod 网络,对底层物理网络没有任何要求。
- 缺点:有性能开销(封装/解封装)和 MTU 损耗。
Calico (BGP)模式 (路由模式 - 高性能与安全)- 比喻:不是“打包裹”,而是“智能导航”。
- 原理:Calico 不使用隧道封装。它在每个 Node 上运行一个“微型路由器”(Felix 代理),利用 BGP 协议(支撑整个互联网的路由协议)在所有 Node 之间“广播”(宣告)路由信息。
- 工作流程:Node A 上的
Felix会告诉其他所有 Node:“嘿!要找10.244.1.0/24这个网段的 IP,请把数据包直接发给我(Node A 的 IP:192.168.0.100)。” - 结果:数据包原封不动(没有封装!)地、直接被路由到目标 Node,性能几乎等同裸金属。
- 安全优势:Calico 基于此能实现 K8S 的
NetworkPolicy(网络策略),即 L3/L4 的防火墙,控制哪些 Pod 之间可以互相访问。
扩展 2:kube-proxy 的“传菜秘籍” (iptables vs. IPVS)
kube-proxy 负责实现 Service。它有两种主流的“武功秘籍”。
iptables模式 (老派但可靠)- 比喻:一个“巨长无比的传菜单”。
- 原理:
kube-proxy会监视Service和Pod的变化,然后在每个 Node 上重写iptables规则。当请求Service IP时,内核需要遍历这个长长的规则链,用“随机概率”的方式(DNAT)转发给某个真实 Pod。 - 痛点:这是时间复杂度 $O(n)$ 的操作。如果
Service数量上万,规则链会变得极其庞大,性能急剧下降。
IPVS模式 (新派且高效)- 比喻:一个“智能调度总台”(哈希表)。
- 原理:
IPVS(IP Virtual Server) 是 Linux 内核中专门用于负载均衡的模块。kube-proxy不再去写长长的iptables链条了,而是直接调用IPVS接口,在内核中创建一个“虚拟服务器”(Service IP)并绑定“真实服务器”(Pod IP列表)。 - 优势:当请求到达时,
IPVS通过哈希表查找,时间复杂度是 $O(1)$!并且支持多种负载均衡算法(如轮询、最少连接)。 - 结论:现在,
IPVS模式基本是大型生产集群的默认标配。
第五部分:帝国“中央账本”的奥秘 (etcd & Raft)
etcd 是帝国的“中央账本”,它必须高可用、强一致。
- 问题:在一个分布式系统(比如 3 台
etcd服务器)中,如何保证“数据一致”? - 答案:Raft 一致性算法。
- 比喻:一个高效的“委员会决策系统”。
- 原理:
- 领袖选举 (Leader Election):集群启动时,所有节点通过投票,选举一个
Leader(领袖)。其他节点自动成为Follower(跟随者)。 - 日志复制 (Log Replication) - 关键:
- 所有“写”请求(来自
apiserver)都必须只发送给Leader。 Leader收到“写”请求,先写入自己的账本。Leader将这条“日志”并行地“复制”给所有的Follower。- 核心:Quorum (法定人数)。
Leader不需要等所有Follower都回复。它只需要等待“大多数”(比如 3 台节点中的 2 台,或 5 台中的 3 台)回复“ACK”(我收到了)。 - 一旦收到“大多数”ACK,
Leader就认为这个“提案”通过了,它将日志“提交”(Commit),并此时才向apiserver回复“OK,创建成功”。
- 所有“写”请求(来自
- 领袖选举 (Leader Election):集群启动时,所有节点通过投票,选举一个
- 结果:这个机制保证了数据强一致性,并且允许集群在“少数节点”(比如 3 台挂 1 台,5 台挂 2 台)宕机的情况下继续可用。
第六部分:帝国“永久仓库” (Storage 原理)
我们聊的 Deployment 都是“无状态”的。Pod 死了就死了。但数据库(MySQL)怎么办?
- 问题:
Pod是“短命的”,Pod里的文件系统随Pod一起销毁。但数据需要“持久化”。 - 比喻:
Pod是“厨师”(可以随便换)。PersistentVolume(PV) 是一个“带锁的专属冷库”。PersistentVolumeClaim(PVC) 是“厨师”用来打开这个“冷库”的“钥匙申请单”。 - K8S 的抽象化:
PersistentVolume(PV):由“集群管理员”创建。它代表一块已经存在的物理存储(比如一块 AWS EBS 硬盘、一个 NFS 共享目录)。PersistentVolumeClaim(PVC):由“应用开发者”(你)创建。你不关心物理存储是啥,你只“声明”:“我需要一个10Gi的冷库”。- 动态绑定:K8S 的
controller-manager会自动帮你“配对”。它找到一个能满足你 PVC 要求的、空闲的 PV,然后把它们“绑定”(Bind)在一起。 Pod使用:你在Pod的 YAML 中声明你要“挂载”那个PVC。K8S 就会确保在启动Pod的时候,把那个 PV(“冷库”)挂载到Pod的指定目录。
- 底层驱动:
CSI(Container Storage Interface)- 问题:K8S 怎么知道如何去 AWS“附加”一块 EBS 硬盘?
- 答案:和 CNI 一样,K8S 定义了一个标准接口
CSI。AWS、Google、Ceph 等所有存储厂商,都提供一个“CSI 驱动程序”。kubelet只会通过标准的 CSI 接口下命令:“CSI 驱动,请把这个 PV 挂载到这个Pod”。
第七部分:帝国的“迎宾大道” (Ingress & API Gateway)
我们之前聊的 Service (ClusterIP) 解决了集群内部的“A 厨师如何找到 B 厨师”的问题(称为东西向流量)。
但现在的问题是: 帝国“外部”(互联网)的顾客,如何访问“帝国“内部”的某个特定厨师(Pod)?这就是南北向流量。
NodePort(开后门)和 LoadBalancer(一对一专车)都有缺陷。
K8S 的终极解决方案:Ingress (帝国总接待处)
Ingress 提供了统一的 L7(HTTP/HTTPS)入口。这个概念包含两个部分:
Ingress资源 (YAML - “规则书”)- 比喻:你撰写的“帝国接待规则”。
- 原理:这只是一个 YAML 文件,一个**“声明”或“愿望”。它本身不干任何活**。你用它来告诉 K8S:
- “当请求的域名 (Host) 是
blog.your-domain.com时,请把它转发给内部的wordpress-service。” - “当请求的域名是
api.your-domain.com时,请转发给api-service。”
- “当请求的域名 (Host) 是
Ingress Controller(软件 - “接待员”)- 比喻:你必须雇佣一个“接待员”(比如 Nginx, Traefik, HAProxy),它才是真正站在“帝国大门”干活的人。
- 原理:
Ingress Controller是一个运行在 K8S 集群里的Deployment。- 它通过
apiserver持续监听集群中所有的Ingress资源(规则书)。 - 当它发现你创建了
blog.your-domain.com的规则,它会自动把这条规则“翻译”成它自己能懂的配置(比如 Nginx Controller 会自动生成nginx.conf并热加载)。
- 它通过
- 流程:外部流量(通常通过一个外部
LoadBalancer) ->Ingress Controller(Nginx Pod) -> Nginx 根据Host头查找规则 -> 转发给 K8S 内部的Service->kube-proxy转发给最终的Pod。
Ingress vs. API GatewayIngress 只是一个“接待员”。而 API Gateway (如 Kong, APISIX) 是“特种兵接待员”。API Gateway 经常扮演 Ingress Controller 的角色,但它在 L7 上做了更多:
- 认证/授权:在流量到达你的 Pod 之前,就强制检查
JWT Token、API Key。 - 速率限制:防止 DDOS 攻击。
- 请求/响应转换等。
第八部分:帝国的“底层黑魔法” (eBPF & Cilium)
这是目前 K8S 社区最火的“黑科技”,它正在彻底颠覆我们之前聊过的 kube-proxy (iptables) 和 Calico (BGP)。
什么是 eBPF?
- 比喻:如果说 Linux 内核是一个“密室”。
iptables是刻在墙上的一套**“静态规则”。当数据包(人)进来时,内核(保安)必须从头到尾**读一遍规则,效率极低。eBPF是一个“魔法系统”,它允许你安全地“注入”一段你自己的“小程序”(魔法咒语)到内核中。
- 原理:这段“小程序”在加载前会被内核的“验证器”(Verifier) 数学上证明是“安全”的(不会搞垮内核),然后被 JIT 编译成原生机器码,“挂载”到内核的“钩子”(Hook)上(比如:“网络包刚到网卡时”)。
- 结果:当网络包到达时,它不再需要去遍历
iptables长链。它会直接触发你的 eBPF 程序,以原生机器码的速度瞬时完成操作(转发、丢弃、修改)。
Cilium:K8S 帝国的“eBPF 终极形态”Cilium 是一个 CNI 插件,它全面拥抱了 eBPF:
Cilium替换kube-proxy:Cilium完全不需要kube-proxy。它加载 eBPF 程序,当Pod访问Service IP时,eBPF 在“数据包刚离开 Pod”的钩子上就介入了,它直接在哈希表里查到目标Pod的真实 IP,当场修改数据包,效率和性能实现了碾压。Cilium实现网络和安全:Cilium也能实现 CNI 路由(通常也是用VXLAN或BGP),但它的“杀手锏”是基于 eBPF 的NetworkPolicy。Calico只能做到 L3/L4 防火墙(“禁止 Pod A 访问 Pod B 的 80 端口”)。Cilium(利用 eBPF) 能“看懂” L7 协议(HTTP, Kafka)。你可以写出**“天神下凡”般的安全策略:“允许 Pod A 访问 Pod B,但仅限 HTTPGET /api/v1/read** 这个路径。禁止HTTP DELETE方法。”
第九部分:帝国的“内部安全局” (Service Mesh - Istio)
Ingress 解决了“南北向”(进出帝国)的流量安全,而 Service Mesh 解决了“东西向”(帝国内部)的流量安全。
- 问题:默认 K8S 集群内,Pod A 访问 Pod B 是明文 HTTP!
- 比喻:帝国(K8S)决定成立一个“内部安全局”(Service Mesh),在每一个“市民”(
Pod)的“房子”里,都必须派驻一个“贴身保镖/翻译官”。 - 这个“保镖”就是
Sidecar(边车代理),最著名的是Envoy。
核心原理:Sidecar 注入与流量劫持
- 自动注入:K8S 的“准入控制器”会“拦截”你的
Pod创建请求,并自动“篡改”你的Pod定义——在你的应用容器(比如python-app)旁边,强行注入一个envoy-proxy容器。 - 共享网络:这两个容器在同一个
Pod里,它们共享同一个网络命名空间 (NET Namespace)。 - 流量劫持:在
Pod启动时,Istio会修改这个Pod网络空间内的iptables规则:“所有” 从python-app发出去的流量(出站),必须先被重定向到envoy-proxy。“所有” 进入这个Pod的流量(入站),也必须先被envoy-proxy处理。
结果:你的 python-app 容器毫不知情,但它的每一根“网线”都被这个“贴身保镖”(Envoy) 接管了。
Istio 实现了什么?
- 1. mTLS (双向 TLS) - 零信任网络 (Zero Trust)
Istio控制平面(Istiod)给每一个Envoy(保镖)都颁发了一个短期的 X.509 证书(“特工身份证”)。- 当
Pod A的Envoy试图连接Pod B的Envoy时,它们会自动进行一次双向 TLS 握手:互相验证“身份证”。 - 结果:① 双方互相验证了身份;② 它们之间的所有通信都自动加密了。这对你(开发者)完全透明!
- 2. 精细化授权 (L7 防火墙)
- Istio 能做到 L7:“允许
Pod A访问Pod B,但仅限 HTTPGET /api/v1/read。”
- Istio 能做到 L7:“允许
- 3. 弹性与韧性 (运维福音)
Envoy会自动处理:“超时控制”、“熔断”(“A,你别再试了,B 已经挂了,免得你把 B 搞死”)、“重试”等。
第十部分:帝国的“蓝图档案室” (GitOps - ArgoCD)
帝国建设好了,“安全局”也入驻了。现在的问题是:帝国太大了。你还在用 kubectl apply -f ... 手动“盖楼”吗?
- 痛点:“漂移” (Drift) 出现了:集群的“实际状态”和你本地的 YAML 文件“期望状态”不一致了!谁在什么时候,因为什么,改了什么?没人知道!
- GitOps 是 K8S 时代的“终极运维哲学”。
- 核心思想:Git 仓库是帝国的“唯一事实来源 (Single Source of Truth)”。
- 比喻:K8S 帝国宣布:“从今天起,任何人都不准再‘手动’盖楼 (不准用
kubectl apply)。所有的‘建筑蓝图’(K8S YAML) 必须提交到‘帝国中央档案室’(Git 仓库)。帝国会自动按照‘档案室’里的蓝图施工。”
核心原理:Pull (拉取) vs. Push (推送)
- 传统 CI/CD (Push):
Jenkins运行测试 -> 打包镜像 ->kubectl apply(**它主动“推”**向 K8S)。 - GitOps (Pull):你把 YAML “推” 到 Git。一个叫
ArgoCD的工具(它自己也活在 K8S 里)时刻“监视”着 Git 仓库。当它发现 Git 里的“期望状态”和 K8S 里的“实际状态”不一致时,它会主动把变更“拉” (Pull) 回 K8S,使 K8S 和 Git 保持一致。
GitOps 带来了什么?
- 1. 杜绝“漂移” (Drift)
- 一个黑客(或者“手滑”的运维)手动
kubectl scale ...试图搞破坏。 ArgoCD(这个“忠诚的管家”)在下一次轮询时立刻发现:“漂移!”ArgoCD立刻自动执行“修正”:把replicas改回 Git 里的声明。
- 一个黑客(或者“手滑”的运维)手动
- 2. 完美的“审计日志” (安全福音)
- 线上出故障了。老板问:“谁干的?”
- 你直接打开 Git 历史 (
git log)。Git 历史不可篡改地记录了:谁 (Author),在何时 (Timestamp),因为什么 (Commit Message / PR),修改了什么 (Git Diff)。
- 3. “一键回滚”
v2版本部署后崩了?你只需要在 Git 里执行:git revert <commit-hash>,然后push。ArgoCD会自动帮你把集群“回滚”到 v1。
第十一部分:帝国的“中央情报局” (可观测性 O11y)
帝国CEO(你)需要一套“帝国运行仪表盘”和“中央情报系统”。这就是 K8S 生态的“可观测性 (Observability)”三叉戟。
1. (Metrics - 指标) Prometheus (健康督察)
- 核心原理 1:Pull Model (拉取模型)
Prometheus(健康督察)不相信任何人。它会**“主动”**、周期性地(比如每 15 秒)去“敲门”问你的“应用程序”:“你健康吗?把你的‘体检报告’(metrics) 给我看看。”- 你的应用只需要在
/metrics路径下暴露一个简单的文本“体检报告”即可。
- 核心原理 2:K8S 服务发现 (Service Discovery)
- 问题:
Pod的 IP 瞬息万变。Prometheus怎么知道要去“敲”哪些“门”? - “魔法” (
kubernetes_sd_config):Prometheus直接去问apiserver:“你好,请帮我监视所有Service,只要这个Service的annotations(注解) 里有prometheus.io/scrape: 'true'这一行。” apiserver(这个“全知者”)立刻返回一个动态更新的 IP 列表给Prometheus。- 全程自动化! 你新部署一个服务,只需要加一行注解,15 秒后监控图表就自动出现了。
- 问题:
2. (Logging - 日志) Loki / EFK (档案库)
- 问题:
Pod是“短命”的。Pod一旦被销毁,它所有的日志文件也随之消失了! - K8S 基础:K8S 的“最佳实践”是:把所有日志“打印”到“标准输出” (
stdout)。kubelet(分店经理)会自动捕获这些日志流,并存到宿主机的/var/log/pods/...目录下。 - 解决方案:日志转发器 (DaemonSet)
DaemonSet(守护神):K8S 的一个“神级”对象。你用它部署一个Pod(比如Promtail或Fluentd),K8S 会自动保证在帝国的每一个Node上,都有且仅有一个这个Pod的副本在运行。Promtail(情报员):这个Pod会挂载宿主机的/var/log/pods/目录,从而“实时读取”这个Node上所有容器的日志。- 日志处理:
Promtail还会去问apiserver:“我现在读的这个日志文件属于哪个Pod?它有什么labels?” - 最后,
Promtail把(日志内容 + 索引标签,如{app="payment"})推送 (Push) 给Loki(中央档案库)。Loki的“黑魔法”是:它只索引“标签”,不索引“全文”。这使得它存储成本极低,查询速度极快(如果你先按标签筛选)。
3. (Tracing - 追踪) Jaeger / OpenTelemetry (邮件追踪)
- 问题:一个“下单”请求花了 5 秒!它依次调用了
Ingress->Order-Service->Payment-Service->Stock-Service。瓶颈在哪? - 核心原理:
Trace ID(邮件追踪号)- 比喻:当一个请求进入帝国(
Ingress)时,Ingress会给它盖上一个全球唯一的“追踪号” (Trace ID),并塞进“信封”(HTTP Header,比如x-b3-traceid)。 - 传递:链条上的每一个服务(A, B, C, D...),在“处理”这封“信”时,都要**“上报”自己的工作记录,称为
Span(跨度),并且必须**把这个Trace ID也传递给它调用的下一个服务。 Jaeger(追踪系统):Jaeger会收集所有这些Span。当你想查某个Trace ID时,Jaeger会把所有Span拼装起来,画出一个“瀑布图”,你一眼就能看出“哦,Payment-Service花了 4.8s!”- 自动注入:如果你用了
Istio(Service Mesh),Envoy(贴身保镖)会自动帮你完成“Trace ID的生成、传递”和“Span的上报”。你(开发者)一行代码都不用改!
- 比喻:当一个请求进入帝国(
第十二部分:帝国的“终极授权” (Operator 模式)
我们之前聊的所有“控制器” (DeploymentController...) 都是 K8S 帝国的“原生公务员”。他们只懂“无状态”应用。
但你现在想管理一个“米其林三星寿司店”(比如一个 PostgreSQL 主从集群)。“副本经理”不懂“寿司店”的“专业知识”。他不知道“主厨”倒了,他应该去“提拔”一个“副厨”(Secondary DB)成为“新主厨”。
K8S 帝国需要“外聘专家”!
Operator (操作员) 模式,就是一套“外聘专家”系统。它允许你把你(人类运维专家)的“专业知识”(比如“如何管理一个 MySQL 主从集群”)“编码”成一个“机器人”,然后把这个“机器人”**“安装”**到 K8S 帝国里,让他成为 K8S 的“新公务员”。
这个模式由两个核心组件构成:
CRD(Custom Resource Definition - 自定义资源定义)- 比喻:你先去“总机”(
apiserver) 那里“注册”一套“行话”。 - 操作:你
apply一个CRD的 YAML,告诉apiserver:“请你学会一个新词,叫kind: MysqlCluster。” - 结果:从这一刻起,K8S 真的能看懂下面这种“行话”YAML 了:
apiVersion: "db.your-domain.com/v1" kind: MysqlCluster spec: replicas: 3 backupSchedule: "0 3 * * *" # K8S 原生 Deployment 可不懂这个
- 比喻:你先去“总机”(
Custom Controller(自定义控制器 - 即 Operator 本身)- 比喻:你“雇佣”的那个“MySQL 专家”机器人。
- 操作:
Operator本身就是一个Deployment!你把它部署到 K8S 里。 - 工作职责:这个
OperatorPod 启动后,它只干一件事:通过apiserver“监听” (Watch) 所有kind: MysqlCluster这种“新表单”的“创建、更新、删除”事件。 - 灵魂 (Reconciliation Loop):当
Operator监听到“新任务”,它开始“调谐”:- 期望:
replicas: 3,backup: true - 现实:啥也没有
- 行动(“专家知识”发挥):
- “不行,数据库是‘有状态’的,我不能用
Deployment,我要创建 1 个StatefulSet。” - “我要创建 1 个
Service指向“主库”。” - “我要创建 1 个
Service指向“从库”。” - “我要创建 1 个
CronJob(K8S 定时任务)去执行“备份脚本”。” - “我要确保
pod-0成为 Primary,pod-1和pod-2成为 Replicas。”
- “不行,数据库是‘有状态’的,我不能用
- 期望:
Operator 的“Day 2” 运维(真正价值所在)
- 场景 1:主库宕机
StatefulSet(K8S 原生)只会重启pod-0。MysqlCluster-Operator(“专家”)会同时“干预”:1. “检测到 Primary 宕机!” 2. “执行‘主从切换’!” 3. “把pod-1“提拔” 为新的 Primary。” 4. “修改”Service指向pod-1。
- 场景 2:你修改了“蓝图”
- 你把
spec.version从8.0改成8.1。 Operator不会“粗暴”升级,它会执行“数据库滚动升级”专家逻辑:先升从库 -> 再升主库。
- 你把
Operator 把 K8S 从一个“容器编排器”(只懂 Pod)**“进化”**成了“万物编排器”(一个“宇宙级的声明式 API 控制平面”)。cert-manager(自动续期证书)就是最著名的 Operator 之一。
第十三部分:帝国的“终极形态” (Serverless & 虚拟机)
帝国已经如此自动化,但 CEO(你)还有“历史包袱”和“终极梦想”。
1. (Serverless - 终极梦想) Knative (帝国魔法部)
- 梦想:“帝国(K8S)已经如此自动化了,我能不能只给帝国‘一段咒语’(函数/代码)?当“客人”(请求)来的时候,帝国‘凭空变出’一个服务员来接待;客人走了,服务员就‘原地消失’(Scale-to-Zero),完全不占资源。”
Knative就是这个“魔法部”(它本身也是个Operator)。- “魔法咒语”:你只提交一个
kind: Service(Knative Service) 的 YAML,里面只写image: ...。 - “魔法原理” (冷启动):
- 缩容到零:一个叫
KPA(Knative Pod Autoscaler) 的组件发现你的应用(比如 60 秒)没流量了,它自动把Deployment的replicas改成0。 - 流量拦截:
Knative修改网络层 (Istio) 的路由,把流量指向一个叫Activator(激活器) 的“中央门卫”。 - 第一个请求:早上 9 点,第一个请求来了。
Activator“截住” (Hold) 了这个请求。Activator“大喊”:“KPA!来客人了!”KPA立刻把Deployment从replicas: 0改成1。- K8S 启动
Pod(这个过程就是“冷启动”,会比较慢)。 Pod就位后,Knative“改回”Istio路由,让流量直接指向新Pod。Activator“松开” 那个被“截住”的请求。- 后续请求将享受原生 K8S 性能,直到下一次“缩容到零”。
- 缩容到零:一个叫
2. (历史包袱 - 终极兼容) KubeVirt (帝国博物馆)
- 包袱:“我还有一些‘前朝遗老’(传统的 VM 虚拟机),他们无法‘容器化’。我能不能用 K8S 帝国去“统一”管理他们?”
KubeVirt就是这个“博物馆”(它也是个Operator)。- “伪装”原理:
- 你
apply一个kind: VirtualMachineInstance(VMI) 的 YAML。 KubeVirt Operator并不会去调用vSphereAPI。- 它在 K8S 里创建一个**“普通的
Pod”**! - “黑魔法”:这个“普通 Pod”里运行着一个**
libvirt** 和QEMU进程(这是 Linux 跑虚拟机的“发动机”)。 - 这个
Pod启动后,它**“内部”的QEMU进程会“启动”** 你的“虚拟机”。
- 你
- 结果:从 K8S 的“外部视角”看,它只是一个“平平无奇的
Pod”。但这个Pod的“肚子”里**“套娃”跑着一个完整的“虚拟机”**。 - 优势:你的“虚拟机”现在可以和“容器”**共享 K8S 的网络(CNI)和存储(CSI)**了!你实现了“万物皆 K8S”的统一管理。
总结:K8S 帝国
我们从“地基”(cgroups) 聊到了“治理”,从“核心”聊到了“生态”,从“自动化” (Operator) 聊到了“终极形态” (Knative, KubeVirt)。
K8S 已经超越了“容器编排器”,它进化成了一个“云时代的分布式操作系统”。它提供了一套通用的、声明式的 API 和一个强大的“调谐循环”引擎,允许你以一种可靠、自动化、可审计的方式,管理和“编排”一切计算资源——无论是容器、函数、还是虚拟机。