网络隔离策略 NetworkPolicy

在 UK8S 集群中中,默认情况下,所有的 Pod 都是互通的,即任一 Pod 既可以接收来自集群中任何 Pod 发送的请求,也可以向任一集群中 Pod 发送请求。

但在实际业务场景中,为了保障业务安全,网络隔离是非常必要的。下面介绍下如何在 UK8S 中实现网络隔离。

安装前检查

⚠️ 在安装 Calico 网络隔离插件之前,请务必确认 CNI 版本大于等于 19.12.1,否则会删除Node上原有的网络配置,导致 Pod 网络不通。CNI 版本查询及升级请参考:CNI 网络插件升级

检查kubernetes版本 <=1.26.7,且>= 1.16.4,并且集群需要通外网拉取Uhub以外的镜像

确认集群中是否使用组件ipamd:

kubectl -n kube-system get ds cni-vpc-ipamd

如果没有使用,可以忽略下面检查; 如果已经使用ipamd,确认ipamd是否开启Calico网络策略支持; 使用如下命令查看参数--calicoPolicyFlag是否为true

kubectl -n kube-system get ds cni-vpc-ipamd -o=jsonpath='{.spec.template.spec.containers[0].args}{"\t"}{"\n"}'

["--availablePodIPLowWatermark=3","--availablePodIPHighWatermark=50","--calicoPolicyFlag=true","--cooldownPeriodSeconds=30"]

如果--calicoPolicyFlag参数不为true,需要使用如下命令开启:

kubectl -n kube-system patch ds cni-vpc-ipamd -p '{"spec":{"template":{"spec":{"containers":[{"name":"cni-vpc-ipamd","args":["--availablePodIPLowWatermark=3","--availablePodIPHighWatermark=50","--calicoPolicyFlag=true","--cooldownPeriodSeconds=30"]}]}}}}'

1. 安装插件

为了在 UK8S 中实现网络隔离,需要部署 Calico 的 Felix 和 Typha 组件,组件模块已容器化,直接在 UK8S 通过 kubectl 命令安装即可.

UK8S 提供了两种版本的 Calico 组件来实现网络隔离,分别兼容以下 UK8S 版本,请自行选择.

UK8S version Calico version
<=1.24.12 3.10.0
1.26.7 3.25.2
calico_version="3.25.2" && kubectl apply -f https://docs.ucloud.cn/uk8s/yaml/networkpolicy/${calico_version}-calico-policy-only.yaml

2. NetworkPolicy 规则解析

安装完 Calico 的网络隔离策略组件后,我们就可以在 UK8S 中创建 NetworkPolicy 对象,用于实现 Pod 的访问控制,如下所示。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6379
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 5978

下面简要描述下各个参数的作用:

  • spec.podSelector: 这个参数的意义用于决定该NetworkPolicy的作用域,即对那些Pod有效。上面的示例表示对default namespace下携带了role=db 标签(label)的pod生效。这里要说明下,NetworkPolicy是namespace级别的资源对象。

  • spec.ingress.from: 入向请求访问控制,即接受哪些源的请求。支持IP、namespace、pod三种控制模式,上面的示例表示放行源地址为172.17/16中除172.17.1/24 之外的请求、或任何携带了标签projcet=myproject的namespace下的所有pod、或Default namespace里携带了role=frontend标签的pod。from中的多组规则是或逻辑,满足上述三个条件中的一个即放行。 其中namespaceSelector这个字段,用于筛选来自多个namespace下的请求源。

  • spec.ingress.ports: 声明开放访问的端口,如果不填写则默认开放所有。上面的示例表示只允许访问6379端口。from和ports是与逻辑,即指允许上述from规则下放行的源访问6379端口(TCP)。

  • spec.egress: 声明允许访问的目的地址,与from类似。上面的示例表示只允许请求IP为10.0.0.0/24网段的地址,并且只允许访问该网段地址的5978端口(TCP)。

通过上面的描述,我们应该清楚,NetworkPolicy是一个白名单机制,即一旦开启NetworkPolicy,除非显式指定,否则一概拒绝。

3. 示例

3.1 限制一组Pod只允许访问VPC内部的资源(不能访问外网)

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: pod-egress-policy
spec:
  podSelector:
    matchLabels:
      pod: internal-only
  egress:
  - to:
    - ipBlock:
        cidr: 10.9.0.0/16

3.2 限制暴露了公网服务的Service的来源IP

首先创建一个通过外网ULB4对公网暴露服务的应用

apiVersion: v1
kind: Service
metadata: 
  name: ucloud-nginx
  labels:
    app: ucloud-nginx
spec: 
  type: LoadBalancer
  externalTrafficPolicy: Local
  ports: 
    - protocol: TCP
      port: 80
  selector:
    app: ucloud-nginx
---
apiVersion: v1
kind: Pod
metadata:
  name: test-nginx
  labels:
    app: ucloud-nginx
spec:
  containers:
  - name: nginx
    image: uhub.service.ucloud.cn/ucloud/nginx:1.9.2
    ports:
    - containerPort: 80

上述应用创建完毕后,我们可以通过外网ULB IP直接访问应用,现在我们设置只允许从办公室环境访问该应用,假设办公室出口IP为106.10.10.10。

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: access-nginx
spec:
  podSelector:
    matchLabels:
      app: ucloud-nginx
  ingress:
  - from:
    - ipBlock:
        cidr: 106.10.10.10/24  #验证时请改为你客户端的出口IP。
    - ipBlock:
        cidr: 10.23.248.0/21  #地域级别公共服务网段,否则ULB健康检查会失败导致隔离策略不生效,详见下文

4. 放行 VPC 公共服务网段

公共服务网段主要用于内网 DNS、ULB 健康检查等,建议在配置 NetworkPolicy 时,放行各地域的公共服务网段。

各地域公共服务网段请参考 VPC 文档:VPC 网段使用限制

最近更新时间:2025-03-19 09:32:07