技术文章2026 年 8 月 21 日约 15.7 分钟

Kubernetes 核心组件详解与实战:从控制平面到应用上线

系统讲解 kube-apiserver、etcd、Scheduler、Controller Manager、kubelet、容器运行时、CNI、Service、Ingress、存储、调度与安全,并提供完整的部署、验收和故障排查实践。

Kubernetes 不只是一个“运行容器的工具”,而是一组围绕声明式 API 协作的控制系统。用户提交期望状态,控制器持续观察实际状态并发起调谐,最终让集群接近目标状态。理解组件之间如何协作,比记住大量 kubectl 命令更重要。

本文以一个名为 web 的无状态 HTTP 服务为例,从控制平面、节点、网络、存储、配置、安全和发布流程逐层拆解,并给出可以在测试集群中执行的配置与验收方法。示例使用 Kubernetes 1.28+ 常见 API,具体字段仍应以目标集群版本和发行版文档为准。

实验约束:请在 kind、minikube、k3d 或独立测试集群中执行。文中的 namespace、Deployment 和 Service 名称均为示例,生产环境执行破坏性命令前必须核对上下文、命名空间、镜像和数据备份。

#一、先建立整体心智模型

Kubernetes 集群可以分成控制平面和工作节点两部分。控制平面保存集群状态并作出调度、编排决策;工作节点负责实际运行 Pod。组件之间主要通过 Kubernetes API Server 交互,而不是彼此随意修改数据库。

一次 Deployment 发布大致经过以下链路:

  1. 用户通过 kubectl、CI 或控制器向 API Server 提交 Deployment。
  2. API Server 完成认证、授权、准入检查和对象持久化。
  3. Deployment Controller 观察到新对象,创建或更新 ReplicaSet。
  4. ReplicaSet Controller 创建 Pod 对象。
  5. Scheduler 为没有节点的 Pod 选择合适节点并写入绑定结果。
  6. 目标节点的 kubelet 观察到 Pod,调用容器运行时创建 Pod sandbox 和容器。
  7. kube-proxy 或 CNI 规则让 Service 流量能够到达 Pod。
  8. kubelet 上报容器状态,Deployment Controller 根据副本数继续调谐。

这个过程体现了三个原则:API 对象是事实来源,控制器是状态转换器,kubelet 是节点侧执行者。手工登录节点修改容器,通常会绕开 Kubernetes 的控制循环,重启后也会丢失。

#二、控制平面组件

#1. kube-apiserver:集群的统一入口

kube-apiserver 提供 Kubernetes API。kubectl、控制器、调度器、Operator 和外部系统都通过它读取或修改资源。它还负责认证、授权、准入控制、版本转换、审计以及与 etcd 的读写协调。

请求进入 API Server 后通常经过:

  1. TLS 和身份认证,例如客户端证书、ServiceAccount Token 或 OIDC。
  2. 授权判断,例如 RBAC 是否允许某个用户在某命名空间创建 Deployment。
  3. 准入控制,例如 Pod Security、ResourceQuota、LimitRange 和自定义 webhook。
  4. schema 校验和默认值填充。
  5. 写入或读取 etcd。

常用检查命令:

bash
kubectl cluster-info
kubectl version
kubectl api-resources | head -n 30
kubectl get --raw='/readyz?verbose'
kubectl auth can-i create deployments -n demo

API Server 访问异常时,先确认 kubeconfig、证书有效期、DNS、负载均衡和控制平面网络。不要直接删除 API Server Pod 作为第一反应;先看控制平面日志、节点状态和 etcd 健康。

#2. etcd:集群状态数据库

etcd 是强一致的分布式键值存储,保存 Deployment、Pod、Service、Secret、ConfigMap、RBAC 和大量集群元数据。etcd 不是普通缓存,磁盘延迟、空间和备份质量会直接影响整个集群。

生产环境要关注:

  • 使用奇数成员数,并将成员分布在故障域中。
  • 使用低延迟、可靠的 SSD 和独立磁盘。
  • 启用 TLS、客户端认证和 peer 认证。
  • 定期做快照,并在隔离环境实际恢复。
  • 监控 leader 变更、提交延迟、数据库大小和磁盘剩余空间。

快照示例:

bash
ETCDCTL_API=3 etcdctl snapshot save /backup/etcd-$(date +%F).db \\
  --endpoints=https://127.0.0.1:2379 \\
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \\
  --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt \\
  --key=/etc/kubernetes/pki/etcd/healthcheck-client.key
ETCDCTL_API=3 etcdctl snapshot status /backup/etcd-$(date +%F).db -w table

路径和证书以 kubeadm 或发行版实际配置为准。不要把 etcd 快照当作唯一备份,备份文件应有访问控制、校验和、异地副本及恢复演练记录。

#3. kube-scheduler:为 Pod 选择节点

Scheduler 只负责为待调度 Pod 选择节点,不负责启动容器。它先过滤不满足条件的节点,再对可行节点打分,最后写入 Pod 的 spec.nodeName 或绑定结果。

影响调度的常见条件包括:

  • 节点资源请求是否有足够 CPU 和内存。
  • nodeSelector、nodeAffinity 和 taint/toleration。
  • PodAffinity、PodAntiAffinity 和拓扑分布约束。
  • 节点污点、可用区、架构和 GPU 资源。
  • 优先级、抢占和调度器扩展。

排查 Pending Pod:

bash
kubectl get pod -n demo
kubectl describe pod -n demo <pod-name>
kubectl get nodes -o wide
kubectl describe node <node-name>

重点看 Events 中的 Insufficient cpu、Insufficient memory、node(s) had taint、node affinity conflict 和 volume binding 失败。不要只给 Pod 增加副本数,先确认资源请求、节点容量和调度约束是否互相矛盾。

#4. controller-manager:持续调谐资源

kube-controller-manager 运行多个控制器,例如 Deployment、ReplicaSet、Node、Job、Namespace、ServiceAccount 和 EndpointSlice 相关控制器。控制器通常监听 API 对象和相关事件,然后把实际状态向期望状态推进。

例如 Deployment 的副本数为 3 时,控制器会确保存在匹配的 ReplicaSet 和 3 个可运行 Pod。Pod 被节点故障删除后,控制器会创建替代 Pod;这不是 kubelet 在做全局决策。

控制器排障要看对象之间的 ownerReferences、selector 和事件:

bash
kubectl describe deployment web -n demo
kubectl get rs,pod -n demo -l app=web --show-labels
kubectl get events -n demo --sort-by=.lastTimestamp

修改 selector 要格外谨慎。selector 不匹配会造成控制器无法管理原有 Pod,甚至产生重复副本或错误发布。

#5. cloud-controller-manager:连接云平台能力

在云环境中,cloud-controller-manager 将 Kubernetes 对象与云厂商 API 对接,例如节点生命周期、云负载均衡、云路由和持久化磁盘。Service 类型 LoadBalancer、云盘 CSI 和节点地址管理通常都依赖它或云厂商组件。

云控制器异常时,应用 Pod 可能正常运行,但 LoadBalancer 一直 Pending、云盘无法挂载或节点状态不完整。排查时同时查看 Kubernetes Events 和云平台审计日志,确认 IAM 权限、配额、子网、安全组和区域是否正确。

#三、工作节点组件

#1. kubelet:节点上的执行与上报代理

kubelet 负责把 PodSpec 转换成节点上的实际容器,并向 API Server 上报节点和 Pod 状态。它管理探针、卷挂载、镜像拉取、容器重启、优雅终止和资源回收。

kubelet 并不会为任意本地容器提供 Kubernetes 管理。只有被 API Server、静态 Pod 清单或节点配置声明的工作才属于它的控制范围。

节点排查命令:

bash
kubectl get nodes
kubectl describe node <node-name>
kubectl get pods -A -o wide --field-selector spec.nodeName=<node-name>
sudo journalctl -u kubelet -n 200 --no-pager

节点 NotReady 时检查 kubelet、容器运行时、CNI、磁盘压力、内存压力、证书、时间同步和到 API Server 的网络。不要先执行 kubectl delete node,因为这会丢失节点对象和排障上下文。

#2. container runtime:实际创建容器

Kubernetes 通过 CRI 与容器运行时交互,常见运行时包括 containerd 和 CRI-O。运行时负责镜像拉取、容器生命周期、sandbox、日志和 cgroup 配置;它不负责 Kubernetes Deployment 的副本调谐。

检查运行时:

bash
kubectl get nodes -o wide
sudo crictl info
sudo crictl ps -a
sudo crictl images

镜像拉取失败要区分认证、仓库 DNS、TLS、架构不匹配、磁盘空间和镜像 tag 不存在。生产环境应固定 digest 或经过验证的版本,不要使用无法审计的 latest。

#3. kube-proxy 与 CNI

kube-proxy 根据 Service 和 EndpointSlice 生成节点上的转发规则,常见实现使用 iptables 或 IPVS。它让访问 ClusterIP 的流量能够被转发到后端 Pod。现代集群也可能使用 eBPF 数据平面替代部分 kube-proxy 能力。

CNI 插件负责 Pod 网络,例如分配 Pod IP、创建网卡和路由、实现跨节点通信。Calico、Cilium、Flannel 和云厂商网络插件在策略、可观测性和实现细节上不同。

检查网络对象:

bash
kubectl get pods -A -o wide
kubectl get svc,endpointslice -n demo
kubectl get networkpolicy -A
kubectl exec -n demo deploy/web -- getent hosts kubernetes.default.svc.cluster.local

服务访问失败时按顺序检查:Pod 是否 Ready、Service selector 是否匹配、EndpointSlice 是否有地址、DNS 是否正常、NetworkPolicy 是否阻断、节点路由和 CNI 日志是否有错误。不要一看到 Service 无法访问就修改 kube-proxy 参数。

#四、核心工作负载和服务对象

#1. Pod:最小调度单位

Pod 是一组共享网络命名空间、IP、卷和生命周期的容器。通常一个主容器配合日志代理、代理或指标 sidecar,但不要为了“看起来模块化”把所有进程都放进一个 Pod。

Pod 的关键状态包括 Pending、Running、Succeeded、Failed 和 Unknown。容器状态还可能出现 Waiting、Running、Terminated。CrashLoopBackOff 不是根因,而是 kubelet 对反复崩溃容器采用退避重启的表现。

#2. Deployment 与 ReplicaSet

Deployment 适合无状态应用。它通过 ReplicaSet 管理 Pod 副本,并支持 RollingUpdate 和 Recreate。生产配置至少声明镜像、资源请求限制、探针、优雅退出和滚动策略:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: demo
spec:
  replicas: 3
  revisionHistoryLimit: 5
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 0
      maxSurge: 1
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      terminationGracePeriodSeconds: 30
      containers:
        - name: web
          image: nginx:1.27.0
          ports:
            - name: http
              containerPort: 80
          resources:
            requests:
              cpu: 100m
              memory: 128Mi
            limits:
              cpu: 500m
              memory: 512Mi
          readinessProbe:
            httpGet:
              path: /
              port: http
            periodSeconds: 5
          livenessProbe:
            httpGet:
              path: /
              port: http
            initialDelaySeconds: 20
            periodSeconds: 10

readiness 失败时 Pod 不接收 Service 流量,但容器可以继续运行;liveness 失败会触发重启。启动慢的应用应增加 startupProbe,避免 liveness 在初始化期间误杀进程。

发布和回滚:

bash
kubectl apply -f deployment.yaml
kubectl rollout status deployment/web -n demo --timeout=180s
kubectl rollout history deployment/web -n demo
kubectl rollout undo deployment/web -n demo

#3. Service 与 EndpointSlice

Service 提供稳定的虚拟 IP、DNS 名称和端口,将流量转发到匹配 selector 的 Pod。ClusterIP 只在集群内部访问,NodePort 暴露节点端口,LoadBalancer 通常请求云平台创建外部负载均衡。

yaml
apiVersion: v1
kind: Service
metadata:
  name: web
  namespace: demo
spec:
  selector:
    app: web
  ports:
    - name: http
      port: 80
      targetPort: http
  type: ClusterIP

验证 Service:

bash
kubectl get svc web -n demo
kubectl get endpointslice -n demo -l kubernetes.io/service-name=web
kubectl run curl --rm -it --restart=Never -n demo --image=curlimages/curl -- curl -fsS http://web/

Service 有 ClusterIP 但没有 EndpointSlice,通常是 selector、Pod label 或 readiness 状态不匹配。Service 端口的 port、targetPort 和容器端口名称也必须对应。

#4. Ingress 与 Gateway API

Ingress 描述 HTTP/HTTPS 路由,但它本身不是控制器。必须安装 NGINX Ingress、Traefik、HAProxy 或云厂商控制器,Ingress 对象才会产生实际代理配置。Gateway API 是更结构化的新一代流量 API,适合把基础设施、路由和应用团队职责分开。

生产流量入口要明确 TLS 证书来源、重定向、超时、请求体大小、访问日志、健康检查和真实客户端 IP。入口返回 404 时先确认 IngressClass、host、path、Service 和控制器日志,不要只改 DNS。

#五、配置、存储与调度

#1. ConfigMap 与 Secret

ConfigMap 用于普通配置,Secret 用于密码、令牌和证书。但 Secret 默认可能只是 base64 编码,必须结合 KMS 静态加密、RBAC、审计和外部 Secret 管理系统。禁止把真实 Secret 写入 Git、镜像层、CI 日志或错误页面。

配置变更后要确认应用是否支持热加载。若配置作为环境变量注入,通常需要重启 Pod;若以文件挂载,应用也不一定会自动重新读取。可用 checksum annotation 让配置变更触发 Deployment 滚动更新。

#2. PV、PVC、StorageClass 与 CSI

PVC 表达应用需要的容量和访问模式,StorageClass 描述动态供给策略,PV 是实际存储资源,CSI Driver 负责与云盘、NAS 或分布式存储交互。应用不应该直接依赖某个节点上的本地路径。

yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: web-data
  namespace: demo
spec:
  accessModes: ["ReadWriteOnce"]
  resources:
    requests:
      storage: 10Gi
  storageClassName: fast

排查 PVC Pending:

bash
kubectl get pvc,pv,storageclass -n demo
kubectl describe pvc web-data -n demo
kubectl get csidrivers
kubectl get volumeattachments

扩容、删除和回收策略都可能涉及真实数据。确认 reclaimPolicy、快照、备份、跨可用区限制和 RPO/RTO 后再操作,不能把删除 PVC 当作普通清理命令。

#3. requests、limits 与 QoS

requests 参与调度,limits 限制容器资源使用。Kubernetes 根据配置将 Pod 分类为 Guaranteed、Burstable 或 BestEffort。没有 requests 的应用可能被错误调度;过低的 limits 会造成 OOMKilled 或 CPU throttling。

容量规划应基于真实指标:CPU 使用、内存工作集、峰值、启动阶段和突发流量。不要把节点总容量全部分给业务 Pod,还要为系统组件、DaemonSet、镜像缓存和故障迁移预留空间。

#4. 节点选择、污点和拓扑分布

nodeSelector 适合简单标签匹配,nodeAffinity 支持更复杂的硬约束和软偏好。taint/toleration 用于阻止普通 Pod 进入专用节点,例如 GPU、存储或控制平面节点。topologySpreadConstraints 可将副本分散到不同节点或可用区。

调度策略的目标不是把 Pod 塞满节点,而是在可用性、成本、数据局部性和故障域之间做平衡。高可用服务至少避免所有副本落在同一节点,数据库还要结合存储复制和故障切换能力。

#六、安全组件与多租户边界

#1. ServiceAccount、RBAC 与 Pod Identity

ServiceAccount 是 Pod 访问 Kubernetes API 的身份。Role 和 RoleBinding 限制命名空间内权限,ClusterRole 和 ClusterRoleBinding 可作用于集群范围。应用只应获得完成工作所需的最小权限。

bash
kubectl auth can-i get secrets -n demo --as=system:serviceaccount:demo:web
kubectl auth can-i list pods -n demo --as=system:serviceaccount:demo:web
kubectl get role,rolebinding -n demo

禁止给普通应用绑定 cluster-admin。令牌要有生命周期和轮换策略,云资源访问优先使用云厂商 Workload Identity,而不是把长期密钥写进 Secret。

#2. Pod Security 与 NetworkPolicy

Pod Security Admission 可以限制特权容器、hostNetwork、hostPath、root 用户和 Linux capabilities。NetworkPolicy 控制 Pod 入站和出站流量,但前提是 CNI 支持并正确执行策略。

安全基线至少考虑:

  • 以非 root 用户运行。
  • 只读根文件系统,按需增加 writable volume。
  • 删除不需要的 capabilities。
  • 禁止 privilege escalation。
  • 限制 egress 到数据库、DNS 和必要外部服务。
  • 为命名空间配置 ResourceQuota 和 LimitRange。

安全策略上线前先在测试命名空间验证,避免一条默认拒绝策略切断 DNS、监控或控制器通信。

#七、一个完整的测试部署流程

创建命名空间并部署最小应用:

bash
kubectl create namespace demo
kubectl config set-context --current --namespace=demo
kubectl create deployment web --image=nginx:1.27.0 --replicas=3
kubectl expose deployment web --port=80 --target-port=80
kubectl rollout status deployment/web --timeout=120s

检查对象关系和网络:

bash
kubectl get deploy,rs,pod,svc -o wide
kubectl get endpointslice
kubectl run test-client --rm -it --restart=Never --image=curlimages/curl -- curl -fsS http://web/

模拟发布失败时,不要直接删除 Deployment。可以发布一个明确错误的镜像 tag,在测试环境观察 rollout:

bash
kubectl set image deployment/web web=nginx:does-not-exist
kubectl rollout status deployment/web --timeout=60s || true
kubectl get pods
kubectl rollout undo deployment/web
kubectl rollout status deployment/web --timeout=120s

这个演练可以验证镜像拉取错误、滚动更新保护、事件记录和回滚权限。测试完成后清理资源:

bash
kubectl delete namespace demo
kubectl config set-context --current --namespace=default

#八、按症状排查故障

#Pod 一直 Pending

先看 kubectl describe pod 的 Events,再检查节点可用资源、污点、亲和性、PVC 和调度约束。资源 request 过大、节点没有匹配标签、存储无法绑定是最常见原因。

#Pod CrashLoopBackOff

查看上一轮容器日志和退出码:

bash
kubectl logs -n demo <pod-name> --previous
kubectl describe pod -n demo <pod-name>
kubectl get pod -n demo <pod-name> -o jsonpath='{.status.containerStatuses[*].lastState}'

重点排查配置缺失、启动参数、权限、依赖不可达、探针过严和 OOMKilled。不要只增加重启次数。

#Service 无法访问

检查 selector、Pod label、readiness、EndpointSlice、Service 端口和 NetworkPolicy。集群内用 DNS 名称测试,节点外访问则继续检查 Ingress、LoadBalancer、安全组和证书。

#发布后流量异常

同时观察 rollout 状态、旧新 ReplicaSet、Pod 事件、应用日志、请求延迟、错误率和连接数。readiness 只应在应用真正能接流量时成功,不能用进程存活替代业务就绪。

#节点 NotReady

查看节点 Conditions、kubelet 日志、容器运行时、CNI、磁盘和内存压力。若需要维护,先 cordon,再在确认工作负载可迁移后 drain:

bash
kubectl cordon <node-name>
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data

drain 可能受 PDB、裸 Pod、本地数据和不可驱逐工作负载影响,生产执行前必须确认业务容量和恢复方案。

#九、生产上线验收清单

控制平面:API Server readyz 正常,etcd 已做恢复演练,Scheduler 和 Controller Manager 无持续错误,审计日志和证书轮换机制正常。

节点:所有节点 Ready,kubelet 和运行时健康,CNI 连通,磁盘和 inode 有余量,时间同步正常,节点标签、污点和架构符合规划。

应用:Deployment rollout 成功,副本分布符合故障域设计,requests/limits 合理,startup/readiness/liveness 探针经过压测,优雅终止和回滚已经演练。

网络:Service EndpointSlice 正常,集群 DNS 可用,NetworkPolicy 只开放必要流量,Ingress/Gateway 的 TLS、超时、访问日志和真实 IP 配置已验证。

存储:PVC 绑定成功,挂载和卸载正常,快照与备份可以恢复,删除和回收策略符合数据保留要求。

安全:RBAC 遵循最小权限,Pod 不使用不必要的特权,Secret 有加密和轮换方案,镜像来源、漏洞扫描和供应链记录完整。

可观测性:应用日志、事件、指标、追踪和告警可用,能够区分调度、启动、网络、依赖和业务错误。上线记录应包含镜像 digest、配置版本、变更人、开始时间、成功标准和回滚命令。

#十、总结

Kubernetes 的核心不是某一个组件,而是 API Server、etcd、控制器、Scheduler、kubelet、运行时和网络存储插件之间形成的控制循环。遇到问题时,沿着“期望对象是否正确、控制器是否调谐、Pod 是否调度、节点是否执行、网络和存储是否可达、应用是否真正就绪”的顺序排查,通常比直接重启更快定位根因。

掌握这些边界后,再学习 Operator、Service Mesh、GPU 调度、Serverless 或多集群管理,都会有更清晰的落点:它们本质上是在 Kubernetes API 和控制循环之上扩展新的资源、策略和执行能力。

写于 2026 年 8 月 21 日

栏目
技术文章
约
15.7 分钟
字数
1.1W
阅读
109

本文为原创记录,转载请注明出处。如果这篇替你省了时间,欢迎留言说说你踩到的坑。

同题 · related

留言 · remarks

00 条

还没有留言,来说点什么吧。

Kubernetes 核心组件详解与实战:从控制平面到应用上线 · LXH·BLOG