云原生进阶(02):容器性能与排障——容器 CPU/内存限制生效、kubelet 日志、coredns 问题、集群性能
更新时间:2026-09-01。本文是
cloud/mesh/云原生进阶第 02 篇,接 Service Mesh。容器和 K8s 集群的排障是运维的核心能力。理解容器 CPU/内存限制怎么生效,kubelet 日志怎么看,CoreDNS 问题怎么排查,集群性能瓶颈在哪里。
本文要回答的问题
- 容器 CPU 限制怎么通过 cgroup 生效?CPU throttle 怎么看?
- 容器 OOM 怎么排查?内存限制和 cgroup 的关系?
- kubelet 日志怎么看?Pod 启动失败、节点 NotReady 怎么排查?
- CoreDNS 问题怎么排查?DNS 解析慢、解析失败怎么办?
一、容器 CPU 限制
text
容器的 CPU 限制通过 cgroup CFS 实现
--cpus=1.5 的解释:
cpu.cfs_period_us = 100000(默认 100ms)
cpu.cfs_quota_us = 150000(每 100ms 最多用 150ms)
所以:cpus=1.5 = quota=150000/period=100000
--cpus=0.5 的解释:
quota=50000/period=100000 → 每 100ms 最多用 50ms CPU
limits:
cpu: "500m" → quota=50000/period=100000CPU throttle 检查:
bash
# 进入容器,查看 cgroup
cat /proc/self/cgroup
# 查看 CPU 限制
cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us
cat /sys/fs/cgroup/cpu/cpu.cfs_period_us
# 查看 CPU throttle 统计
cat /sys/fs/cgroup/cpu/cpu.stat
# nr_periods:统计周期数
# nr_throttled:被限流的周期数
# throttled_time:被限流总时间
# throttle 比例 = nr_throttled / nr_periods
# 如果 > 0.1,说明 CPU 不够,需要扩容CPU 限制建议:
- CPU throttle 比例 > 0.1 → 扩容
- 不要设置 limits 太小,否则 throttle 严重
- 延迟敏感的应用(如 API 网关)不要 throttle
二、容器内存限制
text
容器的内存限制通过 cgroup memory 实现
--memory=256m 的解释:
memory.limit_in_bytes = 268435456(256MB)
超过限制 → OOM kill
OOM 排查:
1. 容器被 kill,状态 OOMKilled
2. 查看 dmesg 确认 OOM 信息
3. 查看容器日志,看 OOM 前后内存使用情况OOM 排查命令:
bash
# 查看容器状态
docker inspect my-container | jq '.[].State.OOMKilled'
# 或 kubectl
kubectl describe pod my-pod | grep -A 5 OOMKilled
# 查看系统 OOM 日志
dmesg | grep -i oom
dmesg | grep -i "killed process"
# 查看容器内存使用
docker stats --no-stream
kubectl top pod my-pod
# 查看 cgroup 内存限制
cat /sys/fs/cgroup/memory/memory.limit_in_bytes
cat /sys/fs/cgroup/memory/memory.usage_in_bytes内存限制建议:
- 设置 limits 时,预留 20-30% 的 buffer,防止 OOM
- 监控内存使用率,超过 80% 需要扩容
- Java 应用注意设置 JVM 堆内存,不要超过容器内存限制
三、kubelet 日志排查
bash
# kubelet 日志(systemd 系统)
journalctl -u kubelet -f # 实时查看
journalctl -u kubelet --since "1 hour ago" # 最近 1 小时
journalctl -u kubelet -n 100 # 最后 100 行
# 常见 kubelet 问题
# 1. 节点 NotReady
kubectl describe node node1
# 检查 kubelet 日志
journalctl -u kubelet | grep -i error
# 2. Pod 启动失败
kubectl describe pod my-pod
# 检查 kubelet 日志中该 Pod 的日志
journalctl -u kubelet | grep my-pod
# 3. 镜像拉取失败
kubectl describe pod my-pod | grep -A 5 "Failed to pull"
journalctl -u kubelet | grep -i "pull"节点 NotReady 常见原因:
- kubelet 未运行:
systemctl status kubelet - 节点资源不足:disk pressure / memory pressure
- 网络问题:节点和 API Server 通信中断
- 容器运行时问题:containerd/docker 未运行
四、CoreDNS 问题
bash
# 检查 CoreDNS Pod 状态
kubectl get pods -n kube-system -l k8s-app=kube-dns
# 查看 CoreDNS 日志
kubectl logs -n kube-system -l k8s-app=kube-dns
# DNS 解析测试
kubectl run dns-test --image=busybox --rm -it -- nslookup kubernetes.default
# 从 Pod 内部测试 DNS
kubectl exec my-pod -- nslookup my-appCoreDNS 常见问题:
| 问题 | 现象 | 对策 |
|---|---|---|
| CoreDNS Pod 重启 | DNS 解析间歇性失败 | 增加副本数,分配资源 |
| DNS 解析慢 | 5 秒以上才解析成功 | 检查 ndots 配置,优化搜索域 |
| 域名解析失败 | 服务名解析不了 | 检查 Service 和 Pod 状态 |
| 大量 DNS 查询 | CoreDNS 负载高 | 用 NodeLocal DNSCache 缓存 |
优化 DNS 搜索域:
yaml
# Pod DNS 配置
spec:
dnsConfig:
searches:
- default.svc.cluster.local
- svc.cluster.local
options:
- name: ndots
value: "2" # 默认 5,减少不必要的 DNS 查询五、集群性能排查
1. 网络性能
bash
# 网络延迟
kubectl run net-test --image=nicolaka/netshoot --rm -it -- \
ping 8.8.8.8
# 网络带宽(iperf3)
# 在 Pod 之间测试网络带宽
kubectl exec iperf-server -- iperf3 -s
kubectl exec iperf-client -- iperf3 -c iperf-server
# 查看网络插件状态
kubectl get pods -n kube-system -l k8s-app=calico-node2. 磁盘性能
bash
# 节点磁盘空间
kubectl describe node node1 | grep -i "Disk Pressure"
# 日志过多导致磁盘满
# 查看容器日志目录大小
du -sh /var/log/containers/
du -sh /var/lib/docker/containers/
# 日志轮转配置
# /etc/containerd/config.toml
# /etc/docker/daemon.json3. API Server 性能
bash
# API Server 响应时间
kubectl get --raw /metrics | grep -i "apiserver_request_duration"
# 查看 API Server 日志
kubectl logs -n kube-system -l component=kube-apiserver
# 大量请求导致 API Server 变慢
# 检查 request count
kubectl get --raw /metrics | grep "apiserver_request_total"六、常见坑对照
| 坑 | 现象 | 对策 |
|---|---|---|
| CPU throttle 严重 | 容器响应慢,CPU 使用率低 | 增加 CPU limits,或减少线程数 |
| OOM 频繁 | 容器不断重启 | 加大内存 limits,或用持久化分析内存使用 |
| CoreDNS 解析慢 | 请求延迟突然增加 | 减少 ndots 值,用 NodeLocal DNSCache |
| 节点磁盘满 | Pod 被驱逐,镜像拉取失败 | 清理日志和旧镜像,设置日志轮转 |
| kubelet 证书过期 | 节点 NotReady | 检查证书有效期,续期 kubelet 证书 |
相关与延伸
Cloud 系列共 11 篇完成。容器底层隔离,见 概念层 namespace/cgroup。CI/CD 流水线,见 CI/CD 流水线。
一句话总结
容器性能与排障:CPU 限制通过 cgroup CFS 实现(quota/period),CPU throttle 比例 > 0.1 需要扩容;内存 OOM 通过 dmesg 和 kubectl describe 排查,预留 20-30% buffer;kubelet 日志用 journalctl -u kubelet 查看,节点 NotReady 常见原因:kubelet 未运行、资源不足、网络中断;CoreDNS 慢用 ndots 优化,高负载用 NodeLocal DNSCache;集群性能三个瓶颈:网络(CNI 插件性能)、磁盘(日志轮转)、API Server(请求量监控)。