NetworkPolicy

36. Egress

36.1 NetworkPolicy

  • 概述
#flannel不支持这个策略
基于NetworkPolicy在三层(网络层)或四层(传输层)控制拒绝或允许请求流量。
1.允许或拒绝特定的pod请求目的namespace中的目的pod的所有或指定端口
2.允许或拒绝特定的namespace请求目的namespace中的所有或特定的pod所有或指定端口
3.允许或拒绝特定的源IP范围或IP地址请求目的pod的所有或特定端口

36.2 实现跨namespace通信及访问限制

1.kubernetes 1.24.x,calico网络组件,2个node节点或以上。

2.两个namespace,linux和python,分别代表不同项目的Pod。

3.每个namespace运行多个pod,且pod可以运行在不同的node主机。

4.测试环境为每个namespace分别运行一个nginx和一个tomcat pod,用于测试不同主机的Pod运行在同一个ns的场景、以及跨ns的访问通信及访问限制。

  • 创建namespae
kubectl create namespace linux
kubectl create namespace python
kubectl label namespaces linux nsname=linux
kubectl label namespaces python nsname=python
  • 在两个namespace中分别创建YAML

linux ns部署nginx和tomcat,并让Nginx可以将来自于/app的请求转发至当前namespace的tomcat pod

python ns部署Nginx和tomcat,并让Nginx可以将来自于/app的请求转发至当前namespace的tomcat pod

#linux
root@k8s-master1:~/NetWorkPolicy-case/linux-ns1# cat nginx.yaml 
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
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: nginx:1.20.2-alpine 
        #command: ["/apps/tomcat/bin/run_tomcat.sh"]
        #imagePullPolicy: IfNotPresent
        imagePullPolicy: Always
        ports:
        - containerPort: 80
          protocol: TCP
          name: http
        - containerPort: 443
          protocol: TCP
          name: https
        env:
        - name: "password"
          value: "123456"
        - name: "age"
          value: "18"
#        resources:
#          limits:
#            cpu: 2
#            memory: 2Gi
#          requests:
#            cpu: 500m
#            memory: 1Gi


---
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: 30008
  - name: https
    port: 443
    protocol: TCP
    targetPort: 443
    nodePort: 30446
  selector:
    app: linux-nginx-selector
root@k8s-master1:~/NetWorkPolicy-case/linux-ns1# cat tomcat.yaml 
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
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: tomcat:7.0.109-jdk8-openjdk 
        #command: ["/apps/tomcat/bin/run_tomcat.sh"]
        #imagePullPolicy: IfNotPresent
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
          protocol: TCP
          name: http
        env:
        - name: "password"
          value: "123456"
        - name: "age"
          value: "18"
#        resources:
#          limits:
#            cpu: 2
#            memory: 2Gi
#          requests:
#            cpu: 500m
#            memory: 1Gi


---
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: 30006
  selector:
    app: linux-tomcat-app1-selector

#python
root@k8s-master1:~/NetWorkPolicy-case/python-ns2# cat nginx.yaml 
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
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: nginx:1.20.2-alpine
        #command: ["/apps/tomcat/bin/run_tomcat.sh"]
        #imagePullPolicy: IfNotPresent
        imagePullPolicy: Always
        ports:
        - containerPort: 80
          protocol: TCP
          name: http
        - containerPort: 443
          protocol: TCP
          name: https
        env:
        - name: "password"
          value: "123456"
        - name: "age"
          value: "18"
#        resources:
#          limits:
#            cpu: 2
#            memory: 2Gi
#          requests:
#            cpu: 500m
#            memory: 1Gi


---
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: 30016
  - name: https
    port: 443
    protocol: TCP
    targetPort: 443
    nodePort: 30456
  selector:
    app: python-nginx-selector
    project: python #一个或多个selector,至少能匹配目标pod的一个标签 
root@k8s-master1:~/NetWorkPolicy-case/python-ns2# cat tomcat.yaml 
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
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:
            #      nodeName: 172.31.7.113
      containers:
      - name: python-tomcat-app1-container
        image: tomcat:7.0.109-jdk8-openjdk 
        #command: ["/apps/tomcat/bin/run_tomcat.sh"]
        #imagePullPolicy: IfNotPresent
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
          protocol: TCP
          name: http
        env:
        - name: "password"
          value: "123456"
        - name: "age"
          value: "18"
#        resources:
#          limits:
#            cpu: 2
#            memory: 2Gi
#          requests:
#            cpu: 500m
#            memory: 1Gi


---
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
  • 对Nginx都创建首页
#思考
	运行在Linux ns的Nginx能否将请求转发至运行在Python ns的tomcat?  答案默认是可以的
kubectl exec -it -n python python-tomcat-app1-deployment-7bf9bb6989-7szqk bash
cd webapps
mkdir app
echo 'app demo python' >app/index.jsp
#测试访问
root@k8s-master1:~# curl http://10.0.0.102:30015/app/index.jsp
app demo python

36.3 测试网络限制

  • podSelector
#先在default名称空间下访问查看是否可以通信 是可以的
root@k8s-master1:~# kubectl exec -it net-test bash
[root@net-test /]# curl 10.200.224.5:8080/app/index.jsp
app demo python

#ingress
#vim case1-ingress-podSelector.yaml 
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条件,如果存在多个matchLabel条件,是and的关系,即要同时满足条件A、条件B、条件X
          project: "python"		#只有带这个标签的pod才可以访问,没有允许的访问就是拒绝
root@k8s-master1:~/NetWorkPolicy-case/python-ns2# kubectl get  networkpolicies.networking.k8s.io -n python 
NAME                           POD-SELECTOR                      AGE
tomcat-access--networkpolicy   app=python-tomcat-app1-selector   13s

#加上这个策略之后default就不能访问了因为他没有这个标签
  • 结果

1.不允许从其它namespace访问目标pod,即默认禁止了跨ns访问目标pod

2.\(\textcolor{red}{没有明确允许的pod,同namespace也无法访问}\)

3.不允许从宿主机访问目标pod

4.该策略只允许同namespce含有特定标签的源pod访问目标pod,比如tomcat只允许了有特定标签的源pod Nginx访问

5.该策略不影响其它namespace的pod内部之间的相互访问,即Linux的pod与linux的pod访问正常

6.该策略不影响各namespace的pod与飞明确禁止的pod之间的访问,即Linux的pod访问Python的其它pod也正常

  • podSelector + 端口限制

以pod为限制单位,只允许同namespace含有特定标签的源pod访问目标pod的所有端口

root@k8s-master1:~/NetWorkPolicy-case/python-ns2# cat case2-ingress-podSelector-ns-SinglePort.yaml 
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条件,是and的关系,即要同时满足条件A、条件B、条件X
          project: "python"
    ports: #入栈规则,如果指定目标端口就是匹配全部端口和协议,协议TCP, UDP, or SCTP
    - protocol: TCP
      port: 8080 #允许通过TCP协议访问目标pod的8080端口,但是其它没有允许的端口将全部禁止访问
      #port: 80
  • podSelector + matchLabels: {} 匹配python名称空间下所有pod

允许同namespace的所有pod访问当前namespace的目标pod多个指定端口或所有端口

root@k8s-master1:~/NetWorkPolicy-case/python-ns2# cat case3-ingress-podSelector-ns-MultiPort.yaml 
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就是所有端口都可以访问
    ports: #入栈规则,如果指定目标端口就是匹配全部端口和协议,协议TCP, UDP, or SCTP
    - protocol: TCP
      port: 8080 #允许通过TCP协议访问目标pod的8080端口,但是其它没有允许的端口将全部禁止访问
      #port: 80
    - protocol: TCP
      port: 3306
    - protocol: TCP
      port: 6379
  • podSelector + ipBlock 白名单

1.只要在白名单范围内没有被except指定禁止的源 pod IP都允许访问

2.在只设置了ipBlock匹配的前提下,其它namespace中没有在except范围的pod也可以访问目标pod,及 linux ns中的pod只要不在except地址范围内,也可以访问Python ns中的pod了

root@k8s-master1:~/NetWorkPolicy-case/python-ns2# cat case5-ingress-ipBlock.yaml.bak 
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: {}
    - ipBlock:
#这个cidr就是你初始化时候设置的地址段
        cidr: 10.200.0.0/16 #白名单,允许访问的地址范围,没有允许的将禁止访问目标pod
        except:
        - 10.200.219.0/24 #在以上范围内禁止访问的源IP地址
        - 10.200.229.0/24 #在以上范围内禁止访问的源IP地址
        - 10.200.207.31/32 #在以上范围内禁止访问的源IP地址
    ports: #入栈规则,如果指定目标端口就是匹配全部端口和协议,协议TCP, UDP, or SCTP
    - protocol: TCP
      port: 8080 #允许通过TCP协议访问目标pod的8080端口,但是其它没有允许的端口将全部禁止访问
      #port: 80
    - protocol: TCP
      port: 3306
    - protocol: TCP
      port: 6379
  • podSelector + namespaceSelector

1.被明确允许的namespace中的pod可以访问目标pod

2.没有明确声明允许的namespace将禁止访问

3.没有明确声明允许的话,即使同一个namespace也禁止访问

4.比如只允许了linux和python两个namespace,那么default中的pod将无法访问

root@k8s-master1:~/NetWorkPolicy-case/python-ns2# cat case6-ingress-namespaceSelector.yaml 
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:
#    - podSelector: #匹配源pod,matchLabels: {}为不限制源pod即允许所有pod,写法等同于resources(不加就是不限制)
#        matchLabels: {}
#    - ipBlock:
#        cidr: 10.200.0.0/16 #指定禁止访问的源网段
#        except:
#        - 10.200.218.0/24 #在以上范围内禁止访问的源IP地址

    - namespaceSelector:
#        matchLabels: {} #允许所有namespace访问python namespace指定的目标端口或指定的pod加指定端口
        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
  • podSelector + egress pod出口方向的IP及目的端口限制-只允许访问指定的目的地址范围及端口

限制指定的pod可以访问指定的IP

1.基于Egress白名单,定义ns中匹配成功的pod可以访问ipBlock指定的地址和ports指定的端口

2.匹配成功的pod访问未明确定义在Egress的白名单的其它IP的请求,将拒绝

3.没有匹配成功的源pod,主动发起的出口访问请求不受影响

root@k8s-master1:~/NetWorkPolicy-case/python-ns2# cat case7-Egress-ipBlock.yaml 
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出口访问的目的主机
    - ipBlock:
        cidr: 0.0.0.0/0 #允许匹配到的pod出口访问的目的主机
    ports:
    - protocol: TCP
      port: 80 #允许匹配到的pod访问目的端口为80的访问
    - protocol: TCP
      port: 53 #允许匹配到的pod访问目的端口为53 即DNS的解析
    - protocol: UDP
      port: 53 #允许匹配到的pod访问目的端口为53 即DNS的解析
  • Pod出口方向目的Pod限制-只允许访问指定的Pod及端口

1.匹配成功的源pod只能访问指定的目的pod的指定端口

2.其它没有允许的出口请求将禁止访问

root@k8s-master1:~/NetWorkPolicy-case/python-ns2# cat case8-Egress-PodSelector.yaml 
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:
#    - ipBlock:
#        cidr: 10.200.0.0/16 #允许访问的目的CIDR地址范围
#    - ipBlock:
#        cidr: 172.31.7.106/32 #允许访问的目的主机地址
#    - ipBlock:
#        cidr: 10.200.218.4/32 #白名单,允许访问的目的主机地址
    - 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
  • Pod出口方向目的IP及目的端口限制-只允许访问指定的目的地址范围及端口

限制匹配成功的pod没有访问指定的namespace

1.匹配成功的源pod可以访问指定的目标namespace

2.不能访问除指定的namespace以外的其它namespace及外网

3.比如允许指定的源pod访问linux和python ns中的8080、3306、6379等端口,但是其它ns无法访问

root@k8s-master1:~/NetWorkPolicy-case/python-ns2# cat case9-Egress-namespaceSelector.yaml 
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:
#    - ipBlock:
#        cidr: 10.200.0.0/16 #允许访问的目的CIDR地址范围
#    - ipBlock:
#        cidr: 172.31.7.106/32 #允许访问的目的主机地址
#    - ipBlock:
#        cidr: 10.200.218.4/32 #允许访问的目的主机地址
#    - podSelector: #匹配pod,matchLabels: {}为不限制源pod即允许所有pod,写法等同于resources(不加就是不限制)
#        matchLabels:
#          app: python-tomcat-app1-selector

    - 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
posted @ 2023-01-02 11:59  YIDADA-SRE  阅读(79)  评论(0编辑  收藏  举报