Kubernetes Network

学习参考:网络策略

环境准备

root@master30:~# kubectl create ns network
root@master30:~# kubectl config set-context --current --namespace network

单主机网络通信

Docker 单机网络

Docker中的网络接口默认都是虚拟的接口。虚拟接口的最大优势就是转发效率极高。这是因为Linux在内核中进行数据复制来实现虚拟接口之间的数据转发,即发送接口的发送缓存中的数据包将被直接复制到接收接口的接收缓存中,而无需通过外部物理网络设备进行交换。

Docker 服务默认会创建一个名称为docker0的Linux网桥(其上有一个docker0内部接口),利用了Linux虚拟网络技术,在本地主机和容器内分别创建一个虚拟接口,并让它们彼此连通(这样的一对接口叫做vethpair)。Docker默认指定了docker0接口的IP地址和子网掩码,让主机和容器之间可以通过网桥相互通信。

在这里插入图片描述

说明:brctl工具由bridge-utils提供。

外部主机要想访问容器,需要通过端口映射实现。

Containerd 单机网络

Containerd 中的网络 与Docker类似,所有网络接口默认都是虚拟接口。

创建容器时,Containerd 会在本地主机和容器内分别创建一个虚拟接口,并让它们彼此连通。

跨主机网络通信

跨主机网络通信架构

在这里插入图片描述

以上图片来源于《基于 kubernetes 的容器云平台实战 》。

跨主机通信方法比较多:

  1. docker 原生的方案:overlay 和 macvlan。
  2. 第三方提供的方案:flannel 、calico、weave等。

以下数据来源于《kubernetes 权威指南》。

方案 特性FlannelCalicomacvlanOpenVswitch直接路由
方案特性通过虚拟设备flannel0实现对docker0的管理基于BGP协议的纯三层的网络方案基于Linux Kernel 的macvlan技术基于隧道的虚拟路由器技术基于Linux Kernel 的 vRouter 技术
对底层网络的要求三层互通三层互通二层互通三层互通二层互通
配置难易程度简单-基于etcd简单-基于etcd简单-直接使用宿主机网络,需要仔细规划IP地址复杂-需手工配置个节点的bridge简单-使用宿主机vRoute功能,需要仔细规划每个Node的IP地址
网络性能host-gw > VxLANBGP 模式性能随时小、IPIP 模式较小性能随时可忽略性能随时较小性能随时较小
网络连通性限制无在不支持BGP的网络环境下无法使用基于macvlan的容器无法与宿主机网络通信无在无法实现大二层互通的网络环境下无法使用

跨主机网络通信方案

跨主机网络意味着将不同主机上的容器用同一个虚拟网络连接起来。常用网络模型包括:

  • Underlay:直接使用底层物理网络转发 Pod 流量,无隧道封装,性能优于 Overlay 网络。
  • Overlay:在宿主机网络之上构建虚拟隧道,将数据包封装到 UDP 中进行传输。虽然所有 Overlay 网络方案底层可以采用 Linux kernel 的 vxlan 模块,尽量减少开销,但这个开销与 Underlay 网络相比还是存在的。

Overlay支持更多的二层网段,能更好地利用已有网络,以及有避免物理交换机 MAC 表耗尽等优势。

1. Flannel

Flannel 提供两种主流工作模式

  1. host-gw(Underlay) - 原理:节点上添加静态路由,目标Pod网段下一跳指向目标宿主机IP;无任何报文封装。 - 流量:Pod原始IP包直接在底层网络传输。 - 约束:底层网络能够转发Pod网段路由;公有云大多不支持。 - 性能:高。
  2. VXLAN(Overlay) - 原理:跨节点Pod报文封装UDP VXLAN包头,通过宿主机网络传输,到达对端解封装。 - 约束:仅要求宿主机之间IP连通,公有云通用。 - 性能:存在封包解包开销,低于host-gw。

Flannel仅负责连通,不提供网络策略NetworkPolicy。

2. Calico
  1. BGP 模式(Underlay) - 节点间通过BGP交换Pod路由,无隧道封装,原生IP转发。 - 性能最优;前提:网络允许BGP协议发布路由。
  2. IPIP / VXLAN模式(Overlay) - 底层不支持BGP时启用IP-in-IP隧道封装;数据包外层增加宿主机IP头。 - 适配公有云;封装带来性能损耗。

Calico最大亮点:原生支持 NetworkPolicy(Pod防火墙策略)。

3. Weave

默认采用 Overlay。

  • 工作方式:节点之间建立UDP隧道,封装Pod流量;自动发现集群节点。
  • 特色: 1. 内置DNS; 2. 支持NetworkPolicy; 3. 可以混合运行加密隧道;
  • 短板: 隧道封装持续占用CPU;大规模集群性能弱于Flannel VXLAN、Calico。

Weave也支持快速MAC路由优化,但主体模型仍然归类Overlay。

4. Macvlan

Macvlan 属于 Underlay 方案

  • 原理:在宿主机物理网卡上虚拟多张独立网卡,每个Pod拥有独立MAC地址;Pod直接接入底层物理局域网。
  • 流量:Pod报文直接在二层物理网络转发,不存在隧道封装。 ✅ 优点:性能极高,Pod和物理机器同等地位,网络延迟极低。 ❌ 限制:
  1. 宿主机网卡不能开启桥接;
  2. 同一父网卡Macvlan子接口无法直接互通(同宿主机Pod互通缺陷);
  3. 网络规划复杂,传统虚拟化环境容易冲突。

典型场景:需要Pod分配局域网独立IP、需要被局域网其他物理设备直接访问。

5. 网络模型比较
CNI方案可用网络模型是否隧道封装支持NetworkPolicy适用场景
Flannelhost-gw(Underlay)、VXLAN(Overlay)VXLAN封装;host-gw无封装❌ 不支持追求简单、不需要Pod访问控制;中小型集群
CalicoBGP(Underlay)、IPIP/VXLAN(Overlay)IPIP/VXLAN封装;BGP无封装✅ 原生支持需要网络策略、自建机房/公有云通用
Weave NetUDP隧道OverlayUDP封装✅ 支持测试环境、小规模集群;部署简单,无需etcd
MacvlanUnderlay(二层直连物理网络)❌ 无任何封装取决于配套CNIPod需要占用局域网独立IP、低延迟业务

跨主机网络通信模型

容器网络的配置是一个复杂的过程,为了应对各式各样的需求:

  • 容器网络的解决方案也多种多样,例如有flannel,calico,kube-ovn,weave等。
  • 容器平台/运行时也是多样的,例如有Kubernetes,Openshift,rkt等。

想要解决这个问题,我们需要一个抽象的接口层,将容器网络配置方案与容器平台方案解耦。

CNM 模型

CNM( Container Network Model,容器网络模型),由 Docker 公司提出,在 docker 项目下的 libnetwork 项目中被采用。按照该模型开发出的 driver 就能与 docker daemon 协同工作,实现容器网络。

  • docker 原生的 driver 包括 none、bridge、overlay 和 macvlan。
  • 第三方 driver 包括 flannel、weave、calico 等。

在这里插入图片描述

容器网络模型对容器网络进行了抽象,由以下三类组件组成:

  • Sandbox 是容器的网络栈,包含容器的 interface、路由表和 DNS 设置。 Linux Network Namespace 是 Sandbox 的标准实现。Sandbox 可以包含来自不同 Network 的 Endpoint。
  • Endpoint 的作用是将 Sandbox 接入 Network。Endpoint 的典型实现是 veth pair,后面我们会举例。一个 Endpoint 只能属于一个网络,也只能属于一个 Sandbox。
  • Network 包含一组 Endpoint,同一 Network 的 Endpoint 可以直接通信。Network 的实现可以是 Linux Bridge、VLAN 等。

如图所示两个容器,一个容器一个 Sandbox,每个 Sandbox 都有一个 Endpoint 连接到 Network 1,第二个 Sandbox 还有一个 Endpoint 将其接入 Network 2.

在这里插入图片描述

下面我们以 docker bridge driver 为例讨论 libnetwork CNM 是如何被实现的。

  1. 两个 Network:默认网络 “bridge” 和自定义网络 “my_net2”。实现方式是 Linux Bridge:“docker0” 和 “br-5d863e9f78b6”。
  2. 三个 Enpoint,由 veth pair 实现,一端(vethxxx)挂在 Linux Bridge 上,另一端(eth0)挂在容器内。
  3. 三个 Sandbox,由 Network Namespace 实现,每个容器有自己的 Sanbox。

在这里插入图片描述

CNI 模型

CNI,全称 Container Network Interface,是 Google 和 CoreOS 联合定制的网络标准,CNI 规范定义了容器和网络插件之间通信规范,实现多容器通信。各个网络厂商通过该接口实现互相通信。

在这里插入图片描述

一个容器可以被加入到被不同插件所驱动的多个网络之中。一个网络有自己对应的插件和唯一的名称。

CNI 模型包含2个概念:

  • 容器: 独立的 linux 网络命名空间。
  • 网络: 用于互联实体, 这些实体拥有各自独立且唯一的 IP 地址, 可以是容器, 物理机, 或者其他网络设备。

通过插件设置网络, 包括 CNI Plugin 和 IPAM ( IP address management) Plugin 两类插件:

  • CNI Plugin 负责配置容器网络。
  • IPAM plugin 负责分配容器的IP 地址。

IPAM Plugin 作为 CNI plugin 的一部分, 与CNI plugin 一起工作。

模型比较
特点CNMCNI
标准规范Libnetworkcni
最小单元容器POD
对守护进程的依赖依赖 dockerd不依赖任何守护进程
扩主机通信依赖外部 KV 数据库用本身的 KV 数据库
灵活程度被 docker 绑定插件可随意替换

K8s 中 Calico 网络

Calico 网络优势

Kubernetes 集群采用 Calico 网络通信方案优势:

  1. 支持 BGP 模式(Underlay) - 节点间通过BGP交换Pod路由,无隧道封装,原生IP转发。 - 性能最优;前提:网络允许BGP协议发布路由。
  2. 支持IPIP / VXLAN模式(Overlay) - 底层不支持BGP时启用IP-in-IP隧道封装;数据包外层增加宿主机IP头。 - 适配公有云;封装带来性能损耗。
  3. 支持 NetworkPolicy(Pod防火墙策略)。

Calico 隧道模式

Calico 支持两种隧道模式:IPIP 和VXLAN 。

ipipMode 隧道
  • 协议:三层隧道,把内层IP包完整封装进外层IP包。
  • 虚拟网卡:tunl0。
  • 封装结构:外层IP头(节点IP) + 内层IP头(Pod IP) + 应用数据。
  • 只封装IP包,不携带二层帧(MAC)。
VXLAN 隧道
  • 协议:二层隧道,UDP报文,默认端口 4789。
  • 虚拟网卡:vxlan.calico。
  • 封装结构:外层IP+UDP头 + VXLAN头部(VNI) + 完整二层帧(MAC+IP+数据)。
  • 保留完整二层,支持广播、组播。
项目IPIPVXLAN
隧道类型三层IP隧道二层UDP隧道
传输载体IP协议号4UDP 4789
是否带二层MAC❌ 不带✅ 完整二层帧
包头开销较小更大(多VXLAN头部,MTU要更小)
云厂商限制很多公有云封禁协议号4,IPIP直接不通UDP端口一般放行,公有云兼容性更好
广播/组播不支持支持
Calico配置ipipMode:Always,vxlanMode:NeveripipMode:Never,vxlanMode:Always
故障排查抓包简单,只有内外两层IP包结构更复杂
适用场景私有机房、底层网络允许IPIP协议公有云、底层网络不允许IPIP
隧道模式选择
选 IPIP 的场景
  1. 私有物理机房,底层网络不拦截IP协议号4
  2. 集群只需要单播Pod通信,不需要二层广播
  3. 想更小的包头开销,追求略高一点性能

缺点:公有云(阿里云/AWS等)默认会拦截IPIP协议,直接无法通信。

选 VXLAN 的场景
  1. 公有云环境(AWS、阿里云、腾讯云),云安全组屏蔽IPIP协议
  2. 需要二层广播能力(少数特殊业务)
  3. 底层网络不支持透传IP协议4号

缺点:封装头部更大,MTU需要调小;性能略低于IPIP。


Calico 工作模式

ipipMode 隧道
  1. Always(默认),所有跨节点Pod流量封装隧道包,路由下一跳指向 tunl0。节点只需要三层可达,不需要底层网络感知Pod网段。
  2. Never(BGP原生/Underlay),不封装IPIP,依靠BGP在节点之间同步Pod网段路由;路由下一跳是节点物理网卡。要求节点同子网L2互通。
  3. CrossSubnet(混合),同子网节点之间通信:不封装IPIP(BGP原生);跨子网节点之间通信:自动启用IPIP隧道封装。

无论是否开启IPIP,Calico都会运行BGP进程,BGP负责同步Pod网段;IPIP开关只决定数据包是否封装隧道。


VXLAN 隧道

vxlanMode 也支持三个取值:Never / Always / CrossSubnet,功能于 ipipMode 取值一致。

  1. Always,所有跨节点 Pod 流量全部封装 VXLAN 隧道(Overlay)。
  2. Never,不启用 VXLAN 隧道。
  3. CrossSubnet 混合模式,同子网节点之间通信不封装;跨子网节点之间通信启用VXLAN隧道封装。
工作模式选择
  1. 选 Never
  • 没有隧道封装,性能优;
  • 抓包可以直接观察Pod原生IP;
  1. 选 Always
  • 节点分布在不同子网,节点之间无法二层互通;
  • 公有云(阿里云/腾讯云/AWS)部署Calico;
  • 不想依赖底层网络支持BGP。
  1. 选 CrossSubnet
  • 企业机房,节点划分为多个子网;
  • 同网段节点直接路由,跨网段节点自动走IPIP隧道。

查看工作模式

IPPool是Calico控制隧道模式的核心资源。

# 方法1:查看 IPPool 资源
root@master30:~# kubectl get ippool -o yaml|egrep 'ipip|vxlan'
    ipipMode: Always
    vxlanMode: Never

# 方法2:查看宿主机路由表
# 在任意节点执行
root@master30 ~# ip route | grep '/26 via'
10.224.19.0/26 via 10.1.8.31 dev tunl0 proto bird onlink 
10.224.113.128/26 via 10.1.8.32 dev tunl0 proto bird onlink
# 路由条目末尾出现 `dev tunl0` → IPIP隧道模式(数据包走IPIP封装)
# 路由条目指向物理网卡 `dev ens32` → BGP原生路由模式

修改工作模式

⚠️ 风险提示:修改IPPool会立刻改变集群跨节点Pod转发行为,生产环境需要业务低峰操作,提前备份。

# 步骤1:备份原有IPPool配置,`egrep` = **grep -E**,支持**扩展正则**,`| + ? ()` 不用反斜杠转义
root@master30 ~# kubectl get ippool default-ipv4-ippool -o yaml > ippool-backup.yaml

# 步骤2:直接编辑 default-ipv4-ippool
root@master30 ~# kubectl edit ippool default-ipv4-ippool
apiVersion: crd.projectcalico.org/v1
kind: IPPool
metadata:
  name: default-ipv4-ippool
spec:
  cidr: 10.224.0.0/16
  # 修改 ipipMode
  ipipMode: Never
...

配置下发等待30~60秒自动生效;长时间不生效,可以重启calico-node daemonset:

# 步骤3:验证路由表
root@master30 ~# ip route | grep '/26'
10.224.19.0/26 via 10.1.8.31 dev ens32 proto bird 
10.224.113.128/26 via 10.1.8.32 dev ens32 proto bird 

网络策略

网络策略介绍

默认情况,集群网络连通性如下:

  • 集群外部主机可以访问集群内部应用
  • 集群内部应用也可以访问集群外部主机
  • 各个namespace之间没有做任何的隔离策略

如果希望在 IP 地址或端口层面控制网络流量, 考虑使用 Kubernetes 网络策略(NetworkPolicy)。

  • NetworkPolicy 是一种以应用为中心的结构,允许你设置如何允许 Pod 与网络上的各类网络“实体” 通信。
  • NetworkPolicy 适用于一端或两端与 Pod 的连接,与其他连接无关。

**提示:**网络策略通过网络插件来实现。 要使用网络策略,你必须使用支持 NetworkPolicy 的网络解决方案,例如 calico。

网络策略规约

Pod 有两种隔离: 出口的隔离和入口的隔离。

  • 默认情况下,**一个 Pod 的出口是非隔离的,即所有外向连接都是被允许的。**如果有任何的 NetworkPolicy 选择该 Pod 并在其 policyTypes 中包含 “Egress”,则该 Pod 是出口隔离的, 我们称这样的策略适用于该 Pod 的出口。当一个 Pod 的出口被隔离时, 唯一允许的来自 Pod 的连接是适用于出口的 Pod 的某个 NetworkPolicy 的 egress 列表所允许的连接。 这些 egress 列表的效果是相加的。
  • 默认情况下,**一个 Pod 对入口是非隔离的,即所有入站连接都是被允许的。**如果有任何的 NetworkPolicy 选择该 Pod 并在其 policyTypes 中包含 “Ingress”,则该 Pod 被隔离入口, 我们称这种策略适用于该 Pod 的入口。当一个 Pod 的入口被隔离时,唯一允许进入该 Pod 的连接是来自该 Pod 节点的连接和适用于入口的 Pod 的某个 NetworkPolicy 的 ingress 列表所允许的连接。这些 ingress 列表的效果是相加的。

**网络策略是相加的,所以不会产生冲突。**如果策略适用于 Pod 某一特定方向的流量, Pod 在对应方向所允许的连接是适用的网络策略所允许的集合。 因此,评估的顺序不影响策略的结果。

**要允许从源 Pod 到目的 Pod 的连接,则源 Pod 的出口策略和目的 Pod 的入口策略都需要允许连接。**如果任何一方不允许连接,建立连接将会失败。

示例:

apiVersion: networking.k8s.io/v1     # NetworkPolicy所属API组与稳定版本,Kubernetes 1.16+正式生效
kind: NetworkPolicy                  # 资源类型,网络策略,用于定义Pod的入站/出站流量访问规则,实现集群内网络隔离
metadata:                            # 元数据区块,定义资源标识与生效范围
  name: test-network-policy          # 网络策略资源名称,命名空间内唯一
  namespace: default                 # 策略生效的命名空间,仅管控该命名空间内的Pod
spec:                                # 核心规格配置区块,定义具体的网络访问管控规则
  # 使用标签过滤限制哪些pod
  podSelector:                       # 目标Pod选择器;通过标签匹配该策略作用于哪些Pod,空选择器会匹配命名空间内所有Pod
    matchLabels:                     # 精确标签匹配规则
      role: db                       # 匹配带有role=db标签的Pod,仅对这类Pod生效网络访问管控
  policyTypes:                       # 策略类型列表,声明该策略管控的流量方向
  # Ingress控制外部访问内部
  - Ingress                          # 入站流量策略;管控外部来源对目标Pod的访问权限
  # Egress控制pod访问外部
  - Egress                           # 出站流量策略;管控目标Pod主动对外发起访问的权限
  ingress:                           # 入站规则列表,定义允许进入目标Pod的流量来源与端口
  # from限制允许哪些主机可以访问pod
  - from:                            # 入站流量白名单来源;多个条目为或关系,满足任意一条即可访问目标Pod
    # 通过ip限制
    - ipBlock:                       # IP网段白名单;基于IP地址段放行访问来源
        cidr: 172.17.0.0/16         # 允许访问的源IP网段范围
        except:                      # 排除的IP段;在上述cidr范围内排除部分子网,被排除网段无法访问
        - 172.17.1.0/24             # 排除172.17.1.0/24网段
    # 限制namespace中pod
    - namespaceSelector:             # 命名空间选择器;放行所有带有指定标签的命名空间内的全部Pod
        matchLabels:
          project: myproject         # 匹配带有project=myproject标签的命名空间,其内所有Pod均可访问目标Pod
    # 限制同一namespace中pod
    - podSelector:                   # Pod选择器;放行当前命名空间内带有指定标签的Pod
        matchLabels:
          role: frontend             # 匹配带有role=frontend标签的Pod,允许其访问目标Pod
    # 限制pod上哪些端口可以访问
    ports:                           # 允许访问的端口列表;仅放行指定协议与端口的流量,其余端口全部拒绝
    - protocol: TCP                  # 传输层协议,支持TCP、UDP、SCTP
      port: 6379                     # 允许访问的目标端口,对应数据库服务端口
  egress:                            # 出站规则列表,定义目标Pod允许对外访问的目标地址与端口
  - to:                              # 出站流量白名单目标;多个条目为或关系,满足任意一条即可对外访问
    - ipBlock:                       # 目标IP网段白名单;限制Pod仅可访问指定IP段内的地址
        cidr: 10.0.0.0/24           # 允许Pod访问的目标IP网段范围
    ports:                           # 允许对外访问的端口列表
    - protocol: TCP
      port: 5978                     # 允许访问的目标端口

  • 必需字段:与所有其他的 Kubernetes 配置一样,NetworkPolicy 需要 apiVersion、 kind 和 metadata 字段。
  • spec:NetworkPolicy 规约 中包含了在一个命名空间中定义特定网络策略所需的所有信息。
  • spec.podSelector:每个 NetworkPolicy 都包括一个 podSelector, 它对该策略所适用的一组 Pod 进行选择。示例中的策略选择带有 “role=db” 标签的 Pod。 空的 podSelector 选择命名空间下的所有 Pod。
  • spec.policyTypes:每个 NetworkPolicy 都包含一个 policyTypes 列表,其中包含 Ingress 或 Egress 或两者兼具。policyTypes 字段表示给定的策略是应用于进入所选 Pod 的入站流量还是来自所选 Pod 的出站流量,或两者兼有。 如果 NetworkPolicy 未指定 policyTypes 则默认情况下始终设置 Ingress; 如果 NetworkPolicy 有任何出口规则的话则设置 Egress。
  • spec.ingress:每个 NetworkPolicy 可包含一个 ingress 规则的白名单列表。 每个规则都允许同时匹配 from 和 ports 部分的流量。示例策略中包含一条简单的规则: 它匹配某个特定端口,来自三个来源中的一个:
  • 第一个通过 ipBlock 指定
  • 第二个通过 namespaceSelector 指定
  • 第三个通过 podSelector 指定。
  • spec.egress:每个 NetworkPolicy 可包含一个 egress 规则的白名单列表。 每个规则都允许匹配 to 和 port 部分的流量。该示例策略包含一条规则, 该规则将指定端口上的流量匹配到 10.0.0.0/24 中的任何目的地。

to 和 from 选择器

可以在 ingress 的 from 部分或 egress 的 to 部分中指定四种选择器:

  • podSelector:此选择器将在与 NetworkPolicy 相同的命名空间中选择特定的 Pod,应将其允许作为入站流量来源或出站流量目的地。
  • namespaceSelector:此选择器将选择特定的命名空间,应将所有 Pod 用作其入站流量来源或出站流量目的地。
  • namespaceSelector 和 podSelector:指定 namespaceSelector 和 podSelector 的 to/from 条目选择特定命名空间中的特定 Pod。

示例:

yaml ... ingress: - from: - namespaceSelector: matchLabels: user: alice - podSelector: matchLabels: role: client ...

在 from 数组中包含两个元素,允许来自本地命名空间中标有 role=client 的 Pod 的连接,或来自任何命名空间中标有 user=alice 的任何 Pod 的连接。

  • ipBlock:此选择器将选择特定的 IP CIDR 范围以用作入站流量来源或出站流量目的地。 这些应该是集群外部 IP,因为 Pod IP 存在时间短暂的且随机产生。

集群的入站和出站机制通常需要重写数据包的源 IP 或目标 IP。 在发生这种情况时,不确定在 NetworkPolicy 处理之前还是之后发生, 并且对于网络插件、云提供商、Service 实现等的不同组合,其行为可能会有所不同。

  • 对入站流量而言,这意味着在某些情况下,你可以根据实际的原始源 IP 过滤传入的数据包, 而在其他情况下,NetworkPolicy 所作用的 源IP 则可能是 LoadBalancer 或 Pod 的节点等。
  • 对于出站流量而言,这意味着从 Pod 到被重写为集群外部 IP 的 Service IP 的连接可能会或可能不会受到基于 ipBlock 的策略的约束。

实施网络策略

准备实验环境

环境说明:

  • namespace-web 中有3个 pod:web1、web2、test
  • namespace-cyw 中有1个pod:test
  • 如没有特别说明,默认namespace是web
# 创建名为web的命名空间;create ns是create namespace简写,用于集群资源逻辑隔离
root@master30:~# kubectl create ns web

# 切换当前上下文默认命名空间为web;kubens为kubectx工具集命令,简化命名空间切换操作
root@master30:~# kubens web

# 创建独立Pod web1;run直接运行单Pod,--image指定容器镜像,--image-pull-policy设置镜像拉取策略为本地存在则不拉取
root@master30:~# kubectl run web1 --image=hub.cyw.cloud/library/nginx --image-pull-policy=IfNotPresent

# 进入web1容器修改默认首页;-it开启交互式终端,--分隔kubectl参数与容器内命令,bash -c执行shell命令写入首页内容
root@master30:~# kubectl exec -it web1 -- bash -c 'echo Hello web1 > /usr/share/nginx/html/index.html'

# 创建独立Pod web2
root@master30:~# kubectl run web2 --image=hub.cyw.cloud/library/nginx --image-pull-policy=IfNotPresent

# 进入web2容器修改首页内容,用于区分不同后端实例
root@master30:~# kubectl exec -it web2 -- bash -c 'echo Hello web2 > /usr/share/nginx/html/index.html'

# 暴露web1 Pod为NodePort类型Service;expose发布Pod端口为服务,--port设置服务监听端口,--target-port指定容器目标端口,--type设置服务类型为节点端口映射
root@master30:~# kubectl expose pod web1 --port=80 --target-port=80 --type=NodePort

# 暴露web2 Pod为NodePort类型Service
root@master30:~# kubectl expose pod web2 --port=80 --target-port=80 --type=NodePort

# 查看当前命名空间Service资源列表,确认端口分配与服务状态
root@master30:~# kubectl get service
NAME   TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
web1   NodePort   10.103.36.143    <none>        80:30790/TCP   11s     # web1服务,集群IP 10.103.36.143,映射节点端口30790
web2   NodePort   10.111.250.224   <none>        80:32686/TCP   7s      # web2服务,映射节点端口32686

根据 pod 标签限定

根据pod标签限定:

  • 限定同一ns中pod之间访问
  • 所有其他ns中pod或者集群外主机都无法访问ns中pod

示例1:允许同一ns中具有标签run: test的pod,访问具有标签run: web1的pod 80端口。

# 创建网络策略配置文件;vim编辑新建yaml文件,定义仅允许指定标签Pod访问web1的入站隔离规则
root@master30:~# vim netpol.yaml
apiVersion: networking.k8s.io/v1     # NetworkPolicy所属API组与稳定版本
kind: NetworkPolicy                  # 资源类型,网络策略,实现Pod级别的流量访问管控
metadata:                            # 元数据区块,定义资源标识属性
  name: my-network-policy            # 网络策略资源名称,命名空间内唯一
spec:                                # 核心规格配置区块
  podSelector:                       # 目标Pod选择器;通过标签匹配策略作用的目标Pod
    matchLabels:                     # 精确标签匹配规则
      run: web1                      # 匹配带有run=web1标签的Pod,仅对该Pod生效入站管控
  policyTypes:                       # 策略类型列表,声明管控的流量方向
  - Ingress                          # 仅管控入站流量,出站流量默认不受限制
  ingress:                           # 入站规则白名单列表,仅允许匹配的流量进入目标Pod
  - from:                            # 允许的入站流量来源
    - podSelector:                   # Pod级别的来源白名单,同命名空间内按标签匹配
        matchLabels:
          run: test                  # 仅允许带有run=test标签的Pod访问目标Pod
    ports:                           # 允许访问的端口列表,仅放行指定协议端口
    - protocol: TCP                  # 传输层协议为TCP
      port: 80                       # 允许访问的目标端口为80
# 应用网络策略配置到集群;-f指定从本地文件读取资源清单,生效Pod入站访问隔离规则
root@master30:~# kubectl apply -f netpol.yaml

# 查看当前命名空间网络策略列表;netpol是networkpolicy的资源简写,快速查询已配置的隔离规则
root@master30:~# kubectl get netpol
NAME                POD-SELECTOR   AGE
my-network-policy   run=web1       4s     # 已生效的网络策略,作用于run=web1标签的Pod,创建时长4秒
# 同命名空间内test Pod访问web1服务;exec进入容器执行curl命令,-s静默模式不输出进度条
root@master30:~# kubectl exec test -- curl -s web1
Hello web1     # 正常返回web1内容,run=test标签的Pod在白名单内,访问被允许

# 跨命名空间test Pod访问web1服务;-n指定目标Pod所在命名空间,--connect-timeout设置3秒连接超时避免长时间等待
root@master30:~# kubectl exec test -n cyw -- curl -s --connect-timeout 3 web1.web
command terminated with exit code 28     # 连接超时退出码28,跨命名空间Pod不在白名单内,访问被网络策略拒绝
# 修改test Pod的标签;label命令更新Pod标签,--overwrite覆盖已有的run标签值,将test改为web2
root@master30:~/network# kubectl label pod test run=web2 --overwrite

# 查看Pod并展示完整标签;--show-labels参数输出每个Pod的全部标签,验证标签修改结果
root@master30:~/network# kubectl get pods --show-labels 
NAME   READY   STATUS    RESTARTS   AGE    LABELS
test   1/1     Running   0          9m9s   run=web2     # test Pod标签已变更为run=web2,不再匹配白名单规则
web1   1/1     Running   0          13m    run=web1     # 目标Pod标签保持run=web1,策略持续生效
web2   1/1     Running   0          13m    run=web2     # web2 Pod标签为run=web2,不在白名单内

# 标签修改后再次访问web1服务;验证标签变更后网络策略是否自动拦截访问
root@master30:~/network# kubectl exec test -- curl -s --connect-timeout 3 web1
command terminated with exit code 28     # 连接超时,test Pod标签已不满足白名单要求,访问被网络策略拒绝,隔离生效

示例2:允许同一namespace中所有pod访问具有标签run: web1的pod 80端口。

设置podSelector: {},则针对namespace中所有pod。

# 编辑网络策略配置文件;更新入站白名单规则,配置同命名空间所有Pod均可访问web1的80端口
root@master30:~# vim netpol.yaml
apiVersion: networking.k8s.io/v1     # NetworkPolicy所属API组与稳定版本
kind: NetworkPolicy                  # 资源类型,网络策略,实现Pod粒度的流量访问管控
metadata:                            # 元数据区块,定义资源标识属性
  name: my-network-policy            # 网络策略资源名称,命名空间内唯一
spec:                                # 核心规格配置区块
  podSelector:                       # 目标Pod选择器,匹配策略生效的目标Pod
    matchLabels:
      run: web1                      # 匹配带有run=web1标签的Pod,仅对该Pod生效入站管控
  policyTypes:                       # 策略类型列表,声明管控的流量方向
  - Ingress                          # 仅管控入站流量,出站流量默认不受限制
  ingress:                           # 入站规则白名单列表
  - from:                            # 允许的入站流量来源
    - podSelector: {}                # 空Pod选择器;匹配当前命名空间内所有Pod,即同命名空间全部Pod均在白名单内
    ports:                           # 允许访问的端口列表
    - protocol: TCP                  # 传输层协议为TCP
      port: 80                       # 允许访问的目标端口为80
# 应用更新后的网络策略到集群;覆盖原有同名策略,使新的入站放行规则立即生效
root@master30:~# kubectl apply -f netpol.yaml
# 同命名空间test Pod访问web1服务;验证空选择器下普通Pod的访问权限
root@master30:~# kubectl exec test -- curl -s web1
Hello web1     # 访问成功,同命名空间Pod在白名单范围内

# 同命名空间web2 Pod访问web1服务;验证非白名单标签Pod的访问权限
root@master30:~# kubectl exec web2 -- curl -s web1
Hello web1     # 访问成功,空选择器已放行同命名空间所有Pod
# 跨命名空间测试Pod访问web1服务;--connect-timeout设置3秒超时避免长时间等待
root@master30:~# kubectl exec test -n cyw -- curl -s --connect-timeout 3 web1.web
command terminated with exit code 28     # 连接超时,空Pod选择器仅匹配当前命名空间,跨命名空间Pod不在白名单内,访问被拒绝

示例3:允许同一ns中具有标签run: test的pod,访问所有pod 80端口。

设置podSelector: {},则针对namespace中所有pod。

apiVersion: networking.k8s.io/v1     # NetworkPolicy所属API组与稳定版本
kind: NetworkPolicy                  # 资源类型,网络策略,实现Pod级别的流量访问管控
metadata:                            # 元数据区块,定义资源标识属性
  name: my-network-policy            # 网络策略资源名称,命名空间内唯一
spec:                                # 核心规格配置区块
  podSelector: {}                    # 目标Pod选择器;空选择器匹配当前命名空间内所有Pod,即该策略对命名空间全部Pod生效
  policyTypes:                       # 策略类型列表,声明管控的流量方向
  - Ingress                          # 仅管控入站流量,出站流量默认不受限制
  ingress:                           # 入站规则白名单列表,仅允许匹配的流量进入目标Pod
  - from:                            # 允许的入站流量来源
    - podSelector:                   # Pod级别的来源白名单,同命名空间内按标签匹配
        matchLabels:
          run: test                  # 仅允许带有run=test标签的Pod访问目标Pod
    ports:                           # 允许访问的端口列表,仅放行指定协议端口
    - protocol: TCP                  # 传输层协议为TCP
      port: 80                       # 允许访问的目标端口为80

根据 ns 标签限定

用于限定,来源于其他namespace中pod。

示例1:允许具有标签project: myproject的namespace中所有pod,访问当前ns中具有标签run: web1的pod 80端口。

# 编辑网络策略配置文件;定义基于命名空间标签的入站白名单规则,限定仅匹配标签的命名空间可访问web1的80端口
root@master30:~# vim netpol.yaml
apiVersion: networking.k8s.io/v1     # NetworkPolicy所属API组与稳定版本
kind: NetworkPolicy                  # 资源类型,实现Pod粒度的流量访问管控
metadata:                            # 元数据区块,定义资源标识与生效范围
  name: my-network-policy            # 网络策略资源名称,命名空间内唯一
  namespace: web                     # 策略生效的命名空间,限定仅管控该命名空间内的目标Pod
spec:                                # 核心规格配置区块
  podSelector:                       # 目标Pod选择器,通过标签匹配策略作用的目标Pod
    matchLabels:                     # 精确标签匹配规则
      run: web1                      # 匹配带有run=web1标签的Pod,仅对该Pod生效入站管控
  policyTypes:                       # 策略类型列表,声明管控的流量方向
  - Ingress                          # 仅管控入站流量,出站流量默认不受限制
  ingress:                           # 入站规则白名单列表,仅允许匹配的流量进入目标Pod
  - from:                            # 允许的入站流量来源
    - namespaceSelector:             # 命名空间选择器,按命名空间标签放行来源,匹配标签的命名空间内所有Pod均可访问
        matchLabels:
          project: myproject         # 匹配带有project=myproject标签的命名空间,纳入入站白名单
    ports:                           # 允许访问的端口列表,仅放行指定协议端口
    - protocol: TCP                  # 传输层协议为TCP
      port: 80                       # 允许访问的目标端口为80

# 应用网络策略到集群;-f指定从本地yaml文件读取资源清单,更新同名策略使规则立即生效
root@master30:~# kubectl apply -f netpol.yaml

# 同命名空间test Pod访问web1;exec进入容器执行curl,-s静默模式输出响应内容
root@master30:~# kubectl exec test -- curl -s web1
# 无返回内容     # 同命名空间Pod未被namespaceSelector匹配,访问被网络策略拦截

# 跨命名空间cyw的test Pod访问web1;-n指定Pod所在命名空间,使用服务名.命名空间格式解析地址
root@master30:~# kubectl exec -n cyw test -- curl -s web1.web
# 无返回内容     # cyw命名空间无匹配标签,未命中白名单规则,访问被拒绝

# 为cyw命名空间添加匹配标签;label命令为命名空间设置标签,使其符合网络策略的白名单条件
root@master30:~# kubectl label namespaces cyw project=myproject

# 标签生效后再次跨命名空间访问web1;验证白名单标签生效后的访问权限
root@master30:~# kubectl exec -n cyw test -- curl -s web1.web
Hello web1     # 访问成功,cyw命名空间已匹配白名单标签,流量被网络策略放行

示例2:允许所有namespace中所有pod,访问当前ns中具有标签run: web1的pod 80端口。

# 编辑网络策略配置文件;配置空命名空间选择器,放行集群所有命名空间的Pod访问web1的80端口
root@master30:~# vim netpol.yaml
apiVersion: networking.k8s.io/v1     # NetworkPolicy所属API组与稳定版本
kind: NetworkPolicy                  # 资源类型,实现Pod粒度的流量访问管控
metadata:                            # 元数据区块,定义资源标识与生效范围
  name: my-network-policy            # 网络策略资源名称,命名空间内唯一
  namespace: web                     # 策略生效的命名空间,限定管控范围
spec:                                # 核心规格配置区块
  podSelector:                       # 目标Pod选择器,匹配策略作用的目标Pod
    matchLabels:                     # 精确标签匹配规则
      run: web1                      # 匹配带有run=web1标签的Pod
  policyTypes:                       # 策略类型列表,声明管控的流量方向
  - Ingress                          # 仅管控入站流量
  ingress:                           # 入站规则白名单列表
  - from:                            # 允许的入站流量来源
    - namespaceSelector: {}          # 空命名空间选择器;匹配集群内全部命名空间,所有命名空间的Pod均纳入入站白名单
    ports:                           # 允许访问的端口列表
    - protocol: TCP                  # 传输层协议为TCP
      port: 80                       # 允许访问的目标端口为80

# 应用网络策略到集群;-f指定从本地yaml文件读取资源清单,更新同名策略使规则立即生效
root@master30:~# kubectl apply -f netpol.yaml

# 同命名空间test Pod访问web1;exec进入容器执行curl命令,-s静默模式输出响应内容
root@master30:~# kubectl exec test -- curl -s web1
Hello web1     # 访问成功,空命名空间选择器已放行当前命名空间流量

# 跨命名空间cyw的test Pod访问web1;-n指定Pod所在命名空间,使用服务名.命名空间格式解析目标地址
root@master30:~# kubectl exec -n cyw test -- curl -s web1.web
Hello web1     # 访问成功,空命名空间选择器已放行所有命名空间的入站流量

根据 pod IP 限定

示例1:允许网段10.1.8.0/24但不包括子网10.1.8.128/26中主机,访问具有标签run: web1的pod 80端口。

# 编辑网络策略配置文件;基于IP网段配置入站白名单,放行10.1.8.0/24网段,排除10.1.8.128/26子网,仅允许指定IP段访问web1的80端口
root@master30:~# vim netpol.yaml
apiVersion: networking.k8s.io/v1     # NetworkPolicy所属API组与稳定版本
kind: NetworkPolicy                  # 资源类型,实现Pod粒度的流量访问管控
metadata:                            # 元数据区块,定义资源标识与生效范围
  name: my-network-policy            # 网络策略资源名称,命名空间内唯一
  namespace: web                     # 策略生效的命名空间,限定管控范围
spec:                                # 核心规格配置区块
  podSelector:                       # 目标Pod选择器,通过标签匹配策略作用的目标Pod
    matchLabels:                     # 精确标签匹配规则
      run: web1                      # 匹配带有run=web1标签的Pod
  policyTypes:                       # 策略类型列表,声明管控的流量方向
  - Ingress                          # 仅管控入站流量
  ingress:                           # 入站规则白名单列表
  - from:                            # 允许的入站流量来源
    - ipBlock:                       # IP网段白名单;基于源IP地址段放行访问来源
        cidr: 10.1.8.0/24            # 允许访问的源IP网段范围
        except:                      # 排除的IP段;在上述cidr范围内排除部分子网,被排除网段无法访问
        - 10.1.8.128/26              # 排除10.1.8.128/26子网
    ports:                           # 允许访问的端口列表
    - protocol: TCP                  # 传输层协议为TCP
      port: 80                       # 允许访问的目标端口为80

# 应用网络策略到集群;-f指定从本地yaml文件读取资源清单,更新同名策略使规则立即生效
root@master30:~# kubectl apply -f netpol.yaml

# 同命名空间test Pod访问web1;exec进入容器执行curl,-s静默模式输出响应
root@master30:~# kubectl exec test -- curl -s web1
# 无返回     # 访问失败,Pod源IP属于集群内部Pod网段,不在10.1.8.0/24白名单范围内

# 跨命名空间cyw的test Pod访问web1;-n指定Pod所在命名空间,使用服务名.命名空间格式解析目标地址
root@master30:~# kubectl exec -n cyw test -- curl -s web1.web
# 无返回     # 访问失败,跨命名空间Pod源IP同样不在IP白名单网段内

# 集群外客户端通过worker30节点NodePort访问web1;节点IP在放行网段,但流量经非Pod所在节点转发会做SNAT
root@client:~# curl http://10.1.8.30:30251
# 无返回     # 访问失败,非Pod所在节点转发时源IP被转换,无法匹配网络策略的IP白名单

# 集群外客户端通过worker31节点NodePort访问web1
root@client:~# curl http://10.1.8.31:30251
# 无返回     # 访问失败,非Pod所在节点的NodePort访问无法命中IP白名单规则

# 集群外客户端通过worker32节点NodePort访问web1;Pod运行在该节点,流量未经过节点间转发SNAT
root@client:~# curl http://10.1.8.32:30251
Hello web1     # 访问成功,Pod所在节点的NodePort访问可正常匹配IP白名单规则

# 查看web1 Pod所在节点;describe输出Pod详情,grep过滤Node字段确认调度位置
root@master30:~# kubectl describe pod web1|grep Node:
Node:         worker32.cyw.cloud/10.1.8.32     # Pod调度在worker32节点,对应IP 10.1.8.32,与访问现象一致

从实验测试结果来看,根据网段控制来源还不完善。

如果想放行所有主机,阻止部分主机,规则如下:

    - ipBlock:                       # IP网段白名单配置;基于源IP地址管控入站访问权限
        cidr: 0.0.0.0/0             # 允许访问的源IP网段;0.0.0.0/0代表所有IPv4地址,默认放行全部来源
        except:                     # 排除网段列表;在cidr范围内排除指定子网,被排除的网段无法访问
        - 10.1.8.0/26               # 排除10.1.8.0/26子网,该网段的来源流量会被策略拒绝

限定所有端口

port参数不设置,代表限定所有端口。

# 编辑网络策略配置文件;配置仅允许带run=test标签的Pod访问web1,未显式指定ports时默认放行所有协议与端口
root@master30:~# vim netpol.yaml
apiVersion: networking.k8s.io/v1     # NetworkPolicy所属API组与稳定版本,Kubernetes 1.16+正式生效
kind: NetworkPolicy                  # 资源类型,网络策略,实现Pod粒度的流量访问管控与隔离
metadata:                            # 元数据区块,定义资源标识与生效范围
  name: my-network-policy            # 网络策略资源名称,命名空间内唯一标识
  namespace: web                     # 策略生效的命名空间,仅管控该命名空间内的目标Pod
spec:                                # 核心规格配置区块
  podSelector:                       # 目标Pod选择器;通过标签匹配该策略作用于哪些Pod
    matchLabels:                     # 精确标签匹配规则
      run: web1                      # 匹配带有run=web1标签的Pod,仅对该Pod生效入站管控
  policyTypes:                       # 策略类型列表,声明该策略管控的流量方向
  - Ingress                          # 仅管控入站流量,出站流量默认不受限制
  ingress:                           # 入站规则白名单列表,仅允许匹配的流量进入目标Pod
  - from:                            # 入站流量白名单来源;多个条目为或关系,满足任意一条即可访问
    - podSelector:                   # Pod级来源白名单,同命名空间内按标签匹配放行
        matchLabels:
          run: test                  # 仅允许带有run=test标签的Pod访问目标Pod;未指定ports时默认放行所有协议端口

# 应用策略
root@master30:~# kubectl apply -f netpol.yaml     # 从本地yaml文件应用资源,覆盖更新同名网络策略,规则立即生效

# 查看Pod列表并输出扩展信息;-o wide展示Pod IP、调度节点等额外字段,确认Pod网络拓扑与位置
root@master30:~# kubectl get pods -o wide
NAME   READY   STATUS    RESTARTS   AGE   IP              NODE                  NOMINATED NODE   READINESS GATES
test   1/1     Running   0          64m   10.224.193.70   worker32.cyw.cloud   <none>           <none>     # test Pod,与web1同节点,Pod IP为10.224.193.70,标签匹配白名单
web1   1/1     Running   0          82m   10.224.193.67   worker32.cyw.cloud   <none>           <none>     # web1目标Pod,运行在worker32节点,Pod IP为10.224.193.67
web2   1/1     Running   0          81m   10.224.41.132   worker31.cyw.cloud   <none>           <none>     # web2 Pod,调度在worker31节点,不在白名单内

# 此时满足条件的pod可以ping通pod地址
# 创建临时测试Pod并进入交互终端;--rm退出后自动删除Pod不残留资源,-l设置Pod标签匹配白名单规则,--分隔kubectl参数与容器内命令
root@master30:~# kubectl run --rm -it ubuntu -l run=test --image ubuntu -- bash

# 更新apt软件包索引;同步本地软件源列表,为安装网络工具做准备
root@ubuntu:/# apt update

# 安装ping工具包;iputils-ping提供ICMP ping命令,用于测试三层网络连通性
root@ubuntu:/# apt install -y iputils-ping

# 直接ping web1的Pod IP,测试Pod间三层直连连通性;-c1指定仅发送1个ICMP探测包
root@ubuntu:/# ping -c1 10.224.193.67
PING 10.224.193.67 (10.224.193.67) 56(84) bytes of data.
64 bytes from 10.224.193.67: icmp_seq=1 ttl=62 time=0.831 ms     # 收到响应,策略未限制端口时ICMP流量被放行,Pod直连可达
--- 10.224.193.67 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.831/0.831/0.831/0.000 ms

# 通过Service名称ping测试;Service基于iptables/IPVS实现四层端口转发,仅支持TCP/UDP协议
root@ubuntu:/# ping web1 -c1
PING web1.web.svc.cluster.local (10.96.144.145) 56(84) bytes of data.
--- web1.web.svc.cluster.local ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms     # 全部丢包,Service本身不处理ICMP协议报文,与网络策略无关

# 退出容器交互终端;临时Pod会随--rm参数自动销毁
root@ubuntu:/# exit

# 仍然 ping不通 service,因为service只开放80端口
# 补充说明:Service仅支持TCP/UDP四层端口转发,ICMP协议无法通过ClusterIP转发,并非网络策略拦截;通过Service访问TCP 80端口则正常连通

限定端口范围
# 编辑网络策略配置文件;配置端口范围放行规则,仅允许带run=test标签的Pod访问web1的32000-32768连续TCP端口段
root@master30:~# vim netpol.yaml
apiVersion: networking.k8s.io/v1     # NetworkPolicy所属API组与稳定版本
kind: NetworkPolicy                  # 资源类型,实现Pod粒度的流量访问管控与隔离
metadata:                            # 元数据区块,定义资源标识与生效范围
  name: my-network-policy            # 网络策略资源名称,命名空间内唯一标识
  namespace: web                     # 策略生效的命名空间,仅管控该命名空间内的目标Pod
spec:                                # 核心规格配置区块
  podSelector:                       # 目标Pod选择器,通过标签匹配策略作用的目标Pod
    matchLabels:                     # 精确标签匹配规则
      run: web1                      # 匹配带有run=web1标签的Pod,作为策略管控的目标
  policyTypes:                       # 策略类型列表,声明管控的流量方向
  - Ingress                          # 仅管控入站流量,出站流量默认不受限制
  ingress:                           # 入站规则白名单列表
  - from:                            # 允许的入站流量来源
    - podSelector:                   # Pod级来源白名单,同命名空间内按标签匹配放行
        matchLabels:
          run: test                  # 仅允许带有run=test标签的Pod访问目标Pod
    ports:                           # 允许访问的端口列表,可配置单端口或连续端口范围
    - protocol: TCP                  # 传输层协议为TCP;仅TCP协议支持endPort端口范围配置
      port: 32000                    # 端口范围起始值,放行的最低端口号
      endPort: 32768                 # 端口范围结束值,与port配合覆盖32000~32768之间所有连续端口

多条件规则

只要有一个满足条件就可以访问pod。

# 编辑网络策略配置文件;配置多来源或逻辑入站白名单,IP网段、指定标签命名空间、指定标签Pod三类来源满足其一即可访问web1的TCP 80端口
root@master30:~# vim netpol.yaml
apiVersion: networking.k8s.io/v1     # NetworkPolicy所属API组与稳定版本
kind: NetworkPolicy                  # 资源类型,实现Pod粒度的流量访问管控与隔离
metadata:                            # 元数据区块,定义资源标识与生效范围
  name: my-network-policy            # 网络策略资源名称,命名空间内唯一标识
  namespace: web                     # 策略生效的命名空间,仅管控该命名空间内的目标Pod
spec:                                # 核心规格配置区块
  podSelector:                       # 目标Pod选择器,通过标签匹配策略作用的目标Pod
    matchLabels:                     # 精确标签匹配规则
      run: web1                      # 匹配带有run=web1标签的Pod,作为策略管控的目标
  policyTypes:                       # 策略类型列表,声明管控的流量方向
  - Ingress                          # 仅管控入站流量,出站流量默认不受限制
  ingress:                           # 入站规则白名单列表
  - from:                            # 入站流量白名单来源;同一条规则下多个条目为或关系,满足任意一项即可放行访问
    - ipBlock:                       # 来源条件1:IP网段白名单,指定网段的所有来源均可访问目标Pod
        cidr: 10.1.1.0/24            # 允许访问的源IP网段范围
    - namespaceSelector:             # 来源条件2:命名空间选择器,匹配对应标签的命名空间内所有Pod均可访问
        matchLabels:
          project: myproject         # 匹配带有project=myproject标签的命名空间,整体纳入入站白名单
    - podSelector:                   # 来源条件3:Pod选择器,同命名空间内匹配对应标签的Pod均可访问
        matchLabels:
          run: test                  # 匹配带有run=test标签的Pod,纳入入站白名单
    ports:                           # 统一端口限制;所有满足来源条件的流量,仅可访问指定协议与端口
    - protocol: TCP                  # 传输层协议为TCP
      port: 80                       # 允许访问的目标端口为80

# 创建network policy
# 补充:执行apply后规则自动持久化存入集群etcd数据库,属于永久生效规则,节点重启、Pod重建、集群重启均不会丢失
root@master30:~# kubectl apply -f netpol.yaml

# namespace-web中pod-test可以访问web1
# 补充:同命名空间的test Pod标签匹配podSelector白名单条件,满足放行规则,可正常访问web1的80端口
root@master30:~# kubectl exec test -- curl -s web1
Hello web1     # 正常返回web1首页内容,网络策略白名单放行规则生效

默认策略

默认允许所有入站流量
apiVersion: networking.k8s.io/v1     # NetworkPolicy所属API组与稳定版本,Kubernetes 1.16+正式生效
kind: NetworkPolicy                  # 资源类型,网络策略,实现Pod粒度的入站/出站流量访问管控
metadata:                            # 元数据区块,定义资源标识属性
  name: allow-all-ingress            # 网络策略资源名称,标识该策略为全量放行入站流量的规则
spec:                                # 核心规格配置区块
  podSelector: {}                    # 目标Pod选择器;空选择器匹配当前命名空间内所有Pod,该策略对全部Pod生效
  policyTypes:                       # 策略类型列表,声明该策略管控的流量方向
  - Ingress                          # 仅管控入站流量,出站流量默认不受限制
  ingress:                           # 入站规则白名单列表
  - {}                               # 空规则体;不限制任何来源IP、端口与协议,放行所有入站流量,所有来源均可访问命名空间内全部Pod

默认拒绝所有入站流量
apiVersion: networking.k8s.io/v1     # NetworkPolicy所属API组与稳定版本,Kubernetes 1.16+正式生效
kind: NetworkPolicy                  # 资源类型,网络策略,实现Pod粒度的流量访问管控与隔离
metadata:                            # 元数据区块,定义资源标识属性
  name: default-deny-ingress         # 网络策略资源名称,标识该策略为命名空间默认入站拒绝规则
spec:                                # 核心规格配置区块
  podSelector: {}                    # 目标Pod选择器;空选择器匹配当前命名空间内所有Pod,该策略对全部Pod生效
  policyTypes:                       # 策略类型列表,声明该策略管控的流量方向
  - Ingress                          # 仅管控入站流量;声明Ingress策略类型但未配置任何ingress放行规则,默认拒绝所有入站流量

此策略可以确保即使容器没有选择其他任何 NetworkPolicy,也仍然可以被隔离。 此策略不会更改默认的出口隔离行为。

默认允许所有出站流量
apiVersion: networking.k8s.io/v1     # NetworkPolicy所属API组与稳定版本,Kubernetes 1.16+正式生效
kind: NetworkPolicy                  # 资源类型,网络策略,实现Pod粒度的入站/出站流量访问管控
metadata:                            # 元数据区块,定义资源标识属性
  name: allow-all-egress             # 网络策略资源名称,标识该策略为全量放行所有出站流量的规则
spec:                                # 核心规格配置区块
  podSelector: {}                    # 目标Pod选择器;空选择器匹配当前命名空间内所有Pod,该策略对全部Pod生效
  policyTypes:                       # 策略类型列表,声明该策略管控的流量方向
  - Egress                           # 仅管控出站流量,定义Pod主动对外发起访问的权限范围
  egress:                            # 出站规则白名单列表
  - {}                               # 空规则体;不限制任何目标地址、端口与协议,放行所有出站流量,命名空间内所有Pod可对外发起任意访问

默认拒绝所有出站流量
apiVersion: networking.k8s.io/v1     # NetworkPolicy所属API组与稳定版本,Kubernetes 1.16+正式生效
kind: NetworkPolicy                  # 资源类型,网络策略,实现Pod粒度的流量访问管控与隔离
metadata:                            # 元数据区块,定义资源标识属性
  name: default-deny-egress          # 网络策略资源名称,标识该策略为命名空间默认出站拒绝规则
spec:                                # 核心规格配置区块
  podSelector: {}                    # 目标Pod选择器;空选择器匹配当前命名空间内所有Pod,该策略对全部Pod生效
  policyTypes:                       # 策略类型列表,声明该策略管控的流量方向
  - Egress                           # 仅管控出站流量;声明Egress策略类型但未配置任何egress放行规则,默认拒绝所有Pod对外发起的出站访问

此策略可以确保即使没有被其他任何 NetworkPolicy 选择的 Pod 也不会被允许流出流量。 此策略不会更改默认的入站流量隔离行为。

默认拒绝所有入口和所有出站流量
apiVersion: networking.k8s.io/v1     # NetworkPolicy所属API组与稳定版本,Kubernetes 1.16+正式生效
kind: NetworkPolicy                  # 资源类型,网络策略,实现Pod粒度的入站与出站双向流量访问管控
metadata:                            # 元数据区块,定义资源标识属性
  name: default-deny-all             # 网络策略资源名称,标识该策略为命名空间双向默认拒绝的全局隔离规则
spec:                                # 核心规格配置区块
  podSelector: {}                    # 目标Pod选择器;空选择器匹配当前命名空间内所有Pod,该策略对全部Pod生效
  policyTypes:                       # 策略类型列表,声明该策略同时管控两个方向的流量
  - Ingress                          # 管控入站流量;未配置任何ingress放行规则,默认拒绝所有入站访问
  - Egress                           # 管控出站流量;未配置任何egress放行规则,默认拒绝所有Pod对外发起的出站访问

此策略可以确保即使没有被其他任何 NetworkPolicy 选择的 Pod 也不会被 允许入站或出站流量。

无法完成的工作

  • 特定于节点的策略。
  • 基于名字的策略。
  • 实现适用于所有命名空间或 Pods 的默认策略。
  • 显式地拒绝策略的能力。NetworkPolicy 的模型默认采用拒绝操作, 其唯一的能力是添加允许策略。
  • **禁止本地回路或指向宿主的网络流量。**Pod 目前无法阻塞 localhost 访问, 它们也无法禁止来自所在节点的访问请求)。

环境清理

root@master30:~# kubectl delete ns network web cyw
Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐