主题
01 — Linux 系统管理深度教材
高级 K8s 运维工程师的 linux 功底直接决定排障效率。本章覆盖内核参数调优、cgroup v1/v2、namespace 隔离机制、systemd 管理、iptables/nftables 规则链,全部配有生产级配置与排障命令。
1. 内核参数调优
1.1 sysctl 核心参数(K8s 节点必备)
bash
# === /etc/sysctl.d/99-k8s.conf ===
# 网络基础
net.ipv4.ip_forward = 1 # Pod 网络必需
net.bridge.bridge-nf-call-iptables = 1 # bridge 流量过 iptables
net.bridge.bridge-nf-call-ip6tables = 1
# TCP 调优(高并发场景)
net.ipv4.tcp_max_syn_backlog = 65535 # SYN 队列长度
net.ipv4.tcp_tw_reuse = 1 # TIME_WAIT 复用
net.ipv4.tcp_fin_timeout = 15 # FIN_WAIT2 超时
net.ipv4.tcp_keepalive_time = 600 # TCP 保活时间
net.ipv4.tcp_keepalive_intvl = 30 # 保活探测间隔
net.ipv4.tcp_keepalive_probes = 3 # 保活探测次数
# 连接跟踪(iptables conntrack)
net.netfilter.nf_conntrack_max = 1048576 # 大规模集群必须调大
net.netfilter.nf_conntrack_tcp_timeout_established = 86400
# 文件系统
fs.inotify.max_user_watches = 524288 # kubelet/inotify 监控
fs.inotify.max_user_instances = 8192 # 容器数量多时需要
fs.file-max = 2097152 # 系统文件描述符上限
# 虚拟内存
vm.swappiness = 1 # 尽量不用 swap
vm.overcommit_memory = 1 # 允许内存超分(etcd 需要)
vm.panic_on_oom = 0 # OOM 时不 panic
kernel.panic = 10 # panic 后 10 秒重启
kernel.panic_on_oops = 1 # oops 时 panicbash
# 应用配置
sysctl --system1.2 ulimit 与文件描述符
bash
# /etc/security/limits.d/99-k8s.conf
* soft nofile 1048576
* hard nofile 1048576
* soft nproc 65535
* hard nproc 65535
* soft memlock unlimited # etcd 需要锁定内存
* hard memlock unlimited
# systemd 服务的 ulimit 在 service 文件中设置:
# [Service]
# LimitNOFILE=1048576
# LimitNPROC=655351.3 内核模块管理
bash
# K8s 必需的内核模块 → /etc/modules-load.d/k8s.conf
br_netfilter # bridge 流量过 netfilter
overlay # overlay 文件系统(容器存储驱动)
nf_conntrack # 连接跟踪
ip_vs # IPVS(kube-proxy IPVS 模式)
ip_vs_rr # IPVS 轮询调度
ip_vs_wrr # IPVS 加权轮询
ip_vs_sh # IPVS 源哈希
# 立即加载并验证
modprobe br_netfilter overlay nf_conntrack ip_vs ip_vs_rr ip_vs_wrr ip_vs_sh
lsmod | grep -E 'br_netfilter|overlay|ip_vs|nf_conntrack'2. cgroup — 容器资源隔离的基石
2.1 cgroup v1 vs v2 对比
| 特性 | cgroup v1 | cgroup v2 |
|---|---|---|
| 层级结构 | 每个子系统独立层级 | 统一层级树 |
| 挂载点 | /sys/fs/cgroup/<subsystem> | /sys/fs/cgroup/(统一) |
| 压力监控 | 无 | cgroup.pressure(PSI) |
| 生产采用 | CentOS 7/RHEL 7/Ubuntu 18 | RHEL 8+/Ubuntu 22+/Fedora |
| K8s 兼容性 | 完全支持 | K8s 1.25+ 默认 |
2.2 cgroup v1 子系统操作
bash
# 查看进程的 cgroup 归属
cat /proc/<pid>/cgroup
# CPU 限制(对应 K8s CPU limits)
cat /sys/fs/cgroup/cpu/kubepods/podXXX/cpu.cfs_quota_us # -1=不限
cat /sys/fs/cgroup/cpu/kubepods/podXXX/cpu.cfs_period_us # 通常 100000
# CPU shares(权重,对应 K8s CPU requests)
cat /sys/fs/cgroup/cpu/kubepods/podXXX/cpu.shares # 1024=1核
# 内存限制(对应 K8s Memory limits)
cat /sys/fs/cgroup/memory/kubepods/podXXX/memory.limit_in_bytes
cat /sys/fs/cgroup/memory/kubepods/podXXX/memory.usage_in_bytes
cat /sys/fs/cgroup/memory/kubepods/podXXX/memory.stat # 详细统计
# OOM 事件检测
cat /sys/fs/cgroup/memory/kubepods/podXXX/memory.oom_control
# oom_kill 1 → 发生了 OOM kill
# IO 限制(blkio)
cat /sys/fs/cgroup/blkio/kubepods/podXXX/blkio.throttle.read_bps_device2.3 cgroup v2 操作
bash
# 查看某 Pod 的资源控制
cat /sys/fs/cgroup/kubepods.slice/.../cpu.max # "max 100000" = 不限
cat /sys/fs/cgroup/kubepods.slice/.../memory.max # 内存上限
cat /sys/fs/cgroup/kubepods.slice/.../memory.current # 当前使用
# PSI(Pressure Stall Information)— 检测资源压力
cat /sys/fs/cgroup/kubepods.slice/.../cpu.pressure
cat /sys/fs/cgroup/kubepods.slice/.../memory.pressure
# some avg10=5.23 avg60=3.12 avg300=1.05 total=12345678
# some = 至少一个任务因资源不足而 stalled
# full = 所有 non-idle 任务都 stalled2.4 K8s requests/limits 与 cgroup 映射
CPU requests → cgroup cpu.shares(权重,不影响上限)
CPU limits → cgroup cpu.cfs_quota_us(硬上限,超出被 throttle)
Memory requests → 仅影响调度,不设 cgroup
Memory limits → cgroup memory.limit_in_bytes(超出 OOM Kill)
生产常见问题:
1. CPU throttle:设了 limits 但应用被 throttle
→ 查看 cpu.stat 中的 nr_throttled/throttled_time
→ 解决:去掉 CPU limits 或调大
2. OOM Kill:Memory limits 设太小
→ 查看 memory.oom_control 或 dmesg | grep -i oom
→ 解决:调大 limits 或优化应用内存
3. 容器 nproc 显示宿主机全部核心
→ 但 cgroup 限制了实际可用 CPU 时间
→ 应用线程池应参考 limits 而非 nproc3. namespace — 容器隔离的另一基石
3.1 六种 namespace
| Namespace | 隔离内容 | 验证命令 |
|---|---|---|
| PID | 进程 ID 空间 | lsns -t pid |
| Network | 网络设备、IP、端口、路由表 | lsns -t net |
| Mount | 文件系统挂载点 | lsns -t mnt |
| UTS | 主机名和域名 | lsns -t uts |
| IPC | 进程间通信 | lsns -t ipc |
| User | UID/GID 映射 | lsns -t user |
3.2 进入容器 namespace 调试
bash
# 找到容器的 PID
CRICONTAINER_ID=$(crictl ps -q --name <container-name>)
PID=$(crictl inspect $CRICONTAINER_ID | jq .info.pid)
# 进入各种 namespace
nsenter -t $PID -n ip addr # 网络 namespace
nsenter -t $PID -m cat /etc/hosts # 挂载 namespace
nsenter -t $PID -p ps aux # PID namespace
nsenter -t $PID -u hostname # UTS namespace
# 一行命令进入容器(等效 docker exec)
nsenter -t $PID -m -u -i -n -p -- /bin/bash
# 查看 namespace 文件描述符
ls -la /proc/$PID/ns/3.3 Network Namespace 实战
bash
# 手动创建 network namespace
ip netns add test-ns
ip netns exec test-ns ip addr # 只有 lo
# 创建 veth pair 连接 namespace
ip link add veth0 type veth peer name veth1
ip link set veth1 netns test-ns
ip addr add 10.0.0.1/24 dev veth0
ip link set veth0 up
ip netns exec test-ns ip addr add 10.0.0.2/24 dev veth1
ip netns exec test-ns ip link set veth1 up
ip netns exec test-ns ip link set lo up
# 测试连通性
ping 10.0.0.2
ip netns exec test-ns ping 10.0.0.14. systemd — 服务管理
4.1 K8s 组件的 systemd 管理
bash
# RKE2 组件
systemctl status rke2-server # 控制面节点
systemctl status rke2-agent # worker 节点
# 查看 kubelet 的实际配置
systemctl cat kubelet
ps aux | grep kubelet
# journalctl 查看日志
journalctl -u kubelet --since "1 hour ago" --no-pager | tail -50
journalctl -u containerd --since today -f # 实时跟踪4.2 systemd 资源限制
bash
# 在 service 文件中限制资源
# [Service]
# CPUQuota=200% # 最多 2 核
# MemoryMax=4G # 最多 4GB 内存
# TasksMax=4096 # 最多 4096 个线程
# LimitNOFILE=1048576 # 文件描述符上限
# 实时查看各 cgroup 的资源使用
systemd-cgtop5. iptables / nftables
5.1 iptables 四表五链
入站: NIC → [raw PREROUTING] → [mangle PREROUTING]
→ [nat PREROUTING] → 路由判断
→ [mangle INPUT] → [filter INPUT] → 本地进程
转发: → [mangle FORWARD] → [filter FORWARD]
→ [mangle POSTROUTING] → [nat POSTROUTING] → NIC
出站: 本地进程 → [mangle OUTPUT] → [nat OUTPUT]
→ [filter OUTPUT] → [nat POSTROUTING] → NIC
四表:raw → mangle → nat → filter
五链:PREROUTING → INPUT → FORWARD → OUTPUT → POSTROUTING5.2 K8s 场景下的 iptables
bash
# 查看 kube-proxy 创建的规则
iptables -t nat -L KUBE-SERVICES -n --line-numbers | head -20
iptables -t nat -L KUBE-SVC-XXXX -n # 某个 Service 的规则
# 统计规则匹配次数
iptables -t nat -L KUBE-SERVICES -n -v --line-numbers | sort -k1 -rn | head
# 查看 DNAT 规则(Service ClusterIP → Pod IP)
iptables -t nat -S | grep KUBE-SVC | head -20
# 导出/导入规则
iptables-save > /tmp/iptables-backup.rules
iptables-restore < /tmp/iptables-backup.rules5.3 nftables 快速上手
bash
# 查看当前规则集
nft list ruleset
# 集合(Set)—— 高效匹配大量 IP
nft add set ip filter blocklist { type ipv4_addr \; flags interval \; }
nft add element ip filter blocklist { 192.168.1.0/24, 10.0.0.0/8 }
nft add rule ip filter input ip saddr @blocklist drop
# RHEL 8+ 默认使用 nftables 后端(iptables-nft 兼容层)6. 面试高频问题
Q: 容器内 CPU limits 导致 throttle 怎么排查?
bash
# 1. 确认 throttle
cat /sys/fs/cgroup/cpu/.../cpu.stat
# nr_throttled / nr_periods = throttle 比例
# 2. 检查 limits
kubectl get pod <name> -o jsonpath='{.spec.containers[*].resources}'
# 3. 解决:去掉 CPU limits 或调大Q: cgroup OOM vs 内核 OOM 怎么区分?
bash
# cgroup OOM:容器内存超 limits
dmesg | grep 'oom-kill' | grep cgroup
# 内核 OOM:宿主机整体内存不足
dmesg | grep 'Out of memory'
# cgroup OOM 只杀容器进程;内核 OOM 可能杀 kubeletQ: conntrack 表满导致网络异常?
bash
conntrack -C # 当前条目数
cat /proc/sys/net/netfilter/nf_conntrack_max # 上限
dmesg | grep 'conntrack.*table full' # 告警
sysctl -w net.netfilter.nf_conntrack_max=1048576 # 调大