kubeadm 集群初始化参数 pod-network-cidr 有什么作用?

问题

kubeadm init 创建集群时有个参数,即 pod-network-cidr,在以往使用过程中,不设置该参数似乎创建的集群也能正常工作,那它究竟有什么作用呢?

影响范围

kubeadm 给出的参数释义是:

--pod-network-cidr Specify range of IP addresses for the pod network. If set, the control plane will automatically allocate CIDRs for every node.

大概意思是该参数指明了 Pod 网络的 CIDR,以用于 Node 相关配置,估计应该是网络相关配置,那到底配置了什么呢?

经过对比分析,该参数至少影响:

1. kube-proxycluster-cidr 配置

如果创建集群时指定了该参数,那么 kube-proxycluster-cidr 就会被设置成该值(不指定该参数时,cluster-cidr 的默认值为空)。cluster-cidr 主要用于帮助 kube-proxy 区分内外流量:当值为空时,kube-proxy 认为所有流量都是内部流量,不做 SNAT(MASQ);当值非空时,来自 cluster-cidr 网络(即 Pod 网络)的流量被当成内部流量,访问 Service 时不做 SNAT(MASQ),来自其他网络的流量被当成外部流量,访问 Service 时需要做 SNAT(MASQ)。此外,kube-proxy 还提供了一个独立参数 masquerade-all,如果设置了该参数,那所有访问 Service 的流量都会做 SNAT(MASQ),不再区分内外流量。

当设置了 cluster-cidr (这里以 192.168.0.0/16 为例)时,生成的对非 Pod 网络流量执行 SNAT(MASQ) 的 iptables 规则示意如下:

# iptables -t nat -S 
...
-A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A KUBE-SERVICES ! -s 192.168.0.0/16 -d 10.96.0.1/32 -p tcp -m comment --comment "default/kubernetes:https cluster IP" -m tcp --dport 443 -j KUBE-MARK-MASQ
-A KUBE-MARK-MASQ -j MARK --set-xmark 0x4000/0x4000
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -m mark --mark 0x4000/0x4000 -j MASQUERADE
...
2. kube-controller-managercluster-cidr 配置

如果创建集群时指定了该参数,那么 kube-controller-managercluster-cidr 启动参数就会被设置成该值。对于 kube-controller-managercluster-cidr 需要在 allocate-node-cidrs 参数设置为 true 时才能联合发挥作用,主要用于为没有设置 Spec.PodCIDR 的 Node 节点配置 PodCIDR 地址,这个属性在某些场景下能帮助节点完成网络相关的设置工作。

当指定 cluster-cidr 参数(这里以 192.168.0.0/16 为例)后, kube-controller-manager 的启动参数形如:

  containers:
  - command:
    - kube-controller-manager
    - --allocate-node-cidrs=true
    - --authentication-kubeconfig=/etc/kubernetes/controller-manager.conf
    - --authorization-kubeconfig=/etc/kubernetes/controller-manager.conf
    - --bind-address=127.0.0.1
    - --client-ca-file=/etc/kubernetes/pki/ca.crt
    - --cluster-cidr=192.168.0.0/16
    - --cluster-signing-cert-file=/etc/kubernetes/pki/ca.crt
    - --cluster-signing-key-file=/etc/kubernetes/pki/ca.key
    - --controllers=*,bootstrapsigner,tokencleaner
    - --kubeconfig=/etc/kubernetes/controller-manager.conf
    - --leader-elect=true
    - --node-cidr-mask-size=24
    - --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt
    - --root-ca-file=/etc/kubernetes/pki/ca.crt
    - --service-account-private-key-file=/etc/kubernetes/pki/sa.key
    - --use-service-account-credentials=true
    image: k8s.gcr.io/kube-controller-manager:v1.14.2

作用分析

kube-proxy 对访问 Service 的流量执行 SNAT(MASQ) 的目的,引用原文如下:

The idea is that you can establish a static route for your Service range, routing to any node, and that node will bridge into the Service for you.  
Since that might bounce off-node, we masquerade here.

简单理解就是,如果有这个 SNAT(MASQ) 功能,那集群外的 Node 就可以通过设置静态路由的方式,将访问 Service 网络的数据包路由到集群内的任何一台机器上,即可从集群外轻松访问集群内的 Service,类似于集群内机器可以充当跳板 Router。否则,在集群外访问 Service 服务就没那么容易了。从这点来看,如果有从集群外访问 Service 的需求,还是应该设置 pod-network-cidr ,开启 SNAT(MASQ) 功能的。如果没有这种需求,那就设不设置均可。附上官方关于开启 MASQ 的 ISSUE https://github.com/kubernetes/kubernetes/issues/24224 和 PR https://github.com/kubernetes/kubernetes/pull/24429

不开启 SNAT 时,网络不通的流量示意图:
kubeadm 集群初始化参数 pod-network-cidr 有什么作用?_第1张图片开启 SNAT 时,网络通的流量示意图:
kubeadm 集群初始化参数 pod-network-cidr 有什么作用?_第2张图片

kube-controller-managercluster-cidr 主要用于配置 Node 的 Spec.PodCIDR。对于某些依赖该特性的网络插件,比如 flannel,可能是必须的,不依赖该特性的网络插件就可以忽略。这个参数也会影响使用 cloud provider 场景下的集群网络配置,比如 aws 路由配置。

结论

1. 当有从集群外节点通过静态路由方式访问集群内 Service 的需求时,需要在创建集群时指定 pod-network-cidr, 以对来自非 Pod 网络的流量(外部流量)执行 MASQ
2. 当使用的网络插件或云提供商对 kube-controller-managercluster-cidr 参数有特别要求时,需要设置 pod-network-cidr,以辅助完成网络相关配置

感谢阅读,如有偏差,欢迎指正!

你可能感兴趣的:(容器技术)