modprobe / lsmod —— 内核模块加载
一句话定义
Linux 内核大部分功能(驱动、网络协议、文件系统)以模块形式存在,按需加载。modprobe 加载 / 卸载模块,lsmod 看现在装载着哪些。K8s 装机必加载几个模块:br_netfilter、overlay、ip_vs_*。
典型场景
- Day0 装 K8s 前:加
br_netfilter+overlay - 用 IPVS 模式 kube-proxy:加
ip_vs系列 - 装新文件系统支持:
modprobe xfs - 内核模块开机自动加载:
/etc/modules-load.d/*.conf
看现在装载了哪些模块
lsmod # 列所有
lsmod | head
# Module Size Used by
# br_netfilter 32768 0
# bridge 258048 1 br_netfilter
# overlay 147456 21
# nf_conntrack 172032 4 nf_nat,...
# ...
| 列 | 含义 |
|---|---|
Module | 模块名 |
Size | 内存占用 |
Used by | 依赖它的其它模块数 + 名字 |
Used by 不为 0 表示有别的模块依赖——不能直接 rmmod,要先卸下游。
看某个模块
lsmod | grep br_netfilter
modinfo br_netfilter
# filename: /lib/modules/.../br_netfilter.ko
# alias: ...
# license: GPL
# depends: bridge
# ...
modinfo 显示模块文件位置、依赖、参数。
加载 / 卸载
modprobe br_netfilter # 加载
modprobe -r br_netfilter # 卸载(remove)
modprobe -n -v br_netfilter # dry-run(看会做什么,不真做)
modprobe --first-time br_netfilter # 已加载则报错
modprobe 会自动加载依赖——比 insmod 更智能。
验证加载成功
lsmod | grep br_netfilter
# br_netfilter 32768 0 ← 加载了
或者:
modprobe -n -v br_netfilter
# insmod /lib/modules/.../br_netfilter.ko
-n dry-run 不真加载、-v 显示动作。
开机自动加载:/etc/modules-load.d/*.conf
modprobe 加载是临时的,重启后没了。要持久:
cat > /etc/modules-load.d/k8s.conf <<'EOF'
br_netfilter
overlay
EOF
systemd 在开机时跑 systemd-modules-load.service,自动 modprobe 这个目录下所有文件里列的模块。
测试:
modprobe -r br_netfilter # 卸载
systemctl restart systemd-modules-load # 重新加载
lsmod | grep br_netfilter # 应该回来
或者直接 reboot 后验证。
历史位置:/etc/modules
# /etc/modules
br_netfilter
overlay
老 Debian 系用的,仍然支持。新写法是 /etc/modules-load.d/。
K8s 必需模块
cat > /etc/modules-load.d/k8s.conf <<'EOF'
# 容器存储 overlay 驱动(containerd 用)
overlay
# bridge netfilter(让 iptables 看到 bridge 上的包)
br_netfilter
# IPVS(如果 kube-proxy 用 IPVS 模式)
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
EOF
# 立即加载(不等重启)
modprobe overlay
modprobe br_netfilter
modprobe ip_vs
modprobe ip_vs_rr
modprobe ip_vs_wrr
modprobe ip_vs_sh
modprobe nf_conntrack
各模块作用
| 模块 | 作用 |
|---|---|
overlay | containerd 镜像层叠(OverlayFS) |
br_netfilter | 让 iptables / nftables 能看到桥接流量 |
bridge | Linux bridge(CNI 用)—— br_netfilter 自动带 |
ip_vs 系列 | IPVS 模式 kube-proxy |
nf_conntrack | netfilter conntrack(kube-proxy iptables 模式也用) |
验证
lsmod | grep -E 'br_netfilter|overlay|ip_vs'
# overlay
# br_netfilter
# ip_vs_rr
# ...
模块参数
某些模块支持运行时参数:
modinfo -p e1000e
# debug:Debug level (0=none,...)
# eee:Enable/disable on parts that support the feature
# ...
# 加载时传参数
modprobe e1000e debug=1
持久化:
# /etc/modprobe.d/e1000e.conf
options e1000e debug=1
黑名单:禁止加载某模块
某些场景要阻止内核自动加载某模块(旧驱动 / 不安全):
# /etc/modprobe.d/blacklist-nouveau.conf
blacklist nouveau # NVIDIA 开源驱动
options nouveau modeset=0
加完之后需要 rebuild initramfs:
update-initramfs -u # Debian / Ubuntu
dracut -f # CentOS / RHEL
然后 reboot。
别名(alias)
# /etc/modprobe.d/alias.conf
alias eth0 e1000e # 让 eth0 这个名字代表 e1000e
K8s 节点通常不需要 alias / blacklist,知道有就行。
卸载模块
modprobe -r br_netfilter # 推荐(处理依赖)
rmmod br_netfilter # 老命令,不处理依赖
卸载失败:
modprobe: FATAL: Module br_netfilter is in use.
被别人用着。看 Used by:
lsmod | grep br_netfilter
# br_netfilter 32768 1 some_other_module
要先卸 some_other_module。
现代 K8s 节点几乎不需要卸载模块。除非排查疑难杂症。
模块文件在哪
ls /lib/modules/$(uname -r)/kernel/
# arch/ block/ crypto/ drivers/ fs/ kernel/ lib/ mm/ net/ ...
# 找某模块文件
find /lib/modules/$(uname -r) -name "br_netfilter*"
# /lib/modules/5.15.0-x/kernel/net/bridge/br_netfilter.ko
modinfo br_netfilter | grep filename
# 等价但更便捷
升级内核之后模块目录变——升级前要 apt install linux-image-$VERSION linux-modules-$VERSION,否则 reboot 后旧内核找不到新模块。
实战:Day0 配置
ssh root@$ip 'bash -s' <<'EOF'
# 1. 写 modules-load
cat > /etc/modules-load.d/k8s.conf <<'MOD'
overlay
br_netfilter
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
MOD
# 2. 立即加载
modprobe overlay
modprobe br_netfilter
modprobe ip_vs
modprobe ip_vs_rr
modprobe ip_vs_wrr
modprobe ip_vs_sh
modprobe nf_conntrack
# 3. 验证
lsmod | grep -E 'overlay|br_netfilter|ip_vs|nf_conntrack'
# 4. 之后 sysctl 才能生效(见 sysctl.md)
EOF
常见踩坑
坑 1:sysctl 报 "cannot stat /proc/sys/net/bridge/..."
sysctl -w net.bridge.bridge-nf-call-iptables=1
# sysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-iptables: No such file or directory
br_netfilter 模块没装。先 modprobe:
modprobe br_netfilter
sysctl -w net.bridge.bridge-nf-call-iptables=1
并写 /etc/modules-load.d/k8s.conf 持久化。
坑 2:modprobe 之后重启又没了
modprobe br_netfilter
reboot
lsmod | grep br_netfilter # 空
modprobe 是临时的。写 /etc/modules-load.d/:
echo 'br_netfilter' > /etc/modules-load.d/k8s.conf
坑 3:模块名拼错
modprobe br_netfilters # 多了 s
# modprobe: FATAL: Module br_netfilters not found
正确:br_netfilter(无 s)。modinfo 或 lsmod 看正确名字。
坑 4:升内核后模块没了
apt upgrade -y # 升内核到 5.15 → 5.16
reboot
modprobe br_netfilter
# modprobe: FATAL: Module br_netfilter not found in directory /lib/modules/5.16.0-x
升内核时没装对应 modules 包。修:
apt install -y linux-modules-extra-$(uname -r)
# 或
apt install -y linux-image-$(uname -r) linux-modules-$(uname -r)
最稳的:每次升内核之前 apt install -y linux-image-... linux-modules-extra-...。
坑 5:模块依赖问题
modprobe ip_vs_rr
# modprobe: ERROR: could not insert 'ip_vs_rr': Unknown symbol in module
依赖的模块 ip_vs 没有加载。modprobe 应该自动处理,但有时碰到内核版本不匹配。
modprobe ip_vs # 先加 base
modprobe ip_vs_rr # 再加子模块
坑 6:blacklist 没生效
echo "blacklist nouveau" > /etc/modprobe.d/blacklist.conf
reboot
lsmod | grep nouveau
# 还在
blacklist 只防止"自动加载"——initramfs 已经加载的可能不算。重建 initramfs:
update-initramfs -u # Debian
dracut -f # RHEL
reboot
坑 7:modules-load.d 文件名错
cat /etc/modules-load.d/k8s # 没 .conf 后缀
# br_netfilter
reboot
lsmod | grep br_netfilter # 没加载
必须 .conf 后缀:
mv /etc/modules-load.d/k8s /etc/modules-load.d/k8s.conf
坑 8:测试 sysctl-related 模块的"先后顺序"
# 改了 modules-load 但没立刻 modprobe
echo 'br_netfilter' > /etc/modules-load.d/k8s.conf
# 然后想 sysctl -w net.bridge.... → 失败
写 modules-load.d 只决定下次启动自动加载。当前没生效——要手动 modprobe。
正确顺序:
# 1. 写持久化(下次开机)
echo 'br_netfilter' > /etc/modules-load.d/k8s.conf
# 2. 现在立刻加载
modprobe br_netfilter
# 3. 应用 sysctl
sysctl -w net.bridge.bridge-nf-call-iptables=1
坑 9:在容器里跑 modprobe
kubectl exec my-pod -- modprobe overlay
# modprobe: ERROR: could not insert ...: Operation not permitted
容器没 CAP_SYS_MODULE,改不了内核状态。
模块属于节点全局,应该在节点上加载,pod 自动用到。
一些常被问的"内核 vs 模块" 概念
- 内核分编译进内核(builtin) 和模块(loadable) 两种功能
- 看
cat /lib/modules/$(uname -r)/builtin.modules:编译进去的 - 模块装载是动态的、不需要重启内核
- 容器跟节点共享内核 / 共享模块(pod 不能改)
K8s 节点上的模块对所有 pod 生效——所以 br_netfilter 在节点加一次,所有 pod 网络都能用。