Kubernetes 基础体系 · 第 1/83 篇。示例基于 Kubernetes 当前稳定 API;弃用、版本偏差、云厂商差异和生产风险会明确说明。

Kubernetes 完整学习路线:从 Pod 与控制面到安全、运维和 Operator

Kubernetes 是一个通过声明式 API 管理容器化工作负载的分布式系统。用户提交“期望状态”,控制器持续观察“当前状态”,并通过 API Server、Scheduler、kubelet、容器运行时和网络插件等组件,把当前状态逐步推向期望状态。

这句话包含了整条学习路线的主线:

  1. 先理解 Linux 容器、进程、网络和存储;
  2. 再掌握 Pod 这一最小调度与管理单元;
  3. 接着理解控制面如何存储对象、调度 Pod 和执行控制循环;
  4. 然后学习 Deployment、Service、Ingress、Job、StatefulSet 等 API;
  5. 在此基础上处理安全、网络、存储、观测、发布和故障恢复;
  6. 最后理解 CRD 与 Operator,能够扩展 Kubernetes 的控制模型。

一、开始 Kubernetes 之前必须具备的前置知识

Kubernetes 不是容器运行时,也不是简单的“批量执行 Docker 命令”的工具。它把多个节点上的进程、网络、存储和权限组织成一个统一的控制系统,因此至少需要以下前置知识。

1. Linux 进程与容器

容器本质上仍然是 Linux 进程,只是通过内核能力隔离其视图和资源:

  • Namespace 隔离进程、网络、挂载点、用户等资源;
  • cgroups 限制和统计 CPU、内存等资源;
  • Linux capabilities、seccomp、SELinux 或 AppArmor 限制进程权限;
  • 镜像提供用户空间文件系统,不等于虚拟机操作系统。

例如,容器中的 PID 1 不是普通意义上的“第一个业务进程”。它需要正确处理信号和子进程回收,否则会出现优雅终止失败或僵尸进程堆积。

2. 网络基础

学习 Kubernetes 网络前,应能解释:

  • IP、端口、TCP、DNS 和路由;
  • NAT 与负载均衡;
  • Linux network namespace、veth、bridge;
  • TLS、证书、SNI 和 HTTP;
  • CNI、Service、Ingress 或 Gateway 分别解决什么问题。

Kubernetes 中“Pod 有 IP”并不意味着外部客户端可以直接访问它。Pod IP 通常属于集群内部网络,生命周期也可能随 Pod 重建而改变。

3. 存储基础

需要区分:

  • 容器可写层:通常随容器销毁而丢失;
  • emptyDir:随 Pod 生命周期存在;
  • PersistentVolume:由集群或外部存储系统提供的持久卷;
  • 文件系统语义:读写、挂载、权限、锁和故障恢复;
  • 数据库一致性:单纯把数据库进程放进 Pod,不会自动获得高可用能力。

4. YAML、JSON 和 API

Kubernetes 配置不是任意 YAML。YAML 最终会被解析为 JSON,再根据资源的 API Schema 验证。

典型对象包含:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3

其中:

  • apiVersion 决定对象属于哪个 API 组和版本;
  • kind 决定对象类型;
  • metadata 描述名称、命名空间、标签和注解;
  • spec 是用户声明的期望状态;
  • status 通常由 Kubernetes 组件写入,描述观察到的状态。

不要把 status 当作用户配置。直接修改它通常没有实际意义,且可能被控制器覆盖。


二、Kubernetes 的核心抽象:声明式对象与控制循环

Kubernetes 的核心不是某条命令,而是以下控制关系:

Reconcile(Observed State,Desired State)Actions\text{Reconcile}(\text{Observed State}, \text{Desired State}) \rightarrow \text{Actions}

其中:

  • Desired State 是用户提交的 spec
  • Observed State 是控制器从 API Server 或底层系统观察到的状态;
  • Actions 是创建、更新、删除、调度、挂载、启动等操作;
  • 控制器重复执行这个过程,直到状态收敛。

1. 为什么 Kubernetes 能够自动恢复

假设用户声明:

spec:
  replicas: 3

Deployment 控制器会创建或维护一个 ReplicaSet,ReplicaSet 再保证匹配标签的 Pod 数量为 3。

如果某个 Pod 被删除:

  1. ReplicaSet 观察到实际 Pod 数量从 3 变成 2;
  2. 控制器计算差异:desired - actual = 3 - 2 = 1
  3. 创建一个新 Pod;
  4. Scheduler 为未绑定节点的 Pod 选择节点;
  5. kubelet 让该节点达到 Pod 的运行状态;
  6. 控制器再次观察,直到数量恢复为 3。

这不是一次性的“修复脚本”,而是持续运行的闭环。

2. 反例:声明副本数不等于服务可用

如果三个 Pod 都因为应用配置错误而启动后立即退出,ReplicaSet 仍可能不断创建替代 Pod。副本数看似满足,但服务并不可用。

因此 Kubernetes 至少区分:

  • Pod 是否存在;
  • 容器是否正在运行;
  • 容器是否通过存活检查;
  • Pod 是否通过就绪检查;
  • Service 是否拥有可用后端;
  • 应用是否真正能够处理业务请求。

这也是为什么 kubectl get pods 显示 Running,并不等价于应用健康。


三、总体架构:控制面、节点与数据流

一个 Kubernetes 集群通常由控制面和工作节点组成。

flowchart LR
    User[kubectl / client] --> API[ kube-apiserver ]
    API --> ETCD[(etcd)]
    API --> Sched[ kube-scheduler ]
    API --> CM[ kube-controller-manager ]

    API --> K1[ kubelet ]
    K1 --> CRI[Container Runtime]
    CRI --> C[Containers / Pods]

    API --> KubeProxy[kube-proxy]
    KubeProxy --> Net[Service forwarding]

    C --> CNI[CNI network plugin]
    C --> CSI[CSI storage plugin]

1. API Server:唯一的集群 API 入口

API Server 负责:

  1. 接收 HTTP 请求;
  2. 认证请求者是谁;
  3. 授权请求者能做什么;
  4. 执行准入检查和变更;
  5. 校验资源 Schema;
  6. 读写 etcd;
  7. 通过 Watch 通知控制器和客户端资源变化。

一个典型请求路径是:

kubectl apply
  → TLS 连接 API Server
  → Authentication
  → Authorization
  → Admission
  → Schema Validation
  → 写入 etcd
  → Watch 事件传播
  → Controller / Scheduler / Kubelet 执行

API Server 并不会直接在节点上启动容器。它保存对象并提供协调入口,真正让 Pod 运行的是节点侧 kubelet 和容器运行时。

2. etcd:控制面状态数据库

etcd 是一致性键值存储,保存 Kubernetes 的核心对象,例如:

  • Pod、Deployment、Service;
  • Secret、ConfigMap;
  • RBAC 配置;
  • CRD 和自定义资源;
  • 节点、租约和控制面状态。

etcd 使用 Raft 类一致性机制维护多副本。对生产集群而言,必须考虑:

  • 控制面节点数量和故障仲裁;
  • etcd 磁盘延迟;
  • 定期快照;
  • 快照加密和访问权限;
  • 恢复演练;
  • etcd 版本与 Kubernetes 版本兼容性。

etcd 不是业务数据库。把大量日志、缓存或高频业务数据写入 Kubernetes API,会增加控制面的负载。

3. Scheduler:为未绑定 Pod 选择节点

Scheduler 处理尚未设置 spec.nodeName 的 Pod。其基本过程可以抽象为:

  1. 获取待调度 Pod;
  2. 过滤不满足条件的节点;
  3. 对可行节点评分;
  4. 选择得分最高的节点;
  5. 通过 API Server 写入 Pod 的绑定结果。

过滤条件可能包括:

  • 节点资源是否满足 Pod requests;
  • nodeSelector 或节点亲和性;
  • 污点与容忍;
  • Pod 亲和性与反亲和性;
  • 拓扑分布约束;
  • 节点端口;
  • 卷的拓扑限制。

调度器通常依据资源请求而不是当前瞬时使用率进行资源可调度性判断。下面的 Pod 声明需要 500m CPU 和 512Mi 内存:

resources:
  requests:
    cpu: "500m"
    memory: "512Mi"
  limits:
    cpu: "1"
    memory: "1Gi"

500m 表示半个逻辑 CPU。调度器主要会检查节点上可分配资源是否足以容纳 requests,而不是保证应用实际始终只使用这么多资源。

4. Controller Manager:持续执行控制循环

Controller Manager 中包含多个控制器,例如:

  • Node Controller:处理节点失联;
  • ReplicaSet Controller:维持 Pod 副本数;
  • Deployment Controller:管理发布和 ReplicaSet;
  • Job Controller:管理一次性任务;
  • EndpointSlice Controller:根据 Service 和 Pod 生成后端切片;
  • Namespace、ServiceAccount 等相关控制器。

控制器不是“执行一次命令后退出”,而是不断监听资源变化,并在发生变化或定期重新检查时执行协调。

5. Node:真正运行工作负载的位置

节点侧的主要组件包括:

  • kubelet:负责该节点上的 Pod 生命周期;
  • 容器运行时:通过 CRI 接口创建和管理容器;
  • CNI 网络插件:为 Pod 配置网络;
  • CSI 存储插件:挂载和管理持久卷;
  • kube-proxy 或等效数据面组件:实现 Service 流量转发。

不同发行版可能替换或组合这些组件。例如,某些网络插件同时实现 NetworkPolicy 和 Service 数据面,某些环境使用 eBPF 数据面替代传统 kube-proxy。组件职责应以实际集群部署为准。


四、Pod 完整模型:Kubernetes 的最小调度单元

Pod 不是“一个容器的别名”。Pod 是一组共享部分 Linux 命名空间、网络地址和存储卷的容器集合,也是 Kubernetes 的最小调度和管理单元。

1. Pod 为什么是调度单位

Scheduler 调度的是 Pod,而不是 Pod 中的单个容器。Pod 中所有容器必须能够在同一个节点上运行,因此它们的资源请求会合并参与调度。

如果一个 Pod 有两个容器:

resources:
  requests:
    cpu: "200m"
    memory: "256Mi"

另一个容器为:

resources:
  requests:
    cpu: "300m"
    memory: "128Mi"

那么 Pod 至少需要:

  • CPU:200m + 300m = 500m
  • 内存:256Mi + 128Mi = 384Mi

这只是普通容器请求的基本合计。包含 init container 时,调度资源还要考虑 init 容器请求与常驻容器请求之间的取大规则,而不是简单地全部相加。

2. Pod 的共享网络模型

一个 Pod 通常拥有一个独立的网络命名空间和一个 Pod IP。Pod 内的容器共享:

  • IP 地址;
  • 网络接口;
  • 端口空间;
  • loopback 地址 127.0.0.1

因此同一 Pod 内的两个容器可以通过 localhost 通信,但必须使用不同端口:

容器 A: localhost:8080
容器 B: localhost:15000

如果两个容器都监听 0.0.0.0:8080,它们会因为共享网络命名空间而发生端口冲突。

Pod IP 的典型数据路径是:

Pod 容器
  → Pod network namespace
  → veth / CNI
  → 节点网络
  → 其他 Pod 或 Service

Pod IP 通常是临时的。Pod 被重新创建后,即使名称相同,也可能得到新的 UID 和 IP。需要稳定访问时,应使用 Service,而不是把 Pod IP 写进配置。

3. Sandbox 和基础设施容器

Pod 启动时,运行时通常先创建一个 Pod sandbox,用于承载 Pod 的网络命名空间等基础环境,再启动业务容器。

常见实现会有一个 pause 或等价的基础设施容器,但这是实现细节,不应把特定容器名称当作 Kubernetes API 保证。Pod 的网络共享模型是需要理解的规范行为,sandbox 的具体实现可能随容器运行时变化。

4. 共享存储:emptyDir 和挂载卷

emptyDir 在 Pod 被调度到节点后创建,Pod 内容器可以共享它:

apiVersion: v1
kind: Pod
metadata:
  name: shared-volume-demo
spec:
  containers:
  - name: writer
    image: busybox:1.36
    command: ["/bin/sh", "-c"]
    args: ["echo hello > /shared/message; sleep 3600"]
    volumeMounts:
    - name: shared
      mountPath: /shared
  - name: reader
    image: busybox:1.36
    command: ["/bin/sh", "-c"]
    args: ["sleep 2; cat /shared/message; sleep 3600"]
    volumeMounts:
    - name: shared
      mountPath: /shared
  volumes:
  - name: shared
    emptyDir: {}

执行:

kubectl apply -f shared-volume.yaml
kubectl logs shared-volume-demo -c reader

预期输出:

hello

这个示例成立的原因是两个容器挂载了同一个 Pod 级卷。它不适合保存数据库数据,因为删除 Pod 后 emptyDir 也会被删除。

5. Init container 与主容器

Init container 在业务容器之前按顺序执行,并且必须成功退出,后续 init container 或主容器才会启动。它适合:

  • 生成配置;
  • 执行一次性初始化;
  • 等待某个前置条件;
  • 调整共享卷中的文件。

如果 init container 一直失败,Pod 常见状态会是 Init:x/y 或反复重启。此时查看主容器日志通常没有帮助,应先查看 init container:

kubectl describe pod <pod-name>
kubectl logs <pod-name> -c <init-container-name>

不要把长期运行的代理进程随意放入 init container;它完成后会退出,无法承担常驻 sidecar 的职责。某些 Kubernetes 版本支持原生 sidecar 语义,但该能力存在版本和发行版差异,使用前应以目标集群 API 文档和 Feature Gate 状态为准。

6. Pod 生命周期与状态

Pod 的生命周期阶段通常包括:

  • Pending:已被 API 接受,但尚未完全运行;
  • Running:至少一个容器正在运行,或正在启动/重启;
  • Succeeded:所有容器成功退出;
  • Failed:所有容器终止,且至少一个失败;
  • Unknown:无法获得 Pod 状态。

这些阶段是 Pod 的高层相位,不等价于容器状态。容器还可能处于:

  • Waiting
  • Running
  • Terminated

删除 Pod 时,典型流程是:

  1. API Server 为 Pod 设置删除时间戳;
  2. kubelet 观察到删除请求;
  3. 执行 preStop,如果配置了;
  4. 向进程发送终止信号;
  5. 等待终止宽限期;
  6. 必要时发送强制终止信号;
  7. 清理容器和 sandbox。

preStop 不是可靠的分布式事务。节点宕机或强制删除时,它可能无法执行,应用必须能够处理非优雅终止。


五、一个可运行的端到端应用示例

下面的清单创建:

  • 一个 Deployment;
  • 两个副本;
  • 容器端口;
  • 资源请求和限制;
  • 存活探针;
  • 就绪探针;
  • 一个 ClusterIP Service。
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  labels:
    app: web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: web
        image: nginx:1.27
        ports:
        - name: http
          containerPort: 80
        resources:
          requests:
            cpu: "100m"
            memory: "128Mi"
          limits:
            cpu: "500m"
            memory: "256Mi"
        readinessProbe:
          httpGet:
            path: /
            port: http
          initialDelaySeconds: 2
          periodSeconds: 5
        livenessProbe:
          httpGet:
            path: /
            port: http
          initialDelaySeconds: 10
          periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector:
    app: web
  ports:
  - name: http
    port: 80
    targetPort: http
  type: ClusterIP

执行:

kubectl apply -f web.yaml
kubectl rollout status deployment/web
kubectl get pods -l app=web -o wide
kubectl get endpointslice -l kubernetes.io/service-name=web

预期现象:

  • Deployment 最终显示 2/2
  • 两个 Pod 进入 Running
  • 两个 Pod 通过就绪检查后,EndpointSlice 中出现两个后端地址;
  • Service 获得一个集群内部虚拟 IP。

测试 Service:

kubectl run curl \
  --rm -it \
  --image=curlimages/curl:8.10.1 \
  --restart=Never \
  -- curl -sS http://web/

预期会得到 Nginx 的 HTML 响应。

1. readiness 和 liveness 的因果区别

就绪检查失败:

  • Pod 仍可能处于 Running
  • Pod 不再被加入 Service 的可用后端;
  • 容器通常不会因此重启。

存活检查失败:

  • kubelet 认为容器无法继续工作;
  • 根据 restartPolicy 和容器重启规则重启容器。

常见错误是用同一个检查同时表示“能否接收流量”和“是否应该重启”。例如应用启动很慢时,过于激进的 livenessProbe 会导致启动死循环;应用只是暂时无法连接下游时,直接重启可能放大故障。

对于启动时间明显较长的程序,可以使用 startupProbe,让 kubelet 在启动探针成功前暂缓执行 livenessProbe。


六、从 Pod 到工作负载 API

直接创建 Pod 适合学习和临时调试,生产工作负载通常应使用更高层控制器。

1. ReplicaSet:维持副本数量

ReplicaSet 根据 selector 找到匹配 Pod,并维持数量:

Δ=NdesiredNactual\Delta = N_{\text{desired}} - N_{\text{actual}}

Δ>0\Delta > 0 时创建 Pod;当 Δ<0\Delta < 0 时删除 Pod。

ReplicaSet 不负责版本发布。直接修改 Pod 模板不会形成可靠的滚动发布流程,因此通常由 Deployment 管理 ReplicaSet。

2. Deployment:无状态应用发布

Deployment 将版本发布分解为多个 ReplicaSet。更新 Pod template 时,Deployment 会创建新 ReplicaSet,再逐步扩大新版本、缩小旧版本。

常用操作:

kubectl set image deployment/web web=nginx:1.28
kubectl rollout status deployment/web
kubectl rollout history deployment/web
kubectl rollout undo deployment/web

滚动发布的安全性取决于:

  • 新版本是否能通过 readinessProbe;
  • maxUnavailablemaxSurge 是否适合容量;
  • 新旧版本是否兼容同一数据库 Schema;
  • 应用是否支持并行运行两个版本;
  • 是否有足够节点资源容纳临时额外副本。

反例是数据库 Schema 先被新版本破坏性修改,随后回滚应用镜像。镜像回滚并不等于数据库回滚,发布流程必须考虑向前兼容和迁移阶段。

3. StatefulSet:稳定身份与有序生命周期

StatefulSet 通常提供:

  • 稳定的 Pod 名称;
  • 稳定的网络身份;
  • 每个副本独立的 PVC;
  • 可配置的创建、更新和删除顺序。

它不自动把普通数据库变成高可用数据库。数据库复制、选主、脑裂处理、备份恢复仍由数据库系统或 Operator 负责。

4. DaemonSet、Job 和 CronJob

  • DaemonSet:让符合条件的节点各运行一个或指定数量的 Pod,常用于日志代理、节点监控和网络组件;
  • Job:保证一次性任务完成;
  • CronJob:按时间表创建 Job。

Job 的“完成”依赖容器退出码和 completionsparallelismbackoffLimit 等参数。一个脚本输出“任务完成”但进程退出码为 0,才会被 Kubernetes 认为成功;只写日志而不退出,Job 不会完成。


七、Service、DNS 与入口流量

1. Service 解决什么问题

Pod IP 会变化,Service 提供稳定的访问抽象。Service selector 选择 Pod,EndpointSlice Controller 根据匹配结果生成后端地址。

常见类型:

  • ClusterIP:集群内部访问;
  • NodePort:在节点端口暴露服务;
  • LoadBalancer:请求底层或云厂商提供外部负载均衡;
  • ExternalName:通过 DNS 名称建立外部名称映射,不是四层代理。

Service 的流量是否经过 kube-proxy、是否使用 iptables、IPVS 或 eBPF,取决于集群实现。

2. Service 不会自动把 Pod 纳入后端

Pod 必须同时满足:

  1. 标签匹配 Service selector;
  2. Pod 被认为 Ready;
  3. 网络插件和 EndpointSlice 机制正常。

检查链路:

kubectl get svc web
kubectl get endpointslice -l kubernetes.io/service-name=web
kubectl describe pod <pod-name>

如果 Service 存在但 EndpointSlice 为空,优先检查 selector、Pod 标签和 readinessProbe,而不是先怀疑 DNS。

3. Ingress 与 Gateway

Ingress 是 HTTP/HTTPS 路由 API,但它本身不是流量代理程序,必须有 Ingress Controller 才能真正处理请求。

Gateway API 提供更细粒度的网关资源模型。使用哪种 API 应依据目标集群和网关实现支持情况决定。不要因为对象成功创建,就认为外部流量已经可达;还必须验证:

  • 控制器是否运行;
  • 地址是否分配;
  • DNS 是否指向正确入口;
  • TLS Secret 和证书链是否正确;
  • 网络防火墙和云负载均衡规则是否放行。

八、配置、Secret、存储和网络

1. ConfigMap 与 Secret

ConfigMap 适合非敏感配置;Secret 用于敏感数据,但 Secret 默认并不等于端到端加密。

apiVersion: v1
kind: Secret
metadata:
  name: app-secret
type: Opaque
stringData:
  DB_USER: app
  DB_PASSWORD: change-me

stringData 由 API Server 转换为 data,客户端不需要手工 Base64。Base64 只是编码,不是加密:

echo -n 'change-me' | base64

生产集群至少需要考虑:

  • etcd 静态加密;
  • API 访问权限;
  • 审计日志中的敏感字段;
  • Secret 是否会进入 Git、镜像层或 CI 日志;
  • 外部密钥系统和轮换机制。

2. PersistentVolume、PVC 和 StorageClass

PVC 是用户对存储的请求,PV 是可绑定的存储资源,StorageClass 描述动态供应策略。

典型关系:

Pod → PVC → PV → Storage backend

动态供应时,创建 PVC 可能触发 CSI Provisioner 创建后端卷。Pod 挂载失败时,检查:

kubectl get pvc
kubectl describe pvc <pvc-name>
kubectl get pv
kubectl get events --sort-by=.lastTimestamp

Pending 可能意味着:

  • 没有匹配的 StorageClass;
  • 可用容量不足;
  • 访问模式不支持;
  • 节点拓扑不满足;
  • CSI 控制器或节点插件异常。

删除 PVC 的风险取决于 StorageClass 的回收策略。Delete 可能连带删除后端卷,生产数据必须在删除前确认备份与回收策略。

3. NetworkPolicy

NetworkPolicy 是 Kubernetes 的网络访问控制 API,但是否生效取决于网络插件是否实现它。

一个只允许同命名空间、带有 role=frontend 标签的 Pod 访问后端 8080 的示例:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend
spec:
  podSelector:
    matchLabels:
      role: backend
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 8080

这里的 podSelector 默认只匹配同一命名空间中的 Pod。若要跨命名空间选择,通常需要同时使用 namespaceSelector。启用策略后,未被允许的流量可能被拒绝,必须先明确 DNS、监控、日志和控制器所需的访问路径。


九、安全学习路线:从身份到最小权限

Kubernetes 安全不是单一功能,而是多个边界叠加:

客户端身份认证
  → API 授权
  → Admission 准入
  → Pod / 容器权限
  → 网络访问控制
  → 镜像与供应链
  → Secret 与数据保护
  → 审计和检测

1. Authentication、Authorization 和 Admission

三者不能混淆:

  • Authentication:确认“你是谁”;
  • Authorization:判断“你能做什么”;
  • Admission:判断“请求是否允许进入系统”,并可能修改对象。

RBAC 使用四类核心对象:

  • Role:命名空间内的权限规则;
  • ClusterRole:集群范围权限规则;
  • RoleBinding:把 Role 或 ClusterRole 绑定给主体;
  • ClusterRoleBinding:在集群范围绑定权限。

例如只允许某 ServiceAccount 读取命名空间内的 Pod:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: pod-reader
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-reader
subjects:
- kind: ServiceAccount
  name: pod-reader
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

验证:

kubectl auth can-i list pods \
  --as=system:serviceaccount:<namespace>:pod-reader \
  -n <namespace>

预期输出:

yes

风险在于给控制器绑定 cluster-admin。这会让一个应用 Pod 获得近乎整个集群的管理权限;若该应用存在命令注入或依赖供应链漏洞,攻击者可能进一步控制集群。

2. Pod 安全

生产 Pod 需要明确考虑:

  • 是否必须以 root 运行;
  • 是否可以使用只读根文件系统;
  • 是否需要 Linux capabilities;
  • 是否需要特权容器;
  • 是否允许 HostNetwork、HostPID、HostPath;
  • seccomp、SELinux 或 AppArmor 配置;
  • 进程和文件系统权限。

Pod Security Admission 根据命名空间标签实施 privilegedbaselinerestricted 等安全级别。具体行为以目标 Kubernetes 版本支持的 Pod Security 标准为准。不要把已经废弃的 PodSecurityPolicy 当作新集群设计方案。

3. 镜像供应链

镜像安全包括:

  • 固定可信 registry;
  • 避免依赖可变的 latest 标签;
  • 使用 digest 固定内容;
  • 扫描漏洞;
  • 生成并验证 SBOM;
  • 使用签名和准入策略;
  • 定期重建基础镜像。

镜像扫描结果不是绝对安全证明。它可能漏报业务逻辑漏洞,也可能把不可利用的系统包漏洞列为高风险。扫描应与运行时权限、网络策略和补丁流程结合。


十、资源、调度与容量

1. requests 和 limits

requests 主要影响调度和资源保障;limits 主要限制容器可用上限。

CPU 超过 limit 时,通常表现为节流;内存超过 limit 时,可能触发 OOM Kill。Pod 的 QoS 类别与 requests、limits 的设置有关,节点内存压力下不同 QoS Pod 的驱逐风险不同。

一个常见错误是只设置很大的 limit,却不设置合理 request。这样可能导致调度器低估实际资源需求,节点上运行过多工作负载,最终出现内存压力或严重 CPU 争用。

2. 污点、容忍和亲和性

  • Taint 作用于节点,阻止不匹配的 Pod 调度;
  • Toleration 作用于 Pod,使其可以容忍指定污点;
  • Affinity 表达 Pod 应该或不应该靠近某些节点或 Pod。

例如专用节点可以设置污点:

kubectl taint nodes node-a workload=database:NoSchedule

只有带有对应 toleration 的 Pod 才能调度到该节点。删除污点:

kubectl taint nodes node-a workload=database:NoSchedule-

这类命令会改变生产调度边界,执行前应记录原始污点,并在恢复时验证工作负载是否重新平衡。

3. 高可用不是简单增加 replicas

三个副本如果都被调度到同一节点,节点故障时仍会同时丢失。Pod 反亲和性或拓扑分布约束可以表达跨节点、跨可用区分布要求,但必须确认:

  • 集群中是否存在足够拓扑域;
  • 约束是硬约束还是软约束;
  • 资源容量是否足够;
  • 跨可用区网络和存储成本是否可接受。

十一、观测、诊断与故障路径

Kubernetes 运维应沿着“对象状态 → 事件 → 组件日志 → 节点和底层系统”逐层定位。

1. 基本诊断顺序

kubectl get pods -A
kubectl describe pod <pod-name> -n <namespace>
kubectl logs <pod-name> -n <namespace> -c <container-name>
kubectl logs <pod-name> -n <namespace> -c <container-name> --previous
kubectl get events -n <namespace> --sort-by=.lastTimestamp

每条命令关注不同证据:

  • get:快速查看阶段和重启次数;
  • describe:查看调度、挂载、探针和事件;
  • logs:查看当前容器进程输出;
  • --previous:查看上一次已崩溃容器输出;
  • events:查看调度器、kubelet 和控制器记录的过程事件。

2. 常见失败状态

Pending

可能原因:

  • 没有可用节点;
  • requests 超过节点可分配资源;
  • nodeSelector、亲和性或污点不匹配;
  • PVC 未绑定;
  • 调度器约束过严。

先执行:

kubectl describe pod <pod-name>

重点看 Events 中的 FailedScheduling

CrashLoopBackOff

这不是根因,而是 kubelet 对反复崩溃容器采用退避重启的表现。诊断:

kubectl logs <pod-name> --previous
kubectl describe pod <pod-name>

可能是配置错误、依赖不可用、启动参数错误或探针失败。

ImagePullBackOff

通常涉及:

  • 镜像名称或 tag 不存在;
  • registry 网络不可达;
  • 私有仓库认证失败;
  • 节点证书或代理配置错误;
  • 镜像架构不匹配。

Running 但没有流量

按数据流检查:

容器监听端口
  → readinessProbe
  → Pod Ready
  → EndpointSlice
  → Service selector
  → Service 转发
  → Ingress / Gateway / LoadBalancer
  → DNS 和防火墙

不要只检查 Service 是否存在。Service 没有后端时,客户端通常会得到连接失败或超时。

3. 监控对象与应用指标

Kubernetes 自身状态指标、节点资源指标和应用业务指标属于不同层次:

  • kubelet、API Server、Scheduler 等组件指标;
  • 节点 CPU、内存、磁盘、网络;
  • Pod 重启、OOM、调度延迟;
  • 应用 QPS、延迟、错误率;
  • 业务队列长度和数据处理进度。

kubectl top 依赖 Metrics Server 或等价组件,不能默认假设所有集群都已安装。它适合查看即时资源使用,不等于完整历史监控系统。


十二、发布、升级、备份和生产就绪

1. 发布流程

一个可验证的 Deployment 发布流程至少包括:

kubectl apply -f web.yaml
kubectl rollout status deployment/web --timeout=5m
kubectl get pods -l app=web
kubectl get endpointslice -l kubernetes.io/service-name=web

验证不能只看 Pod 是否 Running,还要确认:

  • 新版本通过 readiness;
  • Service 后端数量符合预期;
  • 关键接口返回正确;
  • 错误率和延迟没有异常;
  • 旧版本是否已经按策略退出。

2. 回滚边界

kubectl rollout undo deployment/web

这个操作通常只回滚 Deployment 的 Pod 模板,不会自动回滚:

  • 数据库 Schema;
  • 外部消息格式;
  • ConfigMap 中已经修改的内容;
  • 外部云资源;
  • 用户数据。

因此发布应尽量采用可回滚的应用变更、向前兼容的数据迁移和独立验证步骤。

3. etcd 备份不等于完整灾备

etcd 快照可以恢复 Kubernetes 对象,但不一定包含:

  • 外部数据库数据;
  • 对象存储中的文件;
  • 云负载均衡器的全部外部状态;
  • 节点本地数据;
  • 镜像仓库内容;
  • 第三方 Operator 管理的外部资源。

生产灾备需要定义恢复目标:

  • RPO:最多允许丢失多少数据;
  • RTO:最多允许多长时间恢复;
  • 恢复顺序;
  • 密钥和证书如何恢复;
  • 跨区域或跨集群切换方式。

备份最重要的验证不是“命令成功”,而是定期在隔离环境执行真实恢复,并验证应用可用性。

4. 版本偏差和弃用

Kubernetes API 版本会随发行版升级变化。必须区分:

  • 稳定 API:例如 apps/v1batch/v1networking.k8s.io/v1
  • 仍可用但已弃用的 API;
  • Alpha 或 Beta 特性;
  • 发行版额外提供的 API。

检查当前集群支持的资源:

kubectl api-resources
kubectl api-versions
kubectl explain deployment.spec

云厂商托管集群还可能在以下方面不同:

  • 控制面是否可访问;
  • CNI 和 Service 数据面实现;
  • LoadBalancer 行为;
  • StorageClass 和 CSI;
  • IAM 与 Kubernetes ServiceAccount 的集成;
  • 节点自动扩缩容;
  • 审计和日志服务。

不能把某家云厂商的注解、负载均衡参数或存储类名称当成 Kubernetes 通用规范。


十三、Operator:把领域知识编码为控制器

Operator 是一种软件模式:使用 Kubernetes API 管理某类复杂应用,并把领域运维知识编码到控制器中。

它通常包含:

  1. CRD:定义新的资源类型;
  2. Custom Resource:用户提交某个实例的期望状态;
  3. Controller:观察资源并执行协调;
  4. 可能的 Webhook:执行校验或默认值填充;
  5. 关联的 Deployment、StatefulSet、Service、PVC 等资源。

1. CRD 与自定义资源

一个简化 CRD:

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: caches.example.com
spec:
  group: example.com
  scope: Namespaced
  names:
    plural: caches
    singular: cache
    kind: Cache
    shortNames:
    - cache
  versions:
  - name: v1
    served: true
    storage: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            required:
            - replicas
            properties:
              replicas:
                type: integer
                minimum: 1
                maximum: 10

创建后可以提交:

apiVersion: example.com/v1
kind: Cache
metadata:
  name: demo
spec:
  replicas: 3

CRD Schema 会在 API Server 层校验 replicas 是否为 1 到 10 的整数。它不能自动创建缓存集群;真正的行为由 Operator Controller 实现。

2. Operator 的协调过程

假设用户把 spec.replicas 从 3 改为 5:

  1. API Server 校验并保存自定义资源;
  2. Controller 收到 Watch 事件;
  3. Controller 读取当前关联资源;
  4. 发现实际副本为 3,期望为 5;
  5. 创建或更新底层工作负载;
  6. 观察底层资源是否就绪;
  7. 更新自定义资源的 status
  8. 如果中途失败,记录事件并按退避策略重试。

控制器必须是幂等的:同一个事件重复到达时,重复执行不应破坏系统。因为 Watch 断线、控制器重启和事件重放都是正常情况。

3. Operator 的错误处理

良好的 Operator 不应只把错误写入日志,还应:

  • status.conditions 中记录可观察状态;
  • 设置 observedGeneration
  • 记录失败原因和重试信息;
  • 对临时错误重试;
  • 对永久配置错误避免无限制造资源;
  • 在删除时处理 finalizer;
  • 明确资源所有权和级联删除策略。

Finalizer 的逻辑是:

  1. 用户请求删除自定义资源;
  2. API Server 不立即物理删除,而是设置删除时间戳;
  3. Controller 看到删除状态;
  4. Controller 清理外部资源;
  5. 清理完成后移除 finalizer;
  6. API Server 才最终删除对象。

如果 Controller 永久失效,资源可能长期停留在 Terminating。直接手工删除 finalizer 可能留下云资源、数据库实例或存储卷泄漏,只有确认清理责任已转移时才应这样做。

4. Operator 的边界

Operator 不会自动解决所有高可用问题。它仍然依赖:

  • 正确的底层存储;
  • 足够节点和拓扑;
  • 应用自身的复制协议;
  • 备份和恢复能力;
  • RBAC、Webhook 和升级兼容性;
  • 对外部资源的幂等管理。

学习 Operator 时,应先能手工部署一个应用,再把“创建资源、升级资源、检查健康、备份、恢复、删除清理”等流程逐步编码进控制器。


十四、推荐的完整学习顺序

阶段一:运行环境与对象基础

掌握:

  • Linux 进程、Namespace、cgroups;
  • OCI 镜像与容器运行时;
  • YAML、JSON、HTTP、TLS;
  • kubectl、kubeconfig、命名空间;
  • Pod、容器、日志、事件和资源描述。

练习目标是能够解释一个 Pod 从提交到运行经历了哪些组件。

阶段二:控制面与节点

掌握:

  • API Server 的认证、授权、准入;
  • etcd 的状态存储和备份;
  • Scheduler 的过滤与评分;
  • Controller Manager 的控制循环;
  • kubelet、CRI、CNI、CSI;
  • Pod sandbox 和容器生命周期。

练习目标是能根据事件和组件日志定位 Pod 为什么没有被调度或启动。

阶段三:工作负载和网络

掌握:

  • ReplicaSet、Deployment;
  • StatefulSet、DaemonSet;
  • Job、CronJob;
  • Service、EndpointSlice、DNS;
  • Ingress 或 Gateway;
  • NetworkPolicy;
  • readiness、liveness、startup 探针。

练习目标是完成一次发布、流量切换、故障注入和回滚。

阶段四:存储、资源和高可用

掌握:

  • requests、limits、QoS;
  • 调度约束、污点和容忍;
  • PVC、PV、StorageClass、CSI;
  • 跨节点和跨可用区分布;
  • PDB、HPA、VPA 等自动化能力的适用边界;
  • 备份、恢复与容量规划。

练习目标是验证节点故障、Pod 驱逐、卷挂载失败和资源不足时的行为。

阶段五:安全与生产运维

掌握:

  • RBAC 和 ServiceAccount;
  • Pod Security;
  • Secret 加密与轮换;
  • 镜像扫描、签名和准入;
  • NetworkPolicy;
  • 审计、指标、日志和追踪;
  • 升级、回滚和灾备演练。

练习目标是让一个应用在最小权限、资源边界、网络边界和可观测条件下运行。

阶段六:CRD 与 Operator

掌握:

  • CRD Schema 和版本;
  • 自定义资源的 spec/status;
  • Watch、队列和幂等 Reconcile;
  • ownerReferences 与 finalizer;
  • Webhook、RBAC 和指标;
  • Operator 升级与数据迁移。

练习目标是编写一个能够创建、更新、报告状态并安全删除底层资源的 Operator。


十五、最终综合练习:从部署到故障恢复

可以构建一个包含以下组件的练习环境:

  • Deployment 管理无状态 API;
  • Service 提供集群内部访问;
  • Ingress 或 Gateway 提供外部 HTTP 入口;
  • ConfigMap 管理非敏感配置;
  • Secret 管理凭据;
  • PVC 保存需要持久化的数据;
  • NetworkPolicy 限制前后端通信;
  • ServiceAccount 和 Role 实施最小权限;
  • readiness、liveness、startup 探针描述健康状态;
  • HPA 根据资源或自定义指标扩缩容;
  • 监控和日志记录发布与故障;
  • Operator 管理一个有状态组件。

随后依次执行并记录结果:

  1. 删除一个 Pod,验证控制器是否重建;
  2. 修改镜像为错误版本,观察发布失败和回滚;
  3. 让 readinessProbe 失败,验证 Service 是否移除后端;
  4. 删除或限制 PVC,定位挂载失败路径;
  5. 移除 ServiceAccount 权限,观察 API 调用失败;
  6. 添加 NetworkPolicy,确认允许和拒绝的流量;
  7. 模拟节点不可用,观察 Pod 重新调度和持久卷行为;
  8. 执行备份与恢复,确认恢复后的应用数据和控制面对象;
  9. 修改自定义资源,验证 Operator 的协调、状态和错误重试;
  10. 删除自定义资源,验证 finalizer 是否正确清理外部资源。

完成这些练习后,Kubernetes 的知识就不再是资源类型清单,而会形成一条完整的因果链:

用户声明对象
  → API Server 验证并持久化
  → Watch 事件触发控制器和调度器
  → 节点侧创建 Pod sandbox 与容器
  → CNI 配置网络、CSI 挂载存储
  → kubelet 执行探针和生命周期管理
  → Service / EndpointSlice 提供访问路径
  → 观测系统记录状态和故障
  → 控制器持续修正偏差
  → Operator 将领域运维流程扩展为新的控制循环

这条链路也是判断 Kubernetes 行为的基本方法:先确定期望状态,再确认对象是否被 API Server 接受,然后沿控制面、节点、网络、存储和应用进程逐层验证,而不是只根据一个 kubectl get 结果下结论。

完整学习目录

一、架构与 API

  1. Kubernetes 架构:API Server、Scheduler、Controller Manager、etcd 和 Node
  2. Kubernetes API 对象:GVK、Metadata、Spec、Status、版本和兼容
  3. Kubernetes 声明式配置:YAML、默认值、字段所有权、Apply 和 Diff
  4. kubectl 完整工作流:Context、查询、Patch、Debug、输出和安全
  5. Kubernetes Label、Selector、Annotation 与 OwnerReference:对象关系设计
  6. Kubernetes Namespace:作用域、资源配额、权限、多租户和删除
  7. Kubernetes 调谐循环:Desired State、Watch、Queue、幂等和最终一致
  8. Kubernetes etcd 数据层:Revision、Watch、事务、Compaction 和备份
  9. Kubernetes 调度器:Queue、Filter、Score、Bind、插件和扩展
  10. Kubelet 与容器运行时:CRI、Pod Sync、PLEG、Probe 和资源状态
  11. Kubernetes CRI、CNI 与 CSI:运行时、网络、存储插件责任边界

二、工作负载

  1. Kubernetes Pod 完整模型:共享 Namespace、容器、Sandbox 和生命周期
  2. Pod 生命周期:Phase、Condition、RestartPolicy、终止和 Eviction
  3. Init、Sidecar 与 Ephemeral Container:启动顺序、共享和调试边界
  4. Deployment 与 ReplicaSet:滚动更新、Revision、暂停、回滚和失败
  5. StatefulSet:稳定身份、顺序、PVC、更新和分布式系统边界
  6. DaemonSet:节点级 Agent、调度、更新、容忍和资源治理
  7. Job 与 CronJob:并行、重试、补跑、时区、幂等和清理
  8. Kubernetes Probe:Startup、Readiness、Liveness、gRPC 和误配置风险
  9. Kubernetes Resource 与 QoS:Request、Limit、CPU Throttle、OOM 和 Eviction
  10. ConfigMap 与 Secret:注入、更新、不可变、轮换和安全边界
  11. Kubernetes 调度约束:NodeSelector、Affinity、Taint、Topology 和 Spread
  12. Kubernetes Priority 与 Preemption:优先级、抢占、公平和关键服务保护
  13. Pod 拓扑设计:Zone、Node、故障域、反亲和和数据局部性

三、网络与入口

  1. Kubernetes Service:ClusterIP、NodePort、LoadBalancer、EndpointSlice 和流量
  2. kube-proxy 与服务转发:iptables、IPVS、nftables、Session 和诊断
  3. Kubernetes DNS:CoreDNS、Service Discovery、Search、缓存和故障
  4. Ingress 与 Gateway API:路由、TLS、Controller、策略和迁移
  5. Kubernetes CNI 网络:Pod IP、路由、Overlay、Underlay 和插件选型
  6. Kubernetes NetworkPolicy:Selector、Ingress、Egress、默认拒绝和验证
  7. Kubernetes 出站流量治理:Egress、NAT、代理、DNS、白名单和审计
  8. Kubernetes Service Mesh:Sidecar、mTLS、流量治理、遥测和边界
  9. Kubernetes 证书与 TLS:集群 PKI、cert-manager、轮换和故障
  10. Kubernetes 网络排障:DNS、Service、CNI、MTU、Conntrack 和抓包

四、存储与有状态服务

  1. Kubernetes PV 与 PVC:绑定、访问模式、回收策略和生命周期
  2. StorageClass 与动态供给:Provisioner、Binding、扩容和拓扑
  3. Kubernetes CSI:Controller、Node、Attach、Mount、快照和故障
  4. Kubernetes VolumeSnapshot:一致性、Class、恢复、克隆和备份边界
  5. Kubernetes 存储拓扑:Zone、Local PV、延迟绑定和故障恢复
  6. 数据库运行在 Kubernetes:Operator、存储、拓扑、备份和责任边界
  7. Kubernetes 备份与 Velero:资源、卷、Hook、恢复顺序和演练

五、安全与多租户

  1. Kubernetes 认证:证书、Token、OIDC、Webhook 和用户生命周期
  2. Kubernetes RBAC:Role、ClusterRole、Binding、聚合和最小权限
  3. Kubernetes ServiceAccount:Projected Token、Audience、轮换和 Workload Identity
  4. Kubernetes Pod Security:Standards、Admission、SecurityContext 和基线
  5. Kubernetes 运行时安全:非 root、Capabilities、Seccomp、AppArmor 和只读根
  6. Kubernetes Secret 治理:etcd 加密、KMS、External Secrets、轮换和泄漏
  7. Kubernetes Admission Control:内置插件、Webhook、策略、失败和可用性
  8. Kubernetes 供应链安全:镜像签名、SBOM、扫描、准入和来源验证
  9. Kubernetes 多租户:Namespace、RBAC、NetworkPolicy、Quota 和隔离极限
  10. Kubernetes 审计日志:Policy、Stage、Backend、性能和合规留存
  11. ResourceQuota 与 LimitRange:租户预算、默认值、对象数量和治理

六、交付与运维

  1. Helm 完整指南:Chart、Template、Values、Release、Hook 和回滚
  2. Kustomize 配置管理:Base、Overlay、Patch、Generator 和边界
  3. Kubernetes GitOps:期望状态、调谐、Secret、漂移、晋级和回滚
  4. Kubernetes 发布策略:Rolling、Canary、Blue-Green、流量和回滚
  5. PodDisruptionBudget 与可用性:自愿中断、Eviction、滚动和误区
  6. Kubernetes HPA 与 VPA:指标、算法、稳定窗口、冲突和容量
  7. Kubernetes 节点自动扩缩容:Pending Pod、Node Group、缩容和成本
  8. Kubernetes Node 生命周期:Condition、Lease、Taint、NotReady 和恢复
  9. Kubernetes 节点维护:Cordon、Drain、Eviction、DaemonSet 和恢复验证
  10. Kubernetes 集群升级:Version Skew、API 弃用、节点灰度和回滚
  11. Kubernetes API 弃用治理:发现、迁移、兼容测试和升级门禁
  12. Kubernetes etcd 备份恢复:Snapshot、证书、Revision 和灾难演练
  13. Kubernetes 指标与监控:Metrics Server、Prometheus、告警和 SLO
  14. Kubernetes 日志架构:stdout、Node Agent、Sidecar、采集和留存
  15. Kubernetes 分布式追踪:OpenTelemetry、Context、采样和基础设施关联
  16. Kubernetes 容量规划:Request、利用率、碎片、故障余量和压测
  17. Kubernetes 成本治理:资源归属、闲置、Spot、存储网络和优化边界
  18. Kubernetes 工作负载排障:Pending、CrashLoop、ImagePull、OOM 和 Probe
  19. Kubernetes 节点排障:Kubelet、Runtime、DiskPressure、PID 和网络
  20. Kubernetes 事件响应:止损、证据、审计、凭据轮换和恢复
  21. Kubernetes 灾难恢复:控制面、资源、数据、DNS、依赖和演练
  22. Kubernetes 生产就绪检查:架构、安全、容量、观测、发布和运行手册

七、扩展与 Operator

  1. Kubernetes CRD:Schema、版本、Defaulting、Validation、Conversion 和存储
  2. Kubernetes Controller 开发:client-go、Cache、Queue、Reconcile 和幂等
  3. Kubernetes Operator 模式:领域状态机、升级、备份、恢复和测试
  4. Kubernetes Admission Webhook 开发:Mutating、Validating、证书和高可用
  5. Kubernetes CRD Conversion Webhook:Hub、Spoke、兼容、存储和回滚
  6. Kubernetes Server-Side Apply:Field Manager、冲突、所有权和 Controller
  7. Kubernetes API Aggregation:Extension API Server、发现、认证和可用性
  8. Kubernetes 调度性能与扩展:Profile、Plugin、Queue、规模和测试

系列导航与关联阅读

官方资料

本文依据 Kubernetes、CNCF 与相关项目官方文档重新梳理;正文和生产清单由 WR BLOG 编写。