K8s 零信任实战:如何用 NetworkPolicy 拦截集群内的“非法访问”?
在很多人的潜意识里,Kubernetes 内部是一个绝对安全的“乌托邦”:只要把服务部署到了集群里,不暴露 NodePort 或者 Ingress,外部黑客就打不进来,内部服务也是绝对安全的。
但现实往往很骨感。Kubernetes 的默认网络模型是“扁平且全开放”的。
这意味着什么?这意味着如果你的集群里运行着一个电商系统和一个内部财务系统,只要它们在同一个集群网络下,电商系统里的任意一个微服务,都可以畅通无阻地 ping 通财务系统里的核心数据库!一旦某个边缘微服务存在漏洞被拿下,攻击者就能以此为跳板,在集群内部横向移动(Lateral Movement)。
今天,我们就来实战演练一把:如何打破这种“全连通”的默认状态,用 NetworkPolicy(网络策略) 给核心服务穿上防弹衣。
🔪 场景重现:合法的 API 与非法的“黑客”
假设我们在 auth-space 命名空间下,运行着一个极其重要的数据库服务 mysql(带有标签 db=mysql)。
现在,集群里潜伏着两个访客:
- 合法的业务服务:名叫
api-server。 - 模拟的恶意服务:名叫
hacker。
我们在终端里敲下这两行命令,把它们跑起来:
1. 模拟合法的访问者 (贴上身份标签 role=api-server)
kubectl run api-server --image=busybox --labels=role=api-server -n auth-space -- sleep 3600
2. 模拟非法的访问者 (贴上可疑标签 role=hacker)
kubectl run hacker --image=busybox --labels=role=hacker -n auth-space -- sleep 3600
💡 小知识: 结尾的 -- sleep 3600 是为了让没有常驻进程的 busybox 容器持续运行,方便我们接下来“钻”进容器里做测试。在没有安全策略的情况下,如果我们分别进入这两个容器去访问 mysql,你会发现:两者都能瞬间秒连。K8s 根本不在乎你是谁,只要网络通,一律放行。
🛡️ 破局:部署 NetworkPolicy 建立白名单
在云原生时代,我们不再基于 IP 去做防火墙策略(因为 Pod 的 IP 随时会变),而是基于 Label(标签)。
我们需要写一张“安保规则”告诉 Kubernetes:
“去守住带有db=mysql标签的 Pod,只允许带有role=api-server标签的家伙进来,其他人一律拉黑!”
将这个逻辑翻译成 K8s 听得懂的 YAML 配置,长这样:
mysql-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: mysql-security-policy
namespace: auth-space
spec:
1. 保护谁?保护带有 db=mysql 标签的 Pod
podSelector:
matchLabels:
db: mysql
2. 限制什么方向的流量?入站 (Ingress)
policyTypes:
- Ingress
3. 白名单里有谁?只允许带有 role=api-server 标签的 Pod
ingress:
- from:
- podSelector:
matchLabels:
role: api-server
- podSelector:
保存文件并应用策略:
kubectl apply -f mysql-policy.yaml
🎯 见证奇迹:微隔离生效了吗?
规则下发后,底层网络插件(如 Calico 或 Cilium)会瞬间更新节点上的 iptables/eBPF 规则。让我们重新测试一下访问权限。
第一步:合法访问者测试 我们让 api-server 再次尝试呼叫 mysql,并设置 2 秒超时:
kubectl exec -n auth-space api-server -- wget -qO- --timeout=2 mysql
太棒了!这个选题非常契合当下云原生安全(DevSecOps)的热点,既有理论深度,又有可以直接“抄作业”的代码,非常容易受到技术读者的欢迎。
以下为你精心撰写的博客正文。你可以直接复制发布到掘金、CSDN、知乎或你个人的独立博客中。
K8s 零信任实战:如何用 NetworkPolicy 拦截集群内的“非法访问”?
标签: Kubernetes / 云原生安全 / NetworkPolicy / 实战教程 字数: 约 1500 字 阅读时长: 5 分钟
在很多人的潜意识里,Kubernetes 内部是一个绝对安全的“乌托邦”:只要把服务部署到了集群里,不暴露 NodePort 或者 Ingress,外部黑客就打不进来,内部服务也是绝对安全的。
但现实往往很骨感。Kubernetes 的默认网络模型是“扁平且全开放”的。
这意味着什么?这意味着如果你的集群里运行着一个电商系统和一个内部财务系统,只要它们在同一个集群网络下,电商系统里的任意一个微服务,都可以畅通无阻地 ping 通财务系统里的核心数据库!一旦某个边缘微服务存在漏洞被拿下,攻击者就能以此为跳板,在集群内部横向移动(Lateral Movement)。
今天,我们就来实战演练一把:如何打破这种“全连通”的默认状态,用 NetworkPolicy(网络策略) 给核心服务穿上防弹衣。
🔪 场景重现:合法的 API 与非法的“黑客”
假设我们在 auth-space 命名空间下,运行着一个极其重要的数据库服务 mysql(带有标签 db=mysql)。
现在,集群里潜伏着两个访客:
- 合法的业务服务:名叫
api-server。 - 模拟的恶意服务:名叫
hacker。
我们在终端里敲下这两行命令,把它们跑起来:
Bash
# 1. 模拟合法的访问者 (贴上身份标签 role=api-server)
kubectl run api-server --image=busybox --labels=role=api-server -n auth-space -- sleep 3600
# 2. 模拟非法的访问者 (贴上可疑标签 role=hacker)
kubectl run hacker --image=busybox --labels=role=hacker -n auth-space -- sleep 3600
💡 小知识: 结尾的 -- sleep 3600 是为了让没有常驻进程的 busybox 容器持续运行,方便我们接下来“钻”进容器里做测试。在没有安全策略的情况下,如果我们分别进入这两个容器去访问 mysql,你会发现:两者都能瞬间秒连。K8s 根本不在乎你是谁,只要网络通,一律放行。
🛡️ 破局:部署 NetworkPolicy 建立白名单
在云原生时代,我们不再基于 IP 去做防火墙策略(因为 Pod 的 IP 随时会变),而是基于 Label(标签)。
我们需要写一张“安保规则”告诉 Kubernetes:
“去守住带有db=mysql标签的 Pod,只允许带有role=api-server标签的家伙进来,其他人一律拉黑!”
将这个逻辑翻译成 K8s 听得懂的 YAML 配置,长这样:
YAML
# mysql-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: mysql-security-policy
namespace: auth-space
spec:
# 1. 保护谁?保护带有 db=mysql 标签的 Pod
podSelector:
matchLabels:
db: mysql
# 2. 限制什么方向的流量?入站 (Ingress)
policyTypes:
- Ingress
# 3. 白名单里有谁?只允许带有 role=api-server 标签的 Pod
ingress:
- from:
- podSelector:
matchLabels:
role: api-server
保存文件并应用策略:
Bash
kubectl apply -f mysql-policy.yaml
🎯 见证奇迹:微隔离生效了吗?
规则下发后,底层网络插件(如 Calico 或 Cilium)会瞬间更新节点上的 iptables/eBPF 规则。让我们重新测试一下访问权限。
第一步:合法访问者测试 我们让 api-server 再次尝试呼叫 mysql,并设置 2 秒超时:
Bash
kubectl exec -n auth-space api-server -- wget -qO- --timeout=2 mysql
结果: 成功获取到响应数据。因为它的标签完美命中了白名单规则,保安微微一笑,予以放行。
第二步:非法访问者测试 现在,轮到 hacker 出场了:
kubectl exec -n auth-space hacker -- wget -qO- --timeout=2 mysql
结果: 终端卡住,过了 2 秒后弹出残酷的报错:wget: download timed out。 网络层直接把它的请求丢弃了(Drop),它连 mysql 的大门在哪都摸不到。
💡 核心总结 (Takeaways)
通过这个小实验,我们需要将以下三个概念刻在脑子里:
- 默认全开,显式拒绝:K8s 默认网络是不设防的。但一旦你针对某个 Pod 绑定了哪怕一条 NetworkPolicy,它就会瞬间变成“默认拒绝(Default Deny)”状态,只有规则里写明的才放行。
- 认签不认人:K8s 的网络防火墙不看你的 Pod 叫什么名字,也不看你的 IP 是多少,唯一查验的凭证就是 Label。身份管理即标签管理。
- 零信任的基石:这种将防御边界缩小到单个容器级别的方法,被称为“微隔离(Micro-segmentation)”。这是构建云原生零信任架构的第一步。
下次在部署高优核心业务时,别忘了给它写一份 NetworkPolicy,别让你的服务在集群里“裸奔”!