一、前提
上一节学习了flannel,但是我们应该了解flannel只能提供网络通讯,而不能提供网络策略。因此,我们本节学习canal,让它来提供网络策略,来配合flannel使用。
canal是calico的一个项目;
calico的网址:https://docs.projectcalico.org/v3.6/introduction/
Installing Calico for policy and flannel for networking:
https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/flannel
几个注意事项:
1、kubelet必须配置为CNI网络插件(即--network-plugin-cni,默认新版本默认就是CNI)
2、kube-proxy必须以iptables模式启动,不能以ipvs方式启动;
3、kube-proxy不能以--masquerade-all方式启动,因为这和calico策略冲突;
4、k8s版本至少要v1.3.0
二、部署使用canal
https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/flannel
部署:
(1)If your cluster has RBAC enabled, issue the following command to configure the roles and bindings that Calico requires.
kubectl apply -f https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/hosted/canal/rbac.yaml
(2)Issue the following command to install Calico.
kubectl apply -f https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/hosted/canal/canal.yaml
稍等片刻,查看:
[root@master ~]# kubectl get pods -n kube-system
Egres:出站,表示pod自己是客户端,访问别人。
Ingress:入站,表示Pod自己是目标,别人来访问自己。
通常,客户端的端口是随机的,服务端的端口是固定的。
Network Policy:用来控制哪个pod来和外部或内部进行通信。
podSelecto:pod选择器
policyTypes:用来控制Ingres和Egres哪个生效。
使用:
(3)示例: ingress
建立两个namespace,在两个namespace里再创建pod,让两个namespace里的pod通信,并添加策略控制;
建立两个名称空间,一个模拟测试,一个模拟生产;
a、查看资源定义清单字段
[root@master ~]# kubectl explain networkpolicy
[root@master ~]# kubectl explain networkpolicy.spec
b、定义一个ingress,拒绝的所有的,只对特定的开放;
可以出去,但是别人不能进来;
c、创建ingress
[root@master networkpolicy]# kubectl apply -f ingress-def.yaml -n dev #-n表示只对哪个名称空间生效
查看
d、在dev命名空间中创建pod,看能不能被访问
[root@master networkpolicy]# kubectl apply -f pod-a.yaml -n dev pod/pod1 created
[root@master networkpolicy]# kubectl get pods -n dev -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod1 1/1 Running 0 9m5s 10.244.1.2 node01 <none> <none>
[root@master networkpolicy]# curl 10.244.1.2 #测试证明不能被访问
e、在prod命名空间创建pod测试;
[root@master networkpolicy]# kubectl apply -f pod-a.yaml -n prod pod/pod1 created [root@master networkpolicy]# kubectl get pods -n prod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod1 1/1 Running 0 31s 10.244.1.3 node01 <none> <none> [root@master networkpolicy]# curl 10.244.1.3 Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a> #可以访问到
f、下面改一下ingress资源定义清单,允许所有入站;
[root@master networkpolicy]# vim ingress-def.yaml apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: deny-all-ingress spec: podSelector: {} ingress: - {} #表示允许所有 policyTypes: - Ingress
[root@master networkpolicy]# kubectl apply -f ingress-def.yaml -n dev networkpolicy.networking.k8s.io/deny-all-ingress configured [root@master networkpolicy]# kubectl get pods -n dev -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod1 1/1 Running 0 28m 10.244.1.2 node01 <none> <none> [root@master networkpolicy]# curl 10.244.1.2 Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a> #此时可以访问了 [root@master networkpolicy]# curl 10.244.1.3 Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
g、将dev命令空间中的pod1打标,稍后设定能访问有此标签的pod的80端口;
[root@master networkpolicy]# kubectl label pods pod1 app=myapp -n dev #打标签 pod/pod1 labeled [root@master networkpolicy]# vim allow-netpol-demo.yaml apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-myapp-ingress spec: podSelector: matchLabels: app: myapp #选择有myapp标签的pod ingress: - from: - ipBlock: cidr: 10.244.0.0/16 #允许这个网段的 except: - 10.244.1.2/32 #但是不允许这个地址 ports: - protocol: TCP port: 80 #开放80端口 [root@master networkpolicy]# kubectl apply -f allow-netpol-demo.yaml -n dev #创建 networkpolicy.networking.k8s.io/allow-myapp-ingress created [root@master networkpolicy]# kubectl get netpol -n dev NAME POD-SELECTOR AGE allow-myapp-ingress app=myapp 16s deny-all-ingress <none> 76m [root@master networkpolicy]# [root@master networkpolicy]# curl 10.244.1.2 #访问 Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
(4)egress
a、创建egress(拒绝所有),并生效到prod名称空间
[root@master networkpolicy]# vim egress-def.yaml apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: deny-all-egress spec: podSelector: {} policyTypes: - Egress #拒绝所有出站流量 [root@master networkpolicy]# kubectl apply -f egress-def.yaml -n prod networkpolicy.networking.k8s.io/deny-all-egress created [root@master networkpolicy]# kubectl get pods -n prod NAME READY STATUS RESTARTS AGE pod1 1/1 Running 0 63m [root@master ~]# kubectl get pods -n kube-system -o wide |grep coredns coredns-86c58d9df4-8lwrg 1/1 Running 9 74d 10.244.0.18 master <none> <none> coredns-86c58d9df4-z66dd 1/1 Running 8 74d 10.244.0.19 master <none> <none> [root@master networkpolicy]# kubectl exec pod1 -it -n prod -- /bin/sh / # ping 10.244.0.18 #连入prod下的pod,ping coredns,发现ping不通
b、放行所有
[root@master networkpolicy]# vim egress-def.yaml apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: deny-all-egress spec: podSelector: {} egress: - {} #允许所有出站流量 policyTypes: - Egress [root@master networkpolicy]# kubectl apply -f egress-def.yaml -n prod networkpolicy.networking.k8s.io/deny-all-egress configured [root@master networkpolicy]# [root@master networkpolicy]# kubectl exec pod1 -it -n prod -- /bin/sh #连入 / # ping 10.244.0.18 PING 10.244.0.18 (10.244.0.18): 56 data bytes 64 bytes from 10.244.0.18: seq=0 ttl=62 time=43.914 ms #可以ping通了 64 bytes from 10.244.0.18: seq=1 ttl=62 time=0.403 ms
为了安全,我们可以先设置每个名称空间拒绝所有入站、拒绝所有出站,然后单独放行;
但是这样也会有一个问题,就是同一名称空间的pod也不能通信;
所以还要加条策略就是允许本名称空间的pod之间可以互相通信(放行所有出站目标为本名称空间内的所有pod),但是不允许和外部名称空间之间进行通信;