第 9 / 18 篇

第 8 章 健康检查与资源:让系统知道应用的状态

Running 不等于能服务

容器进程存在,只能说明它在运行;它可能还在加载数据,也可能已经卡死。Kubernetes 提供三种探针。

readinessProbe(就绪探针)回答“现在能接流量吗”。失败时,Pod 会变为未就绪,通常不再作为 Service 的就绪后端;它本身不会因此被重启。

livenessProbe(存活探针)回答“是否需要重启这个容器”。连续失败达到阈值后,kubelet 会按重启策略处理。错误地把外部数据库偶发故障作为存活失败原因,可能造成大量无效重启。

startupProbe(启动探针)给慢启动应用留时间。配置了启动探针后,在它成功之前,就绪和存活探针不会开始工作。简单 NGINX 静态网页启动很快,本书完整示例只使用就绪和存活探针。

若两种探针都检查同一个路径,删除页面可能同时触发两种失败,不能据此推断“就绪失败导致重启”。分开验证时,应让就绪路径失败、存活路径仍成功,观察 Service 就绪后端移除而 restartCount 不变;再单独破坏存活路径,检查容器重启与恢复。随书自动化实验用另建的故障 Pod 完成这项隔离检查,主线网页清单仍保持易读。

requests 与 limits

requests 是调度时用于计算资源需求的重要依据。limits 约束运行时资源使用。CPU 的 100m 是 0.1 核,内存 64Mi 是 64 × 1024 × 1024 字节。

CPU 超出限制通常会被限流;内存达到限制后,进程可能被内核终止,出现 OOMKilled。节点内存压力也可能导致 Pod 被驱逐。资源不足时应结合事件和实际负载分析,不能见到重启就无限增大上限。

把前面知识合成完整应用

将之前的 deployment.yaml 替换为下面内容。这是完整文件,不是片段。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-web
spec:
  replicas: 2
  revisionHistoryLimit: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 0
      maxSurge: 1
  selector:
    matchLabels:
      app: hello-web
  template:
    metadata:
      labels:
        app: hello-web
    spec:
      containers:
        - name: web
          image: nginx:1.28
          ports:
            - name: http
              containerPort: 80
          resources:
            requests:
              cpu: 100m
              memory: 64Mi
            limits:
              cpu: 500m
              memory: 128Mi
          readinessProbe:
            httpGet:
              path: /
              port: http
            initialDelaySeconds: 2
            periodSeconds: 5
          livenessProbe:
            httpGet:
              path: /
              port: http
            initialDelaySeconds: 10
            periodSeconds: 10
          volumeMounts:
            - name: page
              mountPath: /usr/share/nginx/html
              readOnly: true
      volumes:
        - name: page
          configMap:
            name: hello-page

这个清单挂载整个网页目录,所以该目录中原镜像自带的文件会被挂载内容遮住。readOnly 表示容器不能通过这个挂载点改写配置。普通 NGINX 镜像的权限模型适合本地教学,不要据此假定已满足生产环境的非 root 与安全加固要求。

kubectl apply -n k8s-book -f configmap.yaml
kubectl apply -n k8s-book -f deployment.yaml
kubectl apply -n k8s-book -f service.yaml
kubectl rollout status deployment/hello-web -n k8s-book --timeout=120s
kubectl get pods -n k8s-book

保持 port-forward 运行,刷新浏览器。如果转发因 Pod 替换退出,重新执行第 6 章的转发命令。你应该看到中文欢迎页。

本章自测:就绪失败是否必然重启容器?100m 是一百核吗?为什么 ConfigMap 缺失可能导致 Pod 一直无法启动?