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 发布大致经过以下链路:
- 用户通过 kubectl、CI 或控制器向 API Server 提交 Deployment。
- API Server 完成认证、授权、准入检查和对象持久化。
- Deployment Controller 观察到新对象,创建或更新 ReplicaSet。
- ReplicaSet Controller 创建 Pod 对象。
- Scheduler 为没有节点的 Pod 选择合适节点并写入绑定结果。
- 目标节点的 kubelet 观察到 Pod,调用容器运行时创建 Pod sandbox 和容器。
- kube-proxy 或 CNI 规则让 Service 流量能够到达 Pod。
- kubelet 上报容器状态,Deployment Controller 根据副本数继续调谐。
这个过程体现了三个原则:API 对象是事实来源,控制器是状态转换器,kubelet 是节点侧执行者。手工登录节点修改容器,通常会绕开 Kubernetes 的控制循环,重启后也会丢失。
#二、控制平面组件
#1. kube-apiserver:集群的统一入口
kube-apiserver 提供 Kubernetes API。kubectl、控制器、调度器、Operator 和外部系统都通过它读取或修改资源。它还负责认证、授权、准入控制、版本转换、审计以及与 etcd 的读写协调。
请求进入 API Server 后通常经过:
- TLS 和身份认证,例如客户端证书、ServiceAccount Token 或 OIDC。
- 授权判断,例如 RBAC 是否允许某个用户在某命名空间创建 Deployment。
- 准入控制,例如 Pod Security、ResourceQuota、LimitRange 和自定义 webhook。
- schema 校验和默认值填充。
- 写入或读取 etcd。
常用检查命令:
kubectl cluster-info
kubectl version
kubectl api-resources | head -n 30
kubectl get --raw='/readyz?verbose'
kubectl auth can-i create deployments -n demoAPI Server 访问异常时,先确认 kubeconfig、证书有效期、DNS、负载均衡和控制平面网络。不要直接删除 API Server Pod 作为第一反应;先看控制平面日志、节点状态和 etcd 健康。
#2. etcd:集群状态数据库
etcd 是强一致的分布式键值存储,保存 Deployment、Pod、Service、Secret、ConfigMap、RBAC 和大量集群元数据。etcd 不是普通缓存,磁盘延迟、空间和备份质量会直接影响整个集群。
生产环境要关注:
- 使用奇数成员数,并将成员分布在故障域中。
- 使用低延迟、可靠的 SSD 和独立磁盘。
- 启用 TLS、客户端认证和 peer 认证。
- 定期做快照,并在隔离环境实际恢复。
- 监控 leader 变更、提交延迟、数据库大小和磁盘剩余空间。
快照示例:
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:
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 和事件:
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 清单或节点配置声明的工作才属于它的控制范围。
节点排查命令:
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 的副本调谐。
检查运行时:
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 和云厂商网络插件在策略、可观测性和实现细节上不同。
检查网络对象:
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。生产配置至少声明镜像、资源请求限制、探针、优雅退出和滚动策略:
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: 10readiness 失败时 Pod 不接收 Service 流量,但容器可以继续运行;liveness 失败会触发重启。启动慢的应用应增加 startupProbe,避免 liveness 在初始化期间误杀进程。
发布和回滚:
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 通常请求云平台创建外部负载均衡。
apiVersion: v1
kind: Service
metadata:
name: web
namespace: demo
spec:
selector:
app: web
ports:
- name: http
port: 80
targetPort: http
type: ClusterIP验证 Service:
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 或分布式存储交互。应用不应该直接依赖某个节点上的本地路径。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: web-data
namespace: demo
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
storageClassName: fast排查 PVC Pending:
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 可作用于集群范围。应用只应获得完成工作所需的最小权限。
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、监控或控制器通信。
#七、一个完整的测试部署流程
创建命名空间并部署最小应用:
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检查对象关系和网络:
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:
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这个演练可以验证镜像拉取错误、滚动更新保护、事件记录和回滚权限。测试完成后清理资源:
kubectl delete namespace demo
kubectl config set-context --current --namespace=default#八、按症状排查故障
#Pod 一直 Pending
先看 kubectl describe pod 的 Events,再检查节点可用资源、污点、亲和性、PVC 和调度约束。资源 request 过大、节点没有匹配标签、存储无法绑定是最常见原因。
#Pod CrashLoopBackOff
查看上一轮容器日志和退出码:
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:
kubectl cordon <node-name>
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-datadrain 可能受 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
- 机房网络和 K8S 网络,其实是同一套东西从 Underlay 与 Overlay 的分层讲到 VXLAN 封装和 EVPN 控制平面,再对照 K8S 的 CNI、Service、EndpointSlice 和 Ingress,最后给出一张可以直接拿去排障的同构映射表。
- 把博客从 docker-compose 搬到 k3s:单机迁移与上线全过程在 4C3.6G 的云主机上把博客从 docker-compose 迁到单机 k3s。附完整 YAML 清单(Deployment、Service、PVC、Ingress、Certificate 等)与全部配置命令,记录部署、数据迁移与切换上线的踩坑过程。
- 5 台服务器,从二进制装 K8s 到 Spring Cloud 上线用 5 台服务器把整套平台搭出来:二进制部署 Kubernetes 1.36 高可用集群,装完 Harbor、Gitea、Nexus、Jenkins、Argo CD、监控日志链路追踪,最后把 Spring Cloud 微服务项目发布上线。每一步都给可执行命令。
留言 · remarks
00 条还没有留言,来说点什么吧。