前言

概念篇过了理论,这次动手:把一个带健康检查、资源限额、优雅升级能力的生产级 Deployment 从零部署起来。环境用 kind(本地单机 K8s)。

# 5 分钟准备实验环境
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.23.0/kind-linux-amd64
install ./kind /usr/local/bin/kind
kind create cluster --name lab
kubectl cluster-info

一、完整的生产级清单

web.yaml——每一块都是实战标配:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-web
  labels:
    app: demo-web
spec:
  replicas: 3
  revisionHistoryLimit: 5            # 保留 5 个历史版本(回滚用)
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1                    # 滚动时最多多起 1 个
      maxUnavailable: 0              # 滚动时不允许少副本(零中断)
  selector:
    matchLabels:
      app: demo-web
  template:
    metadata:
      labels:
        app: demo-web
    spec:
      containers:
      - name: web
        image: registry.cn-hangzhou.aliyuncs.com/zy-repo/demo-web:v1.0.0
        ports:
        - containerPort: 8080
        env:
        - name: APP_ENV
          value: "production"
        resources:
          requests:                  # 调度依据( 保证值)
            cpu: 100m                # 100m = 0.1 核
            memory: 128Mi
          limits:                    # 硬顶(超内存会被 OOMKill)
            cpu: 500m
            memory: 256Mi
        startupProbe:                # 启动探针: 先等它通过, 再开始健康检查
          httpGet: {path: /healthz, port: 8080}
          failureThreshold: 30
          periodSeconds: 2
        livenessProbe:               # 存活探针: 失败重启容器
          httpGet: {path: /healthz, port: 8080}
          periodSeconds: 10
          failureThreshold: 3
        readinessProbe:              # 就绪探针: 失败摘除流量(不重启)
          httpGet: {path: /ready, port: 8080}
          periodSeconds: 5
        lifecycle:
          preStop:                   # 优雅退出: 先等流量排空
            exec: {command: ["sleep", "5"]}
      terminationGracePeriodSeconds: 30
---
apiVersion: v1
kind: Service
metadata:
  name: demo-web
spec:
  selector:
    app: demo-web
  ports:
  - port: 80
    targetPort: 8080
kubectl apply -f web.yaml
kubectl get pods -o wide
kubectl get deploy,svc

二、三个探针的分工(面试高频)

探针 失败后果 用来发现
livenessProbe 重启容器 死锁、进程假死
readinessProbe 摘除流量(不重启) 依赖未就绪、过载降级
startupProbe 推迟上面两个的计时 慢启动应用(JVM 老铁都懂)
流量路径: Service → 只发给 ready 的 Pod
自愈路径: liveness 挂 → kubelet 重启容器 → ready 才回流量

探针方式:httpGet(状态码 2xx/3xx 算过)/ exec(退出码 0 算过)/ tcpSocket(能连通算过)。

三、资源限额的学问

resources:
  requests: {cpu: 100m, memory: 128Mi}
  limits:   {cpu: 500m, memory: 256Mi}
  • requests:调度器按它找节点;节点超卖(所有 pod requests 之和 > 容量才拒绝)
  • limits:CPU 超限被节流(throttle,变慢不挂);内存超限被 OOMKill(exit code 137)
  • QoS 等级:requests == limits 时是 Guaranteed,资源紧张时最后被驱逐
# 观察实际用量
kubectl top pods
# 排查 OOMKill
kubectl describe pod xxx | grep -A2 "Last State"

四、发布与回滚

# 触发滚动更新(改镜像)
kubectl set image deploy/demo-web web=.../demo-web:v1.1.0

# 实时看滚动过程
kubectl rollout status deploy/demo-web
# Waiting for deployment "demo-web" rollout to finish: 2 of 3 updated...

# 零中断的秘密: maxUnavailable=0 + readinessProbe
#   新 Pod 没 ready 前, 老 Pod 一个都不删

# 查看历史与回滚
kubectl rollout history deploy/demo-web
kubectl rollout undo deploy/demo-web                    # 回上一个
kubectl rollout undo deploy/demo-web --to-revision=2    # 回指定版本

# 暂停/恢复(灰度改多字段时用)
kubectl rollout pause deploy/demo-web
kubectl set image ... ; kubectl set env ...
kubectl rollout resume deploy/demo-web

五、扩缩容

kubectl scale deploy/demo-web --replicas=5       # 手动

# HPA 自动扩缩容(按 CPU)
kubectl autoscale deploy/demo-web --min=3 --max=10 --cpu-percent=70
kubectl get hpa

压测验证:ab -n 100000 -c 200 http://$NODE_IP:$PORT/,看副本数随 CPU 爬升。

六、排障命令流(背下来)

# 1. Pod 卡在 Pending → 资源不够/节点选择器没匹配
kubectl describe pod xxx | tail -20        # 看 Events 段!

# 2. Pod 卡 ImagePullBackOff → 镜像名/仓库认证问题
kubectl describe pod xxx | grep -A5 Events

# 3. CrashLoopBackOff → 容器起来就崩
kubectl logs xxx --previous               # 上一次崩溃的日志!

# 4. Service 不通 → 端点列表空?
kubectl get endpoints demo-web            # NONE = selector/label 不匹配
kubectl exec -it xxx -- curl localhost:8080   # 容器内自测

# 5. OOM / 重启循环
kubectl get pod xxx -o jsonpath='{.status.containerStatuses[0].restartCount}'
kubectl describe pod xxx | grep -B2 -A5 "State"

# 6. 进入容器 & 看资源
kubectl exec -it xxx -- sh
kubectl top pod xxx

Events 永远是第一现场——90% 的部署问题,describe 最后那段 Events 直接给了答案。

七、常用字段速查

kubectl get all -n default             # 一屏看全
kubectl get pod -o wide                # 带节点/IP
kubectl get pod -w                     # watch 模式
kubectl explain deploy.spec.strategy   # 现场查字段文档(神器)
kubectl diff -f web.yaml               # apply 前看差异
kubectl delete -f web.yaml             # 删除
kubectl run debug --rm -it --image=busybox -- sh   # 临时调试 Pod

小结

需求 配置
不接坏流量 readinessProbe
假死自愈 livenessProbe
零中断发布 maxUnavailable=0 + 探针
回滚 rollout undo –to-revision
资源 requests 调度 / limits 封顶 / 内存超限 OOM
排障 describe 的 Events → logs –previous → endpoints

本文是「云原生」系列第 6 篇。