Kubernetes 基础体系 · 第 75/83 篇。示例基于 Kubernetes 当前稳定 API;弃用、版本偏差、云厂商差异和生产风险会明确说明。
Kubernetes 生产就绪检查:架构、安全、容量、观测、发布和运行手册
生产就绪不是“Pod 能启动”的同义词,而是系统在正常负载、依赖异常、节点故障、版本升级和人员误操作下,仍具备可验证的服务目标、可控的故障半径和可恢复的运行路径。
可以把一个工作负载是否生产就绪表示为:
其中:
- :Architecture,架构能够承受预期故障;
- :Security,身份、权限、网络和供应链边界明确;
- :Capacity,容量、碎片和故障余量满足目标;
- :Observability,能够发现、定位并量化故障;
- :Release,发布、回滚和数据库变更可控;
- :Procedures,值班人员拥有经过验证的运行手册。
其中任一项缺失,系统都可能在演练或真实事故中表现为“看起来正常,但无法安全运行”。
本文示例使用当前稳定 Kubernetes API,例如 apps/v1、batch/v1、autoscaling/v2、policy/v1、networking.k8s.io/v1。具体 Kubernetes 版本、发行版和云厂商可能改变默认行为;生产环境应先执行 kubectl api-resources、kubectl explain 和发行版兼容性检查,不能仅凭博客中的旧 API 版本判断可用性。
一、先定义生产就绪的边界
“高可用”至少有三个不同层次:
- 组件高可用:控制面、节点和关键依赖存在冗余。
- 服务高可用:业务 Pod 分布在不同故障域,单个实例或节点故障不会让服务失去全部端点。
- 恢复能力:发生数据损坏、区域故障或错误发布后,能够在目标时间内恢复到可接受状态。
这三者不能互相替代。例如,三个控制平面节点可以避免单个控制面节点故障,但不会自动保证数据库数据安全;三个副本的 Deployment 如果全部位于同一个节点,也不能抵御节点故障。
生产检查应先把目标写成可验证的条件:
- 可用性目标:例如月度可用性不低于某个 SLO;
- 恢复时间目标(RTO):故障发生后多久恢复服务;
- 恢复点目标(RPO):最多允许丢失多长时间的数据;
- 最大允许发布影响:例如滚动发布期间可用副本不得低于某个数量;
- 最大故障域:例如单节点、单可用区或单机房故障是否必须继续提供服务。
没有这些条件时,“生产就绪”只能变成主观印象。
二、架构检查:控制面、数据面和故障域
2.1 请求经过哪些组件
一个典型的 Kubernetes 请求路径如下:
flowchart LR
U[用户或发布系统] --> API[kube-apiserver]
API --> AUTH[认证]
AUTH --> AUTHZ[授权]
AUTHZ --> ADM[准入控制]
ADM --> ETCD[(etcd)]
API --> SCH[kube-scheduler]
API --> CM[kube-controller-manager]
SCH --> APIS[API Server]
CM --> APIS
APIS --> K1[kubelet]
K1 --> CRI[容器运行时]
CRI --> CNI[CNI 网络]
CNI --> P[Pod]
P --> S[Service/Ingress]
S --> CL[客户端]
关键状态变化是:
- 用户向 API Server 提交 Deployment。
- API Server 完成认证、授权、准入检查,并将期望状态持久化到
etcd。 - Deployment Controller 创建或更新 ReplicaSet。
- ReplicaSet Controller 创建 Pod 对象。
- Scheduler 为未绑定节点的 Pod 选择节点,并写入绑定结果。
- 目标节点的 kubelet 观察到 Pod,调用容器运行时创建容器。
- CNI 配置网络,容器启动并执行探针。
- Service EndpointSlice 根据 Pod 的就绪状态更新后端端点。
- 流量组件根据 Service、Ingress 或 Gateway 配置把请求转发到可用后端。
因此,“Deployment 已创建”只说明期望状态被接受;“Pod 已运行”只说明容器进程存在;只有就绪探针成功后,Pod 才通常会成为 Service 的流量端点。
2.2 控制面高可用的必要条件
etcd 是 Kubernetes 控制面状态的关键存储,使用 Raft 类共识机制维护成员间的一致日志。集群需要多数成员确认才能提交写入,因此法定人数(quorum)为:
其中 是 etcd 成员数。允许同时失效的成员数为:
因此:
- 1 个成员:没有容错能力;
- 3 个成员:可容忍 1 个成员失效;
- 5 个成员:可容忍 2 个成员失效。
3 个成员并不比 2 个成员“少一个副本”,而是因为 2 个成员失效 1 个后无法形成多数;3 个成员失效 1 个后仍有 2 个成员,可以继续提交写入。
但 etcd 成员不能只在逻辑上有多个,还应分布到独立故障域。把三个成员放在同一台物理机上的三个容器,并不能抵抗该主机故障。跨可用区部署还要权衡网络延迟、分区风险和云厂商控制面实现。
控制面检查至少应验证:
kubectl get nodes -o wide
kubectl get --raw='/readyz?verbose'
kubectl get componentstatuses
/readyz?verbose 可以帮助检查 API Server 的就绪子检查;componentstatuses 在新版本中不应作为完整健康判断依据,因为它是历史接口且不能代表整个控制面状态。生产环境还应从控制面主机或管理网络直接检查 etcd 成员健康、磁盘延迟、数据库大小和备份恢复结果。具体命令取决于自建集群还是云托管集群。
失败路径:如果 etcd 无法形成 quorum,API Server 可能无法持久化新的资源变更;已有节点上的容器未必立即停止,但扩缩容、调度、发布和大多数控制操作会逐渐失效。此时反复执行 kubectl apply 通常不会修复问题,应该保留控制面日志和 etcd 证据,按控制面恢复手册处理。
2.3 数据面和故障域
工作负载至少要明确以下故障域:
- 节点;
- 机架或宿主机;
- 可用区;
- 区域;
- 集群;
- 外部依赖所在的故障域。
topology.kubernetes.io/zone 等拓扑标签常用于调度约束,但标签的真实性依赖云厂商或集群管理员。不要仅因为对象上存在标签,就假设两个值一定代表独立电源或网络故障域。
一个跨可用区的 Deployment 示例:
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
namespace: production
spec:
replicas: 6
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: api
containers:
- name: api
image: registry.example.com/api@sha256:REPLACE_WITH_DIGEST
ports:
- containerPort: 8080
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "1"
memory: "1Gi"
readinessProbe:
httpGet:
path: /ready
port: 8080
periodSeconds: 5
failureThreshold: 2
livenessProbe:
httpGet:
path: /live
port: 8080
periodSeconds: 10
failureThreshold: 3
这里 DoNotSchedule 的含义是:如果不能满足跨区域均衡,Pod 不应被调度,而不是把它挤到已有区域。它可能提高故障时的可用性,也可能导致容量不足时 Pod 长期 Pending。因此必须结合区域容量和故障演练,而不是盲目复制配置。
PodDisruptionBudget 只约束自愿中断,如节点排空或集群维护;它不能阻止节点突然断电、内核崩溃或云区域故障,也不能替代副本数:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: api
namespace: production
spec:
minAvailable: 4
selector:
matchLabels:
app: api
对于 6 个副本,minAvailable: 4 表示受 PDB 约束的自愿中断最多同时减少 2 个可用 Pod。若使用 maxUnavailable,其计算同样受副本数和控制器行为影响。错误设置为 minAvailable: 100% 可能阻塞节点维护;设置过低则无法达到维护期间的服务目标。
三、安全检查:从“谁能访问”到“能运行什么”
Kubernetes 安全不是单一开关,而是请求、工作负载、网络、镜像、密钥和节点多个边界叠加的结果。
3.1 认证、授权和准入
请求处理顺序通常可以抽象为:
- 认证(Authentication):请求者是谁;
- 授权(Authorization):该身份能否执行该动作;
- 准入控制(Admission):即使有权限,资源是否符合集群策略;
- 持久化和执行:对象写入状态存储,并由控制器和节点执行。
RBAC 权限应遵循最小权限。下面的 Role 只允许应用读取同一命名空间中的 ConfigMap:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: api-config-reader
namespace: production
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["api-config"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: api-config-reader
namespace: production
subjects:
- kind: ServiceAccount
name: api
namespace: production
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: api-config-reader
resourceNames 能进一步限制对象名称,但不能解决所有动态资源场景。生产检查应特别关注:
kubectl auth can-i \
--as=system:serviceaccount:production:api \
get configmaps/api-config -n production
kubectl auth can-i \
--as=system:serviceaccount:production:api \
list secrets -n production
第二条命令的预期结果应通常是 no。不要把 cluster-admin 绑定给应用 ServiceAccount,也不要误以为“只读权限”天然安全:读取 Secret、Pod 环境变量或某些自定义资源可能暴露凭据。
准入控制可以阻止不符合策略的对象,例如禁止特权容器、强制镜像来源、要求资源请求和限制。Pod Security Admission 是 Kubernetes 内置能力,通常通过命名空间标签选择 privileged、baseline 或 restricted 等级。启用前应先用 warn 或 audit 观察现有工作负载,否则可能在发布时突然拒绝大量合法但不合规的 Pod。具体能力和例外以目标 Kubernetes 版本文档为准。
3.2 Pod 安全边界的实际含义
以下字段常常决定容器是否能够突破预期边界:
spec:
automountServiceAccountToken: false
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containers:
- name: api
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
readOnlyRootFilesystem: true
这些配置的含义分别是:
automountServiceAccountToken: false:应用不需要访问 Kubernetes API 时,不自动挂载令牌;runAsNonRoot:拒绝以 root 用户运行,但镜像本身必须能以非 root 用户工作;RuntimeDefault:使用运行时默认 seccomp 配置;allowPrivilegeEscalation: false:限制通过 setuid 等机制提升权限;- 丢弃 Linux capabilities:减少进程可用的内核权限;
- 只读根文件系统:应用必须把临时文件写到显式挂载的可写卷。
边界:Pod 安全上下文不是虚拟机隔离。内核漏洞、特权容器、主机路径挂载、设备映射和不安全的运行时配置都可能扩大影响范围。需要配合节点加固、补丁、运行时检测和网络隔离。
3.3 网络策略不是默认防火墙
NetworkPolicy 只有在网络插件支持并正确实现时才生效。它通常是命名空间和 Pod 级别的允许规则;没有策略的命名空间在许多插件中默认保持开放。
一个默认拒绝入口和出口的策略:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
应用随后需要显式允许 DNS、入口网关和数据库等依赖。例如,只允许同命名空间中带有 role: gateway 的 Pod 访问 API 的 8080 端口:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-ingress
namespace: production
spec:
podSelector:
matchLabels:
app: api
policyTypes: ["Ingress"]
ingress:
- from:
- podSelector:
matchLabels:
role: gateway
ports:
- protocol: TCP
port: 8080
常见失败表现是:Pod 本身健康,但无法解析 DNS、访问数据库或接收网关流量。诊断必须从 Pod 内部同时检查 DNS、路由、端口和策略,而不能只看 kubectl get pod。
3.4 镜像和 Secret
镜像应尽量使用不可变摘要:
image: registry.example.com/api@sha256:...
标签如 latest 或可变的 v1.2.3 不能证明每次部署使用相同字节。供应链检查还应覆盖:
- 镜像构建来源和构建权限;
- 漏洞扫描及其豁免记录;
- 签名验证;
- 基础镜像更新;
- Registry 凭据轮换;
- 运行时禁止从非批准仓库拉取镜像。
Kubernetes Secret 默认是 Base64 编码,不等于加密。生产环境应确认 API Server 到 etcd 的静态加密配置、访问 RBAC、备份保护和外部密钥系统的轮换流程。任何已经出现在日志、命令行、事件或 Git 仓库中的凭据,都应按“已泄露”处理,而不是只删除对象。
四、容量规划:Request、利用率、碎片和故障余量
4.1 Request、Limit 和实际利用率
- Request 是调度器为 Pod 选择节点时使用的资源需求,也是 CPU、内存等资源超卖和 QoS 判断的重要输入。
- Limit 是容器运行时或内核侧的使用上限。CPU limit 通常表现为节流,内存 limit 超过后可能触发 OOMKill。
- 利用率 是运行时实际消耗,不能替代 request。
调度器通常先检查:
其中 allocatable 是节点可分配给 Pod 的资源,不是物理机总资源。系统守护进程、kubelet、容器运行时和操作系统会消耗一部分资源。
查看节点容量:
kubectl describe node NODE_NAME
kubectl get node NODE_NAME -o jsonpath='{.status.allocatable}{"\n"}'
kubectl top nodes
kubectl top pods -A --containers
kubectl top 依赖 Metrics Server,反映的是采集窗口内的使用量,不是历史峰值,也不能单独用于容量决策。
4.2 计算可用容量和故障余量
假设有 3 个可用区,每区 4 个节点,每个节点的可分配内存为 28 GiB。计划在任一区域故障后仍能承载全部工作负载,并保留 20% 运营余量。
总可分配内存:
单区域故障后剩余:
扣除 20% 余量后的安全容量:
如果所有业务 Pod 的内存 request 总和为 165 GiB,那么在该假设下还剩:
但这只是总量判断。若 Pod 因 topologySpreadConstraints、节点 taint、GPU、架构或本地盘要求不能自由移动,14.2 GiB 可能无法组成足够大的可调度空间。
4.3 碎片导致“总量足够但 Pod Pending”
假设三个节点各有 4 GiB 可分配内存,当前空闲分别为 1 GiB、1 GiB、2 GiB。集群总空闲为 4 GiB,但一个新 Pod 需要 3 GiB request:
- 总空闲: GiB;
- 最大连续可用节点空间: GiB;
- 因此 Pod 仍无法调度。
这就是碎片。诊断时不能只看总利用率,应检查:
kubectl get pod -A --field-selector=status.phase=Pending
kubectl describe pod PENDING_POD -n NAMESPACE
kubectl describe nodes
describe pod 的 Events 通常会说明是 Insufficient memory、节点选择器不匹配、污点未容忍,还是拓扑约束无法满足。扩容节点数量可能无效,真正需要的是更大节点、重新平衡工作负载、调整 request,或减少过度严格的拓扑约束。
4.4 QoS 和 OOM 的误判
Pod QoS 类别由资源配置决定:
Guaranteed:符合条件的容器 CPU 和内存 request、limit 都设置且相等;Burstable:至少有一个 request 或 limit,但不满足 Guaranteed;BestEffort:没有 CPU 和内存 request、limit。
这不是“Guaranteed 永不 OOM”。节点内存压力下,内核仍可能杀死进程;容器超过自身内存 limit 时也可能被 OOMKill。QoS 主要影响驱逐优先级和资源管理行为,不能替代合理的内存上限、缓存控制和负载测试。
对于内存,通常需要把 request 设为稳定工作集加上合理波动,把 limit 设为可接受的峰值,而不是任意设置成极大值。limit 过小会导致频繁 OOM,过大则可能掩盖内存泄漏并增加节点级故障半径。
容量模型还应包含:
- DaemonSet、系统 Pod 和监控代理;
- HPA 扩容后的最大副本数;
- 发布期间
maxSurge产生的临时副本; - 节点排空和故障迁移所需空间;
- 本地临时存储和 inode;
- API Server、etcd、云厂商配额;
- 数据库连接数、消息分区、负载均衡后端数等非 CPU/内存瓶颈。
4.5 压测必须验证故障余量
一次合格的压测至少要记录:
- 目标流量、请求分布和数据规模;
- CPU、内存、网络、磁盘和连接池;
- p50、p95、p99 延迟及错误率;
- HPA 扩容延迟和副本上限;
- 节点故障、Pod 驱逐、依赖降级后的结果;
- 恢复后的积压处理速度。
例如,若队列消费速度为 ,生产速度为 ,积压量为 ,且 ,理论清空时间为:
如果扩容后消费速度只从 100 提升到 120 条/秒,而生产速度为 110 条/秒,积压不会快速恢复,因为净清空速度只有 10 条/秒。这个计算比“CPU 还有 40% 空闲”更接近业务恢复能力。
五、观测检查:必须能回答“发生了什么、影响谁、为什么”
观测性(Observability)不是监控面板数量,而是根据外部输出推断系统内部状态的能力。生产环境至少要形成四类证据:
- Metrics:时间序列数值,如请求量、错误率、延迟、资源使用;
- Logs:离散事件和上下文;
- Traces:跨服务请求的调用链;
- Events:Kubernetes 对象状态变化的原因线索。
5.1 从 SLI 到告警
SLI 是实际测量指标,例如:
若一个月总请求 10 亿次,允许错误预算为 0.1%,则预算为:
告警不应只针对 Pod 重启次数,而应连接用户影响。例如:
- 入口 5 分钟错误率超过阈值;
- p99 延迟持续超过 SLO;
- 可用端点数低于服务副本目标;
- HPA 已达到最大副本且延迟继续上升;
- Pending Pod 持续存在;
- 节点 NotReady 或磁盘压力;
- etcd 写入延迟、数据库连接耗尽或消息积压。
单纯使用 CPU 告警会漏掉数据库连接耗尽、证书过期和应用线程池饱和;单纯使用 Pod 状态又可能在用户已经失败时仍显示“Running”。
5.2 探针的生命周期和错误边界
- startupProbe:应用启动阶段通过前,liveness 和 readiness 可以被延后;适合慢启动应用。
- readinessProbe:决定是否接收流量,不代表进程一定健康。
- livenessProbe:失败后 kubelet 可能重启容器,适合检测进程无法自行恢复的状态。
错误示例是把数据库连通性直接写进 liveness。数据库短暂故障时,所有 Pod 同时被重启,形成重启风暴,反而延长恢复时间。数据库依赖更适合影响 readiness 或由应用实现降级,除非进程确实已经无法继续工作。
探针失败的诊断顺序:
kubectl describe pod POD -n NAMESPACE
kubectl logs POD -n NAMESPACE --all-containers --previous
kubectl get endpointslice -n NAMESPACE -l kubernetes.io/service-name=api -o yaml
应区分:
- 探针请求根本到不了容器;
- 应用端口未监听;
- 应用返回非 2xx;
- 就绪被主动置为 false;
- Service 没有端点;
- Ingress 或网关配置错误。
5.3 事件不是审计日志
kubectl get events -A --sort-by=.lastTimestamp
Events 适合解释近期调度、拉镜像、挂载卷、探针和驱逐原因,但会被聚合、过期或丢失,不能作为长期审计证据。需要回答“谁在什么时候修改了 Deployment”时,应使用 API Server 审计日志、Git 记录、发布系统记录和云平台操作日志。
日志必须包含请求 ID、用户或租户标识、版本、错误类别和依赖调用结果;但不能记录访问令牌、密码和完整个人敏感数据。Tracing 的采样策略也要避免在高错误率时丢失关键失败样本。
六、发布检查:期望状态如何安全变成运行状态
6.1 Deployment 滚动更新的中间状态
Deployment 发布新镜像时,控制器通常创建新的 ReplicaSet,并逐步增加新 ReplicaSet、减少旧 ReplicaSet。maxSurge 控制期望副本数之外允许多出的 Pod,maxUnavailable 控制更新期间最多不可用的副本数。
若副本数为 10,配置:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 2
maxUnavailable: 1
则更新期间最多可有 12 个 Pod,按控制器的可用性判定,最多允许 1 个副本不可用。实际过程还受启动时间、readiness、调度容量、PDB 和终止宽限期影响,不是一次性替换。
查看发布状态:
kubectl rollout status deployment/api -n production --timeout=10m
kubectl rollout history deployment/api -n production
kubectl get rs,pod -n production -l app=api -o wide
成功标准不是“新 Pod 为 Running”,而是:
- 新 Pod 通过 readiness;
- Service 端点包含预期的新实例;
- 错误率和延迟没有违反 SLO;
- 旧版本副本按预期减少;
- 没有持续的重启、拉镜像和探针失败事件。
回滚:
kubectl rollout undo deployment/api -n production
kubectl rollout status deployment/api -n production --timeout=10m
回滚 Deployment 只回退工作负载模板,不会自动回滚数据库 schema、外部配置、消息格式或已经执行的数据迁移。因此数据库变更必须设计为向前兼容,常用顺序是:
- 先发布能同时读旧、新 schema 的代码;
- 执行兼容的 schema 扩展;
- 切换写入路径;
- 验证所有旧 Pod 已退出;
- 最后再删除旧字段或旧格式。
直接发布“代码和破坏性 schema 删除”会使回滚失去意义。
6.2 Pod 终止不是立即杀进程
删除 Pod 时,通常先设置终止时间,kubelet 执行 preStop(如果存在),向容器发送 SIGTERM,等待 terminationGracePeriodSeconds,超时后发送 SIGKILL。与此同时,端点应从流量路径中移除,但网络传播存在延迟。
应用必须处理:
- SIGTERM;
- 停止接收新请求;
- 等待已有请求完成;
- 关闭连接池和消费者;
- 避免
preStop无限等待; terminationGracePeriodSeconds足以覆盖最长正常请求。
如果应用不处理 SIGTERM,滚动发布可能表现为大量 5xx;如果优雅退出时间过长,发布则会积压 Terminating Pod,并消耗额外容量。
6.3 金丝雀和发布闸门
金丝雀的核心不是“先部署一个副本”,而是把一小部分流量或实例暴露给新版本,并比较:
- 错误率;
- 延迟分位数;
- 业务转化或任务成功率;
- 资源使用;
- 依赖调用失败;
- 日志异常类型。
Service 按标签选择 Pod,若要进行精确流量比例控制,通常需要网关、服务网格或云厂商流量管理能力;仅靠两个 Service 的副本数并不能保证精确的请求比例,因为连接复用、客户端缓存和负载均衡算法都会影响实际分布。
七、运行手册:按证据、止损、恢复组织操作
运行手册(runbook)不是命令集合,而是针对一个已知故障模式定义:
- 触发条件;
- 影响判断;
- 证据采集;
- 止损动作;
- 修复动作;
- 验证条件;
- 回滚路径;
- 事后审计和改进。
7.1 Pod 大量 Pending
先区分调度问题和运行时问题:
kubectl get pods -n production
kubectl describe pod POD -n production
kubectl get nodes
kubectl describe nodes
如果 Events 显示 Insufficient cpu 或 Insufficient memory,检查 request 总量、节点 allocatable、碎片和扩容配额。如果显示 taint、affinity 或 topology 约束不匹配,不能简单增加节点,还要确认新节点是否具有所需标签和容忍条件。
止损动作可能是暂时降低非关键工作负载、暂停发布或扩容节点;不应直接删除大量 Pod,因为这会进一步减少可用容量。验证条件是 Pod 进入 Running 且 readiness 成功,并确认业务 SLO 恢复。
7.2 Pod 反复重启
kubectl get pod POD -n production -o wide
kubectl describe pod POD -n production
kubectl logs POD -n production --previous
kubectl get pod POD -n production \
-o jsonpath='{.status.containerStatuses[*].lastState.terminated.reason}{"\n"}'
常见原因和证据不同:
OOMKilled:检查容器内存 limit、工作集、节点内存压力和最近流量;CrashLoopBackOff:查看--previous日志、退出码和启动参数;- 探针失败:查看探针路径、端口、启动时间和依赖初始化;
- 镜像拉取失败:检查 Registry、凭据、节点网络和镜像摘要;
- 配置错误:比较 Deployment 模板、ConfigMap/Secret 版本和发布记录。
临时增加 liveness 的失败阈值可能减少误杀,但不能修复真正的内存泄漏或启动错误。任何参数调整都应保留变更记录和恢复值。
7.3 证书或凭据疑似泄露
正确顺序通常是:
- 确认泄露范围和使用位置;
- 立即撤销或轮换凭据;
- 更新 Secret 或外部密钥系统;
- 重启或触发工作负载重新读取凭据;
- 检查审计日志和依赖侧访问记录;
- 保留证据并完成事后审计。
仅执行:
kubectl delete secret leaked-secret -n production
通常不够,因为已经运行的进程可能仍持有旧凭据,etcd 备份、日志或 Git 历史中也可能留有副本。轮换后要验证旧凭据确实失效,并确认新凭据已被所有消费者加载。
7.4 控制面或区域故障
控制面不可用时,不要把“无法执行 kubectl”误认为“所有业务已经停止”。已有 Pod 可能继续服务,但故障期间可能无法扩缩容、重调度和发布。
区域或集群级恢复还需要考虑:
- 控制面和 etcd 状态;
- Kubernetes 资源清单;
- PersistentVolume 中的数据;
- 对象存储、数据库和消息系统;
- DNS、证书、镜像仓库和身份系统;
- 外部负载均衡和防火墙;
- Secret、密钥和轮换状态。
灾难恢复必须通过定期演练证明。仅有 etcd 快照不等于完整恢复,因为业务数据可能位于外部数据库或卷中。恢复演练应测量实际 RTO/RPO,并验证恢复后的 DNS、凭据、网络策略和应用依赖,而不是只确认 API Server 能返回 200。
八、检查命令和证据保存
生产检查应产生可审计证据,而不是只在终端人工观察。可以在只读权限下执行:
kubectl version
kubectl api-resources
kubectl get nodes -o wide
kubectl get ns --show-labels
kubectl get deploy,sts,ds -A
kubectl get pods -A -o wide
kubectl get pvc -A
kubectl get events -A --sort-by=.lastTimestamp
kubectl get pdb -A
kubectl get networkpolicy -A
执行这些命令时应注意:
kubectl version的客户端和服务端版本偏差可能导致 API 或字段行为不同;get all并不包含所有资源,不能作为完整资产清单;- 输出可能包含敏感信息,保存前要脱敏;
kubectl describe适合诊断,但输出不是稳定的机器接口;- JSONPath、事件和指标采集应记录采集时间、集群标识和命令版本。
生产变更前还应检查:
kubectl diff -f manifests/
kubectl apply --server-side --dry-run=server -f manifests/
kubectl apply -f manifests/
--dry-run=server 会经过 API Server 的字段校验和准入链,但不会持久化对象;它不能证明镜像能拉取、Pod 能调度或应用能通过健康检查。kubectl diff 也不能替代压测和发布演练。
九、最终验收应是“条件通过”,不是“配置存在”
一个工作负载可以在以下条件同时满足时进入生产:
- 控制面和节点的故障域、quorum、升级和备份恢复路径已验证;
- 副本、拓扑约束、PDB 与区域故障模型一致;
- 每个容器有经过测量的 request,内存限制和 OOM 行为已验证;
- 高峰、发布、节点故障和依赖降级后仍有容量余量;
- RBAC、ServiceAccount、Pod 安全、网络策略和镜像来源可审计;
- readiness、liveness、startup 探针分别承担正确职责;
- 指标、日志、事件、追踪和审计能够关联到一次请求和一次变更;
- 发布有暂停、金丝雀、回滚和 schema 兼容策略;
- 值班人员能依据运行手册完成止损、证据采集、恢复和验证;
- 备份、凭据轮换和灾难恢复演练的结果被记录,而不是只存在于设计文档中。
生产就绪的核心不是把所有配置都“加上”,而是证明每项配置与故障目标之间存在因果关系:为什么需要这个副本数,为什么这个 request 足够,为什么探针不会制造重启风暴,为什么权限不会扩大到集群级,为什么回滚能够恢复,为什么值班人员能在没有原作者参与时完成操作。只有这些关系能够被测试和复现,Kubernetes 工作负载才真正具备生产运行条件。
系列导航与关联阅读
- 系列入口:Kubernetes 完整学习路线:从 Pod 与控制面到安全、运维和 Operator
- 上一篇:Kubernetes 灾难恢复:控制面、资源、数据、DNS、依赖和演练
- 下一篇:Kubernetes CRD:Schema、版本、Defaulting、Validation、Conversion 和存储
- 延伸:Kubernetes 容量规划:Request、利用率、碎片、故障余量和压测
- 延伸:Kubernetes 事件响应:止损、证据、审计、凭据轮换和恢复
官方资料
本文依据 Kubernetes、CNCF 与相关项目官方文档重新梳理;正文和生产清单由 WR BLOG 编写。

评论
0 条讨论