十七、Kubernetes之Calico網絡策略


一、網絡策略

 網絡策略(Network Policy )是 Kubernetes 的一種資源。Network Policy 通過 Label 選擇 Pod,並指定其他 Pod 或外界如何與這些 Pod 通信。

​ Pod的網絡流量包含流入(Ingress)和流出(Egress)兩種方向。默認情況下,所有 Pod 是非隔離的,即任何來源的網絡流量都能夠訪問 Pod,沒有任何限制。當為 Pod 定義了 Network Policy,只有 Policy 允許的流量才能訪問 Pod。

​ Kubernetes的網絡策略功能也是由第三方的網絡插件實現的,因此,只有支持網絡策略功能的網絡插件才能進行配置網絡策略,比如Calico、Canal、kube-router等等。

二、配置網絡策略

​在Kubernetes系統中,報文的流入和流出的核心組件是Pod資源,它們也是網絡策略功能的主要應用對象。NetworkPolicy對象通過podSelector選擇 一組Pod資源作為控制對象。NetworkPolicy是定義在一組Pod資源之上用於管理入站流量,或出站流量的一組規則,有可以是出入站規則一起生效,規則的生效模式通常由spec.policyTypes進行 定義。如下圖:

​默認情況下,Pod對象的流量控制是為空的,報文可以自由出入。在附加網絡策略之后,Pod對象會因為NetworkPolicy而被隔離,一旦名稱空間中有任何NetworkPolicy對象匹配了某特定的Pod對象,則該Pod將拒絕NetworkPolicy規則中不允許的所有連接請求,但是那些未被匹配到的Pod對象依舊可以接受所有流量。

​ 就特定的Pod集合來說,入站和出站流量默認是放行狀態,除非有規則可以進行匹配。還有一點需要注意的是,在spec.policyTypes中指定了生效的規則類型,但是在networkpolicy.spec字段中嵌套定義了沒有任何規則的Ingress或Egress時,則表示拒絕入站或出站的一切流量。定義網絡策略的基本格式如下:

apiVersion: networking.k8s.io/v1		#定義API版本
kind: NetworkPolicy					   #定義資源類型
metadata:
  name: allow-myapp-ingress			    #定義NetwokPolicy的名字
  namespace: default
spec:								  #NetworkPolicy規則定義
  podSelector: 						   #匹配擁有標簽app:myapp的Pod資源
    matchLabels:
      app: myapp
  policyTypes ["Ingress"]			    #NetworkPolicy類型,可以是Ingress,Egress,或者兩者共存
  ingress:							  #定義入站規則
  - from:
    - ipBlock:						  #定義可以訪問的網段
        cidr: 10.244.0.0/16
        except:						  #排除的網段
        - 10.244.3.0/24
    - podSelector:					  #選定當前default名稱空間,標簽為app:myapp可以入站
        matchLabels:
          app: myapp
    ports:							 #開放的協議和端口定義
    - protocol: TCP
      port: 80
  
該網絡策略就是將default名稱空間中擁有標簽"app=myapp"的Pod資源開放80/TCP端口給10.244.0.0/16網段,並排除10.244.3.0/24網段的訪問,並且也開放給標簽為app=myapp的所有Pod資源進行訪問。  

 

三、實驗案例

 環境准備

創建linux和python兩個ns並分別在這兩個ns中創建pod資源來用於測試網絡策略

root@k8s-deploy-harbor:~/manifest/network-policy# kubectl create ns linux
namespace/linux created
root@k8s-deploy-harbor:~/manifest/network-policy# kubectl create ns python
namespace/python created
root@k8s-deploy-harbor:~/manifest/network-policy

創建linux namespace中的資源

nginx-linux-ns.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: linux-nginx-deployment-label
  name: linux-nginx-deployment
  namespace: linux
spec:
  replicas: 1
  selector:
    matchLabels:
      app: linux-nginx-selector
  template:
    metadata:
      labels:
        app: linux-nginx-selector
    spec:
      containers:
      - name: linux-nginx-container
        image: harbor.zhrx.com/baseimages/nginx:alpine
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
          protocol: TCP
          name: http
        - containerPort: 443
          protocol: TCP
          name: https
---
kind: Service
apiVersion: v1
metadata:
  labels:
    app: linux-nginx-service-label
  name: linux-nginx-service
  namespace: linux
spec:
  type: NodePort
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 30004
  - name: https
    port: 443
    protocol: TCP
    targetPort: 443
    nodePort: 30443
  selector:
    app: linux-nginx-selector

tomcat-linux-ns.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: linux-tomcat-app1-deployment-label
  name: linux-tomcat-app1-deployment
  namespace: linux
spec:
  replicas: 1
  selector:
    matchLabels:
      app: linux-tomcat-app1-selector
  template:
    metadata:
      labels:
        app: linux-tomcat-app1-selector
    spec:
      containers:
      - name: linux-tomcat-app1-container
        image: harbor.zhrx.com/baseimages/tomcat:7.0.94-alpine
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080
          protocol: TCP
          name: http
---
kind: Service
apiVersion: v1
metadata:
  labels:
    app: linux-tomcat-app1-service-label
  name: linux-tomcat-app1-service
  namespace: linux
spec:
  type: NodePort
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 8080
    nodePort: 30005
  selector:
    app: linux-tomcat-app1-selector

創建資源

root@k8s-deploy-harbor:~/manifest/network-policy/linux-ns# kubectl apply -f nginx-linux-ns.yaml 
deployment.apps/linux-nginx-deployment created
service/linux-nginx-service created

root@k8s-deploy-harbor:~/manifest/network-policy/linux-ns# kubectl apply -f tomcat-linux-ns.yaml 
deployment.apps/linux-tomcat-app1-deployment created
service/linux-tomcat-app1-service created

root@k8s-deploy-harbor:~/manifest/network-policy/linux-ns# kubectl get pod,svc -n linux
NAME                                                READY   STATUS    RESTARTS   AGE
pod/linux-nginx-deployment-74fc689864-f78nb         1/1     Running   0          4m3s
pod/linux-tomcat-app1-deployment-7cc6bdd987-27wf5   1/1     Running   0          14s

NAME                                TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
service/linux-nginx-service         NodePort   10.68.187.8     <none>        80:30004/TCP,443:30443/TCP   4m3s
service/linux-tomcat-app1-service   NodePort   10.68.170.248   <none>        80:30005/TCP                 14s

root@k8s-master:~# kubectl exec -it linux-tomcat-app1-deployment-7cc6bdd987-27wf5 -n linux sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/usr/local/tomcat # mkdir webapps/linux
/usr/local/tomcat # echo "linux tomcat" > webapps/linux/index.jsp

創建python namespace中的資源

nginx-python-ns.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: python-nginx-deployment-label
  name: python-nginx-deployment
  namespace: python
spec:
  replicas: 1
  selector:
    matchLabels:
      app: python-nginx-selector
  template:
    metadata:
      labels:
        app: python-nginx-selector
        project: python
    spec:
      containers:
      - name: python-nginx-container
        image: harbor.zhrx.com/baseimages/nginx:alpine
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
          protocol: TCP
          name: http
        - containerPort: 443
          protocol: TCP
          name: https
---
kind: Service
apiVersion: v1
metadata:
  labels:
    app: python-nginx-service-label
  name: python-nginx-service
  namespace: python
spec:
  type: NodePort
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 30014
  - name: https
    port: 443
    protocol: TCP
    targetPort: 443
    nodePort: 30453
  selector:
    app: python-nginx-selector
    project: python #一個或多個selector,至少能匹配目標pod的一個標簽

tomcat-python-ns.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: python-tomcat-app1-deployment-label
  name: python-tomcat-app1-deployment
  namespace: python
spec:
  replicas: 1
  selector:
    matchLabels:
      app: python-tomcat-app1-selector
  template:
    metadata:
      labels:
        app: python-tomcat-app1-selector
    spec:
      containers:
      - name: python-tomcat-app1-container
        image: harbor.zhrx.com/baseimages/tomcat:7.0.94-alpine
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080
          protocol: TCP
          name: http
---
kind: Service
apiVersion: v1
metadata:
  labels:
    app: python-tomcat-app1-service-label
  name: python-tomcat-app1-service
  namespace: python
spec:
  type: NodePort
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 8080
    nodePort: 30015
  selector:
    app: python-tomcat-app1-selector

創建資源

root@k8s-deploy-harbor:~/manifest/network-policy/python-ns# kubectl apply -f nginx-python-ns.yaml 
deployment.apps/python-nginx-deployment created
service/python-nginx-service created
root@k8s-deploy-harbor:~/manifest/network-policy/python-ns# kubectl apply -f tomcat-python-ns.yaml 
deployment.apps/python-tomcat-app1-deployment created
service/python-tomcat-app1-service created
root@k8s-deploy-harbor:~/manifest/network-policy/python-ns# kubectl get pod,svc -n python
NAME                                                 READY   STATUS    RESTARTS   AGE
pod/python-nginx-deployment-889b9fd95-6c9pv          1/1     Running   0          11s
pod/python-tomcat-app1-deployment-85d7bcb88c-xcrz4   1/1     Running   0          7s

NAME                                 TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
service/python-nginx-service         NodePort   10.68.192.11   <none>        80:30014/TCP,443:30453/TCP   10s
service/python-tomcat-app1-service   NodePort   10.68.88.145   <none>        80:30015/TCP                 7s

root@k8s-master:~# kubectl exec -it  python-tomcat-app1-deployment-85d7bcb88c-xcrz4 -n python sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/usr/local/tomcat # mkdir webapps/python
/usr/local/tomcat # echo "python tomcat" > webapps/python/index.jsp

在default namespace中創建測試pod

testpod-default.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: testpod-busybox-deployment-label
  name: testpod-busybox-deployment
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: python-nginx-selector
      project: python
  template:
    metadata:
      labels:
        app: python-nginx-selector
        project: python
    spec:
      containers:
      - name: testpod-busybox-container
        image: busybox:latest 
        command:
          - sleep
          - "50000000"
        imagePullPolicy: IfNotPresentc

創建資源

root@k8s-deploy-harbor:~/manifest/network-policy/python-ns# kubectl apply -f testpod-busybox.yaml 
deployment.apps/testpod-busybox-deployment created

root@k8s-deploy-harbor:~/manifest/network-policy/python-ns# kubectl get pod 
NAME                                         READY   STATUS    RESTARTS   AGE
testpod-busybox-deployment-8f4f66686-wvw6c   1/1     Running   0          49s

 

case1-ingress-podSelector

僅允許python namespace下擁有project: "python"標簽的pod訪問  擁有app: python-tomcat-app1-selector 標簽的pod 

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tomcat-access--networkpolicy
  namespace: python
spec:
  policyTypes:
  - Ingress
  podSelector:
    matchLabels:
      app: python-tomcat-app1-selector #對匹配到的目的Pod應用以下規則
  ingress: #入棧規則,如果指定目標端口就是匹配全部端口和協議,協議TCP, UDP, or SCTP
  - from:
    - podSelector:
        matchLabels:
          #app: python-nginx-selector #如果存在多個matchLabel條件,是or的關系,即要同時滿足條件A、條件B、條件X
          project: "python"

創建規則並驗證

root@k8s-deploy-harbor:~/manifest/network-policy/python-ns# kubectl apply -f case1-ingress-podSelector.yaml 
networkpolicy.networking.k8s.io/tomcat-access--networkpolicy created

#在python ns下的nginx pod中可以訪問到tomcat
root@k8s-master:~# kubectl get svc -n python
NAME                         TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
python-nginx-service         NodePort   10.68.192.11   <none>        80:30014/TCP,443:30453/TCP   39m
python-tomcat-app1-service   NodePort   10.68.88.145   <none>        80:30015/TCP                 39m
root@k8s-master:~# kubectl exec -it python-nginx-deployment-889b9fd95-6c9pv -n python sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # curl python-tomcat-app1-service/python/
python tomcat


#在linux ns下的nginx pod中不可訪問
root@k8s-master:~# kubectl exec -it linux-nginx-deployment-74fc689864-f78nb -n linux sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # curl python-tomcat-app1-service.python.svc.cluster.local/python/
/ # 阻塞無返回

case2-ingress-podSelector-ns-SinglePort

僅允許python namespace下擁有project: "python"標簽的pod訪問  擁有app: python-tomcat-app1-selector 標簽的pod 的8080端口

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tomcat-access--networkpolicy
  namespace: python
spec:
  policyTypes:
  - Ingress
  podSelector:
    matchLabels:
      app: python-tomcat-app1-selector
  ingress:
  - from:
    - podSelector:
        matchLabels:
          #app: python-nginx-selector #指定訪問源的匹配條件,如果存在多個matchLabel條件,是or的關系,即要同時滿足條件A、條件B、條件X
          project: "python"
    ports: #入棧規則,如果指定目標端口就是匹配全部端口和協議,協議TCP, UDP, or SCTP
    - protocol: TCP
      port: 8080 #允許通過TCP協議訪問目標pod的8080端口,但是其它沒有允許的端口將全部禁止訪問
      #port: 80

創建規則並驗證

root@k8s-deploy-harbor:~/manifest/network-policy/python-ns# kubectl apply -f case2-ingress-podSelector-ns-SinglePort.yaml 
networkpolicy.networking.k8s.io/tomcat-access--networkpolicy created


# 通ns下nginx pod可以訪問tomcat pod的8080端口
root@k8s-master:~# kubectl exec -it python-nginx-deployment-889b9fd95-6c9pv -n python sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # curl 172.20.36.69:8080/python/
python tomcat

 case3-ingress-podSelector-ns-MultiPort

僅允許python namespace下擁有project: "python"標簽的pod訪問  擁有app: python-tomcat-app1-selector 標簽的pod 的8080和8009端口

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tomcat-access--networkpolicy
  namespace: python
spec:
  policyTypes:
  - Ingress
  podSelector: #目標pod
    matchLabels:
      app: python-tomcat-app1-selector
  ingress:
  - from:
    - podSelector: #匹配源pod,matchLabels: {}為不限制源pod即允許所有pod,寫法等同於resources(不加就是不限制)
        matchLabels: {}
    ports: #入棧規則,如果指定目標端口就是匹配全部端口和協議,協議TCP, UDP, or SCTP
    - protocol: TCP
      port: 8080 #允許通過TCP協議訪問目標pod的8080端口,但是其它沒有允許的端口將全部禁止訪問
    - protocol: TCP
      port: 8009

case4-ingress-podSelector-ns

允許當前namespace下所有pod的通信

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tomcat-access--networkpolicy
  namespace: python
spec:
  policyTypes:
  - Ingress
  podSelector: #目標pod
    matchLabels: {} #匹配所有目標pod
  ingress:
  - from:
    - podSelector: #匹配源pod,matchLabels: {}為不限制源pod即允許所有pod,寫法等同於resources(不加就是不限制)
        matchLabels: {}

case5-ingress-ipBlock

允許指定的ip網段訪問tomcat pod的808端口

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tomcat-access--networkpolicy
  namespace: python
spec:
  policyTypes:
  - Ingress
  podSelector: #目標pod
    matchLabels:
      app: python-tomcat-app1-selector
  ingress:
  - from:
    - ipBlock:
        cidr: 10.200.0.0/16 #白名單,允許訪問的地址范圍,沒有允許的將禁止訪問目標pod
        except:
        - 10.200.218.0/24 #在以上范圍內禁止訪問的源IP地址
        - 10.200.229.0/24 #在以上范圍內禁止訪問的源IP地址
        - 10.200.230.239/32 #在以上范圍內禁止訪問的源IP地址
    ports: #入棧規則,如果指定目標端口就是匹配全部端口和協議,協議TCP, UDP, or SCTP
    - protocol: TCP
      port: 8080 #允許通過TCP協議訪問目標pod的8080端口,但是其它沒有允許的端口將全部禁止訪問

case6-ingress-namespaceSelector

允許指定的ns訪問當前ns下的所有pod 的某些端口

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tomcat-access--networkpolicy
  namespace: python
spec:
  policyTypes:
  - Ingress
  podSelector: #目標pod
    matchLabels: {} #允許訪問python namespace 中的所有pod
#      app: python-tomcat-app1-selector #可以只允許訪問python namespace中指定的pod
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          nsname: linux #只允許指定的namespace訪問
    - namespaceSelector:
        matchLabels:
          nsname: python #只允許指定的namespace訪問
    ports: #入棧規則,如果指定目標端口就是匹配全部端口和協議,協議TCP, UDP, or SCTP
    - protocol: TCP
      port: 8080 #允許通過TCP協議訪問目標pod的8080端口,但是其它沒有允許的端口將全部禁止訪問
      #port: 80
    - protocol: TCP
      port: 3306
    - protocol: TCP
      port: 6379

case7-Egress-ipBlock

允許指定pod訪問目的ip網段的指定端口

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-access-networkpolicy
  namespace: python
spec:
  policyTypes:
  - Egress
  podSelector: #目標pod選擇器
    matchLabels:  #基於label匹配目標pod
      app: python-tomcat-app1-selector #匹配python namespace中app的值為python-tomcat-app1-selector的pod,然后基於egress中的指定網絡策略進行出口方向的網絡限制
  egress:
  - to:
    - ipBlock:
        cidr: 10.200.0.0/16 #允許匹配到的pod出口訪問的目的CIDR地址范圍
    - ipBlock:
        cidr: 172.31.7.106/32 #允許匹配到的pod出口訪問的目的主機
    ports:
    - protocol: TCP
      port: 80 #允許匹配到的pod訪問目的端口為80的訪問
    - protocol: TCP
      port: 53 #允許匹配到的pod訪問目的端口為53 即DNS的解析
    - protocol: UDP
      port: 53 #允許匹配到的pod訪問目的端口為53 即DNS的解析

case8-Egress-PodSelector

允許擁有app: python-nginx-selector標簽的pod 訪問 擁有app: python-tomcat-app1-selector 的pod的指定端口

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-access-networkpolicy
  namespace: python
spec:
  policyTypes:
  - Egress
  podSelector: #目標pod選擇器
    matchLabels:  #基於label匹配目標pod
      app: python-nginx-selector #匹配python namespace中app的值為python-tomcat-app1-selector的pod,然后基於egress中的指定網絡策略進行出口方向的網絡限制
  egress:
  - to:
    - podSelector: #匹配pod,matchLabels: {}為不限制源pod即允許所有pod,寫法等同於resources(不加就是不限制)
        matchLabels:
          app: python-tomcat-app1-selector
    ports:
    - protocol: TCP
      port: 8080 #允許80端口的訪問
    - protocol: TCP
      port: 53 #允許DNS的解析
    - protocol: UDP
      port: 53

case9-Egress-namespaceSelector

允許擁有app: python-nginx-selector的pod 去訪問指定ns下的pod 的指定端口

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-access-networkpolicy
  namespace: python
spec:
  policyTypes:
  - Egress
  podSelector: #目標pod選擇器
    matchLabels:  #基於label匹配目標pod
      app: python-nginx-selector #匹配python namespace中app的值為python-tomcat-app1-selector的pod,然后基於egress中的指定網絡策略進行出口方向的網絡限制
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          nsname: python #指定允許訪問的目的namespace
    - namespaceSelector:
        matchLabels:
          nsname: linux #指定允許訪問的目的namespace
    ports:
    - protocol: TCP
      port: 8080 #允許80端口的訪問
    - protocol: TCP
      port: 53 #允許DNS的解析
    - protocol: UDP
      port: 53

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM