云原生技术03-K8s Master崩溃怎么办?3年经验的架构师都答不上来的问题, 从Node到Pod到Container:一口吃透K8s资源层次
从Node到Pod到Container一口吃透K8s资源层次你是否遇到过Pod一直卡在Pending状态、Worker节点突然失联、Master宕机后整个集群抓瞎的崩溃时刻Kubernetes架构看似复杂其实只要理解了这几个核心组件你也能成为集群急救医生。本文将从原理到实战吃透K8s的核心神经系统。目录• 一、Kubernetes架构全景图大脑与四肢的协作• 二、控制平面集群的大脑• 2.1 API Server所有请求的总闸门• 2.2 SchedulerPod的红娘• 2.3 Controller Manager集群的管家• 2.4 etcd唯一的真理之源• 三、工作节点干活的打工人• 3.1 Kubelet节点的监工• 3.2 Kube Proxy网络的交警• 3.3 Container Runtime真正的搬砖工• 四、Scheduler调度全流程从Pod到运行的奇妙旅程• 五、etcd深度解析为什么它是集群的命门• 六、高可用方案Master节点不能单点故障• 七、实战排查Pod卡在Pending的问题• 文末三件套一、Kubernetes架构全景图大脑与四肢的协作想象一下Kubernetes集群就像一个精密运转的工厂•控制平面Control Plane 工厂的管理层总经理、调度员、财务总监•工作节点Worker Node 工厂的生产车间•Pod 车间里的生产线•Container 生产线上的具体工人先来看一张ASCII架构图让你对整体结构一目了然┌─────────────────────────────────────────────────────────────────┐ │ 控制平面 (Control Plane) │ │ ┌─────────────────┐ │ │ │ API Server │ ← 所有请求的总闸门 │ │ └────────┬────────┘ │ │ ┌──────────────────┼──────────────────┐ │ │ ▼ ▼ ▼ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ Scheduler │ │ etcd │ │ Controller │ │ │ │ (调度器) │ │ (数据存储) │ │ Manager │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ ▲ │ └──────────────────────────────────────────────────────┼──────────┘ │ ┌──────────────────────────────────┘ │ HTTPS (6443端口) ▼ ┌─────────────────────────────────────────────────────────────────┐ │ 工作节点 (Worker Node) │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ Kubelet │ │ │ │ (节点的监工汇报状态) │ │ │ └─────────────────────────┬───────────────────────────────┘ │ │ │ │ │ ┌────────────────┼────────────────┐ │ │ ▼ ▼ ▼ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ Kube Proxy │ │ Pod 1 │ │ Pod 2 │ │ │ │ (网络代理) │ │ ┌─────────┐ │ │ ┌─────────┐ │ │ │ └─────────────┘ │ │Container│ │ │ │Container│ │ │ │ │ └─────────┘ │ │ └─────────┘ │ │ │ └─────────────┘ └─────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ Container Runtime (containerd/Docker) │ │ │ │ 真正运行容器的搬砖工 │ │ │ └─────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘效率技巧记住这张图面试时画出来面试官会觉得你有点东西。二、控制平面集群的大脑控制平面是整个Kubernetes集群的大脑负责做出所有决策。如果大脑挂了整个集群就会陷入植物人状态——虽然节点还在运行已有的Pod但无法进行任何新的调度操作。2.1 API Server所有请求的总闸门API Server是Kubernetes的门面担当所有操作无论是kubectl命令、控制器还是调度器都必须通过它。它的核心职责1.认证与授权验证你是谁你能做什么2.数据校验检查你提交的YAML有没有语法错误3.状态存储把资源定义写入etcd4.事件通知告诉其他组件有新活儿了# 示例通过API Server创建Pod的请求流程 apiVersion: v1 kind: Pod metadata: name: nginx-pod spec: containers: - name: nginx image: nginx:1.21 ports: - containerPort: 80⚠️避坑警告API Server默认监听6443端口千万不要直接暴露到公网2023年就有团队因为把API Server暴露在公网结果被黑客挖矿账单直接飙到几万刀。查看API Server状态的命令# 检查API Server是否健康 curl -k https://localhost:6443/healthz # 查看API Server的日志 kubectl logs -n kube-system kube-apiserver-节点名 # 查看当前API Server的端点 kubectl get endpoints kubernetes -o yaml2.2 SchedulerPod的红娘Scheduler的职责很简单给Pod找一个合适的Node安家。它的工作流程就像相亲1.过滤阶段Filtering排除不符合条件的节点比如资源不够、有污点2.打分阶段Scoring给剩下的节点打分选出最优解3.绑定阶段Binding把Pod和Node绑定在一起Scheduler调度流程 ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ 过滤阶段 │ ──▶ │ 打分阶段 │ ──▶ │ 绑定阶段 │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ ▼ ▼ ▼ 排除不符合的 给剩余节点 更新Pod的 节点如内存 打分排序 nodeName字段 不足、有污点 资源余量、 写入etcd 亲和性等效率技巧Scheduler支持自定义调度策略你可以根据业务需求编写自己的调度器。比如让GPU任务优先调度到带GPU的节点。查看Scheduler日志# 查看Scheduler的调度决策日志 kubectl logs -n kube-system kube-scheduler-节点名 | grep Scheduling # 查看Pod的调度事件 kubectl describe pod pod-name | grep -A 10 Events2.3 Controller Manager集群的管家Controller Manager是一堆控制器的集合每个控制器负责一种资源的状态维护控制器职责类比Deployment Controller维护Deployment的期望副本数人力资源经理ReplicaSet Controller确保Pod副本数正确生产线班长Node Controller监控节点健康状态车间主任Service Controller管理Service的Endpoints前台接待EndpointSlice Controller维护EndpointSlice通讯录管理员这些控制器的核心逻辑都是一个无限循环观察当前状态 ──▶ 对比期望状态 ──▶ 执行调整操作 ──▶ 回到观察 ▲ │ └───────────────────────────────────────────────┘幽默一刻Controller Manager就像一个强迫症晚期的管家看到Deployment说要3个Pod实际只有2个立马给你创建一个看到节点失联了立马把上面的Pod标记为需要重新调度。它永远不会累也永远不会下班。2.4 etcd唯一的真理之源etcd是Kubernetes的记忆中枢所有集群状态都存储在这里。它是整个集群的Single Source of Truth。etcd存储的关键数据• 所有API对象Pod、Service、Deployment等• 集群配置信息• 节点状态信息• 密钥和敏感数据如果启用了加密etcd数据层次结构简化版 /registry/ ├── pods/ │ ├── default/ │ │ └── nginx-pod │ └── kube-system/ │ └── coredns-xxx ├── deployments/ │ └── default/ │ └── my-app ├── nodes/ │ ├── node-1 │ ├── node-2 │ └── node-3 └── configmaps/ └── default/ └── app-config⚠️避坑警告etcd是集群的命门如果etcd数据损坏或丢失整个集群的状态就全没了。务必做好etcd的定期备份# 备份etcd数据 ETCDCTL_API3 etcdctl snapshot save backup.db \ --endpointshttps://127.0.0.1:2379 \ --cacert/etc/kubernetes/pki/etcd/ca.crt \ --cert/etc/kubernetes/pki/etcd/server.crt \ --key/etc/kubernetes/pki/etcd/server.key # 恢复etcd数据 ETCDCTL_API3 etcdctl snapshot restore backup.db \ --data-dir/var/lib/etcd-backup三、工作节点干活的打工人如果说控制平面是大脑那工作节点就是四肢。它们负责真正运行容器化的应用。3.1 Kubelet节点的监工Kubelet运行在每个工作节点上是节点的监工负责1.接收指令从API Server接收PodSpecPod定义2.管理容器通过Container Runtime启动、停止容器3.健康检查执行livenessProbe和readinessProbe4.状态上报定期向API Server汇报节点和Pod状态Kubelet工作流程 ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ 监听API │ │ 调用CRI │ │ 上报状态 │ │ Server │ ──▶ │ 创建容器 │ ──▶ │ 到API │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ ▼ ▼ ▼ 获取Pod定义 containerd/ 节点状态 解析PodSpec Docker执行 Pod状态 容器操作 容器状态查看Kubelet状态# 查看Kubelet服务状态 systemctl status kubelet # 查看Kubelet日志 journalctl -u kubelet -f # 查看节点详细信息 kubectl describe node node-name效率技巧如果Pod状态一直是ContainerCreating多半是Kubelet和Container Runtime之间的通信出了问题。检查/var/log/pods/目录下的日志能快速定位问题。3.2 Kube Proxy网络的交警Kube Proxy负责实现Kubernetes的Service网络是集群内部的交警指挥流量该往哪走。它的核心职责1.维护网络规则在节点上配置iptables/IPVS规则2.实现Service把Service的虚拟IP映射到后端Pod3.负载均衡在多个Pod之间分发流量Service流量转发示意图 用户请求 │ ▼ ┌───────────────┐ │ Service IP │ 10.96.0.1:80 │ (虚拟IP) │ └───────┬───────┘ │ ▼ ┌───────────────┐ │ Kube Proxy │ iptables/IPVS规则 │ (负载均衡) │ └───────┬───────┘ │ ┌───┴───┐ ▼ ▼ ┌──────┐ ┌──────┐ │ Pod1 │ │ Pod2 │ │:8080 │ │:8080 │ └──────┘ └──────┘Kube Proxy的三种模式模式原理适用场景iptables使用iptables规则转发默认模式小规模集群ipvs使用IPVS内核模块大规模集群性能更好userspace用户空间代理已废弃不推荐# 查看Kube Proxy使用的模式 kubectl get configmap kube-proxy -n kube-system -o yaml | grep mode # 查看当前节点的iptables规则查看Service转发 iptables -t nat -L KUBE-SERVICES -n | head -203.3 Container Runtime真正的搬砖工Container Runtime是真正运行容器的组件Kubelet通过CRIContainer Runtime Interface与它通信。主流Container Runtime对比Runtime特点现状Docker最流行生态丰富Kubernetes 1.24 移除dockershimcontainerd轻量、高效Docker底层也用推荐使用CRI-O专为K8s设计红帽主推OpenShift默认CRI调用流程 Kubelet ──CRI(gRPC)──▶ containerd ──▶ runc ──▶ Linux容器 │ ▼ containerd-shim (管理容器生命周期)查看Container Runtime信息# 查看节点使用的Runtime kubectl get nodes -o wide # 查看containerd状态 systemctl status containerd # 使用crictl查看容器containerd的CLI工具 crictl ps crictl pods crictl logs container-id⚠️避坑警告Kubernetes 1.24版本正式移除了dockershim如果你还在用Docker作为Runtime要么升级到containerd要么安装cri-dockerd适配器。四、Scheduler调度全流程从Pod到运行的奇妙旅程让我们详细拆解一个Pod从创建到运行的完整调度流程Pod调度全流程时序图 用户 kubectl API Server etcd Scheduler Kubelet Container Runtime │ │ │ │ │ │ │ │ 1.提交YAML │ │ │ │ │ │ │─────────────▶│ │ │ │ │ │ │ │ 2.创建Pod │ │ │ │ │ │ │───────────────▶│ │ │ │ │ │ │ │ 3.写入etcd │ │ │ │ │ │ │──────────────▶│ │ │ │ │ │ │ │ │ │ │ │ │ │ 4.返回成功 │ │ │ │ │ │ │◀──────────────│ │ │ │ │ │◀───────────────│ │ │ │ │ │◀─────────────│ │ │ │ │ │ │ │ │ 5.通知Watcher│ │ │ │ │ │ │───────────────┼─────────────▶│ │ │ │ │ │ │ │ │ │ │ │ │ │ 6.查询未调度Pod │ │ │ │ │◀──────────────┼──────────────│ │ │ │ │ │ │ │ │ │ │ │ │ 7.过滤打分 │ │ │ │ │ │ │ │ (选择最佳节点) │ │ │ │ │ │ │ │ │ │ │ │ 8.绑定Pod到节点 │ │ │ │ │ │◀──────────────┼──────────────│ │ │ │ │ │ │ │ │ │ │ │ │ 9.写入etcd │ │ │ │ │ │ │──────────────▶│ │ │ │ │ │ │ │ │ │ │ │ │ │ 10.通知目标节点的Kubelet │ │ │ │ │ │───────────────┼──────────────┼──────────────▶│ │ │ │ │ │ │ │ │ │ │ │ │ │ 11.调用CRI创建容器 │ │ │ │ │ │──────────────▶│ │ │ │ │ │ │ │ │ │ │ │ │ │ 12.启动容器 │ │ │ │ │ │ │───────────────┼───────────────▶│ │ │ │ │ │ │ │ │ │ │ │ 13.上报状态 │ │ │ │ │ │◀──────────────┼──────────────┼───────────────┼───────────────│ │ │ │ │ │ │ │ │ │ │ 14.更新Pod状态 │ │ │ │ │ │──────────────▶│ │ │ │关键时间点阶段耗时说明1-4 100msAPI Server写入etcd5-9 1sScheduler调度决策10-142-30s拉取镜像启动容器效率技巧Pod调度时间通常小于1秒但如果镜像很大拉取镜像可能占大部分时间。使用镜像缓存或本地镜像仓库能显著加速启动。五、etcd深度解析为什么它是集群的命门etcd是CoreOS开发的分布式键值存储使用Raft共识算法保证数据一致性。它是Kubernetes的大脑皮层没有它集群就失忆了。etcd的核心特性etcd架构图 ┌─────────────────────────────────────────┐ │ etcd Cluster │ │ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ Node 1 │◀─▶│ Node 2 │◀─▶│ Node 3 │ │ │(Leader) │ │(Follower│ │(Follower│ │ └────┬────┘ └─────────┘ └─────────┘ │ │ │ │ ▼ 写入请求 │ │ ┌─────────┐ │ │ │ WAL日志 │ ← 持久化存储 │ │ └─────────┘ │ │ │ │ │ ▼ │ │ ┌─────────┐ │ │ │ BoltDB │ ← 键值数据存储 │ │ └─────────┘ │ └─────────────────────────────────────────┘etcd的关键数据指标•写入延迟 10ms本地SSD•读取延迟 1ms•QPS10,000单节点•数据一致性强一致性Linearizable ReadRaft共识算法简介Raft是etcd使用的分布式一致性算法核心思想是**少数服从多数**Raft节点状态转换 ┌─────────────┐ │ Follower │◀────────────────┐ │ (跟随者) │ │ └──────┬──────┘ │ │ 选举超时 │ ▼ │ ┌─────────────┐ 发现更高任期 │ │ Candidate │─────────────────┘ │ (候选人) │ └──────┬──────┘ │ 获得多数票 ▼ ┌─────────────┐ │ Leader │ │ (领导者) │ └─────────────┘幽默一刻Raft就像一个班级选班长。Follower是普通学生Candidate是举手说我要当班长的人Leader就是选出来的班长。如果班长失联了心跳超时大家重新选举。如果同时有多个人举手就按谁先举手谁优先的规则来。etcd高可用配置⚠️避坑警告etcd集群节点数必须是奇数因为Raft需要多数派同意才能写入偶数节点既不能提高容错能力又浪费资源。节点数可容忍故障说明10单点仅测试使用31生产环境最低配置52大型集群推荐73超大规模集群# 查看etcd集群健康状态 ETCDCTL_API3 etcdctl endpoint health \ --endpointshttps://192.168.1.10:2379,https://192.168.1.11:2379,https://192.168.1.12:2379 \ --cacert/etc/kubernetes/pki/etcd/ca.crt \ --cert/etc/kubernetes/pki/etcd/server.crt \ --key/etc/kubernetes/pki/etcd/server.key # 查看etcd集群成员 ETCDCTL_API3 etcdctl member list -w table # 查看etcd数据库大小 ETCDCTL_API3 etcdctl endpoint status -w table六、高可用方案Master节点不能单点故障生产环境的Kubernetes集群必须实现高可用否则Master一挂整个集群就脑死亡了。高可用架构图K8s高可用架构3 Master节点 ┌─────────────┐ │ Load │ │ Balancer │ ← 可以是云LB、Nginx、Keepalived │ (VIP) │ └──────┬──────┘ │ ┌───────────────┼───────────────┐ │ │ │ ▼ ▼ ▼ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ Master 1 │ │ Master 2 │ │ Master 3 │ │ ┌─────────┐ │ │ ┌─────────┐ │ │ ┌─────────┐ │ │ │API Server│ │ │ │API Server│ │ │ │API Server│ │ │ └─────────┘ │ │ └─────────┘ │ │ └─────────┘ │ │ ┌─────────┐ │ │ ┌─────────┐ │ │ ┌─────────┐ │ │ │Scheduler│ │ │ │Scheduler│ │ │ │Scheduler│ │ │ │(Active) │ │ │(Standby) │ │ │(Standby) │ │ │ └─────────┘ │ │ └─────────┘ │ │ └─────────┘ │ │ ┌─────────┐ │ │ ┌─────────┐ │ │ ┌─────────┐ │ │ │Controller│ │ │ │Controller│ │ │ │Controller│ │ │ │(Active) │ │ │(Standby) │ │ │(Standby) │ │ │ └─────────┘ │ │ └─────────┘ │ │ └─────────┘ │ │ ┌─────────┐ │ │ ┌─────────┐ │ │ ┌─────────┐ │ │ │ etcd │◀│▶│ │ etcd │◀│▶│ │ etcd │ │ │ │(Leader) │ │ │ │(Follower│ │ │ │(Follower│ │ │ └─────────┘ │ │ └─────────┘ │ │ └─────────┘ │ └─────────────┘ └─────────────┘ └─────────────┘关键高可用组件组件高可用方案说明API Server多实例负载均衡无状态可水平扩展Scheduler多实例Leader Election同一时间只有一个工作Controller Manager多实例Leader Election同一时间只有一个工作etcdRaft集群3/5/7节点强一致性存储Leader Election机制Scheduler和Controller Manager通过Kubernetes的Lease API实现Leader Election# 查看当前的Leader kubectl get leases -n kube-system # 查看Scheduler的Leader kubectl get leases kube-scheduler -n kube-system -o yaml # 查看Controller Manager的Leader kubectl get leases kube-controller-manager -n kube-system -o yaml效率技巧如果你看到多个Scheduler或Controller Manager都在工作那一定是Leader Election出了问题赶紧检查七、实战排查Pod卡在Pending的问题Pod卡在Pending是最常见的K8s问题之一。让我们用学到的架构知识来排查。排查流程图Pod Pending排查流程 开始排查 │ ▼ ┌─────────────────┐ │ kubectl describe│ │ pod name │ └────────┬────────┘ │ ▼ 查看Events │ ┌────┴────┐ ▼ ▼ 有错误信息 无错误信息 │ │ ▼ ▼ 根据错误 检查资源 排查 │ ┌────┴────┐ ▼ ▼ 资源不足 节点问题 │ │ ▼ ▼ 扩容节点 检查污点 或清理Pod 和标签常见Pending原因及解决方案# 1. 查看Pod详细状态和事件 kubectl describe pod pod-name # 2. 常见错误1没有可调度的节点No nodes are available # 原因资源不足、污点不匹配、节点选择器不匹配 # 解决 kubectl top nodes # 查看节点资源使用 kubectl get nodes --show-labels # 查看节点标签 kubectl describe node node-name # 查看节点污点 # 3. 常见错误2PVC未绑定 # 原因StorageClass问题、PV不足 # 解决 kubectl get pvc # 查看PVC状态 kubectl describe pvc pvc-name # 查看PVC事件 # 4. 常见错误3镜像拉取失败 # 原因镜像不存在、认证失败、网络问题 # 解决 kubectl get events --field-selector reasonFailedPullImage # 5. 查看Scheduler日志 kubectl logs -n kube-system -l componentkube-scheduler实战案例Pod一直Pending# 场景部署了一个Pod但一直Pending $ kubectl get pod my-app-xxx NAME READY STATUS RESTARTS AGE my-app-xxx 0/1 Pending 0 5m # 第一步查看Pod事件 $ kubectl describe pod my-app-xxx ... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 30s default-scheduler 0/3 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, 2 node(s) didnt match Pods node affinity. # 诊断结果 # 1. 1个Master节点有污点不允许调度普通Pod # 2. 2个Worker节点的标签不匹配Pod的nodeAffinity # 解决方案 # 方案1移除Pod的nodeAffinity限制 # 方案2给节点打上正确的标签 kubectl label nodes node-1 app-tierfrontend # 验证 $ kubectl get pod my-app-xxx NAME READY STATUS RESTARTS AGE my-app-xxx 1/1 Running 0 10s⚠️避坑警告Master节点默认有node-role.kubernetes.io/master:NoSchedule污点普通Pod不会被调度到Master上。如果你测试环境节点少可以移除这个污点但生产环境千万别这么干文末三件套1. 【源码获取】关注此系列获取后续更新后台回复k8s获取链接。2. 【思考题】一个Pod卡在Pending状态可能的原因有哪些点击查看答案1.资源不足节点CPU/内存不够2.污点不匹配Pod不能容忍节点的污点3.节点选择器不匹配nodeSelector/nodeAffinity条件不满足4.PVC未绑定持久卷声明无法绑定5.网络插件问题CNI插件未就绪6.Scheduler异常调度器本身出现故障7.镜像拉取失败虽然这通常是ContainerCreating状态但有时也会表现为Pending3. 【系列预告】•下一篇容器网络与存储 —— 搞懂CNI和CSI让你的Pod畅通无阻•后续篇调度策略深度解析 —— 从NodeAffinity到PodTopologySpread•进阶篇GitOps实践 —— 用ArgoCD实现声明式持续交付总结今天我们深入剖析了Kubernetes的核心架构组件角色关键记忆点API Server总闸门所有请求必经之地6443端口Scheduler红娘给Pod找Node1秒完成调度Controller Manager管家维护期望状态强迫症晚期etcd大脑所有状态存储10ms写入延迟Kubelet监工节点上的Agent管理容器生命周期Kube Proxy交警实现Service网络iptables/IPVSContainer Runtime搬砖工containerd/Docker真正运行容器关键数据回顾• 支持最大节点数5000单个集群• Pod调度时间 1秒• etcd写入延迟 10ms掌握这些核心组件的工作原理你就能在集群出问题时快速定位根因成为真正的集群急救医生。本文是云原生系列第3篇如果觉得有帮助欢迎点赞、收藏、转发标签Kubernetes, etcd, Scheduler, APIserver, K8s架构, 控制平面, 高可用