在kubernetes中的所有的pod在默认情况下,网络都是互通的,pod接收来自任何来源的流量.

那么我们如何限制pod的网络通信,防止非法访问呢?

kubernetes为了解决上诉的问题,为我们提供了一个新的资源NetworkPolicy,主要用来定义pod之间的网络规则,指定进出pod的流量.

先决条件

kubernetes的网络是一个典型的二层网络,pod间为了能够互相通信,专门诞生了cni项目,并出现了很多网络插件,例如Calico,WeaveNet,flannel等等,这些插件实现都有各自的方案,但是总体下来目标一致,都是为kubernetes提供一个二层网络,并且让pod可以直接通信.

NetworkPolicy资源的实际实现也是由网络插件控制,如果网络插件未实现此资源,那么将不起作用.

在官方文档中现在支持的插件有以下几个:

NetworkPolicy资源介绍

NetworkPolicy资源由三个主要部分构成

podSelector: 根据命名空间和label来选择需要应用网络策略的pod

policyTypes: 网络策略类型,数组类型,可选值为Ingress,engress或者两个都填写.如果未指定则默认值为ingress,engress

ingress: 入口白名单规则,可以通过from设置从那些地方进入的流量,子字段ipBlock,namespaceSelector,podSelector等字段提供了对于来源的灵活选择,也可以通过ports可以设置从那些端口进入的流量

engress: 同ingress基本一致,但是from修改为了to

一个包含进出的网络策略示例如下:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  - Ingress
  - Egress
  ingress:
  # from配置来源规则,可以多个
  - 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

本示例的网络策略如下:

  • 通过podSelector选择了default命名空间下的label为role: db的pod,设置网络策略
  • 入口规则设置了一个来源,其中开放了tcp协议6379端口,并满足以下情况:
    • 网段为172.17.0.0/16,但是排除172.17.1.0/24
    • 命名空间的label包含project: myproject
    • default命名空间中,pod标签包含role: frontend
  • 出口规则为选择的pod设置了一个出站规则,从tcp协议的5978端口发出连接,同时需要满足:
    • 子网为10.0.0.0/24

注意: NetworkPolicy资源为命名空间内资源,在使用时需要指定命名空间

默认策略

NetworkPolicy未指定的情况下(也就是我们平常使用的情况),那么pod是允许所有流量进出的.

在podSelector为空对象(即值为{})时,则是选择该命名空间所有的pod,如果ingress/engress为空对象(即值为{})时,则允许所有流量进/出,例如:

默认拒绝所有流量

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny
spec:
  podSelector: {}
  policyTypes:
  - Ingress
# 未配置 ingress 字段,则标示没有允许的入口,则拒绝所有.

默认允许所有流量

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all
spec:
  podSelector: {}
  # 配置了一个空的ingress,标示 所有的入口,则允许所有的进入
  ingress:
  - {}
  policyTypes:
  - Ingress

参照

官方文档

官方示例

NetworkPolicy资源的完整定义