1. 写在最前

请注意你的集群 cni 插件是否支持网络策略功能,否则将无法生效

2. 描述概念

  1. 网络策略的组成是选中一组目标容器pod,然后对这一组目标容器pod进行限制出入站

3. 例子详解

3.1 标签选择

  1. default 名称空间

  2. 选中 default 名称空间中 带有app: nginx标签的pod容器

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  namespace: default
  name: test-policy
spec:
  podSelector: 
    matchLabels:
      app: nginx

3.2 标签表达式

  1. default 名称空间

  2. 选中 default 名称空间中带有app标签 包含 nginx,tomcat,kafka的pod容器

operator有In 包含、NotIn 不包含、DoesNotExist 不存在

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  namespace: default
  name: test-policy
spec:
  podSelector:
    matchExpressions:
      - key: app
        operator: In
        values:
          - nginx
          - tomcat
          - kafka

3.3 策略类型

完成 podSelector 只是第一步,第二步则是配置策略类型(policyTypes

策略类型有两个值,一个是 Ingress(进站) 另一个是Egress(出站)

3.4 进站Ingress

如果你只写上了 policyTypes 却没有写它的具体实现,则表示拒绝所有

3.4.1 拒绝入站流量

  1. tanqidi 名称空间

  2. 选中 tanqidi 名称空间中带有app标签是 tanqidi-service 的pod容器

  3. 拒绝所有入站流量

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  namespace: tanqidi
  name: tanqidi-service
spec:
  podSelector:
    matchLabels:
      app: tanqidi-service
  policyTypes:
  - Ingress

3.4.2 允许入站流量

  1. tanqidi 名称空间

  2. 选中 tanqidi 名称空间中带有app标签是 tanqidi-service 的pod容器

  3. 允许当前 namespace 中的其他pod容器访问我

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  namespace: tanqidi
  name: tanqidi-service
spec:
  podSelector:
    matchLabels:
      app: tanqidi-service
  policyTypes:
    - Ingress
  
  ingress:
    - from:
        - podSelector: {}

3.4.3 标签选择

  1. tanqidi 名称空间

  2. 选中 tanqidi 名称空间中带有app标签是 tanqidi-service 的pod容器

  3. 允许当前 namespace 中的 app 标签包含 tanqidi-web、tanqidi-mgt、tanqid-center 的pod容器访问我

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  namespace: tanqidi
  name: tanqidi-service
spec:
  podSelector:
    matchLabels:
      app: tanqidi-service
  policyTypes:
    - Ingress

  ingress:
    - from:
        - podSelector:
            matchExpressions:
              #可以是任意你想选择的标签
              - key: app 
                operator: In
                values:
                  - tanqidi-web
                  - tanqidi-mgt
                  - tanqidi-center

3.4.4 跨 namespace 入站

namespaceSelector 可以做到跨越namespace的出入站限制,不仅仅是当前 namespace

  1. tanqidi 名称空间

  2. 选中 tanqidi 名称空间中带有app标签是 tanqidi-service 的pod容器

  3. 允许 lisi 名称空间下的所有pod访问我

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  namespace: tanqidi
  name: tanqidi-service
spec:
  podSelector:
    matchLabels:
      app: tanqidi-service
  policyTypes:
    - Ingress

  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: lisi

3.4.5 跨 namespace 入站,and关系

  1. tanqidi 名称空间

  2. 选中 tanqidi 名称空间中带有app标签是 tanqidi-service 的pod容器

  3. 允许 lisi 名称空间的 并且 app 标签是 lisi-service 的pod访问我

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  namespace: tanqidi
  name: tanqidi-service
spec:
  podSelector:
    matchLabels:
      app: tanqidi-service
  policyTypes:
    - Ingress

  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: lisi
          # 开头没有-表示 and关系
          podSelector:
            matchLabels:
              app: lisi-service

3.5 出站egress

3.5.1 拒绝出站流量

如果你只写上了 policyTypes 却没有写它的具体实现,则表示拒绝所有

  1. tanqidi 名称空间

  2. 选中 tanqidi 名称空间中带有app标签是 tanqidi-service 的pod容器

  3. 拒绝所有流量出站

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  namespace: tanqidi
  name: tanqidi-service
spec:
  podSelector:
    matchLabels:
      app: tanqidi-service
  policyTypes:
    - Egress

3.5.2 允许出站流量

这里描述的允许出站指的是仅只能访问当前的 namespace下的任意pod容器,不同的 namespace 他是无法访问的,因为没有使用 namespaceSelector 跨越名称空间

  1. tanqidi 名称空间

  2. 选中 tanqidi 名称空间中带有app标签是 tanqidi-service 的pod容器

  3. 允许出站到当前名称空间

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  namespace: tanqidi
  name: tanqidi-service
spec:
  podSelector:
    matchLabels:
      app: tanqidi-service
  policyTypes:
    - Egress
  egress:
    - to:
        - podSelector: {}

3.5.3 跨 namespace 出站流量(复杂)

目标

  1. tanqidi 名称空间

  2. 选中 tanqidi 名称空间中带有app标签是 tanqidi-db 的pod容器

入站

  1. 允许当前 namespace 中的app 标签是 tanqidi-service的pod容器访问我

  2. 允许 namespace 包含zhangsan,lisi,wangwu的名称空间下的 app 标签包含 app-mgt,app-center,app-proxy下的 pod容器访问我

出站

  1. 允许流量出站到当前 namespace 中的 app标签是 tanqidi-service 的pod容器

  2. 允许流量出站到 namespace 包含zhangsan,lisi,wangwu的名称空间下任意 any 容器

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  namespace: tanqidi
  name: tanqidi-db
spec:
  podSelector:
    matchLabels:
      app: tanqidi-db
  policyTypes:
    - Ingress
    - Egress
  ingress:
    # 允许当前 namespace 下的 app标签是 tanqidi-service 容器访问我
    - from:
        - podSelector:
            matchLabels:
              app: tanqidi-service

    # 允许 namespace包含 zhangsan、lisi、wangwu 的名称空间下 并且 app 标签 包含 app-mgt,app-center,app-proxy 的pod访问我
    - from:
        - namespaceSelector:
            matchExpressions:
              - key: kubernetes.io/metadata.name
                operator: In
                values:
                  - zhangsan
                  - lisi
                  - wangwu
          # 组合方式,表示 and 关系
          podSelector:
            matchExpressions:
              - key: app
                operator: In
                values:
                  - app-mgt
                  - app-center
                  - app-proxy

  egress:
    - to:
        # 允许出站流量到当前 namespace 中的app标签是 tanqidi-service的容器
        - podSelector: 
            matchLabels:
              app: tanqidi-service

        # 允许流量出站到 namespace 包含 zhangsan,lisi,wangwu的任意pod
        - namespaceSelector:
            matchExpressions:
              - key: kubernetes.io/metadata.name
                operator: In
                values:
                  - zhangsan
                  - lisi
                  - wangwu

3.6 条件 and 与 or

3.6.1 and 关系

  1. tanqidi 名称空间

  2. 选中 tanqidi 名称空间中带有app标签是 tanqidi-db 的pod容器

  3. 允许 namespace 为 lisi 的名称空间下的 app标签是 lisi-service的pod访问我

当为namespaceSelector选中 kubernetes.io/metadata.name 为 lisi 的时候,此刻该名称空间下的所有pod 都能访问 目标 tanqidi 名称空间下的 tanqidi-db的pod,但是紧接着你使用了 and关系添加了podSelector 为 app: lisi-service,换而言之条件就变小了变成 lisi的namespace 下的 lisi-service的pod能访问目标 tanqidi 名称空间下的 tanqidi-db的pod

请注意 and 关系到第二个的时候不能在开头加上- 否则就是or 关系了

361dbe439b2da3bfff6301e1005a934d.jpg

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  namespace: tanqidi
  name: tanqidi-db
spec:
  podSelector:
    matchLabels:
      app: tanqidi-db
  policyTypes:
    - Ingress
  ingress:
    - from:
        # 允许 namespace 名称空间为 lisi的访问我
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: lisi
          # 允许 namespace 名称空间为 lisi的 app标签为 lisi-service的访问我。此时就变了,不再是任意lisi下的pod访问我,而只是 lisi下的lisi-service的pod访问我,换而言之 and的关系会将条件进一步缩小
          podSelector:
            matchLabels:
              app: lisi-service

3.6.2 or 关系

  1. tanqidi 名称空间

  2. 选中 tanqidi 名称空间中带有app标签是 tanqidi-db 的pod容器

  3. 允许当前名称空间中 app标签带有 tanqidi-service 的pod访问我

  4. 允许 namespace 为 lisi 的名称空间下的任意pod访问我

or 关系两个都是独立的,需要在新的规则前加上-

图片-uqhu.png

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  namespace: tanqidi
  name: tanqidi-db
spec:
  podSelector:
    matchLabels:
      app: tanqidi-db
  policyTypes:
    - Ingress
  ingress:
    # 允许当前 namespace 下的 app标签是 tanqidi-service 容器访问我
    - from:
        - podSelector:
            matchLabels:
              app: tanqidi-service

    # 允许 namespace 为 lisi 的名称空间下的任意pod访问我
    - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: lisi