calico 三、IPPool与封装

大番茄 2020年03月13日 5,347次浏览

IPPool(地址池)也是calico里的一个资源对象,从地址池中分配地址给pod。
https://docs.projectcalico.org/v3.11/reference/resources/ippool

样例:

apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  name: my.ippool-1
spec:
  cidr: 10.1.0.0/16
  ipipMode: CrossSubnet
  natOutgoing: true
  disabled: false
  nodeSelector: all()

IPPool配置项:
cidr: 地址范围
blockSize: 块大小,按需分配给主机,用于汇总路由。只能在创建ippool的时候设置。
ipipMode: ipip隧道模式,不能与vxlanMode同时使用, 有三个值。

  • Always: 始终使用IPIP隧道。
  • CrossSubnet: 只有在跨子网的时候才使用IPIP隧道。
  • Never: 不使用IPIP。
    vxlanMode: vxlan隧道模式,不能与ipipMode同时使用。有三个值,跟ipipMode的一样。
  • Always: 始终使用VXLAN隧道。
  • CrossSubnet: 只有在跨子网的时候才使用VXLAN隧道。
  • Never: 不使用VXLAN。
    natOutgoing: 启用后,由本地址池分配的容器发往外网的数据包会做伪装(MASQUERADE)。 true, false。
    disabled: 设置为true时,calico IPAM将不会分配本地址池里的地址。
    nodeSelector: 节点标签选择器,calico IPAM只为匹配的节点分配地址。默认: all()。

一、配置pod访问外网SNAT

https://docs.projectcalico.org/v3.11/networking/workloads-outside-cluster
默认就是允许的,IPPool的natOutgoing参数。 启用后将为pod访问外网做SNAT。如果pod只能通过SNAT访问外网,关闭以后,pod将无法访问外网。 也是通过iptables规则实现的。calico生成的规则在kube-proxy之前,所以kube-proxy那个SNAT规则用不上。
就是这条规则, false以后就没有了。

Chain cali-nat-outgoing (1 references)
num   pkts bytes target     prot opt in     out     source               destination
1        3   216 MASQUERADE  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* cali:Dw4T8UWPnCLxRJiI */ match-set cali40masq-ipam-pools src ! match-set cali40all-ipam-pools dst

修改也很简单,首先把在使用的ippool的配置导出来。

calicoctl get ippool -o yaml > ippool.yaml
apiVersion: projectcalico.org/v3
items:
- apiVersion: projectcalico.org/v3
  kind: IPPool
  metadata:
    creationTimestamp: "2020-03-10T11:29:34Z"
    name: default-ipv4-ippool
    resourceVersion: "740608"
    uid: 9c43b0ea-33f4-4fb4-b964-6b635748e10a
  spec:
    blockSize: 26
    cidr: 10.6.0.0/16
    ipipMode: Never
    natOutgoing: true
    nodeSelector: all()
    vxlanMode: Never
kind: IPPoolList
metadata:
  resourceVersion: "743895"

natOutgoint改为false后应用:

[root@k8s-master ~]# calicoctl apply -f ippool.yaml
Successfully applied 1 'IPPool' resource(s)

再看iptables就没有这条规则了。

Chain cali-nat-outgoing (1 references)
num   pkts bytes target     prot opt in     out     source               destination

二、隧道封装

https://docs.projectcalico.org/v3.11/networking/vxlan-ipip

确定MTU大小

https://docs.projectcalico.org/v3.11/networking/mtu
因为会封装额外的头部信息,所以MTU需要与物理MTU小。 IPIP会封装20字节头部,VXLAN会封装50字节头部。 所以,如果物理MTU是1500,IPIP环境需要设置MTU为1480, VXLAN环境需要设置为1450。
修改MTU需要更改configmap里的veth_mtu设置。 然后重启calico-node
新安装的calico默认MTU是1440, 两个封装类型都可以用。 我这里因为修改过了,所以改一下。

17: cali64a9a8c99ea@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 qdisc noqueue state UP mode DEFAULT group default
    link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 0
18: cali14aa1c2585d@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 qdisc noqueue state UP mode DEFAULT group default
    link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 1

可以看到我这里的MTU是9000。 为了两个类型都可以测试,直接修改为1450。

[root@k8s-master ~]# kubectl get configmap -n kube-system
NAME                                 DATA   AGE
calico-config                        8      2d19h
extension-apiserver-authentication   1      6d5h
[root@k8s-master ~]# kubectl edit configmap/calico-config -n kube-system

image.png
把这个改成1450以后保存。
重启calico-node

[root@k8s-master ~]# kubectl get daemonset -n kube-system
NAME          DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR                 AGE
calico-node   3         3         3       3            3           beta.kubernetes.io/os=linux   3h41m
[root@k8s-master ~]# kubectl rollout restart daemonset/calico-node -n kube-system
daemonset.apps/calico-node restarted
[root@k8s-master ~]#

注意,已存在的pod的网卡mtu是不会变的。
image.png

修改为IPIP模式。

注意,修改模式可能会导致正在进行的连接中断。
修改IPPool配置ipipMode: Always
image.png

应用:

[root@k8s-master ~]# calicoctl apply -f ippool.yaml
Successfully applied 1 'IPPool' resource(s)

应用完成以后,多了一个ipip类型的tunl0网卡。类型可以通过ip link list type ipip来确定。

20: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default qlen 1000
    link/ipip 0.0.0.0 brd 0.0.0.0
    inet 10.6.36.73/32 brd 10.6.36.73 scope global tunl0
       valid_lft forever preferred_lft forever

容器里也多出来一个,不知道干嘛用的,而且mtu就是1480,经过后面的一些修改还是1480, 固定不变。

2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ipip 0.0.0.0 brd 0.0.0.0

路由也变了:
image.png

修改为VXLAN模式

修改ippool配置并应用。
image.png
可能需要重新导出一份ippool配置来修改。那个resourceVersion可能有限制。
应用以后多出来一个vxlan类型的vxlan网卡。

20: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default qlen 1000
    link/ipip 0.0.0.0 brd 0.0.0.0
21: vxlan.calico: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1410 qdisc noqueue state UNKNOWN group default
    link/ether 66:8c:73:5a:90:99 brd ff:ff:ff:ff:ff:ff
    inet 10.6.36.74/32 brd 10.6.36.74 scope global vxlan.calico
       valid_lft forever preferred_lft forever
    inet6 fe80::648c:73ff:fe5a:9099/64 scope link
       valid_lft forever preferred_lft forever

查看路由

10.6.107.192/26 via 10.6.107.197 dev vxlan.calico onlink
10.6.169.128/26 via 10.6.169.140 dev vxlan.calico onlink

发现上面vxlan的网卡mtu有点不对, 看来他并不是从configmap里那个参数拿的。可能需要修改FelixConfiguration资源对象。

修改MTU

[root@k8s-master ~]# calicoctl get FelixConfiguration
NAME
default
node.k8s-node1
node.k8s-node2
node.k8s-node3

修改default。
导出配置并修改:

apiVersion: projectcalico.org/v3
kind: FelixConfiguration
metadata:
  creationTimestamp: "2020-03-10T11:29:34Z"
  name: default
  resourceVersion: "747102"
  uid: ff25ed78-3689-44cd-99bc-bfbb7f43a0fe
spec:
  XDPRefreshInterval: null
  ipipEnabled: true
  ipipMTU: 1480
  vxlanMTU: 1450
  logSeverityScreen: Info
  reportingInterval: 0s
  vxlanEnabled: true

ipipMTU与vxlanMTU都指定了。
应用以后,vxlan的网卡mtu就变了。

20: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/ipip 0.0.0.0 brd 0.0.0.0
21: vxlan.calico: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN mode DEFAULT group default
    link/ether 66:8c:73:5a:90:99 brd ff:ff:ff:ff:ff:ff

再次切换到ipip, 发现ipip的网卡mtu还是原来的,估计这个是使用的configmap里指定的那个参数。

FelixConfiguration其他的参数就不研究了。
大家有兴趣的话,官网:
https://docs.projectcalico.org/v3.11/reference/resources/felixconfig

简单看了一下,里面确实说明了,ipipMTU不是从FelixConfiguration里配置的, vxlanMTU是。

其他一些注意事项

  1. calico可以自动判断kube-proxy使用的iptables还是ipvs。 Calico还使用NodePorts将流量路由到集群,但是如果NodePort的默认范围修改了,不是30000:32767, 需要在FelixConfiguration里修改一下KubeNodePortRange选项。
    https://docs.projectcalico.org/v3.11/networking/use-ipvs
    https://docs.projectcalico.org/v3.11/reference/felix/configuration