网络策略

简要概述

使用 K8S 原生网络策略,既接口组 “networking.k8s.io/v1” 下服务,数据结构可参考 NetworkPolicy,以下提供一些有用地址:

  1. 官方概念手册
  2. 在线生成工具

实现原理

根据不通的 CNI 底层分别基于 iptables 或 ebpf 实现,如果 CNI 不支持网络策略,即使在 k8s 上声明了规则,也不会有任何影响。

两种 POD 网络隔离

隔离顺序

网络策略是相加的,不会产生冲突,评估的顺序不影响策略的结果,要允许从源 Pod 到目的 Pod 的连接,源 Pod 的出口策略和目的 Pod 的入口策略都需要允许连接。 如果任何一方不允许连接,建立连接将会失败。

入口隔离(Ingress)

默认情况下,一个 Pod 对入口是非隔离的,即所有入站连接都是被允许的。

出口隔离(Egress)

默认情况下,一个 Pod 的出口是非隔离的,即所有外向连接都是被允许的。

定位目标的四种组合

podSelector

  ...
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app.kubernetes.io/name: nginx
  ...

选择 Pod 标签为 “app.kubernetes.io/name=nginx” 且命名空间同该 NetworkPolicy 声明相同。

namespaceSelector

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

选择 Pod 所在的命名空间包含 “kubernetes.io/metadata.name=default” 标签(也就是 “default” 空间)。

namespaceSelector 和 podSelector

  ...
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: default
      podSelector:
        matchLabels:
          app.kubernetes.io/name: nginx
  ...

选择 Pod 标签为 “app.kubernetes.io/name=nginx” 且命名空间包含 “kubernetes.io/metadata.name=default” 标签(也就是 “default” 空间),注意下面另外一种形式:

  ...
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: default
    - podSelector:
        matchLabels:
          app.kubernetes.io/name: nginx
  ...

选择 Pod 标签为 “app.kubernetes.io/name=nginx” 或命名空间包含 “kubernetes.io/metadata.name=default” 标签(也就是 “default” 空间)。

ipBlock

  ...
  ingress:
  - from:
    - ipBlock:
        cidr: 192.168.31.0/24
        except:
        - 192.168.31.203/32
  ...

选择源 IP 来自 “192.168.31.0/24” 且排除 “192.168.31.203/32” 的网段,这些应该是集群外部 IP,因为 Pod IP 存在时间短暂的且随机产生。

配置示例

仅允许特定命名空间内访问

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: biz-dev-opsaid
spec:
  podSelector:
    matchLabels:
      api.grpc-kit.com/appname: mingqing-apilogin-v1
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: default
    ports:
    - protocol: TCP
      port: 10080

业务应用部署在 “biz-dev-opsaid” 空间内且包含名称 “mingqing-apilogin-v1”,对外提供 10080 服务端口,此时仅允许命名空间标签选择 “kubernetes.io/metadata.name” 匹配名称为 “default” 的 Pod 连接至该 10080 端口。

指定命名空间内 Pod 访问

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: biz-dev-opsaid
spec:
  podSelector:
    matchLabels:
      api.grpc-kit.com/appname: mingqing-apilogin-v1
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: default
      podSelector:
        matchLabels:
          run: nginx
    ports:
    - protocol: TCP
      port: 10080

业务应用同上,当仅允许来自 “default” 命名空间下标签为 “run=nginx” 的 Pod 连接。

拒绝所有入站流量

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Ingress

拒绝 “default” 命名空间下的所以 Pod 流量接入。

允许所有入站流量

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-ingress
  namespace: default
spec:
  podSelector: {}
  ingress:
  - {}
  policyTypes:
  - Ingress

允许 “default” 命名空间下的所以 Pod 流量接入,默认空间均没有限制,所以该规则无需特意编写。

拒绝所有出站流量

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-egress
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress

拒绝 “default” 命名空间下的所以 Pod 流量出去。

允许所有出站流量

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-egress
  namespace: default
spec:
  podSelector: {}
  egress:
  - {}
  policyTypes:
  - Egress

允许 “default” 命名空间下的所以 Pod 流量出去。

拒绝所有入与出站流量

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-egress
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

拒绝 “default” 命名空间下的所以 Pod 流量进出。




最后修改 2023.12.14: docs: 更新网络策略 (6efe4e1)