西西软件园多重安全检测下载网站、值得信赖的软件下载站!
软件
软件
文章
搜索

首页 → 业内动态 → 业内资讯 → 同集群Pod默认互通,我补NetworkPolicy封了Redis

同集群Pod默认互通,我补NetworkPolicy封了Redis

相关软件相关文章发表评论 来源:本站整理时间:2026/11/11 8:00:46字体大小:A-A+

  • 类型:硬件驱动大小:3.85G语言:中文 评分:5.0
  • 标签:
立即下载

去年我们把一套业务拆成十几个 Pod 丢进 Kubernetes,Ingress 配好、Service 配好、探针配好,一切看起来都很标准。三个月后的一个晚上,我收到 Redis 侧的告警:有个陌生的客户端在集群内网段扫端口,扫到我的 Redis 6379,用的是没有密码的默认配置,把里面两个业务库的键值翻了个遍。我第一反应是"我们没把 Redis 暴露到公网啊",查了一圈 Ingress 和 Service,发现 Redis 只监听在集群内部 NetworkPolicy 根本没配但这压根不是重点,重点是:在默认的 Kubernetes 网络模型里,同一个集群内的所有 Pod 之间,本来就是完全互通的。谁在这个集群里跑起来、跑的是谁的镜像,我一个都不知道,但它想访问谁就能访问谁。

如果你也在自建或者托管一套 Kubernetes 集群,这台机器的规格和节点规划其实是整套隔离方案的地基:节点数量、网络插件版本、网卡带宽这几项从一开始就要留出余量,真到了要收紧策略的时候再改就来不及了。可以先看看nube(全球云服务器,提供云主机与独立服务器)这类方案的节点和网络说明,把机器规格和集群规模对上,再回头设计隔离策略会踏实很多。

一、K8s 默认的网络模型:Pod 之间天生互通

先说清楚原理,不然后面所有规则都看不懂。Kubernetes 对容器网络的要求里有一条核心约定:一个集群里的所有 Pod,都被分配到同一个扁平的、虚拟的网段里,每个 Pod 有独立 IP,任意两个 Pod 之间可以直接用 IP 通信。这套模型的好处是简单,Service、Ingress、StatefulSet 这些上层抽象全部建立在这个前提之上Service 的负载均衡本质上就是在做 Pod IP 之间的转发,Ingress Controller 转发进来的流量最终也要落到某个 Pod IP 上。

默认情况下,这条约定是"只进不出"的网络:Kubernetes 只负责保证 Pod 之间能通,不会替你限制谁能访问谁。你可以用一个很简单的实验验证这一点:在任意一个 Pod 里 ping 另一个 Pod 的 IP,或者直接 curl 它的服务端口,只要网络插件是正常工作的,都会通。生产、测试、监控、日志这些 namespace 之间的 Pod,互通程度完全一样。

这就是"东西向流量"(east-west traffic)这个词的含义:流量不是从外面进来再出去,而是在集群内部从 A 服务流到 B 服务。绝大多数人对东西向流量的风险感知很低,因为外部入口那一层通常做了不少防护WAF、高防、HTTPS 证书、认证中间件。但内部这一段,在很多团队里就是一片裸地。

二、Service 和 NetworkPolicy 是两件完全不同的事

我见过不止一次有人把这两个搞混。Service 解决的是"怎么找到服务":它给你一个稳定的 ClusterIP 或者一个 DNS 名,背后挂一组 Pod,帮你做负载均衡和会话保持。NetworkPolicy 解决的是"谁可以访问谁":它在网络层面放行或者拦截指定来源到指定目标的连接。

你可以把它类比成公司前台和门禁。前台(Service)决定"来的人怎么找到对应部门",门禁(NetworkPolicy)决定"哪些人能进哪层楼"。前台装得再漂亮,没有门禁不代表任何人都不能上楼。有些人以为"我的 Redis 只配了 ClusterIP Service,所以外部访问不到"外部确实访问不到,但集群内任何一个 Pod 都能直接按 Pod IP 连它,根本不需要经过 Service。

还有一个必须知道的细节:NetworkPolicy 的执行不是 Kubernetes 自己做的,而是交给 CNI 网络插件。API Server 只是把策略对象存下来,真正的拦截发生在节点的网卡层面,靠 CNI 插件的 agent 往 iptables 或者 eBPF map 里写规则。所以如果你用的 CNI 插件不支持 NetworkPolicy,你在集群里 kubectl get networkpolicy 也能看到对象,YAML 也没有语法错误,但流量照样畅通无阻。这一点很坑,因为"对象创建成功"给了人虚假的安全感。

三、我的那次事故:一个没有密码的 Redis 被同集群的 Pod 读走了

事情发生在凌晨,告警是 Redis 侧的连接数突增。我登录跳板机进集群,先查 Redis 的 CLIENT LIST,发现客户端地址是一串 10.244.x.x 的 Pod IP,属于集群网段,但那个 Pod 不是我部署的任何东西。

后来查清了:那个集群的节点上跑着好几个团队的业务,其中一个同事在做压力测试,用的是一个从网上抄来的 redis:latest 镜像,compose 文件里既没设密码也没绑限制。而这个 Pod 就躺在同一个扁平网段里,扫到我的 Redis IP 和默认端口,直接就连上了。整个过程不需要任何凭证,因为 Redis 默认不带认证。

这次事故让我真正理解了一件事:容器编排解决的是"怎么把应用跑起来",不解决"应用之间该不该互相访问"。你所有 namespace 之间的信任关系,默认全是开的。

四、NetworkPolicy 的两种类型和三个关键字段

策略有两个类型:Ingress(控制入向流量谁能进来)和 Egress(控制出向流量谁能出去)。绝大多数场景大家只配了 Ingress,因为外部流量进不来是主要诉求。但 Egress 往往更值钱一个被攻破的 Pod 如果不能主动外连,它连数据回传都做不到,损失会小得多。

一个策略的骨架是三块:podSelector(作用对象)、matchLabels(匹配来源或目标)、ports(放行的协议和端口)。举个最简单的例子,只允许特定 namespace 里的 Pod 访问 Redis 的 6379:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: redis-ingress
spec:
  podSelector:
    matchLabels:
      app: redis
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
      matchLabels:
        name: backend
    ports:
    - protocol: TCP
      port: 6379
  - to:
    - podSelector:
      matchLabels:
        app: web
    ports:
    - protocol: TCP
     port: 6379

五、四个最容易踩的坑

坑一:以为"不写策略"就是"禁止访问"。在同一个 namespace 里,只要没有任何 NetworkPolicy 选中这个 Pod,它就是全放行的。但一旦你创建了任何一条 选中该 Pod 的 Ingress 策略,这个 Pod 就立刻变成"白名单模式"没被策略明确放行的流量全部拒绝。这是最反直觉的一点,也是我改策略改到业务断连的头号原因:本来 Pod 之间随便通,加了一条只放行 80 端口的策略,结果数据库连不上了。

坑二:只写 podSelector 不写 namespaceSelector,隔离等于没做。一个只写了 podSelector 的 from 段,作用范围是所有 namespace 里的匹配 Pod。你以为"只允许我自己这个 namespace 访问",实际上全集群符合条件的 Pod 都能进。这是我在复盘里看到最多的一处配置疏漏。

坑三:DNS 出口没放行,策略一收紧服务全挂。Pod 要解析 redis.default.svc.cluster.local 这种域名,走的是 CoreDNS 的 53 端口。如果你的 Egress 策略写了"只允许访问特定几个 Pod",而这些 Pod 的 label 恰好没包含 CoreDNS,那么域名解析全部失败,表现是应用大量超时、报 connection reset 或者 no such host,看起来像服务挂了,其实是 DNS 通道被自己掐断。

坑四:CNI 不支持策略,或者策略在节点上没有真正落地。前面提过,API 层面创建成功不等于节点在执行。可以到节点上看 iptables -t nat -L KUBE-NODEPORTS 或者用 calicoctl、cilium 的命令行工具 dump 策略状态,看看规则是不是真的下到网卡上了。

六、怎么验证策略真的生效

别靠猜。我一般用三步验证:

第一步,先在一个被允许的 Pod 里发起访问,确认业务没被误伤;第二步,在一个被禁止的 Pod 里 curl 目标服务,预期是超时(connection timeout)而不是 connection refused被 NetworkPolicy 拦下的流量通常直接丢弃,所以是超时;如果返回 refused,说明网络层压根没拦你,问题在别处。第三步,删除策略再复测一次,确认能通,说明这条策略确实是那个"关键开关",而不是别的原因导致的不通。

另外提醒一句,绝大多数 CNI 插件在策略生效和更新上有几秒到几十秒的延迟,所以策略改完别立刻断言"没生效",等一下再测。

七、我现在的隔离基线

总结一下我目前给每个业务集群定下的规矩:

1. 每个 namespace 至少有一条 default-deny-all 的基础策略,明确拒绝所有入向和出向;
2. 每个服务单独一条策略,只放行业务真正需要的那几个端口;
3. Egress 至少保证 DNS(53/UDP+TCP)能通,以及监控、日志上报的出口;
4. 数据库类服务启用认证,口令走 Secret 挂载,不裸奔在 compose 文件里;
5. 每次改策略前,先在测试集群用同样的 CNI 版本验证一遍;
6. 策略文件进 Git,走 PR 评审,不允许 kubectl 直接改完就上线。

如果你现在还是"什么都能通"的裸奔状态,建议先从最敏感的那个服务下手通常是数据库、缓存、或者带密钥的后台服务。先加一条只放行必要来源的 Ingress 策略,再慢慢往下补 Egress,这样即使策略写错了,爆炸半径也有限。

运维工程师在终端前查看 Kubernetes 集群 Pod 网络连通性

验证策略最直接的办法,就是从一个本该被拒绝的 Pod 里发起真实连接请求,看它是不是真的被挡在网络层。

网络策略隔离的概念图示,两个网络区域之间被屏障阻断

NetworkPolicy 的作用就是把默认的全互通,改成按需放行。策略对象建好之后,真正的拦截动作是在节点网卡上完成的。

Kubernetes 集群节点机房内部机柜与交换机

集群规模越大,节点上的策略规则越多,对网络插件和网卡的处理能力要求也越高。这也是为什么很多团队在自建集群时会把节点规格和 CNI 选型当成头等大事。

Kubernetes 安全策略配置文件放在桌面显示器旁

策略文件一定要进版本库、走评审。我们吃过亏:有人为了临时排查把一条策略删了,忘了加回来,那个窗口期里整个集群又变成了裸奔状态。

节点规格和网络的选型同样值得提前规划。集群要扩容、要做节点隔离、要把高敏感服务放到专门的机器上,这些都需要节点层面的资源余量和独立网络规划,tnahosting(全球云服务器,含 KVM SSD 与独立服务器)这类把云主机和独服放在同一套产品线里的方案比较方便,节点扩容时可以按隔离等级分批采购,不用等到出事再临时找机器。

    相关评论

    阅读本文后您有什么感想? 已有人给出评价!

    • 8 喜欢喜欢
    • 3 顶顶
    • 1 难过难过
    • 5 囧囧
    • 3 围观围观
    • 2 无聊无聊

    发表评论

    昵称:
    表情: 高兴 可 汗 我不要 害羞 好 下下下 送花 屎 亲亲