kubeadm安装报[ERROR FileContent--proc-sys-net-bridge-bridge-nf-call-iptables]: /proc/sys/net/bridge/bridge-nf-call-iptables contents are not set to 1

识趣 发表于: 2021-10-28   最后更新时间: 2021-10-28 19:59:15   2,525 游览

kubeadm安装报错误如下:

[ERROR FileContent--proc-sys-net-bridge-bridge-nf-call-iptables]: /proc/sys/net/bridge/bridge-nf-call-iptables contents are not set to 1

我的操作如下:

kubeadm init --apiserver-advertise-address=10.0.19.91 --pod-network-cidr=192.168.0.0/16

[init] Using Kubernetes version: v1.22.3
[preflight] Running pre-flight checks
error execution phase preflight: [preflight] Some fatal errors occurred:
        [ERROR FileContent--proc-sys-net-bridge-bridge-nf-call-iptables]: /proc/sys/net/bridge/bridge-nf-call-iptables contents are not set to 1
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`
To see the stack trace of this error execute with --v=5 or higher

为什么要设置成1啊?

发表于 2021-10-28

首先,我们来看看kubernetes官方的解释

Network Plugin Requirements

Besides providing the NetworkPlugin interface to configure and clean up pod networking, the plugin may also need specific support for kube-proxy. The iptables proxy obviously depends on iptables, and the plugin may need to ensure that container traffic is made available to iptables. For example, if the plugin connects containers to a Linux bridge, the plugin must set the net/bridge/bridge-nf-call-iptables sysctl to 1 to ensure that the iptables proxy functions correctly. If the plugin does not use a Linux bridge (but instead something like Open vSwitch or some other mechanism) it should ensure container traffic is appropriately routed for the proxy.

By default if no kubelet network plugin is specified, the noop plugin is used, which sets net/bridge/bridge-nf-call-iptables=1 to ensure simple configurations (like Docker with a bridge) work correctly with the iptables proxy.

网络插件要求

除了提供 NetworkPlugin 接口来配置和清理 pod 网络外,该插件可能还需要对 kube-proxy 的特定支持。iptables 代理显然依赖于 iptables,该插件可能需要确保容器的流量对 iptables 可用。例如,如果插件将容器连接到 Linux 网桥,则插件必须将 net/bridge/bridge-nf-call-iptables sysctl 设置为 1,以确保 iptables 代理正常运行。 如果插件不使用 Linux 网桥(而是使用 Open vSwitch 或其他一些机制),它应该确保为代理正确路由容器流量。

默认情况下,如果没有指定kubelet网络插件,就会使用noop插件,将net/bridge/bridge-nf-call-iptables=1以确保简单的配置(如带Docker的bridge)与iptables代理正确工作。

原文:Network Plugin Requirements

没说具体原因,只说了要开,那么我们解释下为什么要改成1

为什么要改成1

在Kubernetes中,不管是 iptables 还是 ipvs 模式,Kubernetes 中访问 service 都会进行 DNAT,将原本访问SVC负载IP:Port 的数据包 DNAT 成 service 的某个Endpoint (PodIP:Port),然后内核将连接信息插入conntrack表以记录连接,目的端回包的时候内核从 conntrack 表匹配连接并SNAT,这样原路返回形成一个完整的连接链路。

net.bridge.bridge-nf-call-iptables

那这个参数是如何影响的返回路径的呢?

CNI使用的是flannel/calico也好,封装的也是linux bridge,linux bridge 是虚拟的二层转发设备,而 iptables conntrack 是在三层上,所以如果直接访问同一网桥内的地址(ip 同一网段),就会直接走二层转发,不经过 conntrack:

结合上面的图来看,同 Node 通过 service 访问 pod 的访问路径如下:

  1. PodA 访问 service, 经过 coreDNS 解析成 SVC IP,不是网桥内的地址(SvcIP 一般跟 PodIP 不在一个网段),走 Conntrack,进行 DNAT,将 SvcIP 转换成 PodIP:Port

  2. DNAT 后发现是要转发到了同节点上的 PodB,PodB 回包时发现目的 IP(此时是 PodA 的 IP) 在同一网桥上(PodA 与 PodB 的 IP 段一致),就直接走二层转发了,不会去调 conntrack,这样就导致回包时没有原路返回。

没有返回包就导致请求方一直等直到超时退出.

最后会发现 PodA 给 PodB 发送了个R Flags, 也就是reset, 就是因为当 PodB 返回握手确认给到 PodA,PodA 根本不认识这个请求,所以直接给 reset 掉了,三手握手都没有建立,这个就是原因了。

这样也是为何访问在其它节点的应用的SVC没有问题,因为目标 PodIP 与源 PodIP 不在同一个网段上,肯定要走conntrack.

结论

禁用net.bridge.bridge-nf-call-iptables这个参数当然也有好外,那就是考虑同网段的 IP 访问没必要走 conntrack,一定程度有助于性能。

kubernetes的官方文档明确提及 Node 节点上需要开启这个参数,不然碰到各种诡异的现象也只是时间问题。

摘自:「bridge-nf-call-iptables 惹的祸」

识趣 -> 半兽人 3年前

666666666

你的答案

查看kubeadm相关的其他问题或提一个您自己的问题