NetworkPolicy 介绍

Network Policy 是 k8s 用于控制集群pod流量的组件

默认情况下,pod是非隔离的,集群中的pod之间是可以互相通信和访问的

pod 在被某个 Network Policy 选中是进入隔离状态,一旦命名空间有pod被 Network Policy 选择,那么这个pod会拒绝 Network Policy 的流量,这个网络策略之间是不会冲突的,多个策略是累加的

Network Policy 字段

  • apiVersion: networking.k8s.io/v1

  • kind: NetworkPolicy

  • spec.podSelector: NetWork policy 是通过 这个字段来选择pod的,多个网络策略可以选择同一组pod,这个情况多个ingress 的规则效果会被叠加,空值的podSelector 匹配对应命名空间的所有规则

  • spec.policyType: 这个是规则类型的列表,用来定义规则类型列表,这个字段有效选项有三个,["ingress"] 这个代表入站流量,["Egress"]这个代表出站流量,["Ingress","Egress"] 入站和出站

  • spec.ingress: 这个是pod的入站规则列表,用来定义对应的规则,如果这个字段为空,那么,这个NetworkPolicy 是不允许任何入站流量的,这个只有满足from条件的客户端才可以访问 ports 定义的目标pod端口号

  • spec.ingress.from: 对符合条件的客户端pod 进行网络放行

  • spec.ingress.from.ipBlock: 如果设置了这个字段是不可以设置其他字段的,这个字段是通过 CIRD来设置范围(例如,192.168.200.0/24,2001.db8::/64),来自这个ip范围的流量才可以访问与 spec.podSelector 匹配的pod集合 ,可以使用 execpt 字段排除在此规则中的pod,实现效果类似于拉黑,如果 except 字段的值超出 ipBlock.cidr 的范围会被视为无效范围

  • spec.ingress.from.namespaceSelector: 通过命名空间选择,如果此字段是空值,会选择所有的命名空间,如果spec.ingress.from.podSelector 被定义,这个两个规则选择的pod都会进行匹配,反之,就只选择该namespace 匹配的所有pod

  • spec.ingress.from.podSelector: podSelector 是通过pod的标签来选择,如果字段是空值,则会 选择所有的pod,如果spec.ingress.from.namespaceSelector 被定义,这个两个规则选择的pod都会进行匹配,反之,就只选择该spec.ingress.from.podSelector 匹配的所有pod

  • spec.ingress.port: 对符合条件的端口进行放行

  • spec.ingress.endPoet: 如果设置了此字段,那么这个策略是放行 port和endPort之间的所有端口,如果没有定义port是不可以使用这个字段的,这个字段的值必须大于等于 port的值

  • spec.ingress.protocol: 这个对应的是网络协议(TCP,UDP,SCTP),默认是TCP

  • spec.egress: 这个是pod的出站规则列表,用来定义对应的规则,如果这个字段为空,那么,这个NetworkPolicy 是不允许任何入站流量的,流量必须同时匹配ports和 to的设置

  • spec.egress.to: 允许访问的服务端信息 (目的ip)

  • spec.egess.ports: 允许访问的服务端的端口号 (目的端口)

  • egress下面的字段和ingress的字段相同,可以参考上面的描述

Network Policy 实战

实验环境说明

创建两个命名空间 network1 和network2

在两个命令空间中分别创建两个 delplyment 工作负载的pod

其中 network1 命名空间下面的工作负载 nginx1 和 nginx2

network2 命令空间下面的工作负载 nginx3

创建实验环境

可以通过apply 如下 yaml创建

apiVersion: v1
kind: Namespace
metadata:
  labels:
    kubernetes.io/metadata.name: network1  #  创建network1 的命名空间
  name: network1
spec:
  finalizers:
  - kubernetes

---
apiVersion: v1
kind: Namespace
metadata:
  labels:
    kubernetes.io/metadata.name: network2  #  创建network1 的命名空间
  name: network2
spec:
  finalizers:
  - kubernetes

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx1
  namespace: network1
  labels:
    app: nginx1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx1
  template:
    metadata:
      labels:
        app: nginx1
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx2
  namespace: network1
  labels:
    app: nginx2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx2
  template:
    metadata:
      labels:
        app: nginx2
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx3
  namespace: network2
  labels:
    app: nginx3
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx3
  template:
    metadata:
      labels:
        app: nginx3
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80       

network1 下的pod只能在同namespace访问

案例 yaml

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: network-test-demo
  namespace: network1
spec:
  ingress: 
  - from:  
    - podSelector: {}   
  podSelector: {} 
  policyTypes:
  - Ingress 

案例 yaml文件说明

  1. 这个yaml的spec.podSelector 为空,含义是选择这个命名空间的下面的所有pod

  2. spec.ingress.from 对符合条件的pod进行放行,这个字段下面的podSelector 为空则会选择所有的pod

因此这个yaml文件可以实现只让同namespace 下面的pod访问

实战效果

运行对应的yaml文件

查看创建的 NetworkPolicy 规则

kubectl describe NetworkPolicy  network-test-demo  -n  network1

测试访问效果

nginx1 可以访问 nginx2 nginx3

nginx 3 无法访问 nginx1 和 nginx 2

network1 下的pod不能被任何pod访问

案例 yaml

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: network-test-demo1
  namespace: network1
spec:  
  podSelector: {}
  policyTypes:
  - Ingress

案例 yaml文件说明

  1. spec.podSelector 字段为空,表示选择该nameSpace所有pod

  2. spec.ingress 字段为空, 表示不允许任何入站流量

实战效果

登录nginx1 查看,可以看到访问 nginx2 不通

只让nginx3 的 IP访问 nginx1 的 80端口

查看nginx3 的IP

案例 yaml

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: network-test-demo2
  namespace: network1
spec:  
  podSelector: 
    matchLabels:
      app: nginx1
  ingress:  
  - from: 
    - ipBlock:
        cidr:  10.16.4.35/32
    ports:
    - protocol: TCP
      port: 80  
  policyTypes:
  - Ingress

案例 yaml文件说明

  1. spec.podSelector.matchLabels 这里通过标签选择了pod,这里选择的 nginx1,这个规则限制的nginx1 的

  2. 在 from中限制,只有来源是 10.16.4.35 的IP才能访问 nginx1 的80端口

实战效果

测试结果。nginx3 可以通, nginx1 不可以通

指定IP段访问,拉黑nginx3的IP

案例 yaml

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: network-test-demo3
  namespace: network1
spec:  
  podSelector: 
    matchLabels:
      app: nginx1
  ingress:  
  - from: 
    - ipBlock:
        cidr:  10.16.4.0/24
        except:  
        - 10.16.4.35/32
    ports:
    - protocol: TCP
      port: 80  
  policyTypes:
  - Ingress

案例 yaml文件说明

通过 cidr: 10.16.4.0/24 允许这个IP段的访问

排除这个 IP 10.16.4.35 , 这个IP是nginx3 的IP

实战效果

测试结果 nginx2 可以正常访问,nginx3 不可以