Kubernetes 容器资源配置与状态诊断探针深度解析
容器计算资源配额管理
请求与约束的核心概念
在 Kubernetes 中,Pod 的资源管理依赖于 requests(请求量)和 limits(上限量)两个核心维度。调度器依据 requests 决定 Pod 的目标节点,而 kubelet 则依据 limits 确保容器运行时资源消耗不越界,同时为容器预留 requests 定义的基础资源。
若节点资源充裕,容器实际消耗可以超过 requests,但绝对无法突破 limits 的天花板。此外,Kubernetes 具备默认资源填充机制:若仅设定了 limits 而漏配 requests,系统会自动将 limits 的值同步给 requests。
资源单位解析
- CPU:以核(Core)为基准单位,1 Core 相当于物理机的 1 个超线程(vCPU)。支持小数表示,如
0.5代表半核,亦可用毫核表示,如500m。 - Memory:以字节为基准。支持以10为底的指数单位(K, M, G)和以2为底的指数单位(Ki, Mi, Gi)。其中 1Ki = 1024B,而 1K = 1000B,这在存储容量换算时需特别注意。
- HugePages:巨页资源(v1.14+ 支持),属于不可超卖资源,一旦分配超限将直接失败。
资源配置实战
以下为一个包含网关与日志收集器的 Pod 资源清单示例:
apiVersion: v1
kind: Pod
metadata:
name: api-gateway
spec:
containers:
- name: gateway-core
image: registry.example.com/gateway:v2
resources:
requests:
memory: "32Mi"
cpu: "200m"
limits:
memory: "64Mi"
cpu: "400m"
- name: sidecar-logger
image: registry.example.com/logger:v1
resources:
requests:
memory: "32Mi"
cpu: "200m"
limits:
memory: "64Mi"
cpu: "400m"
OOM 异常排查与调优
当运行内存敏感型应用(如数据库)时,资源上限设置不当极易触发 OOMKilled。部署如下清单:
apiVersion: v1
kind: Pod
metadata:
name: web-app-pod
spec:
containers:
- name: frontend-server
image: nginx
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
- name: backend-db
image: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: "securePass"
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
通过 kubectl get pod -o wide -w 监控,会发现 Pod 不断重启,状态在 Running 与 OOMKilled 间震荡。这是因为 128Mi 内存无法满足 MySQL 启动需求。可通过 kubectl describe pod 查看具体事件确认。
在排查内存不足时,常会用到 drop_caches 手动释放系统缓存,但生产环境中强烈不建议随意修改此内核参数。稳定运行的系统 free 内存看似较小,实则是被 Buffer/Cache 高效利用,盲目清空仅能掩盖应用层面的内存泄漏或容量规划问题。
修正方案为提升数据库容器的 limits 阈值:
- name: backend-db
image: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: "securePass"
resources:
requests:
memory: "512Mi"
cpu: "0.5"
limits:
memory: "1Gi"
cpu: "1"
重新部署后,观察 Node 资源分配占比,若节点总容量为 2C2G,此时 CPU requests 占比约 37%,Limits 占比 75%,内存 requests 占比约 30%,Limits 占比 61%,均在合理范围内。
运行状态诊断探针
探针分类
- livenessProbe(存活探针):检测容器进程是否存活。失败时 kubelet 将依据重启策略重启容器。
- readinessProbe(就绪探针):检测服务是否已准备好接收流量。失败时,该 Pod 将从关联 Service 的 Endpoints 列表中剔除。
- startupProbe(启动探针):用于慢启动应用,在其成功之前,其余两类探针均被屏蔽。若最终失败,容器将被重启。
探测机制与参数
探针支持三种动作:exec(执行命令,返回0为健康)、httpGet(HTTP请求,状态码在200-399区间为健康)、tcpSocket(建立TCP连接成功即为健康)。
关键控制参数:
initialDelaySeconds:容器启动后等待多少秒才开始首次探测。periodSeconds:探测周期。failureThreshold:连续失败多少次才认定为最终失败。timeoutSeconds:单次探测超时时间。
Exec 探针实践
通过判断临时文件是否存在来模拟业务状态:
apiVersion: v1
kind: Pod
metadata:
name: exec-check-pod
spec:
containers:
- name: checker
image: busybox
command: ["/bin/sh","-c","touch /tmp/health-status; sleep 30; rm -rf /tmp/health-status; sleep 3600"]
livenessProbe:
exec:
command: ["ls", "/tmp/health-status"]
initialDelaySeconds: 1
periodSeconds: 3
该 Pod 启动后 30 秒内正常,随后文件被删除,探针失败,触发容器重启。
HTTPGet 探针实践
对 Nginx 默认页面进行存活性检测:
apiVersion: v1
kind: Pod
metadata:
name: http-probe-pod
spec:
containers:
- name: web-server
image: nginx
ports:
- name: http
containerPort: 80
livenessProbe:
httpGet:
port: http
path: /index.html
initialDelaySeconds: 1
periodSeconds: 3
timeoutSeconds: 10
当手动进入容器删除 /usr/share/nginx/html/index.html 后,HTTP 请求返回 404,存活探针失败导致 Pod 重启。因镜像本身包含该文件,重启后恢复正常。
TCPSocket 探针实践
以 TCP 端口连通性判断健康状态:
apiVersion: v1
kind: Pod
metadata:
name: tcp-probe-pod
spec:
containers:
- name: web-server
image: nginx
livenessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 5
periodSeconds: 3
由于 Nginx 默认监听 80 端口,8080 端口探测将失败引发重启。将端口修正为 80 后,Pod 即可保持稳定运行。
Readiness 就绪探针与流量控制
就绪探针直接影响 Service 的流量转发。配置一个探测不存在的路径:
apiVersion: v1
kind: Pod
metadata:
name: http-ready-check
spec:
containers:
- name: web-server
image: nginx
readinessProbe:
httpGet:
port: 80
path: /ready.html
initialDelaySeconds: 1
periodSeconds: 3
livenessProbe:
httpGet:
port: 80
path: /index.html
initialDelaySeconds: 1
periodSeconds: 3
此时 Pod 处于 Running 但非 Ready 状态。使用 kubectl exec 创建对应文件后,就绪探针通过,Pod 进入 Ready 状态。
结合 Service 的多副本场景,更能体现就绪探针的价值:
apiVersion: v1
kind: Pod
metadata:
name: web-a
labels:
app: web-cluster
spec:
containers:
- name: nginx
image: nginx
readinessProbe:
httpGet:
port: 80
path: /index.html
initialDelaySeconds: 5
periodSeconds: 5
---
# 省略 web-b, web-c 类似配置
---
apiVersion: v1
kind: Service
metadata:
name: web-cluster-svc
spec:
selector:
app: web-cluster
ports:
- port: 80
targetPort: 80
若删除 web-a 中的 /index.html,其就绪探针将失败,Service 会自动将 web-a 从 Endpoints 中剥离,停止向其分发请求,保证业务可用性。
容器生命周期钩子
Kubernetes 提供了 postStart 和 preStop 钩子,分别在容器创建后和终止前执行。结合 initContainers 可以观察执行顺序:
apiVersion: v1
kind: Pod
metadata:
name: hook-demo-pod
spec:
containers:
- name: main-app
image: nginx
lifecycle:
postStart:
exec:
command: ["/bin/sh","-c","echo 'Hook postStart executed' >> /var/log/nginx/app.log"]
preStop:
exec:
command: ["/bin/sh","-c","echo 'Hook preStop executed' >> /var/log/nginx/app.log"]
volumeMounts:
- name: app-logs
mountPath: /var/log/nginx/
initContainers:
- name: init-setup
image: nginx
command: ["/bin/sh","-c","echo 'Init container setup' >> /var/log/nginx/app.log"]
volumeMounts:
- name: app-logs
mountPath: /var/log/nginx/
volumes:
- name: app-logs
hostPath:
path: /data/volumes/app/log/
type: DirectoryOrCreate
容器启动后查看日志,输出顺序为:Init container setup -> Hook postStart executed。当 Pod 被终止时,日志中会追加 Hook preStop executed。需注意,postStart 与容器入口点并行触发,若其阻塞过长,可能导致容器无法进入 Running 状态。