一、前提
上一節學習了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),但是不允許和外部名稱空間之間進行通信;