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 相关配置,估计应该是网络相关配置,那到底配置了什么呢?
经过对比分析,该参数至少影响:
kube-proxy
的 cluster-cidr
配置如果创建集群时指定了该参数,那么 kube-proxy
的 cluster-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
...
kube-controller-manager
的 cluster-cidr
配置如果创建集群时指定了该参数,那么 kube-controller-manager
的 cluster-cidr
启动参数就会被设置成该值。对于 kube-controller-manager
,cluster-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 时,网络不通的流量示意图:
开启 SNAT 时,网络通的流量示意图:
kube-controller-manager
的 cluster-cidr
主要用于配置 Node 的 Spec.PodCIDR
。对于某些依赖该特性的网络插件,比如 flannel,可能是必须的,不依赖该特性的网络插件就可以忽略。这个参数也会影响使用 cloud provider 场景下的集群网络配置,比如 aws 路由配置。
1. 当有从集群外节点通过静态路由方式访问集群内 Service 的需求时,需要在创建集群时指定 pod-network-cidr
, 以对来自非 Pod 网络的流量(外部流量)执行 MASQ
2. 当使用的网络插件或云提供商对 kube-controller-manager
的 cluster-cidr
参数有特别要求时,需要设置 pod-network-cidr
,以辅助完成网络相关配置
感谢阅读,如有偏差,欢迎指正!