带你玩转kubernetes-k8s(第49篇:深入分析k8s网络原理-[直接路由,Calico部署])

释放双眼,带上耳机,听听看~!

        我们知道,docker0网桥上的IP地址在Node网络上是看不到的。从一个Node到一个Node内的docker0是不通的,因为它不知道某个IP地址在哪里。如果能够让这些机器知道对端docker0地址在哪里,就可以让这些docker0互相通信了。这样,在所有Node上运行的Pod就都可以互相通信了。

       我们可以通过部署MultiLayer Switch(MLS)来实现这一点,在MLS中配置每个docker0子网地址到Node地址的路由项,通过MLS将docker0的IP寻址定向到对应的Node上。
另外,我们可以将这些docker0和Node的匹配关系配置在Linux操作系统的路由项中,这样通信发起的Node就能够根据这些路由信息直接找到目标Pod所在的Node,将数据传输过去。            

我们在每个Node的路由表中增加对方所有docker0的路由项。

 

     例如,Pod1所在docker0网桥的IP子网是10.1.10.0,Node的地址为192.168.1.128;而Pod2所在docker0网桥的IP子网是10.1.20.0,Node的地址为192.168.1.129。
在Node1上用route add命令增加一条到Node2上docker0的静态路由规则:


1
2
1route add -net 10.1.20.0 netmask 255.255.255.0 gw 192.168.1.129
2

     同样,在Node2上增加一条到Node1上docker0的静态路由规则:


1
2
1route add -net  10.1.10.0 netmask 255.255.255.0 gw 192.168.1.128
2

   在Node1上通过ping命令验证到Node2上docker0的网络连通性。这里10.1.20.1为Node2上docker0网桥自身的IP地址.

   可以看到,路由转发规则生效,Node1可以直接访问Node2上的docker0网桥,进一步就可以访问属于docker0网段的容器应用了。

    在大规模集群中,在每个Node上都需要配置到其他docker0/Node的路由项,这会带来很大的工作量;并且在新增机器时,对所有Node都需要修改配置;在重启机器时,如果docker0的地址有变化,则也需要修改所有Node的配置,这显然是非常复杂的。

    为了管理这些动态变化的docker0地址,动态地让其他Node都感知到它,还可以使用动态路由发现协议来同步这些变化。在运行动态路由发现协议代理的Node时,会将本机LOCAL路由表的IP地址通过组播协议发布出去,同时监听其他Node的组播包。通过这样的信息交换,Node上的路由规则就都能够相互学习。当然,路由发现协议本身还是很复杂的,感兴趣的话,可以查阅相关规范。在实现这些动态路由发现协议的开源软件中,常用的有Quagga(http://www.quagga.net)、Zebra等。下面简单介绍直接路由的操作过程。

  

     首先,手工分配Docker bridge的地址,保证它们在不同的网段是不重叠的。建议最好不用Docker Daemon自动创建的docker0(因为我们不需要它的自动管理功能),而是单独建立一个bridge,给它配置规划好的IP地址,然后使用–bridge=XX来指定网桥。
然后,在每个节点上都运行Quagga。

    完成这些操作后,我们很快就能得到一个Pod和Pod直接互相访问的环境了。由于路由发现能够被网络上的所有设备接收,所以如果网络上的路由器也能打开RIP协议选项,则能够学习到这些路由信息。通过这些路由器,我们甚至可以在非Node上使用Pod的IP地址直接访问Node上的Pod了。

    除了在每台服务器上安装Quagga软件并启动,还可以使用Quagga容器运行(例如index.alauda.cn/georce/router)。在每个Node上下载该Docker镜像:


1
2
1docker pull index.alauda.cn/georce/router
2

      在运行Quagga容器之前,需要确保每个Node上docker0网桥的子网地址不能重叠,也不能与物理机所在的网络重叠,这需要网络管理员的仔细规划。

    下面以3个Node为例,每个Node的docker0网桥的地址如下(前提是Node物理机的IP地址不是10.1.X.X地址段):


1
2
3
4
1node1:#if config docker0 10.1.10.1/24
2node2: #if config docker0 10.1.20.1/24
3node3: #if config docker0 10.1.30.1/24
4

       在每个Node上启动Quagga容器。需要说明的是,Quagga需要以–privileged特权模式运行,并且指定–net=host,表示直接使用物理机的网络:


1
2
1docker run -itd --name=router --privileged --net=host  index.alauda.cn/georce/router
2

启动成功后,各Node上的Quagga会相互学习来完成到其他机器的docker0路由规则的添加。

一段时间后,在Node1上使用route -n命令来查看路由表,可以看到Quagga自动添加了两条到Node2和到Node3上docker0的路由规则:


1
2
1route -n
2

在Node2上查看路由表,可以看到自动添加了两条到Node1和Node3上docker0的路由规则:


1
2
1route -n
2

至此,所有Node上的docker0就都可以互联互通了。

      当然,聪明的你还会有新的疑问:这样做的话,由于每个Pod的地址都会被路由发现协议广播出去,会不会存在路由表过大的情况?实际上,路由表通常都会有高速缓存,查找速度会很快,不会对性能产生太大的影响。当然,如果你的集群容量在数千个Node以上,则仍然需要测试和评估路由表的效率问题。

Calico容器网络和网络策略实战

   本节以Calico为例讲解kubernetes中CNI插件和网络策略的原理和应用。

Calico简介

    Calico是一个基于BGP的纯三层的网络方案,与OpenStack、Kubernetes、AWS、GCE等云平台都能够良好地集成。Calico在每个计算节点都利用Linux Kernel实现了一个高效的vRouter来负责数据转发。每个vRouter都通过BGP1协议把在本节点上运行的容器的路由信息向整个Calico网络广播,并自动设置到达其他节点的路由转发规则。Calico保证所有容器之间的数据流量都是通过IP路由的方式完成互联互通的。Calico节点组网时可以直接利用数据中心的网络结构(L2或者L3),不需要额外的NAT、隧道或者Overlay Network,没有额外的封包解包,能够节约CPU运算,提高网络效率。

    Calico在小规模集群中可以直接互联,在大规模集群中可以通过额外的BGP route reflector来完成。

   此外,Calico基于iptables还提供了丰富的网络策略,实现了Kubernetes的Network Policy策略,提供容器间网络可达性限制的功能。

   Calico的系统架构如下图所示:

 

Calico的主要组件如下。
◎ Felix:Calico Agent,运行在每个Node上,负责为容器设置网络资源(IP地址、路由规则、iptables规则等),保证跨主机容器网络互通。
◎ etcd:Calico使用的后端存储。
◎ BGP Client:负责把Felix在各Node上设置的路由信息通过BGP协议广播到Calico网络。
◎ Route Reflector:通过一个或者多个BGP Route Reflector来完成大规模集群的分级路由分发。
◎ CalicoCtl:Calico命令行管理工具。

部署Calico服务   

在Kubernetes中部署Calico的主要步骤如下。
(1)修改Kubernetes服务的启动参数,并重启服务。
◎ 设置Master上kube-apiserver服务的启动参数:–allow-privileged=true(因为calico-node需要以特权模式运行在各Node上)。

本例中的Kubernetes集群包括两个Node:k8s-node-1(IP地址为192.168.18.3)和k8s-node-2(IP地址为192.168.18.4)。

(2)创建Calico服务,主要包括calico-node和calico policy controller。需要创建的资源对象如下。
◎ 创建ConfigMap calico-config,包含Calico所需的配置参数。
◎ 创建Secret calico-etcd-secrets,用于使用TLS方式连接etcd。
◎ 在每个Node上都运行calico/node容器,部署为DaemonSet。
◎ 在每个Node上都安装Calico CNI二进制文件和网络配置参数(由install-cni容器完成)。
◎ 部署一个名为calico/kube-policy-controller的Deployment,以对接Kubernetes集群中为Pod设置的Network Policy。

      从Calico官网下载Calico的YAML配置文件,下载地址为:


1
2
1http://docs.projectcalico.org/v3.5/getting-started/kubernetes/installation/hosted/calico.yaml
2

该配置文件包括启动Calico所需的全部资源对象的定义,下面对它们逐个进行说明。

(1)Calico所需的配置,以ConfigMap对象进行创建:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
1kind: ConfigMap
2apiVersion: v1
3metadata:
4  name: calico-config
5  namespace: kube-system
6data:
7  # 配置etcd的服务URL
8  etcd_endpoints: "http://192.168.18.3:2379"
9
10  # 如何etcd启用了https安全认证,则需要配置etcd相关证书
11  etcd_ca: ""   # "/calico-secrets/etcd-ca"
12  etcd_cert: "" # "/calico-secrets/etcd-cert"
13  etcd_key: ""  # "/calico-secrets/etcd-key"
14  # Typha is disabled.
15  typha_service_name: "none"
16  # 设置Calico 使用的backennd 类型,默认是bird
17  calico_backend: "bird"
18
19  # 设置 mtu值
20  veth_mtu: "1440"
21
22  # The CNI network configuration to install on each node.  The special
23  # values in this config will be automatically populated.
24  # 设置CNI 网络配置文件的内容
25  cni_network_config: |-
26    {
27      "name": "k8s-pod-network",
28      "cniVersion": "0.3.0",
29      "plugins": [
30        {
31          "type": "calico",
32          "log_level": "info",
33          "etcd_endpoints": "__ETCD_ENDPOINTS__",
34          "etcd_key_file": "__ETCD_KEY_FILE__",
35          "etcd_cert_file": "__ETCD_CERT_FILE__",
36          "etcd_ca_cert_file": "__ETCD_CA_CERT_FILE__",
37          "mtu": __CNI_MTU__,
38          "ipam": {
39              "type": "calico-ipam"
40          },
41          "policy": {
42              "type": "k8s"
43          },
44          "kubernetes": {
45              "kubeconfig": "__KUBECONFIG_FILEPATH__"
46          }
47        },
48        {
49          "type": "portmap",
50          "snat": true,
51          "capabilities": {"portMappings": true}
52        }
53      ]
54    }
55
56

对主要参数说明如下。

◎ etcd_endpoints:Calico使用etcd来保存网络拓扑和状态,该参数指定etcd服务的地址。
◎ calico_backend:Calico的后端,默认为bird。
◎ cni_network_config:符合CNI规范的网络配置。其中type=calico表示kubelet将从/opt/cni/bin目录下搜索名为calico的可执行文件,并调用它来完成容器网络的设置。ipam中的type=calico-ipam表示kubelet将在/opt/cni/bin目录下搜索名为calico-ipam的可执行文件,用于完成容器IP地址的分配。

    如果etcd服务配置了TLS安全认证,则还需指定相应的ca、cert、key等文件。

(2)访问etcd所需的secret,对于无TLS的etcd服务,将data设置为空即可:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1apiVersion: v1
2kind: Secret
3type: Opaque
4metadata:
5  name: calico-etcd-secrets
6  namespace: kube-system
7data:
8  # Populate the following with etcd TLS configuration if desired, but leave blank if
9  # not using TLS for etcd.
10  # The keys below should be uncommented and the values populated with the base64
11  # encoded contents of each file that would be associated with the TLS data.
12  # Example command for encoding a file contents: cat <file> | base64 -w 0
13  # 如果配置了TLS ,则需要设置相应的证书和密钥文件路径
14  # etcd-key: null
15  # etcd-cert: null
16  # etcd-ca: null
17
18
19
20

(3)calico-node,以DaemonSet方式在每个Node上都运行一个calico-node服务和一个install-cni服务:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
1kind: DaemonSet
2apiVersion: extensions/v1beta1
3metadata:
4  name: calico-node
5  namespace: kube-system
6  labels:
7    k8s-app: calico-node
8spec:
9  selector:
10    matchLabels:
11      k8s-app: calico-node
12  updateStrategy:
13    type: RollingUpdate
14    rollingUpdate:
15      maxUnavailable: 1
16  template:
17    metadata:
18      labels:
19        k8s-app: calico-node
20      annotations:
21        # This, along with the CriticalAddonsOnly toleration below,
22        # marks the pod as a critical add-on, ensuring it gets
23        # priority scheduling and that its resources are reserved
24        # if it ever gets evicted.
25        scheduler.alpha.kubernetes.io/critical-pod: ''
26    spec:
27      nodeSelector:
28        beta.kubernetes.io/os: linux
29      hostNetwork: true
30      tolerations:
31        # Make sure calico-node gets scheduled on all nodes.
32        - effect: NoSchedule
33          operator: Exists
34        # Mark the pod as a critical add-on for rescheduling.
35        - key: CriticalAddonsOnly
36          operator: Exists
37        - effect: NoExecute
38          operator: Exists
39      serviceAccountName: calico-node
40      # Minimize downtime during a rolling upgrade or deletion; tell Kubernetes to do a "force
41      # deletion": https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods.
42      terminationGracePeriodSeconds: 0
43      initContainers:
44        # This container installs the Calico CNI binaries
45        # and CNI network config file on each node.
46        - name: install-cni
47          image: calico/cni:v3.5.8
48          command: ["/install-cni.sh"]
49          env:
50            # Name of the CNI config file to create.
51            - name: CNI_CONF_NAME
52              value: "10-calico.conflist"
53            # The CNI network config to install on each node.
54            - name: CNI_NETWORK_CONFIG
55              valueFrom:
56                configMapKeyRef:
57                  name: calico-config
58                  key: cni_network_config
59            # The location of the Calico etcd cluster.
60            - name: ETCD_ENDPOINTS
61              valueFrom:
62                configMapKeyRef:
63                  name: calico-config
64                  key: etcd_endpoints
65            # CNI MTU Config variable
66            - name: CNI_MTU
67              valueFrom:
68                configMapKeyRef:
69                  name: calico-config
70                  key: veth_mtu
71            # Prevents the container from sleeping forever.
72            - name: SLEEP
73              value: "false"
74          volumeMounts:
75            - mountPath: /host/opt/cni/bin
76              name: cni-bin-dir
77            - mountPath: /host/etc/cni/net.d
78              name: cni-net-dir
79            - mountPath: /calico-secrets
80              name: etcd-certs
81      containers:
82        # Runs calico/node container on each Kubernetes node.  This
83        # container programs network policy and routes on each
84        # host.
85        - name: calico-node
86          image: calico/node:v3.5.8
87          env:
88            # The location of the Calico etcd cluster.
89            - name: ETCD_ENDPOINTS
90              valueFrom:
91                configMapKeyRef:
92                  name: calico-config
93                  key: etcd_endpoints
94            # Location of the CA certificate for etcd.
95            - name: ETCD_CA_CERT_FILE
96              valueFrom:
97                configMapKeyRef:
98                  name: calico-config
99                  key: etcd_ca
100            # Location of the client key for etcd.
101            - name: ETCD_KEY_FILE
102              valueFrom:
103                configMapKeyRef:
104                  name: calico-config
105                  key: etcd_key
106            # Location of the client certificate for etcd.
107            - name: ETCD_CERT_FILE
108              valueFrom:
109                configMapKeyRef:
110                  name: calico-config
111                  key: etcd_cert
112            # Set noderef for node controller.
113            - name: CALICO_K8S_NODE_REF
114              valueFrom:
115                fieldRef:
116                  fieldPath: spec.nodeName
117            # Choose the backend to use.
118            - name: CALICO_NETWORKING_BACKEND
119              valueFrom:
120                configMapKeyRef:
121                  name: calico-config
122                  key: calico_backend
123            # Cluster type to identify the deployment type
124            - name: CLUSTER_TYPE
125              value: "k8s,bgp"
126            # Auto-detect the BGP IP address.
127            - name: IP
128              value: "autodetect"
129            # Enable IPIP
130            - name: CALICO_IPV4POOL_IPIP
131              value: "Always"
132            # Set MTU for tunnel device used if ipip is enabled
133            - name: FELIX_IPINIPMTU
134              valueFrom:
135                configMapKeyRef:
136                  name: calico-config
137                  key: veth_mtu
138            # The default IPv4 pool to create on startup if none exists. Pod IPs will be
139            # chosen from this range. Changing this value after installation will have
140            # no effect. This should fall within `--cluster-cidr`.
141            - name: CALICO_IPV4POOL_CIDR
142              value: "192.168.0.0/16"
143            # Disable file logging so `kubectl logs` works.
144            - name: CALICO_DISABLE_FILE_LOGGING
145              value: "true"
146            # Set Felix endpoint to host default action to ACCEPT.
147            - name: FELIX_DEFAULTENDPOINTTOHOSTACTION
148              value: "ACCEPT"
149            # Disable IPv6 on Kubernetes.
150            - name: FELIX_IPV6SUPPORT
151              value: "false"
152            # Set Felix logging to "info"
153            - name: FELIX_LOGSEVERITYSCREEN
154              value: "info"
155            - name: FELIX_HEALTHENABLED
156              value: "true"
157          securityContext:
158            privileged: true
159          resources:
160            requests:
161              cpu: 250m
162          livenessProbe:
163            httpGet:
164              path: /liveness
165              port: 9099
166              host: localhost
167            periodSeconds: 10
168            initialDelaySeconds: 10
169            failureThreshold: 6
170          readinessProbe:
171            exec:
172              command:
173              - /bin/calico-node
174              - -bird-ready
175              - -felix-ready
176            periodSeconds: 10
177          volumeMounts:
178            - mountPath: /lib/modules
179              name: lib-modules
180              readOnly: true
181            - mountPath: /run/xtables.lock
182              name: xtables-lock
183              readOnly: false
184            - mountPath: /var/run/calico
185              name: var-run-calico
186              readOnly: false
187            - mountPath: /var/lib/calico
188              name: var-lib-calico
189              readOnly: false
190            - mountPath: /calico-secrets
191              name: etcd-certs
192      volumes:
193        # Used by calico/node.
194        - name: lib-modules
195          hostPath:
196            path: /lib/modules
197        - name: var-run-calico
198          hostPath:
199            path: /var/run/calico
200        - name: var-lib-calico
201          hostPath:
202            path: /var/lib/calico
203        - name: xtables-lock
204          hostPath:
205            path: /run/xtables.lock
206            type: FileOrCreate
207        # Used to install CNI.
208        - name: cni-bin-dir
209          hostPath:
210            path: /opt/cni/bin
211        - name: cni-net-dir
212          hostPath:
213            path: /etc/cni/net.d
214        # Mount in the etcd TLS secrets with mode 400.
215        # See https://kubernetes.io/docs/concepts/configuration/secret/
216        - name: etcd-certs
217          secret:
218            secretName: calico-etcd-secrets
219            defaultMode: 0400
220
221
222

在该Pod中包括如下两个容器。
◎ install-cni:在Node上安装CNI二进制文件到/opt/cni/bin目录下,并安装相应的网络配置文件到/etc/cni/net.d目录下,设置为initContainers并在运行完成后退出。
◎ calico-node:Calico服务程序,用于设置Pod的网络资源,保证Pod的网络与各Node互联互通。它还需要以hostNetwork模式运行,直接使用宿主机网络。

calico-node服务的主要参数如下:

◎ CALICO_IPV4POOL_CIDR:Calico IPAM的IP地址池,Pod的IP地址将从该池中进行分配。
◎ CALICO_IPV4POOL_IPIP:是否启用IPIP模式。启用IPIP模式时,Calico将在Node上创建一个名为tunl0的虚拟隧道。
◎ IP_AUTODETECTION_METHOD:获取Node IP地址的方式,默认使用第1个网络接口的IP地址,对于安装了多块网卡的Node,可以使用正则表达式选择正确的网卡,例如"interface=ens.*"表示选择名称以ens开头的网卡的IP地址。
◎ FELIX_IPV6SUPPORT:是否启用IPv6。
◎ FELIX_LOGSEVERITYSCREEN:日志级别。
◎ securityContext.privileged=true:以特权模式运行。

另外,如果启用RBAC权限控制,则可以设置ServiceAccount。

     IP Pool可以使用两种模式:BGP或IPIP。使用IPIP模式时,设置CALICO_IPV4POOL_IPIP="always",不使用IPIP模式时,设置CALICO_IPV4POOL_IPIP="off",此时将使用BGP模式。

 

    IPIP是一种将各Node的路由之间做一个tunnel,再把两个网络连接起来的模式,启用IPIP模式时,Calico将在各Node上创建一个名为tunl0的虚拟网络接口。

   BGP模式则直接使用物理机作为虚拟路由器(vRouter),不再创建额外的tunnel。

(4)calico-kube-controllers容器,用于对接Kubernetes集群中为Pod设置的Network Policy:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
1apiVersion: extensions/v1beta1
2kind: Deployment
3metadata:
4  name: calico-kube-controllers
5  namespace: kube-system
6  labels:
7    k8s-app: calico-kube-controllers
8spec:
9  # The controllers can only have a single active instance.
10  replicas: 1
11  strategy:
12    type: Recreate
13  template:
14    metadata:
15      name: calico-kube-controllers
16      namespace: kube-system
17  namespace: kube-system
18  labels:
19    k8s-app: calico-kube-controllers
20spec:
21  # The controllers can only have a single active instance.
22  replicas: 1
23  strategy:
24    type: Recreate
25  template:
26    metadata:
27      name: calico-kube-controllers
28      namespace: kube-system
29      labels:
30        k8s-app: calico-kube-controllers
31      annotations:
32        scheduler.alpha.kubernetes.io/critical-pod: ''
33    spec:
34      nodeSelector:
35        beta.kubernetes.io/os: linux
36      # The controllers must run in the host network namespace so that
37      # it isn't governed by policy that would prevent it from working.
38      hostNetwork: true
39      tolerations:
40        # Mark the pod as a critical add-on for rescheduling.
41        - key: CriticalAddonsOnly
42          operator: Exists
43        - key: node-role.kubernetes.io/master
44          effect: NoSchedule
45      serviceAccountName: calico-kube-controllers
46      containers:
47        - name: calico-kube-controllers
48          image: calico/kube-controllers:v3.5.8
49          env:
50            # The location of the Calico etcd cluster.
51            - name: ETCD_ENDPOINTS
52              valueFrom:
53                configMapKeyRef:
54                  name: calico-config
55                  key: etcd_endpoints
56            # Location of the CA certificate for etcd.
57            - name: ETCD_CA_CERT_FILE
58              valueFrom:
59                configMapKeyRef:
60                  name: calico-config
61                  key: etcd_ca
62            # Location of the client key for etcd.
63            - name: ETCD_KEY_FILE
64              valueFrom:
65                configMapKeyRef:
66                  name: calico-config
67                  key: etcd_key
68            # Location of the client certificate for etcd.
69            - name: ETCD_CERT_FILE
70              valueFrom:
71                configMapKeyRef:
72                  name: calico-config
73                  key: etcd_cert
74            # Choose which controllers to run.
75            - name: ENABLED_CONTROLLERS
76              value: policy,namespace,serviceaccount,workloadendpoint,node
77          volumeMounts:
78            # Mount in the etcd TLS secrets.
79            - mountPath: /calico-secrets
80              name: etcd-certs
81          readinessProbe:
82            exec:
83              command:
84              - /usr/bin/check-status
85              - -r
86      volumes:
87        # Mount in the etcd TLS secrets with mode 400.
88        # See https://kubernetes.io/docs/concepts/configuration/secret/
89        - name: etcd-certs
90          secret:
91            secretName: calico-etcd-secrets
92            defaultMode: 0400
93
94

     如果启用RBAC权限控制,则可以设置ServiceAccount。

    用户在Kubernetes集群中设置了Pod的Network Policy之后,calico-kube-controllers就会自动通知各Node上的calico-node服务,在宿主机上设置相应的iptables规则,完成Pod间网络访问策略的设置。


1
2
3
1kubecatl apply -f calico.yaml
2
3

    确保Calico的个服务正确运行,calico-node在正常运行之后,会根据CNI规范,在/etc/cni/net.d/目录下生成如下文件和目录,并在/opt/cni/bin/目录下安装二进制文件calico和calico-ipam,供kubelet调用。

◎ 10-calico.conf:符合CNI规范的网络配置,其中type=calico表示该插件的二进制文件名为calico。
◎ calico-kubeconfig:Calico所需的kubeconfig文件。
◎ calico-tls目录:以TLS方式连接etcd的相关文件。
查看k8s-node-1服务器的网络接口设置,可以看到一个新的名为tunl0的接口,并设置了网络地址为10.1.109.64/32。

查看k8s-node-2服务器的网络接口设置,同样可以看到一个新的名为tunl0的接口,网络地址为10.1.140.64/32。

     这两个子网都是从calico-node设置的IP地址池(CALICO_IPV4POOL_CIDR="10.1.0.0/16")中进行分配的。同时,docker0对于Kubernetes设置Pod的IP地址将不再起作用。

    查看两台主机的路由表。首先,查看k8s-node-1服务器的路由表,可以看到一条到k8s-node-2的私网10.1.140.64的路由转发规则:


1
2
1ip route
2

然后,查看k8s-node-2服务器的路由表,可以看到一条到k8s-node-1的私网10.1.109.64/26的路由转发规则:


1
2
1ip route
2

      这样,通过Calico就完成了Node间容器网络的设置。在后续的Pod创建过程中,kubelet将通过CNI接口调用Calico进行Pod网络的设置,包括IP地址、路由规则、iptables规则等。

     如果设置CALICO_IPV4POOL_IPIP="off",即不使用IPIP模式,则Calico将不会创建tunl0网络接口,路由规则直接使用物理机网卡作为路由器进行转发。

     查看k8s-node-1服务器的路由表,可以看到一条到k8s-node-2的私网10.1.140.64的路由转发规则,将通过本机ens33网卡进行转发.

    查看k8s-node-2服务器的路由表,可以看到一条到k8s-node-1的私网10.1.109.64/26的路由转发规则,将通过本机ens33网卡进行转发

3.Calico设置容器IP地址,跨主机容器网络连通性验证

   下面创建几个Pod,验证Calico对它们的网络设置。以mysql和myweb为例。

mysql-rc.yaml


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1apiVersion: v1
2kind: ReplicationController
3metadata:
4  name: mysql
5spec:
6  replicas: 1
7  selector:
8    app: mysql
9  template:
10    metadata:
11      labels:
12        app: mysql
13    spec:
14      containers:
15      - name: mysql
16        image: mysql:5.7
17        ports:
18        - containerPort: 3306
19        env:
20        - name: MYSQL_ROOT_PASSWORD
21          value: "123456"
22

myweb-rc.yaml


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
1apiVersion: v1
2kind: ReplicationController
3metadata:
4  name: myweb
5spec:
6  replicas: 2
7  selector:
8    app: myweb
9  template:
10    metadata:
11      labels:
12        app: myweb
13    spec:
14      containers:
15      - name: myweb
16        image: kubeguide/tomcat-app:v1
17        ports:
18        - containerPort: 8080
19        env:
20        - name: MYSQL_SERVICE_HOST
21          value: 'mysql'
22        - name: MYSQL_SERVICE_PORT
23          value: '3306'
24

1
2
1kubectl apply -f mysql-rc.yaml -f myweb-rc.yaml
2

    查看各Pod的IP地址,可以看到是通过Calico设置的以10.1开头的IP地址。

    进入运行在k8s-node-2上的Pod,在容器内访问运行在k8s-node-1上的Pod“mysql”的IP地址。


1
2
1ping 10.1.109.71
2

   在容器内访问物理机k8s-node-1的IP地址192.168.18.3


1
2
1ping 192.168.18.3
2

   这说明跨主机容器间、容器与宿主机之间的网络都能互联互通了。

    查看k8s-node-2物理机的网络接口和路由表,可以看到Calico为Pod“myweb-s86sk”新建了一个网络接口cali439924adc43,并为其设置了一条路由规则:


1
2
1ip addr show
2

另外,Calico为该网络接口cali439924adc43设置了一系列iptables规则:


1
2
1iptables -L
2

4.使用网络策略实现Pod间的访问策略

   下面以一个提供服务的Nginx Pod为例,为两个客户端Pod设置不同的网络访问权限,允许包含Label“role=nginxclient”的Pod访问Nginx容器,不包含该Label的容器则拒绝访问。为了实现这个需求,需要通过以下步骤完成。

(1)创建Nginx Pod,并添加Label“app=nginx”:


1
2
3
4
5
6
7
8
9
10
11
12
1apiVersion: v1
2kind: Pod
3metadata:
4  name: nginx
5  labels:
6    app: nginx
7spec:
8  containers:
9  - name: nginx
10    image: nginx
11
12

(2)为Nginx设置网络策略,编辑文件networkpolicy-allow-nginxclient.yaml,内容如下。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1kind: NetworkPolicy
2apiVersion: networking.k8s.io/v1
3metadata:
4  name: allow-nginxclient
5spec:
6  podSelector:
7    matchLabels:
8      app: nginx
9  ingress:
10    - from:
11      - podSelector:
12          matchLabels:
13            role: nginxclient
14    - ports:
15      - protocol: TCP
16        port: 80
17
18

(3)创建两个客户端Pod,一个包含Label“role=nginxclient”,另一个无此Label。分别进入各Pod,访问Nginx容器,验证网络策略的效果。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
1---
2apiVersion:v1
3kind: Pod
4metadata:
5  name: client1
6  labels:
7    role: nginxclient
8spec:
9  containers:
10  - name: client1
11    image: busybox
12    command: ["sleep", "3600"]
13---
14apiVersion:v1
15kind: Pod
16metadata:
17  name: client2
18spec:
19  containers:
20  - name: client2
21    image: busybox
22    command: ["sleep", "3600"]
23---
24

 

登录Pod“client1”,尝试连接Nginx容器的80端口:成功访问到Nginx的服务,说明NetworkPolicy生效。

登录Pod“client2”,尝试连接Nginx容器的80端口:访问超时,说明NetworkPolicy生效,对没有Label“role=nginxclient”的客户端Pod拒绝访问。

     本例中的网络策略是由calico-kube-controllers具体实现的,calico-kube-controllers持续监听Kubernetes中NetworkPolicy的定义,与各Pod通过Label进行关联,将允许访问或拒绝访问的策略通知到各calico-node服务,最终calico-node完成对Pod间网络访问的设置,实现应用的网络隔离。  

   小结:

          本节内容到此结束,谢谢大家的支持!

给TA打赏
共{{data.count}}人
人已打赏
安全运维

故障复盘的简洁框架-黄金三问

2021-9-30 19:18:23

安全运维

OpenSSH-8.7p1离线升级修复安全漏洞

2021-10-23 10:13:25

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索