Skip to content

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 时 panic
bash
# 应用配置
sysctl --system

1.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=65535

1.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 v1cgroup v2
层级结构每个子系统独立层级统一层级树
挂载点/sys/fs/cgroup/<subsystem>/sys/fs/cgroup/(统一)
压力监控cgroup.pressure(PSI)
生产采用CentOS 7/RHEL 7/Ubuntu 18RHEL 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_device

2.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 任务都 stalled

2.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 而非 nproc

3. 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
UserUID/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.1

4. 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-cgtop

5. 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 → POSTROUTING

5.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.rules

5.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 可能杀 kubelet

Q: 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 # 调大