K8s学习笔记(二十三) 网络策略 NetworkPolicy

K8s学习笔记(二十三) 网络策略NetworkPolicy

Kubernetes 的NetworkPolicy(网络策略) 是用于控制 Pod 之间网络访问的规则系统,相当于 K8s 集群内的 "防火墙"。它通过标签(Labels) 筛选目标 Pod,定义允许 / 拒绝的入站(Ingress)和出站(Egress)流量,解决了 "默认情况下 Pod 之间可自由通信" 的安全风险。

1 NetworkPolicy 的核心作用

默认情况下,K8s 集群中所有 Pod 之间可以自由通信(无论是否在同一 Node、同一命名空间),这在生产环境中存在安全隐患(比如数据库 Pod 不应被所有 Pod 访问)。

NetworkPolicy 的核心价值:

  • 限制 Pod 的入站流量(谁能访问我);
  • 限制 Pod 的出站流量(我能访问谁);
  • 基于 Pod 标签、命名空间标签、IP 地址范围等精细化控制。

2 NetworkPolicy 依赖什么?

NetworkPolicy 本身是 K8s 的 API 对象(类似 Pod、Deployment),但需要 CNI 插件支持才能生效(并非所有 CNI 都支持)。

支持 NetworkPolicy 的主流 CNI:

  • Calico(最常用,企业级);
  • Weave Net;
  • Cilium;

不支持的 CNI:Flannel(仅解决互通,无策略能力)。

因此,学习前需确保你的 K8s 集群使用了支持 NetworkPolicy 的 CNI(推荐用 Calico,前面已讲过部署方法)。

3 NetworkPolicy 的核心要素

一个完整的 NetworkPolicy 由以下关键部分组成,通过 YAML 定义:

yaml 复制代码
apiVersion: networking.k8s.io/v1  # 固定版本
kind: NetworkPolicy
metadata:
  name: 策略名称
  namespace: 作用的命名空间  # 策略是命名空间级别的,只对当前命名空间的Pod生效
spec:
  podSelector:  # 筛选"被该策略管控的Pod"(通过标签匹配)
    matchLabels:
      app: mysql  # 例:管控所有带app=mysql标签的Pod
  policyTypes:  # 策略类型:Ingress(入站)、Egress(出站),至少指定一种
  - Ingress
  - Egress
  ingress:  # 入站规则(允许哪些流量进入被管控的Pod)
  - from:  # 流量来源(谁能访问)
    - podSelector:  # 来源是特定标签的Pod
        matchLabels:
          app: web
    - namespaceSelector:  # 来源是特定标签的命名空间
        matchLabels:
          env: prod
    - ipBlock:  # 来源是特定IP段(支持CIDR)
        cidr: 192.168.0.0/16
        except:  # 排除某个子段
        - 192.168.1.0/24
    ports:  # 允许访问的端口和协议
    - protocol: TCP
      port: 3306
  egress:  # 出站规则(允许被管控的Pod访问哪些目标)
  - to:  # 访问目标(和from语法相同)
    - podSelector:
        matchLabels:
          app: redis
    ports:  # 允许访问的端口和协议
    - protocol: TCP
      port: 6379

关键要素拆解:

  1. podSelector

    决定 "哪些 Pod 会被该策略管控"。若为空({}),则管控当前命名空间下的所有 Pod

  2. policyTypes

    必须显式声明策略类型(Ingress/Egress),否则规则不生效。

  3. ingress.from(流量来源):

    支持三种来源:

    • podSelector:同一命名空间内,带特定标签的 Pod;
    • namespaceSelector:带特定标签的命名空间(其内所有 Pod);
    • ipBlock:IP 地址段(可用于允许集群外部 IP 访问,如公司内网)。
  4. ingress.ports / egress.ports

    限制允许的协议(TCP/UDP/SCTP)和端口,若不指定,则允许所有端口。

4 常见场景与示例

通过具体场景学习,更容易理解。以下示例均假设在default命名空间操作。

场景 1:只允许 web Pod 访问 mysql Pod(入站控制)

需求:default命名空间中,带app=mysql标签的 Pod,只允许带app=web标签的 Pod 访问其 3306 端口,拒绝其他所有入站流量。

yaml 复制代码
# mysql-allow-web.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: mysql-allow-web
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: mysql  # 管控mysql Pod
  policyTypes:
  - Ingress  # 只控制入站
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: web  # 只允许web Pod访问
    ports:
    - protocol: TCP
      port: 3306  # 只允许3306端口

应用策略:

bash 复制代码
kubectl apply -f mysql-allow-web.yaml

效果验证

  • app=web的 Pod ping 或 telnet mysql 的 3306 端口 → 成功;
  • 用其他标签(如app=test)的 Pod 访问 → 失败(超时)。

场景 2:禁止 Pod 访问外部网络(出站控制)

需求:default命名空间中,带app=backend标签的 Pod,只能访问集群内带app=db标签的 Pod,禁止访问任何外部 IP(包括集群外的公网)。

yaml 复制代码
# backend-restrict-egress.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: backend-restrict-egress
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: backend  # 管控backend Pod
  policyTypes:
  - Egress  # 只控制出站
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: db  # 只允许访问db Pod
    # 不指定ports → 允许所有端口访问db

效果验证

  • backend Pod 访问 db Pod → 成功;
  • backend Pod 访问公网 IP(如ping 8.8.8.8) → 失败。

场景 3:默认拒绝所有入站流量(最小权限原则)

需求:default命名空间中,所有 Pod 默认拒绝入站流量,只允许显式配置的规则访问(生产环境推荐)。

yaml 复制代码
# default-deny-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: default
spec:
  podSelector: {}  # 空选择器 → 管控所有Pod
  policyTypes:
  - Ingress  # 无任何ingress规则 → 默认拒绝所有入站

注意:此策略会阻断所有未被其他策略允许的入站流量。如需允许某些访问,需额外创建允许规则(策略会叠加生效)。

场景 4:允许访问特定命名空间的 Pod

需求:default命名空间的app=frontend Pod,允许被prod命名空间(带env=prod标签)的所有 Pod 访问 80 端口。

yaml 复制代码
# frontend-allow-prod.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: frontend-allow-prod
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: frontend
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          env: prod  # 来源是带env=prod标签的命名空间
    ports:
    - protocol: TCP
      port: 80

前提 :需先给prod命名空间打标签:

bash 复制代码
kubectl label namespace prod env=prod

5 策略的 "叠加性" 与优先级

NetworkPolicy 是叠加生效的,而非覆盖:

  • 若多个策略匹配同一个 Pod,所有策略的规则会 "合并"(取并集);
  • 没有策略时,默认允许所有流量;
  • 一旦有策略匹配 Pod,仅允许策略中显式允许的流量,其他流量均被拒绝("默认拒绝未允许的")。

6 操作与验证命令

1. 常用命令

bash 复制代码
# 创建策略
kubectl apply -f policy.yaml

# 查看当前命名空间的所有策略
kubectl get networkpolicy  # 缩写:kubectl get netpol

# 查看策略详情(包括规则)
kubectl describe netpol <策略名称>

# 删除策略
kubectl delete netpol <策略名称>

2. 验证策略是否生效

最直接的方式是 "测试流量是否符合预期":

  • kubectl run创建测试 Pod(带特定标签):

    bash 复制代码
    # 创建一个带app=test标签的测试Pod(用busybox,支持ping、wget)
    kubectl run test-pod --image=busybox:1.35 --rm -it -- sh
  • 在测试 Pod 中执行命令(如ping <目标Pod IP>wget -qO- <目标Pod IP:端口>),观察是否通断。

7 常见问题与注意事项

  1. 策略不生效?

    • 检查 CNI 是否支持 NetworkPolicy(如 Calico 是否正常运行:kubectl get pods -n calico-system);
    • 检查podSelector标签是否匹配目标 Pod(标签错误是常见原因);
    • 检查policyTypes是否包含需要的类型(如漏写 Ingress)。
  2. 命名空间隔离?

    NetworkPolicy 是命名空间级别的,只能管控当前命名空间的 Pod。跨命名空间的访问需通过namespaceSelector指定来源命名空间。

  3. IPBlock 的注意事项

    • ipBlock.cidr支持集群内外的 IP,但不建议直接使用 Pod IP(Pod 重建后 IP 会变,应优先用标签);
    • 集群内部的 Service ClusterIP 属于ipBlock的范围,可通过 CIDR 允许访问。

总结

NetworkPolicy 的核心是 "基于标签的精细化流量控制",关键是掌握:

  • podSelector选择被管控的 Pod;
  • from/to定义流量的来源 / 目标(Pod、命名空间、IP);
  • ports限制允许的端口和协议。
相关推荐
AI_56783 小时前
脑科学支持的Python学习法:每天2小时碎片化训练,用‘神经可塑性’打败拖延症“
开发语言·python·学习
摇滚侠3 小时前
Spring Boot3零基础教程,定制 Health 健康端点,笔记83
spring boot·笔记·spring
suknna4 小时前
记一次 Kubebuilder Operator 开发中的 CRD 注解超限问题
kubernetes
ysa0510304 小时前
利用数的变形简化大规模问题#数论
c++·笔记·算法
superior tigre4 小时前
esp32学习随笔文档1
学习·esp32
报错小能手4 小时前
计算机网络自顶向下方法10——应用层 HTTP/2 成帧 响应报文优先次序和服务器推
笔记·计算机网络
love530love4 小时前
【笔记】Podman Desktop 部署 开源数字人 HeyGem.ai
人工智能·windows·笔记·python·容器·开源·podman
本郡主是喵5 小时前
基于区块链的航班延误保险系统的设计与实现(源码+文档)
学习·区块链
17岁的勇气5 小时前
Unity Shader unity文档学习笔记(二十二):雪地几种实现方式(1. 2D贴花式 2.3D曲面细分并且实现顶点偏移)
笔记·学习·unity·shader