专栏: 云原生 & DevOps
难度: 进阶
标签: Kubernetes 生产环境 checklist 踩坑 最佳实践


前言

K8s 在测试环境跑得好好的,一到生产就出问题。本文总结了真实血泪经验中的18个坑,每一条都是真实事故凝练的经验。


坑1:没配资源 limits,被一个Pod打挂整个节点

resources:
  requests:
    cpu: "250m"
    memory: "256Mi"
  limits:
    cpu: "1000m"
    memory: "512Mi"

教训: requests 用于调度,limits 用于限制。不配 limits,一个内存泄漏的 Pod 会把节点内存耗尽,导致 OOMKill 雪崩。


坑2:镜像标签用 latest,滚动更新失效

# 错误
image: myapp:latest

# 正确
image: myapp:1.2.3-abc1234  # 包含git commit hash

教训: latest 不是版本,imagePullPolicy: Always 会导致每次都拉镜像,降低启动速度。


坑3:没配健康检查,流量打到未就绪的Pod

readinessProbe:
  httpGet:
    path: /health/ready
    port: 8080
  initialDelaySeconds: 10
  periodSeconds: 5
  failureThreshold: 3

livenessProbe:
  httpGet:
    path: /health/live
    port: 8080
  initialDelaySeconds: 30
  periodSeconds: 10
  failureThreshold: 3

教训: readinessProbe 控制是否接收流量,livenessProbe 控制是否重启容器,两者缺一不可。


坑4:PodDisruptionBudget 没配,滚动更新导致服务中断

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: myapp-pdb
spec:
  minAvailable: 2   # 滚动时保持至少2个可用
  selector:
    matchLabels:
      app: myapp

坑5:没配 HPA,突发流量直接挂

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: myapp-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: myapp
  minReplicas: 2
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70

坑6:ConfigMap 热更新不生效

默认情况下 Pod 不会感知 ConfigMap 的变更。解决方案:

  1. 使用 Reloader(推荐):https://github.com/stakater/Reloader
  2. 将配置版本写入 Deployment annotation,触发滚动更新
# 方案2:在annotation中记录configmap版本
spec:
  template:
    metadata:
      annotations:
        configmap-version: "v3"   # 改这里触发滚动更新

坑7:Service 类型用 NodePort 暴露生产服务

生产环境应使用 LoadBalancer 或 Ingress,NodePort 端口范围有限且难以管理。


坑8:没配 Pod 反亲和性,所有副本跑在同一节点

affinity:
  podAntiAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
    - labelSelector:
        matchLabels:
          app: myapp
      topologyKey: "kubernetes.io/hostname"

坑9:Secret 明文写在 YAML 里推送到 Git

使用 Sealed Secrets 或 Vault:

# 安装 Sealed Secrets
helm repo add sealed-secrets https://bitnami-labs.github.io/sealed-secrets
helm install sealed-secrets sealed-secrets/sealed-secrets -n kube-system

# 加密Secret
kubeseal -o yaml < secret.yaml > sealed-secret.yaml

坑10:命名空间没做资源配额,Dev环境把生产资源耗尽

apiVersion: v1
kind: ResourceQuota
metadata:
  name: dev-quota
  namespace: development
spec:
  hard:
    requests.cpu: "4"
    requests.memory: 8Gi
    limits.cpu: "8"
    limits.memory: 16Gi
    count/pods: "20"

坑11:没配terminationGracePeriodSeconds,应用被强杀

spec:
  terminationGracePeriodSeconds: 60  # 给应用60秒优雅退出时间
  containers:
  - name: myapp
    lifecycle:
      preStop:
        exec:
          command: ["/bin/sh", "-c", "sleep 5"]  # 等待LB摘除此Pod

坑12 - 坑18(核心原则速览)

坑号问题解决方案
12etcd 没备份配置 etcd 自动备份到 S3/OSS
13节点磁盘打满,Pod 被驱逐配置 evictionHard 阈值,及时清理镜像
14日志直接写容器内,重启丢失使用 DaemonSet 收集日志(Filebeat/Fluentd)
15RBAC 给了 cluster-admin,权限过大遵循最小权限原则
16镜像拉取无重试,冷启动失败配置 imagePullPolicy: IfNotPresent
17单 Master 高可用差生产至少3个 Master 节点
18升级 K8s 版本前未测试在独立集群先验证,看 Changelog

结语: 这18个坑没有一个是"偶然"发生的,都有据可查。把这个 checklist 贴在你们团队的部署规范里,可以避免80%的生产事故。

更多推荐