最佳实践与陷阱
Kubernetes 全手册常见陷阱汇总、最佳实践清单与生产检查清单。
1. 陷阱汇总
1.1 概念与设计陷阱
| 陷阱 | 说明 | 正确做法 |
|---|---|---|
| 🚨 Pod IP 不可依赖 | Pod 重建后 IP 会变化 | 始终通过 Service DNS 访问,不要硬编码 Pod IP |
| 🚨 单 Pod 放太多容器 | 违反单一职责,耦合度高 | 每个 Pod 只放 1 个主容器 + 必要的 Sidecar |
| 🚨 StatefulSet 适用所有有状态应用 | 复杂数据库集群用 SS 管理过于复杂 | 评估复杂度,考虑使用 Operator 或迁出 K8s |
| 🚨 ConfigMap 放密码 | ConfigMap 明文存储 | 密码/令牌/密钥放 Secret |
| 🚨 Secret 视为安全 | Secret 只是 Base64 编码,不是加密 | 结合 RBAC、静态加密、Vault 等多层防护 |
| 🚨 所有服务都用 NodePort | 多节点时管理混乱 | 内部服务用 ClusterIP,外部用 Ingress/LoadBalancer |
1.2 YAML 配置陷阱
| 陷阱 | 说明 | 正确做法 |
|---|---|---|
| 🚨 selector 与 template labels 不匹配 | Deployment/StatefulSet 创建失败 | spec.selector.matchLabels 必须包含于 spec.template.metadata.labels |
| 🚨 StatefulSet serviceName 不匹配 | 网络标识异常 | serviceName 必须与 Headless Service 的 name 一致 |
| 🚨 apiVersion 写错 | 资源无法创建 | 对照:Deployment→apps/v1,Pod→v1,Ingress→networking.k8s.io/v1 |
| 🚨 缩进使用 Tab | YAML 解析失败 | 始终用空格缩进(2 个空格),编辑器开启显示空白字符 |
| 🚨 ConfigMap 超 1 MiB | 创建失败 | 大配置文件使用独立存储卷或文件存储服务 |
1.3 存储陷阱
| 陷阱 | 说明 | 正确做法 |
|---|---|---|
| 🚨 hostPath 用于多节点集群 | Pod 重新调度后数据丢失 | 多节点用 local 卷或网络存储 |
| 🚨 local 卷不支持动态创建 | PVC Pending | 需手动创建 PV 并配置 nodeAffinity |
| 🚨 PVC 容量匹配误区 | 多个小 PV 无法满足大 PVC | 单 PV 容量 ≥ PVC 请求 |
| 🚨 StatefulSet PVC 不自动删除 | 删除 SS 后 PVC 残留 | 手动清理:kubectl delete pvc -l app=mysql |
| 🚨 PV 回收策略选择不当 | Delete 策略会导致数据随 PVC 丢失 | 重要数据使用 Retain 策略 |
1.4 容器与镜像陷阱
| 陷阱 | 说明 | 正确做法 |
|---|---|---|
| 🚨 K3s 系统 ctr 与 k3s ctr 混淆 | 镜像导入到错误的 containerd | 始终使用 sudo k3s ctr 和 sudo k3s crictl |
| 🚨 ctr 导入不指定平台 | 架构不匹配导致容器无法启动 | 加 --platform linux/amd64 |
| 🚨 crictl 不能导入导出镜像 | 直接使用会失败 | 导入导出用 k3s ctr images import/export |
| 🚨 镜像拉取策略为 Always 且无网络 | 内网环境启动失败 | 设置 imagePullPolicy: IfNotPresent |
1.5 发布与管理陷阱
| 陷阱 | 说明 | 正确做法 |
|---|---|---|
| 🚨 金丝雀发布无法按请求内容分流 | Service 只在 TCP 层负载均衡 | 需要精细控制时使用 Istio/Argo Rollouts |
| 🚨 同一用户多次请求路由到不同版本 | Service 负载均衡无粘性 | 使用 Session Affinity 或 Service Mesh |
| 🚨 Init Container 无限循环 | until 无超时,永远不失败 |
设置重试上限,超时后 exit 1 让 Pod 重启 |
| 🚨 回滚后不清理旧版本 | 遗留无用 Deployment 占用资源 | 确认回滚成功后清理旧资源 |
2. 最佳实践清单
2.1 资源设计
- 每个 Pod 运行单个主容器 + 必要的 Sidecar
- 所有 Pod 设置
resources.requests和resources.limits - 为 Deployment 配置
livenessProbe和readinessProbe - 使用
minReadySeconds防止就绪检查假阳性 - 有状态应用考虑使用 Operator 而非手工 StatefulSet
2.2 配置管理
- 非敏感配置使用 ConfigMap,敏感数据使用 Secret
- ConfigMap/Secret 通过卷挂载而非环境变量(支持热更新)
- 使用
stringData创建 Secret(避免手动 Base64 编码错误) - 配置修改后使用
kubectl rollout restart deploy/<name>重启
2.3 网络与服务
- 内部服务使用 ClusterIP,外部 HTTP 服务使用 Ingress
- 使用 Headless Service 搭配 StatefulSet
- 为所有资源添加有意义的 Label(遵循
app.kubernetes.io/*约定) - 敏感服务配置 NetworkPolicy 限制访问
2.4 存储
- 生产环境使用网络存储或云存储,避免 hostPath/local
- 重要数据的 PV 使用 Retain 回收策略
- 定期备份持久卷中的数据
2.5 部署与运维
- 优先使用 Helm 部署第三方复杂应用
-
helm install前先--dry-run检查 - 每次发布使用
kubectl annotate记录变更原因 - 发布后监控
kubectl rollout status - 多环境使用不同 values.yaml 管理
2.6 K3s 特有
- 操作容器运行时时使用
sudo k3s crictl而非sudo crictl - 导入镜像使用
sudo k3s ctr -n k8s.io images import - 私有仓库配置
registries.yaml后重启 K3s
3. 生产检查清单
3.1 安全
- 禁用默认 ServiceAccount 的自动挂载(
automountServiceAccountToken: false) - 配置 RBAC 最小权限
- Secret 启用 etcd 静态加密
- 镜像不使用
latest标签 - Pod 设置
securityContext(非 root 运行、只读根文件系统) - 配置 PodSecurityPolicy 或 PodSecurityStandards
- 限制 API Server 的匿名访问
3.2 高可用
- 关键应用设置
replicas ≥ 2 - 配置
podAntiAffinity避免单个节点故障影响所有副本 - 配置
PodDisruptionBudget防止自愿中断导致全部 Pod 不可用 - 配置 HPA 自动弹性扩缩
- etcd 多节点部署(生产环境)
- 定期 etcd 备份
3.3 可观测性
- 部署 metrics-server 以支持
kubectl top和 HPA - 配置容器日志收集(如 Filebeat/Fluentd → Elasticsearch)
- 部署 Prometheus + Grafana 监控集群和业务指标
- 配置告警规则(节点/Pod/存储/网络)
- 关键业务配置分布式追踪(如 Jaeger/Zipkin)
3.4 资源管理
- 所有容器设置
resources.requests和resources.limits - 命名空间设置 ResourceQuota
- 命名空间设置 LimitRange
- 监控节点资源使用趋势,规划扩容
- 清理未使用的资源(悬空镜像、未绑定的 PVC)
3.5 灾难恢复
- 制定备份策略:etcd 快照 + PVC 数据备份
- 验证备份恢复流程
- 记录各应用的回滚步骤
- 保留至少 3 个历史版本
- 基础架构文档化(集群拓扑、网络配置、存储架构)
4. 故障排查速查表
| 症状 | 可能原因 | 排查命令 |
|---|---|---|
| Pod Pending | 资源不足 / PVC 未绑定 / 节点选择器不匹配 | kubectl describe pod <name> |
| Pod CrashLoopBackOff | 启动命令错误 / 探针失败 / OOM | kubectl logs <pod> --previous |
| Pod ImagePullBackOff | 镜像不存在 / 仓库认证失败 / 网络不通 | kubectl describe pod <name> 查看 Events |
| Service 访问不通 | Selector 不匹配 / 端口错误 / Endpoint 为空 | kubectl get ep <svc> |
| PVC Pending | 无匹配 PV / StorageClass 不存在 | kubectl describe pvc <name> |
| 节点 NotReady | kubelet 异常 / 磁盘压力 / 内存压力 | kubectl describe node <name> |
| Ingress 不生效 | Ingress Controller 未部署 / 规则错误 | kubectl get ingress -A |
| DNS 解析失败 | CoreDNS 异常 / 网络策略阻隔 | kubectl get pod -n kube-system -l k8s-app=kube-dns |