Kubernetes-网络策略

在Kubernetes集群中,Pod之间默认是完全互通的------无论是同一命名空间内的Pod,还是不同命名空间的Pod,都能自由发起网络请求。这种"无隔离"的模式在开发环境可能没问题,但在生产环境中,会带来严重的安全风险:比如前端Pod被入侵后,攻击者可直接访问后端数据库Pod,造成数据泄露。

而Kubernetes网络策略(NetworkPolicy),就是解决这个问题的核心工具------它像集群内部的"防火墙",通过定义规则,精准控制Pod的入站(Ingress)和出站(Egress)流量,实现Pod间的网络隔离与访问控制。

本文将从"是什么→为什么用→怎么用→怎么验证→踩坑总结",带你从零吃透NetworkPolicy,全程搭配实操命令和配置示例,新手也能跟着上手实践。

一、先搞懂:NetworkPolicy 核心基础

1. 什么是NetworkPolicy?

NetworkPolicy是Kubernetes的一种资源对象,用于定义Pod之间、Pod与外部网络之间的流量规则。它的核心作用是:通过"选择器"匹配目标Pod,通过"流量规则"允许/拒绝特定流量

关键注意点:

  • NetworkPolicy仅对"被选中的Pod"生效,未被任何策略选中的Pod,依然保持默认互通。

  • 策略的规则是"白名单模式"------默认拒绝所有流量,只有明确允许的流量才能通过(除非策略明确配置"允许所有")。

  • NetworkPolicy依赖CNI插件支持(如Calico、Cilium、Flannel+),如果你的集群CNI不支持,创建策略也不会生效(这是新手最常踩的坑之一)。

2. 为什么必须用NetworkPolicy?

举3个生产环境中最常见的场景,帮你理解其必要性:

  1. 安全隔离:数据库Pod仅允许后端服务Pod访问,拒绝前端Pod、测试Pod的请求,防止数据泄露。

  2. 环境隔离:开发环境的Pod不能访问生产环境的Pod,避免测试操作影响生产服务。

  3. 流量管控:限制Pod只能访问指定的外部接口(如仅允许访问第三方支付接口),禁止访问无关外网地址。

简单说:没有NetworkPolicy,Kubernetes集群的网络就像"不设防的小区",任何人都能随意进出;有了NetworkPolicy,就能实现"分区管控、按需放行",提升集群安全性。

3. NetworkPolicy 核心组成部分

任何一个NetworkPolicy配置文件,都包含4个核心部分,理解这4部分,就能读懂所有策略:

组成部分 作用 示例
podSelector 选择"要应用策略的Pod",通过标签匹配 podSelector: { matchLabels: { app: nginx } }(匹配所有app=nginx的Pod)
policyTypes 指定策略管控的流量类型,可选Ingress(入站)、Egress(出站) policyTypes: [Ingress, Egress](同时管控入站和出站)
ingress 定义"允许进入Pod的流量"规则(来源、端口) 允许来自app=backend的Pod,访问80端口
egress 定义"允许Pod发出的流量"规则(目标、端口) 允许访问外部IP为10.0.0.10,端口3306(数据库)

补充:podSelector为空(podSelector: {})时,表示匹配"当前命名空间内的所有Pod";如果需要跨命名空间匹配,可使用namespaceSelector。

二、实操必备:5个常用NetworkPolicy配置示例

以下所有示例均基于「Calico CNI」(最常用的CNI之一),配置文件可直接复制使用,注释已写清楚,新手可直接上手测试。

提示:所有策略均作用于「default命名空间」,如果需要作用于其他命名空间,可在metadata中添加namespace字段。

示例1:默认拒绝所有入站流量(default-deny-ingress)

最基础、最常用的策略之一:拒绝当前命名空间内所有Pod的入站流量,即所有Pod都无法被其他Pod访问(但Pod可主动发起出站请求)。

复制代码
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress  # 策略名称,自定义
  namespace: default          # 策略作用的命名空间
spec:
  podSelector: {}             # 匹配当前命名空间所有Pod
  policyTypes:
    - Ingress                 # 仅管控入站流量
# 没有定义ingress规则 → 默认拒绝所有入站流量

应用命令:kubectl apply -f default-deny-ingress.yaml

示例2:允许所有入站流量(allow-all-ingress)

与示例1相反,允许当前命名空间内所有Pod接收来自任何来源的入站流量,等价于"关闭入站隔离",恢复Pod默认互通状态。

复制代码
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-ingress
  namespace: default
spec:
  podSelector: {}
  ingress:
    - {}  # 空规则表示允许所有入站流量
  policyTypes:
    - Ingress

示例3:默认拒绝所有出站流量(default-deny-egress)

拒绝当前命名空间内所有Pod的出站流量,即所有Pod都无法主动访问其他Pod、外部网络(但可接收入站请求)。

复制代码
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-egress
  namespace: default
spec:
  podSelector: {}
  policyTypes:
    - Egress  # 仅管控出站流量
# 没有定义egress规则 → 默认拒绝所有出站流量

示例4:允许所有出站流量(allow-all-egress)

允许当前命名空间内所有Pod向任何目标发起出站请求,等价于"关闭出站隔离"。

复制代码
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-egress
  namespace: default
spec:
  podSelector: {}
  egress:
    - {}  # 空规则表示允许所有出站流量
  policyTypes:
    - Egress

示例5:精准管控(最实用)------ 仅允许后端Pod访问数据库Pod

生产环境最常用的场景:假设我们有两类Pod------backend(后端服务,标签app=backend)、db(数据库,标签app=db,端口3306),要求:仅允许backend Pod访问db Pod的3306端口,拒绝其他所有Pod访问。

复制代码
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-backend-to-db
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: db  # 策略应用于db Pod(管控谁的入站流量)
  policyTypes:
    - Ingress
  ingress:
    - from:  # 允许的流量来源
        - podSelector:
            matchLabels:
              app: backend  # 仅允许app=backend的Pod访问
      ports:  # 允许访问的端口
        - protocol: TCP
          port: 3306  # db Pod的数据库端口

说明:这个策略是"作用于db Pod",管控db Pod的入站流量,只有backend Pod能访问它的3306端口,其他Pod(如frontend)的请求会被拒绝。

三、关键实操:如何验证NetworkPolicy是否生效?

很多新手创建策略后,不知道怎么确认策略是否生效,这里以「示例1:default-deny-ingress」为例,教你完整的验证流程(通用所有策略)。

核心原则:NetworkPolicy仅管控Pod与Pod之间的流量,节点与Pod之间的流量默认不受管控(这是新手最容易混淆的点!)。

验证步骤(全程实操)

  1. 应用策略 kubectl apply -f default-deny-ingress.yaml ``# 确认策略已创建 ``kubectl get networkpolicies # 简称:kubectl get netpol输出中能看到default-deny-ingress,说明策略创建成功。

  2. 创建两个测试Pod (均在default命名空间,用nginx镜像,自带curl工具) # 创建pod-a(作为被访问方) ``kubectl run pod-a --image=nginx ``# 创建pod-b(作为访问方) ``kubectl run pod-b --image=nginx等待Pod状态变为Running:kubectl get pods

  3. 获取被访问方Pod的IP # 获取pod-a的IP(假设为10.244.140.75) ``POD_A_IP=$(kubectl get pod pod-a -o jsonpath='{.status.podIP}') ``echo $POD_A_IP # 输出Pod IP,后续使用

  4. 在pod-b中访问pod-a(Pod到Pod流量,受策略管控) kubectl exec -it pod-b -- curl --connect-timeout 5 $POD_A_IP✅ 预期结果:请求超时(curl: (28) Connection timed out),说明入站流量被策略拦截,策略生效。

  5. 对比验证(删除策略,确认流量恢复) # 删除策略 ``kubectl delete netpol default-deny-ingress ``# 再次在pod-b中访问pod-a ``kubectl exec -it pod-b -- curl --connect-timeout 5 $POD_A_IP✅ 预期结果:返回nginx默认页面的HTML内容,说明流量恢复正常,进一步确认策略之前确实生效。

常见验证误区

❌ 误区1:在集群节点(如master节点)上执行curl Pod IP,期望被拦截。

原因:节点与Pod之间的流量,默认不受NetworkPolicy管控,即使策略拒绝所有入站,节点访问Pod依然能成功。

❌ 误区2:Pod状态为Running,就认为能正常访问。

原因:Pod Running仅表示容器启动成功,若镜像精简(如部分busybox镜像),可能缺少curl、wget工具,导致无法执行测试命令,可换用nginx或busybox:1.36镜像。

四、新手必踩的5个坑及解决方案

结合我自己学习和实操的经历,整理了新手最常遇到的问题,每个问题都附解决方案,帮你少走弯路。

坑1:创建策略后,流量依然互通/被拒绝,策略不生效

✅ 解决方案:

  • 检查CNI插件是否支持NetworkPolicy:Flannel默认不支持,需替换为Calico、Cilium,或安装Flannel的扩展插件。

  • 检查策略的namespace是否正确:策略仅作用于自身所在的命名空间,跨命名空间的策略不生效。

  • 检查podSelector是否匹配目标Pod:标签是否正确(如app=nginx,不要写错为app=ngnix),空selector匹配所有Pod。

坑2:执行kubectl exec时,提示"container not found"

✅ 解决方案:

  • 检查Pod名称是否正确:用kubectl get pods查看准确的Pod名称,避免手动输入错误。

  • 检查Pod状态是否为Running:若为ContainerCreating或CrashLoopBackOff,等待Pod就绪或重新创建。

  • 显式指定容器名称:kubectl exec -it pod-b -c pod-b -- curl ...(单容器Pod可省略,但显式指定更稳妥)。

坑3:策略配置正确,但部分流量依然能通过

✅ 解决方案:

  • 检查是否有多个NetworkPolicy作用于同一个Pod:多个策略的规则会"叠加",只要有一个策略允许某类流量,该流量就会通过。

  • 检查流量类型是否在policyTypes中:若策略只配置了Ingress,則出站流量不受管控;反之亦然。

坑4:跨命名空间的Pod无法访问,即使配置了策略

✅ 解决方案:

默认策略仅匹配当前命名空间的Pod,跨命名空间访问需在ingress.from中添加namespaceSelector,示例:

复制代码
ingress:
  - from:
      - podSelector:
          matchLabels:
            app: backend
        namespaceSelector:  # 匹配指定命名空间的Pod
          matchLabels:
            name: dev-namespace

坑5:删除策略后,流量依然被拦截

✅ 解决方案:

  • 检查是否有其他默认拒绝策略:如default-deny-all,若存在,需同时删除。

  • 重启Pod:部分CNI插件(如Calico)在策略删除后,需重启Pod才能恢复流量(kubectl rollout restart pod xxx)。

五、学习总结与进阶方向

1. 核心总结

  • NetworkPolicy是Kubernetes集群内部的"防火墙",核心是"匹配Pod + 管控流量"。

  • 规则是白名单模式:默认拒绝所有流量,仅允许明确配置的流量通过。

  • 仅管控Pod与Pod之间的流量,节点与Pod之间的流量默认不受管控。

  • 常用策略:默认拒绝入站/出站、允许所有入站/出站、精准管控Pod间访问(生产核心)。

2. 进阶学习方向

如果想深入掌握NetworkPolicy,可继续学习以下内容:

  1. 复杂规则配置:结合namespaceSelector、ipBlock(管控外部IP)、端口范围等。

  2. CNI插件与NetworkPolicy的联动:如Calico的策略日志、流量可视化。

  3. 生产环境最佳实践:如按命名空间隔离、按服务层级配置策略、策略的版本控制与备份。

  4. 高级特性:如Egress流量的DNS匹配、策略的优先级配置。

最后

NetworkPolicy看似简单,但实操中容易踩坑,建议新手先从本文的5个示例入手,亲手应用、验证,理解"Pod选择器"和"流量规则"的关联,再逐步尝试复杂场景。

记住:网络策略的核心是"最小权限原则"------只允许必要的流量通过,拒绝所有无关流量,这样才能最大化提升Kubernetes集群的安全性。

后续我会继续更新NetworkPolicy的进阶实操(如Calico策略日志、跨命名空间管控),关注我,一起吃透Kubernetes!

如果本文对你有帮助,欢迎点赞、收藏、转发,若有疑问,可在评论区留言,我会逐一回复~

相关推荐
lpfasd1232 小时前
Docker 使用注意事项:从磁盘爆满到安全实践的完整避坑指南
安全·docker·容器
毅炼2 小时前
Netty 常见问题总结
java·网络·数据结构·算法·哈希算法
Whisper_Sy2 小时前
Flutter for OpenHarmony移动数据使用监管助手App实战 - 周报告实现
开发语言·javascript·网络·flutter·php
源力祁老师3 小时前
Odoo日志系统核心组件_logger
网络·数据库·php
郝学胜-神的一滴3 小时前
深入理解Linux套接字(Socket)编程:从原理到实践
linux·服务器·开发语言·网络·c++·程序人生·算法
程序猿编码3 小时前
高性能HTTP服务压测工具:设计思路与实现原理(C/C++代码实现)
c语言·网络·c++·网络协议·tcp/ip·http
勇气要爆发4 小时前
Docker+Ollama+LangChain:从零搭建企业级“隐私优先”本地 RAG 知识库 (附源码)
docker·容器·langchain·lora·rag·ollama·llama 3
迎仔4 小时前
网络硬件设备通俗指南:从“大喇叭”到“算力工厂”
网络·智能路由器
LaoZhangGong1234 小时前
学习TCP/IP的第4步:重点掌握TCP序列号和确认号
网络·学习·tcp/ip·以太网