文章目录

  • 前言
  • 准备工作
  • linux命名空间
  • python命名空间
  • Ingress策略
  • podSelector
  • podSelector-SinglePort
  • podSelector-MultiPort
  • ingress-ipBlock
  • ingress-namespace
  • Egress策略
  • egress-ipBlock
  • egress-PodSelector
  • egress-namespace


前言

NetworkPolicy网络策略可以在 IP 地址或端口层面(OSI 第 3 层或第 4 层)控制网络流量。 NetworkPolicy 是一种以应用为中心的结构,允许你设置如何允许 Pod 与网络上的各类网络“实体”通信。 NetworkPolicies 适用于一端或两端与 Pod 的连接,与其他连接无关。

Pod 可以通信的 Pod 是通过如下三个标识符的组合来辩识的:

  1. 其他被允许的 Pods(例外:Pod 无法阻塞对自身的访问)
  2. 被允许的名字空间
  3. IP 组块(例外:与 Pod 运行所在的节点的通信总是被允许的, 无论 Pod 或节点的 IP 地址)


准备工作

创建两个命名空间,每个空间运行多个pod,多个pod运行在不同的节点。

kubectl create ns linux
kubectl create ns python
kubectl label ns linux nsname=linux 
kubectl label ns python nsname=python



命名空间linux与python均部署nginx与tomcat。

tomcat镜像构建:

FROM tomcat:7.0.109-jdk8-openjdk
# 自定义tomcat app路径首页
RUN mkdir /usr/local/tomcat/webapps/app/
ADD index.jsp /usr/local/tomcat/webapps/app/



nginx镜像构建:

FROM nginx:1.20.2-alpine
# 自定义首页,配置nginx
ADD default.conf /etc/nginx/conf.d/
ADD index.html /usr/share/nginx/html/

nginx配置,将访问app路径转发给tomcat。

vim /etc/nginx/conf.d/default.conf

location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

location /app {
        proxy_pass http://10.68.4.22:80;
    }



测试容器,前台卡住一天时间,用于测试网络策略效果:

kubectl run net-test-centos-pod1 --image=centos:7.9.2009 sleep 86400 -n linux
kubectl run net-test-centos-pod1 --image=centos:7.9.2009 sleep 86400 -n python
kubectl run centos-net-test1 --image=centos:7.9.2009 sleep 86400



linux命名空间

部署linux-tomcat:

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: tomcat:7.0.109-jdk8-openjdk 
        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: 38080
  selector:
    app: linux-tomcat-app1-selector



部署linux-nginx:

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: nginx:1.20.2-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: 30080
  - name: https
    port: 443
    protocol: TCP
    targetPort: 443
    nodePort: 30443
  selector:
    app: linux-nginx-selector



python命名空间

部署python-tomcat:

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:
      nodeName: 192.168.100.164
      containers:
      - name: python-tomcat-app1-container
        image: tomcat:7.0.109-jdk8-openjdk 
        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: 38081
  selector:
    app: python-tomcat-app1-selector



部署python-tomcat:

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: nginx:1.20.2-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: 30081
  - name: https
    port: 443
    protocol: TCP
    targetPort: 443
    nodePort: 30444
  selector:
    app: python-nginx-selector
    project: python #一个或多个selector,至少能匹配目标pod的一个标签



Ingress策略

Pod 有两种隔离: 出口的隔离和入口的隔离。入口隔离(Ingress)策略较为常用。

podSelector

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  #and关系
          project: "python"
  1. 对命名空间python中的app=python-tomcat-app1-selector的pod进行网络隔离
  2. 入口隔离,即只对谁可以访问该pod进行管控
  3. 标签project=python的pod允许访问
  4. 未指定则允许访问全部端口全部协议


在project=linux的pod进行测试:

# NetworkPolicy前
curl http://172.20.153.199:8080/app/
tomcat app python 456

# NetworkPolicy后
curl http://172.20.153.199:8080/app/
curl: (7) Failed connect to 172.20.153.199:8080; Connection timed out



podSelector-SinglePort

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
  1. 对命名空间python中的app=python-tomcat-app1-selector的pod进行网络隔离
  2. 入口隔离,即只对谁可以访问该pod进行管控
  3. 标签project=python的pod允许访问
  4. 只允许访问tcp协议的8080端口


podSelector-MultiPort

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 
      endPort: 8090
    - protocol: TCP
      port: 3306
    - protocol: TCP
      port: 6379
  1. 对命名空间python中的app=python-tomcat-app1-selector的pod进行网络隔离
  2. 入口隔离,即只对谁可以访问该pod进行管控
  3. 所有pod允许访问
  4. 允许访问tcp协议的8080至8090,3306,6379这些端口访问


ingress-ipBlock

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: 10.200.0.0/16 #白名单,允许访问的地址范围,没有允许的将禁止访问目标pod
        except:
        - 10.200.100.0/24 #在以上范围内禁止访问的源IP地址
        - 10.200.200.0/24 #在以上范围内禁止访问的源IP地址
  1. 对命名空间python中的app=python-tomcat-app1-selector的pod进行网络隔离
  2. 入口隔离,即只对谁可以访问该pod进行管控
  3. 所有pod允许访问全部端口与协议
  4. 只允许10.200.0.0/16访问,其中10.200.100.0/24和10.200.200.0/24不允许访问


ingress-namespace

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tomcat-access--networkpolicy
  namespace: python
spec:
  policyTypes:
  - Ingress
  podSelector: #目标pod
    matchLabels: {} #允许访问python namespace 中的所有pod
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          nsname: linux #只允许指定的namespace访问
    - namespaceSelector:
        matchLabels:
          nsname: python #只允许指定的namespace访问
  1. 对命名空间python中全部的pod进行网络管控
  2. 入口隔离,即只对谁可以访问该pod进行管控
  3. 只允许命名空间为linux或python的全部pod访问
  4. 可以访问全部端口与协议



Egress策略

egress-ipBlock

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的解析
  1. 对命名空间python中的app=python-tomcat-app1-selector的pod进行网络隔离
  2. 出口隔离,即对该pod可以访问谁进行管控
  3. 只允许往外访问10.200.0.0/16 和172.31.7.106/32
  4. 同时只允许访问这些外部IP的80/tcp,53/tcp,53/udp端口协议


egress-PodSelector

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
  1. 对命名空间python中的app=python-nginx-selector的pod进行网络隔离
  2. 出口隔离,即对该pod可以访问谁进行管控
  3. 只允许该pod访问标签app=python-tomcat-app1-selector的pod
  4. 允许访问外部pod的全部端口与协议


egress-namespace

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
  1. 对命名空间python中的app=python-nginx-selector的pod进行网络隔离
  2. 出口隔离,即对该pod可以访问谁进行管控
  3. 允许该pod访问命名空间为python或linux的全部pod
  4. 允许访问外部这些pod的8080/tcp,53/tcp,53/udp