Kubernetes Network

学习参考:网络策略

环境准备

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

一、单主机网络通信

1.1 Docker 单机网络

  1. Docker 的网络接口==默认使用虚拟接口,Linux在内核中进行数据复制来实现虚拟接口之间的数据转发,==不需要经过物理网卡,转发效率高。

  2. 默认创建docker0 Linux 网桥;

    使用 veth‑pair 成对虚拟网卡:一端在宿主机网桥,一端在容器内部。

  3. docker0 配置 IP 与子网,实现==主机和容器互通==。

brctl 工具由bridge‑utils软件包提供。

4.外部主机访问容器必须依靠端口映射。

在这里插入图片描述

1.2 Containerd 单机网络

网络原理和 Docker 类似,同样==使用虚拟接口 veth‑pair,==宿主机与容器分别生成**虚拟网卡成对连通。**

二、跨主机网络通信

2.1 跨主机网络通信架构

在这里插入图片描述

跨主机通信:不同节点上的 Pod / 容器互通。

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

2.2 跨主机网络通信方案

跨主机网络:将不同主机上的容器用同一个虚拟网络连接起来。

两种网络模型:

  • Underlay:直接使用底层物理网络转发 Pod 流量,无隧道封装,性能更高。

  • Overlay:在**宿主机网络之上构建虚拟隧道,数据包封装在 UDP 传输;会有封装开销**。

    • 优势:支持更多二层网段,保护物理交换机 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和物理机器同等地位,网络延迟极低。
    ❌ 限制:

    • 宿主机网卡不能开启桥接;

    • 同一父网卡Macvlan子接口无法直接互通(同宿主机Pod互通缺陷);

    • 网络规划复杂,传统虚拟化环境容易冲突。

典型场景: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、低延迟业务

2.3 跨主机网络通信模型

目的:把网络插件和容器平台解耦,适配多种容器运行时。

2.3.1 CNM 模型

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

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

在这里插入图片描述

由以下三类组件组成:

  • Sandbox 是容器的网络栈,由 Linux Network Namespace 实现,保存网卡、路由、DNS。Sandbox 可以包含来自不同 Network 的 Endpoint。

  • Endpoint 的作用是将 Sandbox 接入 Network:veth‑pair 实现,把 Sandbox 接入网络;一个 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。
2.3.2 CNI 模型

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

在这里插入图片描述

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

CNI 模型包含2个概念:

  • 容器: 独立的 linux 网络命名空间。

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

两类插件

  1. CNI Plugin:配置容器网络。
  2. IPAM Plugin:分配 Pod IP 地址。

不依赖守护进程,插件可替换;最小处理单元为 Pod。

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

三、K8s 中 Calico 网络

3.1 Calico 网络优势

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

  1. 支持 BGP 模式(Underlay)

    • 节点间通过BGP交换Pod路由,无隧道封装,原生IP转发。
    • 性能最优;前提:网络允许BGP协议发布路由。
  2. 支持IPIP / VXLAN模式(Overlay)

    • 底层不支持BGP时启用IP-in-IP隧道封装;数据包外层增加宿主机IP头。
    • 适配公有云;封装带来性能损耗。
  3. 支持 NetworkPolicy(Pod防火墙策略)。


3.2 Calico 隧道模式

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

3.2.1 ipipMode 隧道
  • 协议:三层隧道,把内层IP包完整封装进外层IP包。
  • 虚拟网卡:tunl0。
  • 封装结构:外层IP头(节点IP) + 内层IP头(Pod IP) + 应用数据。
  • 只封装IP包,不携带二层帧(MAC)。
3.2.2 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
3.2.3 隧道模式选择
选 IPIP 的场景
  1. 私有物理机房,底层网络不拦截IP协议号4
  2. 集群只需要单播Pod通信,不需要二层广播
  3. 想更小的包头开销,追求略高一点性能

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

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

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


3.3 Calico 工作模式

3.3.1 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开关只决定数据包是否封装隧道。


3.3.2 VXLAN 隧道

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

  1. Always,所有跨节点 Pod 流量全部封装 VXLAN 隧道(Overlay)。
  2. Never,不启用 VXLAN 隧道。
  3. CrossSubnet 混合模式,同子网节点之间通信不封装;跨子网节点之间通信启用VXLAN隧道封装。
3.3.3 工作模式选择
  1. 选 Never
  • 没有隧道封装,性能优;

  • 抓包可以直接观察Pod原生IP;

  1. 选 Always

    • 节点分布在不同子网,节点之间无法二层互通;

    • 公有云(阿里云/腾讯云/AWS)部署Calico;

    • 不想依赖底层网络支持BGP。

  2. 选 CrossSubnet

    • 企业机房,节点划分为多个子网;
    • 同网段节点直接路由,跨网段节点自动走IPIP隧道。

3.4 查看工作模式

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原生路由模式

3.5 修改工作模式

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

# 步骤1:备份原有IPPool配置
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 

四、网络策略

4.1 网络策略介绍

  • 前提条件:CNI 插件必须支持 NetworkPolicy,Calico 支持,Flannel 不支持。
  • 默认集群所有 Pod、命名空间网络全部互通。
  • NetworkPolicy 实现 Pod 级别白名单访问控制,没有拒绝规则,只做允许白名单;多条策略效果相加。

4.2 Ingress / Egress 核心规则

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

  1. Ingress(入站):外部访问 Pod 默认全部放行;policyTypes 包含 Ingress,该 Pod 入站隔离,仅 ingress 白名单允许流量。
  2. Egress(出站):Pod 访问外部 默认全部放行;policyTypes 包含 Egress,该 Pod 出站隔离,仅 egress 白名单允许流量。

✅建立连接必须:源 Pod Egress 放行 AND 目标 Pod Ingress 放行,连接才可以建立。

网络策略是相加的,所以不会产生冲突。

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

示例:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  # 使用标签过滤限制哪些pod
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  # Ingress控制外部访问内部
  - Ingress
  # Egress控制pod访问外部
  - Egress
  ingress:
  # from限制允许哪些主机可以访问pod
  - from:
    # 通过ip限制
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    # 限制namespace中pod
    - namespaceSelector:
        matchLabels:
          project: myproject
    # 限制同一namespace中pod
    - podSelector:
        matchLabels:
          role: frontend
    # 限制pod上哪些端口可以访问
    ports:
    - protocol: TCP
      port: 6379
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    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 中的任何目的地。

4.3 to 和 from 选择器

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

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

  • namespaceSelector:此选择器将选择特定的命名空间,应将所有 Pod 用作其入站流量来源或出站流量目的地。

  • namespaceSelector 和 podSelector:指定 namespaceSelector 和 podSelector 的 to/from 条目选择特定命名空间中的特定 Pod。

    示例:

      ...
      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 的策略的约束。

4.4 实施网络策略

准备实验环境

环境说明:

  • namespace-web 中有3个 pod:web1、web2、test
  • namespace-laoma 中有1个pod:test
  • 如没有特别说明,默认namespace是web
root@master30:~# kubectl create ns web
root@master30:~# kubens web

# 创建 web1
root@master30:~# kubectl run web1 --image=hub.laoma.cloud/library/nginx --image-pull-policy=IfNotPresent
root@master30:~# kubectl exec -it web1 -- bash -c 'echo Hello web1 > /usr/share/nginx/html/index.html'

# 创建 web2
root@master30:~# kubectl run web2 --image=hub.laoma.cloud/library/nginx --image-pull-policy=IfNotPresent
root@master30:~# kubectl exec -it web2 -- bash -c 'echo Hello web2 > /usr/share/nginx/html/index.html'

# 创建service web1和web2
root@master30:~# kubectl expose pod web1 --port=80 --target-port=80 --type=NodePort
root@master30:~# kubectl expose pod web2 --port=80 --target-port=80 --type=NodePort
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
web2   NodePort   10.111.250.224   <none>        80:32686/TCP   7s

# 同一namespace中web1和web2互相访问
root@master30:~/network# kubectl run test --image=hub.laoma.cloud/library/nginx
root@master30:~/network# kubectl exec -it test -- curl -s web1
Hello web1
root@master30:~/network# kubectl exec -it test -- curl -s web2
Hello web2

# 在不同namespace-laoma中创建测试pod-test,访问web1和web2
root@master30:~# kubectl create ns laoma
root@master30:~# kubectl run test -n laoma --image=hub.laoma.cloud/library/nginx
root@master30:~# kubectl exec -n laoma test -- curl -s web1.web
Hello web1
root@master30:~# kubectl exec -n laoma test -- curl -s web2.web
Hello web2

# 集群内访问service web1和web2
root@master30:~# curl 10.103.36.143
Hello web1
root@master30:~# curl 10.111.250.224
Hello web2

# 集群外节点访问web1和web2
root@client:~# curl http://10.1.8.30:30790
Hello web1
root@client:~# curl http://10.1.8.30:32686
Hello web2
4.4.1 根据 pod 标签限定

根据pod标签限定:

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

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

root@master30:~# vim netpol.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: my-network-policy
spec:
  podSelector:
    matchLabels:
      run: web1
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          run: test
    ports:
    - protocol: TCP
      port: 80
# 创建network policy
root@master30:~# kubectl apply -f netpol.yaml
root@master30:~# kubectl get netpol
NAME                POD-SELECTOR   AGE
my-network-policy   run=web1       4s

# 同一namespace中test可以访问web1,web2不可以访问web1
root@master30:~# kubectl exec test -- curl -s web1
Hello web1

# 不同 namespace 中pod,标签满足不可以访问
root@master30:~# kubectl exec test -n laoma -- curl -s --connect-timeout 3 web1.web
command terminated with exit code 28

# 修改现有标签,同一命名空间的test pod也无法访问了。
root@master30:~/network# kubectl label pod test run=web2 --overwrite
root@master30:~/network# kubectl get pods --show-labels 
NAME   READY   STATUS    RESTARTS   AGE    LABELS
test   1/1     Running   0          9m9s   run=web2
web1   1/1     Running   0          13m    run=web1
web2   1/1     Running   0          13m    run=web2

# 超时退出
root@master30:~/network# kubectl exec test -- curl -s --connect-timeout 3 web1
command terminated with exit code 28

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

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

root@master30:~# vim netpol.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: my-network-policy
spec:
  podSelector:
    matchLabels:
      run: web1
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector: {}
    ports:
    - protocol: TCP
      port: 80
# 应用策略
root@master30:~# kubectl apply -f netpol.yaml

# 同一namespace中所有pod都可以访问web1
root@master30:~# kubectl exec test -- curl -s web1
Hello web1
root@master30:~# kubectl exec web2 -- curl -s web1
Hello web1

# 不同namespace中pod不可以访问web1
root@master30:~# kubectl exec test -n laoma -- curl -s --connect-timeout 3 web1.web
command terminated with exit code 28

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

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

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: my-network-policy
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          run: test
    ports:
    - protocol: TCP
      port: 80
4.4.2 根据 ns 标签限定

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

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

root@master30:~# vim netpol.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: my-network-policy
  namespace: web
spec:
  podSelector:
    matchLabels:
      run: web1
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          project: myproject
    ports:
    - protocol: TCP
      port: 80
# 应用策略
root@master30:~# kubectl apply -f netpol.yaml

# 此时namespace-web中pod和namespace-laoma中pod都无法访问web1
root@master30:~# kubectl exec test -- curl -s web1
root@master30:~# kubectl exec -n laoma test -- curl -s web1.web

# 给namespace-laoma添加标签project=myproject,此时namespace-laoma中pod可以访问web1.web
root@master30:~# kubectl label namespaces laoma project=myproject
root@master30:~# kubectl exec -n laoma test -- curl -s web1.web
Hello web1

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

root@master30:~# vim netpol.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: my-network-policy
  namespace: web
spec:
  podSelector:
    matchLabels:
      run: web1
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector: {}
    ports:
    - protocol: TCP
      port: 80
# 创建network policy
root@master30:~# kubectl apply -f netpol.yaml

# 所有namespace中所有pod都可以访问web1
root@master30:~# kubectl exec test -- curl -s web1
Hello web1
root@master30:~# kubectl exec -n laoma test -- curl -s web1.web
4.4.3 根据 pod IP 限定

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

root@master30:~# vim netpol.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: my-network-policy
  namespace: web
spec:
  podSelector:
    matchLabels:
      run: web1
  policyTypes:
  - Ingress
  ingress:
  - from:
    - ipBlock:
        # 放行 网段10.1.8.0/24
        cidr: 10.1.8.0/24
        # 不放行网段
        except:
        - 10.1.8.128/26
    ports:
    - protocol: TCP
      port: 80
# 应用策略
root@master30:~# kubectl apply -f netpol.yaml

# 访问失败
root@master30:~# kubectl exec test -- curl -s web1
root@master30:~# kubectl exec -n laoma test -- curl -s web1.web

root@client:~# curl http://10.1.8.30:30251
root@client:~# curl http://10.1.8.31:30251
# 访问成功失败
root@client:~# curl http://10.1.8.32:30251
Hello web1

# 理论上:10.1.8.0/24网段中主机都可以通过集群任意节点访问web1
# 实际测试:只可以通过pod所在主机的IP访问web1 (10.1.8.32:30790),不可以访问10.1.8.30:30790或10.1.8.31:30790

# 在worker31上也可以通过10.103.36.143访问pod-web1
root@master30:~# kubectl describe pod web1|grep Node:
Node:         worker32.laoma.cloud/10.1.8.32

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

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

    - ipBlock:
        cidr: 0.0.0.0/0
        except:
        - 10.1.8.0/26
4.4.4 限定所有端口

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

root@master30:~# vim netpol.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: my-network-policy
  namespace: web
spec:
  podSelector:
    matchLabels:
      run: web1
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          run: test
# 应用策略
root@master30:~# kubectl apply -f netpol.yaml

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.laoma.cloud   <none>           <none>
web1   1/1     Running   0          82m   10.224.193.67   worker32.laoma.cloud   <none>           <none>
web2   1/1     Running   0          81m   10.224.41.132   worker31.laoma.cloud   <none>           <none>

# 此时满足条件的pod可以ping通pod地址
root@master30:~# kubectl run --rm -it ubuntu -l run=test --image ubuntu -- bash
root@ubuntu:/# apt update
root@ubuntu:/# apt install -y iputils-ping
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

--- 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

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

root@ubuntu:/# exit

# 仍然 ping不通 service,因为service只开放80端口
4.4.5 限定端口范围
root@master30:~# vim netpol.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: my-network-policy
  namespace: web
spec:
  podSelector:
    matchLabels:
      run: web1
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          run: test
    ports:
    - protocol: TCP
      port: 32000
      endPort: 32768
4.4.6 多条件规则

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

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: my-network-policy
  namespace: web
spec:
  podSelector:
    matchLabels:
      run: web1
  policyTypes:
  - Ingress
  ingress:
  - from:
    - ipBlock:
        cidr: 10.1.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          run: test
    ports:
    - protocol: TCP
      port: 80
# 创建network policy
root@master30:~# kubectl apply -f netpol.yaml

# namespace-web中pod-test可以访问web1
root@master30:~# kubectl exec test -- curl -s web1
Hello web1

4.5 默认策略

默认允许所有入站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-ingress
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  ingress:
  - {}
默认拒绝所有入站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
spec:
  podSelector: {}
  policyTypes:
  - Ingress

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

默认允许所有出站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-egress
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - {}
默认拒绝所有出站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-egress
spec:
  podSelector: {}
  policyTypes:
  - Egress

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

默认拒绝所有入口和所有出站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

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

4.6 无法完成的工作

  • 特定于节点的策略。

  • 基于名字的策略。

  • 实现适用于所有命名空间或 Pods 的默认策略。

  • 显式地拒绝策略的能力。NetworkPolicy 的模型默认采用拒绝操作, 其唯一的能力是添加允许策略。

  • **禁止本地回路或指向宿主的网络流量。**Pod 目前无法阻塞 localhost 访问, 它们也无法禁止来自所在节点的访问请求)。

环境清理

root@master30:~# kubectl delete ns network web laoma
root@master30:~# kubectl delete ns web
root@master30:~# kubectl delete ns laoma

出站流量

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-egress
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - {}
默认拒绝所有出站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-egress
spec:
  podSelector: {}
  policyTypes:
  - Egress

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

默认拒绝所有入口和所有出站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

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

4.6 无法完成的工作

  • 特定于节点的策略。

  • 基于名字的策略。

  • 实现适用于所有命名空间或 Pods 的默认策略。

  • 显式地拒绝策略的能力。NetworkPolicy 的模型默认采用拒绝操作, 其唯一的能力是添加允许策略。

  • **禁止本地回路或指向宿主的网络流量。**Pod 目前无法阻塞 localhost 访问, 它们也无法禁止来自所在节点的访问请求)。

环境清理

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

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

更多推荐