K8s Network: CNI 初探, 以 flannel 为例

355 天前
 GopherDaily

在过去的这些年, K8s 参与并推动了两个容器相关的标准.

一个是挂在 OCI 下的 runtime-spec, 定义并规范了容器运行的方方面面. 依赖于此我们使用 K8s 时可以自由选择底层的容器运行时实现而不影响上层功能.

另一个是 CNI (Container Network Interface), 定义了容器运行时如何管理容器网络. 在这个标准下开发的各类插件都可以直接在容器运行时中使用, 不再需要双方适配.

CNI 速览

CNI 中有两个关键角色, 一是容器运行时, 一是各类网络插件. 容器运行时负责在容器创建和销毁时, 根据配置调用指定插件的 ADD 和 DEL 命令.

同时, 比较有意义的点是:

为了避免重复实现, CNI 推荐插件通过调用其他插件来完成部分工作, 即 delegate. 同时, CNI 也为最基本的那部分需求提供了官方插件, 罗列于 Plugins Overview.

flannel

Flannel 是一个简单但流行的容器网络方案, 其提供了一个 200 多行的 Yaml 文件来将自身部署到 K8s 中, 具体参见 kube-flannel.yaml.

部署的核心逻辑在于其中的 DaemonSet,

flannel-cni

容器运行时根据配置文件调用 flannel-cni 后, flannel-cni 会生成具体的配置文件调用其他插件来完成具体工作.

我们可以在宿主机上找到生成的具体配置信息:

~ cat /var/lib/cni/flannel/0e31e47db3bdb67088cd4b2369e641a8eea835208161177a02cbf6b8d26f3373 | jq
{
  "cniVersion": "0.3.1",
  "hairpinMode": true,
  "ipMasq": false,
  "ipam": {
    "ranges": [
      [
        {
          "subnet": "172.22.0.0/24"
        }
      ]
    ],
    "routes": [
      {
        "dst": "172.22.0.0/16"
      }
    ],
    "type": "host-local"
  },
  "isDefaultGateway": true,
  "isGateway": true,
  "mtu": 1500,
  "name": "cbr0",
  "type": "bridge"
}

这份配置文件依然遵循 CNI 的配置规范, 我们可以看出其调用了插件 bridge. bridge 会将宿主机上的所有容器都链接到一个虚拟交换机上. 同时也调用 IPAM 在指定的网段内为容器分配了 IP.

flannel daemon

flannel 以 DaemonSet 的方式运行在宿主机上.

我们以测试集群为例, 其配置保存 ConfigMap 中, 并且开启了 ipmasq.

~ k get -n kube-flannel cm kube-flannel-cfg -o json | jq '.data["net-conf.json"]' -r | jq
{
  "Network": "172.22.0.0/16",
  "Backend": {
    "Type": "host-gw"
  }
}
~ ps -ef | grep flanneld
root      49965  49079  0 8 月 01 ?       09:00:24 /opt/bin/flanneld --ip-masq --kube-subnet-mgr
root     224755 308100  0 12:11 pts/0    00:00:00 grep --color=auto flanneld

flanneld 的主要职责包括三个方面. 一是将提供给 flannel-cni 的配置文件保存到宿主机的文件系统, 其中包括了宿主机的 podCIDR.

~ cat /run/flannel/subnet.env
FLANNEL_NETWORK=172.22.0.0/16
FLANNEL_SUBNET=172.22.0.1/24
FLANNEL_MTU=1500
FLANNEL_IPMASQ=true

二是通过 iptables 为进出容器网络的流量做 SNAT.

~ iptables -t nat -L | grep "Chain FLANNEL-POSTRTG" -A 8
Chain FLANNEL-POSTRTG (1 references)
target     prot opt source               destination
RETURN     all  --  anywhere             anywhere             mark match 0x4000/0x4000 /* flanneld masq */
RETURN     all  --  172.22.0.0/24        172.22.0.0/16        /* flanneld masq */
RETURN     all  --  172.22.0.0/16        172.22.0.0/24        /* flanneld masq */
RETURN     all  -- !172.22.0.0/16        172.22.0.0/24        /* flanneld masq */
MASQUERADE  all  --  172.22.0.0/16       !base-address.mcast.net/4  /* flanneld masq */
MASQUERADE  all  -- !172.22.0.0/16        172.22.0.0/16        /* flanneld masq */

MASQUERADE 的效果类似 SNAT, 其会修改数据包的来源地址. Pod 访问外界网络的请求, 经过宿主机后, 来源地址会被修改宿主机, 因为 Pod IP 仅在容器网络内有效.

三是监听 node 信息后, 通过 ip route 将目标为宿主机上容器的数据包转发到宿主机. 172.22.1.0/24 是另一个节点的 podCIDR, 任何发送到相关容器的流量都会被转发给宿主机.

~ ip route | grep 172.22.1.0/24
172.22.1.0/24 via 10.30.180.55 dev eth0
~ k get nodes 10.30.180.55 -o json | jq '.spec.podCIDR' -r
172.22.1.0/24

Source: https://github.com/j2gg0s/j2gg0s/blob/main/_posts/2023-12-07-k8s%20network%3A%20CNI%20%E5%88%9D%E6%8E%A2%2C%20%E4%BB%A5%20flannel%20%E4%B8%BA%E4%BE%8B.md

969 次点击
所在节点    Kubernetes
2 条回复
FabricPath
355 天前
可以学点好的,比如 Cilium
GopherDaily
355 天前
@FabricPath ROI 很关键,人力有限

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/998348

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX