在复杂的微服务架构中,限制服务间的访问权限是保障系统安全的关键一环。Kubernetes Network Policy(KNP)允许您定义一组规则,控制 Pod 之间的网络通信。本文将通过实战演练,手把手教您如何通过白名单机制,精确锁定哪些 Pod 可以访问目标服务。
什么是 Network Policy 白名单?
默认情况下,Kubernetes 集群中的所有 Pod 都是可以互相通信的。白名单策略的核心思想是:先拒绝所有流量,然后只允许明确指定的、合法的流量通过。
准备工作
您需要一个支持 Network Policy 的 Kubernetes 集群(例如使用 Calico 或 Cilium 作为 CNI)。我们将创建两个服务 Pod (backend 和 frontend),并在同一个命名空间内进行测试。
1. 创建命名空间和应用
首先,创建一个名为 security-demo 的命名空间,并在其中部署我们的应用。
# apps.yaml
apiVersion: v1
kind: Namespace
metadata:
name: security-demo
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
namespace: security-demo
labels:
app: backend
spec:
selector:
matchLabels:
app: backend
replicas: 1
template:
metadata:
labels:
app: backend
spec:
containers:
- name: net-utils
image: busybox
command: ["sh", "-c", "echo 'Backend Service Running' && sleep 3600"]
ports:
- containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
namespace: security-demo
labels:
app: frontend
spec:
selector:
matchLabels:
app: frontend
replicas: 1
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: net-utils
image: busybox
command: ["sleep", "3600"]
---
# 测试用 Pod,用于验证非白名单流量
apiVersion: v1
kind: Pod
metadata:
name: unauthorized-client
namespace: security-demo
labels:
app: unauthorized
spec:
containers:
- name: net-utils
image: busybox
command: ["sleep", "3600"]
执行部署:
kubectl apply -f apps.yaml
# 确认 Pod IP
BACKEND_IP=$(kubectl get pod -n security-demo -l app=backend -o jsonpath='{.items[0].status.podIP}')
2. 初始状态测试(开放)
在未应用 Network Policy 之前,所有 Pod 都可以访问 backend。
从 frontend 访问 backend (应该成功):
kubectl exec -n security-demo deployment/frontend -- wget -T 2 -O - $BACKEND_IP:80
# 预计输出: Backend Service Running
实施白名单策略
白名单实现分为两步:默认拒绝(锁门),然后精确放行(开锁)。
3. 默认拒绝所有 Ingress 流量
创建一个 Network Policy,目标是 backend Pod,并拒绝所有进入该 Pod 的流量。当 policyTypes 中列出了 Ingress 但 rules 列表为空时,即实现了默认拒绝。
# 01-default-deny.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-backend-ingress
namespace: security-demo
spec:
podSelector:
matchLabels:
app: backend
# 仅针对 Ingress 流量生效
policyTypes:
- Ingress
应用策略:
kubectl apply -f 01-default-deny.yaml
4. 验证拒绝效果
再次从 frontend 访问 backend (现在应该被阻止):
kubectl exec -n security-demo deployment/frontend -- wget -T 2 -O - $BACKEND_IP:80
# 预计输出: wget: download timed out (连接超时)
5. 实现精确白名单放行
现在,我们只允许拥有标签 app: frontend 的 Pod 访问 backend Pod 的 80 端口。
# 02-whitelist-frontend.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-access
namespace: security-demo
spec:
podSelector:
matchLabels:
app: backend # 目标 Pod (backend)
policyTypes:
- Ingress
rules:
- from:
- podSelector:
matchLabels:
app: frontend # 允许来自具有此标签的 Pod 的流量
ports:
- protocol: TCP
port: 80
注意: Network Policy 是累加的。应用此策略后,它会与步骤 3 中的默认拒绝策略合并:先拒绝所有,再根据新策略允许特定流量。
应用策略:
kubectl apply -f 02-whitelist-frontend.yaml
6. 最终验证
测试 1: 白名单访问 (Frontend -> Backend)
kubectl exec -n security-demo deployment/frontend -- wget -T 2 -O - $BACKEND_IP:80
# 结果: 成功。输出 'Backend Service Running'
测试 2: 非白名单访问 (Unauthorized Pod -> Backend)
kubectl exec -n security-demo pod/unauthorized-client -- wget -T 2 -O - $BACKEND_IP:80
# 结果: 失败。连接超时,因为该 Pod 不具备 'app: frontend' 标签,被默认拒绝策略阻止。
总结
通过先应用默认拒绝策略(隐式或显式),然后精确定义 from 或 to 规则,我们成功地在 Kubernetes 中实现了基于 Pod 标签的白名单访问控制。这是保护微服务边界,确保只有授权组件能够互相通信的强大安全实践。
汤不热吧