ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

openEuler上部署Rancher 2.9:cgroupv2与iptables实战指南

openEuler上部署Rancher 2.9:cgroupv2与iptables实战指南 1. 项目背景与问题全景1.1 环境构成与关键版本先说我这边的实际环境这样下面的步骤你才好对照。我用的操作系统是 openEuler 24.03 SP4内核版本 6.6.x设备是一台 4 核 16G 内存的物理服务器磁盘留了 200G 给系统分区。Rancher 版本是 2.9.x容器运行时底层是 containerd 1.7.x兼容 Docker 镜像。集群形态是单节点全角色也就是同一个节点同时承担 etcd、controlplane、worker 三种角色适合验证环境和小规模生产。OpenEuler 24.03 SP4 作为国产化场景里很常见的发行版基础包管理用的是 dnf默认防火墙是 firewalld安全模块也比较完整。单看这些配置本身不复杂但真正部署 Rancher 的时候问题全集中在两个底层细节上cgroupv2 和 iptables。尤其是 cgroupv2内核默认开启了 v2而容器运行时、Kubelet、kube-proxy 这些组件对 cgroup 驱动的要求各不相同。驱动一旦不一致节点要么直接注册不上要么注册上之后状态反复漂移。1.2 两个看不见的底层机制先把概念说清楚后面的排查才有方向。cgroupv2 是内核把进程资源控制的接口升级成了统一版本最大的变化是所有 controller 统一挂在/sys/fs/cgroup下并且只支持进程粒度。Kubernetes 场景里容器运行时和 Kubelet 都需要指定 cgroup 驱动通常只有两个选项cgroupfs 和 systemd。如果系统采用了 systemd 作为 init 进程那么推荐驱动就是 systemd否则可能出现资源统计异常甚至 kubelet 直接拒绝启动。openEuler 主流的部署方式肯定是用 systemd所以这里绝大多数问题都出在运行时还在用 cgroupfsKubelet 却想用 systemd这种错位状态。iptables 的问题更隐蔽。openEuler 24.03 SP4 默认的防火墙体系已经逐渐转向 nftables 后端但 Kubernetes 的 kube-proxy 在 iptables 模式下操作的仍然是老的nat、filter表。如果系统里没有完整加载 iptables 相关内核模块或者/usr/sbin/iptables实际只是 nft 的兼容命令那么给 Service 创建映射规则时会静默失败规则看着没报错但流量就是不通。2. 部署前必须搞懂的两个底层机制2.1 cgroupv2 对容器运行时的硬性要求我在安装过程中第一次看到kubelet cgroup driver: systemd is different from docker cgroup driver: cgroupfs的时候第一反应是检查 Docker 配置。因为 Rancher 2.9 在单机场景下仍然可以基于 Docker 启动 Server而节点侧的容器运行时如果用的是 Docker那 docker 的exec-opts就必须加上native.cgroupdriversystemd。具体修改方式是在/etc/docker/daemon.json里追加{ exec-opts: [native.cgroupdriversystemd], log-driver: json-file, log-opts: { max-size: 100m, max-file: 3 }, storage-driver: overlay2, iptables: true, ip-masq: false }改完之后依次重启 Docker 和所有相关容器再检查docker info --format {{.CgroupDriver}}输出必须是systemd。如果输出还是 cgroupfs说明 daemon.json 没生效或者 Docker 版本太老不支持这个字段。如果不用 Docker Runtime而是像 RKE2 那样直接用 containerd那么需要检查/etc/rancher/rke2/config.yaml。RKE2 默认会给 Kubelet 传递 systemd 驱动但如果你自己装了 containerd再让 Rancher 的 agent 容器去调用就要确认 containerd 的/etc/containerd/config.toml里SystemdCgroup是否打开。推荐的配置是[plugins.io.containerd.grpc.v1.cri.containerd.runtimes.runc] runtime_type io.containerd.runc.v2 [plugins.io.containerd.grpc.v1.cri.containerd.runtimes.runc.options] SystemdCgroup true这里有个容易忽略的细节即使 containerd 配了 SystemdCgroup底层仍然需要 cgroupv2 的 mount 存在。你可以用mount | grep cgroup检查如果发现只有 cgroup 没有 cgroup2那就要确认内核启动参数是否把 v2 禁用掉了。openEuler 24.03 默认启用了 cgroupv2正常不需要额外操作但如果你做过内核参数调整还是看一眼稳妥。2.2 iptables 与 nftables 的关系Kube-proxy 为什么容易踩坑openEuler 24.03 SP4 默认加载的是 nftables 框架但 Kubernetes 的 kube-proxy 服务依赖仍然沿用老一套 iptables 规则。换句话说操作系统本身没有iptables这个内核组件它提供的是兼容层兼容层主要做的是把 iptables 语法的规则翻译成 nftables 规则。理论上是可行的但兼容性总是会晚一步。我在实际操作中发现如果 Rancher Server 容器通过 Docker 方式启动Docker 会自动创建一堆DOCKER、BRIDGE链。此时再打开 kube-proxy它会尝试在nat表里追加 KUBE-SERVICE 链。一旦系统检测不到标准 iptables 模块或者xtables-nft和xtables-legacy的选择不对规则会注入到错误的后端表现出来就是 kube-proxy 日志没有报错但 Service 的 ClusterIP 始终 ping 不通。确认当前系统实际使用的 iptables 后端可以用这个命令iptables --version如果输出里带(nf_tables)说明现在是 nft 兼容后端。如果输出带(legacy)就是老的 iptables 后端。两种后端可以并存但同一时刻只有一种能生效。想让 Kubernetes 稳定工作建议统一使用 legacy 后端。可以通过 update-alternatives 切换update-alternatives --set iptables /usr/sbin/iptables-legacy切换后立刻验证iptables -t nat -L -n ip6tables -t nat -L -n如果能正常列出链列表那 kube-proxy 大概率能正常工作了。这一步看起来简单但我当时的系统里根本没有iptables-legacy这个文件最后是靠dnf install iptables-legacy -y装上的。3. 安装 Rancher 并创建集群的核心步骤3.1 单容器方式启动 Rancher Server我用的是 Rancher 官方给的快速启动方式直接把 Server 跑在 Docker 里。前提是 Docker 已经装好并且 cgroup 驱动改成了 systemd。启动命令docker run -d --name rancher-server \ --restartunless-stopped \ -p 80:80 -p 443:443 \ --privileged \ rancher/rancher:v2.9.4加上--privileged是因为 Rancher Server 容器内部需要操作 iptables 规则来管理端口和代理普通容器权限不够。启动后等待一两分钟用docker logs -f rancher-server观察日志看到Listening on :443之后就说明 Server 起来了。这里有个地方我踩过坑如果你系统防火墙没关80 和 443 端口不一定通。所以启动容器之前先明确自己的策略。我这边是测试环境直接把 firewalld 关了systemctl stop firewalld systemctl disable firewalld生产环境不建议这样操作后面我会单独讲怎么按最小端口放行。3.2 把节点加入集群时的 cgroup 驱动匹配设置Rancher Server 起来之后通过https://服务器IP/访问 Web 界面。首次登录会让你设置 admin 密码然后添加集群。如果选择全新集群并自定义节点Rancher 会生成一段注册命令类似curl --insecure -fL https://服务器IP/system-agent-install.sh | sudo sh -s - \ --server https://服务器IP \ --label cattle.io/oslinux \ --etcd --controlplane --worker在单节点环境里这条命令执行完Rancher 的 agent 会自动部署 kubelet、containerd 和网络插件。但如果你没做前面的 cgroup 驱动对齐执行完这条命令后Web 界面上节点状态会卡在 Waiting一分钟后大概率看到标题里那个经典错误kubelet stopped posting node status。原因是 kubelet 启动后会向 API Server 注册节点但如果它自身的 cgroup 驱动和运行时不一致它根本无法通过健康检查自然也就不会主动上报状态。解决办法就是回到第 2.1 节把运行时的 cgroup driver 改成 systemd然后重启节点侧相关服务。如果不确定是哪个组件报错直接在节点上journalctl -u kubelet -f journalctl -u containerd -f日志里往往直接给出cgroup driver相关的关键字。3.3 手动补 iptables 链的兜底方案在我的环境里即便 cgroup 驱动对齐了kube-proxy 运行一段时间后还是会出现 Service 无法访问的情况。我最后排查到FORWARD链默认策略是 DROP。只要是双网卡或开启了转发Docker 和 Kubernetes 的流量都依赖 FORWARD 链默认 DROP 会导致东西向流量被静默丢弃。临时处理方式很简单iptables -P FORWARD ACCEPT但重启后就失效了。为了持久化我安装了 iptables-servicesdnf install -y iptables-services systemctl enable iptables systemctl start iptables此时/etc/sysconfig/iptables文件会被生成你可以把 FORWARD 链的策略改成 ACCEPT 并保存iptables-save /etc/sysconfig/iptables再确认 kube-proxy 的核心链都存在iptables -t nat -L KUBE-SERVICES -n iptables -t nat -L KUBE-NODEPORTS -n如果这两个链不存在一般是 kube-proxy 没启动或者启动失败。检查 kube-proxy 的 Podkubectl get pods -n kube-system -o wide | grep kube-proxy kubectl logs -n kube-system kube-proxy-pod --tail100日志里如果出现Failed to ensure that the pod: cbr0 ... has the correct IP多半还是网络插件和 iptables 后端不匹配导致的重新确认一遍 legacy 后端即可。4. 常见问题与排查实践4.1 kubelet stopped posting node status 的完整排查路线这个错误在 Rancher 社区里出现频率很高尤其是在国产系统上。我这里整理了一个固定的排查顺序遇到就直接照做。第一步确认节点侧核心进程是否存活systemctl status kubelet systemctl status containerd systemctl status rke2-server第二步看日志中的关键字常见的有cgroup driver、failed to get container info、node not found等。如果 cgroup 驱动不匹配日志会直接写明。确认后修改 daemon.json 或 containerd 配置。第三步检查 Rancher agent 容器日志docker logs --tail 100 rancher-agent容器名第四步检查节点上的 CRI 命令能不能正常列出容器crictl ps如果 crictl 报连接不上说明 containerd 的 socket 路径配置不对。openEuler 下 containerd 默认 socket 在/run/containerd/containerd.sock但 RKE2 的 socket 在/run/k3s/containerd/containerd.sock两者不能混用。把上面四步走完大部分 kubelet 失联问题都能定位到根因剩下的就是改配置重启的事。4.2 iptables 规则不生效、服务无法访问的检查清单规则看起来在但访问还是不通这种情况最容易让人崩溃。我遇到过的几种根因如下。第一种规则注入到了 nft 后端真正给网络路径用的还是 legacy 后端。表现是iptables -L能看到规则但 ping ClusterIP 不通访问 NodePort 也不通。解决办法就是统一后端切到 legacy。第二种br_netfilter内核模块没加载。Kubernetes 的 Service 流量经过 bridge 设备时需要bridge-nf-call-iptables开启否则桥接流量不受 iptables 规则控制。检查命令cat /proc/sys/net/bridge/bridge-nf-call-iptables如果返回 0加载模块并启用modprobe br_netfilter sysctl -w net.bridge.bridge-nf-call-iptables1第三种ip_forward没有开启。K8s 的 Pod 之间以及 Service 流量都依赖内核转发没开启的话 Pod 能启动但互访不了。检查sysctl net.ipv4.ip_forward建议在/etc/sysctl.d/99-kubernetes.conf里写好net.bridge.bridge-nf-call-iptables 1 net.bridge.bridge-nf-call-ip6tables 1 net.ipv4.ip_forward 1执行sysctl --system生效。4.3 组件状态速查表我把这次部署涉及的组件状态整理成一张速查表方便你和以后排查时对照。组件关键命令异常表现常见处理Dockerdocker infoCgroupDriver 不是 systemd修改 /etc/docker/daemon.jsoncontainerdcrictl ps无法连接 socket检查 socket 路径是否匹配kubeletsystemctl status kubeletcgroup driver 不匹配对齐运行时驱动后重启kube-proxykubectl logs -n kube-system无法创建 KUBE-SERVICE 链切换 iptables 到 legacyRancher agentdocker logs rancher-agent无法连接 Server检查 443 端口与证书firewalldsystemctl status firewalld端口不通放行常用端口或临时关闭4.4 顺带说下 Rancher Desktop 与 npipe 报错的区分有朋友在 Windows 上安装 Rancher Desktop 时报了failed to connect to the docker api at npipe:////./pipe/docker_engine这个错。这个和 openEuler 部署 Rancher Server 完全是两件事。Rancher Desktop 是本地开发工具通过 Windows 命名管道连接 Docker 引擎。报错原因通常是 Docker Desktop 没启动或者命名管道权限被限制。解决思路和 Linux 容器平台不冲突先确认 Windows 侧 Docker 服务状态再确认当前用户是否在 docker-users 用户组里。如果只是命令行工具想连远程 Rancher Server不要用 Rancher Desktop直接用 kubectl 配置 kubeconfig 即可。我也是在折腾过程中意识到这两类问题名字相近但处理路径完全不同所以单独提出来帮大家避个坑。5. 安全加固与后续运维建议5.1 恢复防火墙并放行最小端口前面为了快速部署把 firewalld 关了但真正用于生产或内网测试时我建议把防火墙重新打开只放行必要端口。Rancher Server 本身要开 80 和 443如果节点要接入集群还需要开 6443API Server、10250kubelet、2379 和 2380etcd以及 UDP 8472VXLAN等。以我单节点全角色为例最小集合是firewall-cmd --permanent --add-port80/tcp firewall-cmd --permanent --add-port443/tcp firewall-cmd --permanent --add-port6443/tcp firewall-cmd --permanent --add-port10250/tcp firewall-cmd --permanent --add-port2379/tcp firewall-cmd --permanent --add-port2380/tcp firewall-cmd --permanent --add-port8472/udp firewall-cmd --reload这里有个注意点防火墙启动之后iptables 的 FORWARD 链策略可能会随 firewalld 规则重置。如果你之前手动iptables -P FORWARD ACCEPT了重载防火墙后记得再确认一次必要时用firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD ACCEPT固定住。5.2 iptables 安全基线经历过这次折腾之后我对 iptables 的认知不只是K8s 必需组件它同时也是安全防护的关键位置。等集群跑起来之后可以针对管理端口做来源限制。比如只允许办公网段访问 Rancher Web 界面iptables -A INPUT -p tcp --dport 443 -s 192.168.1.0/24 -j ACCEPT iptables -A INPUT -p tcp --dport 443 -j DROP同理SSH、API Server 这些端口也可以按同样的思路做来源白名单。要注意的是在 kube-proxy 和 Docker 同时存在的场景下规则写入顺序很重要别在INPUT链上直接DROP ALL否则节点之间 VXLAN 或 Calico 流量会被拦掉。如果你需要更细粒度的策略建议使用支持 nftables 的防火墙管理工具而不是层层叠加 iptables 命令否则规则多了之后维护成本很高。5.3 监控与日志Rancher 部署完成后节点侧的核心服务日志建议集中收集。系统里至少要做三块监控容器运行时日志journalctl -u containerd、Kubernetes 核心组件指标、Rancher Server 容器本身的状态。Rancher UI 自带监控插件但对资源占用比较大测试环境可以不装。常用替代方案是 node_exporter 加 Prometheus跑起来之后重点盯kubelet_volume_metric、container_cpu_usage_seconds_total这些指标。日志方面至少保证 fluent-bit 或 filebeat 能收集/var/log/containers下的标准输出日志。排错的时候如果所有状态都正常但服务访问异常第一步永远是去翻组件日志而不是反复重启服务。这次经历给我最深的感受是cgroup 和 iptables 问题看起来是环境问题其实根子在于组件对内核和系统配置的前置假设没有满足。只要在安装前把内核模块、sysctl、cgroup 驱动、iptables 后端这四件事对齐Rancher 在 OpenEuler 24.03 SP4 上完全可以稳定跑起来。
返回列表