Network Policies(网络策略)
支持的版本: Kubernetes 1.31, 1.32, 1.33 最后更新: July 3, 2026
Kubernetes Network Policies 是控制 Pod(容器组)之间流量的防火墙规则。本文档涵盖从基础 NetworkPolicy 到 Cilium 和 Calico 扩展的全部内容。
目录
- Network Policy 概述
- Kubernetes NetworkPolicy 规范
- 默认拒绝策略
- 策略顺序与评估
- Cilium Network Policy 扩展
- Calico Network Policy 扩展
- 设计模式
- 测试 Network Policies
- EKS 注意事项
- 可视化工具
Network Policy 概述
什么是 Network Policy?
Network Policies 在 Kubernetes 中充当 Pod 级防火墙。默认情况下,Kubernetes Pods 可以与所有其他 Pods 自由通信,但 Network Policies 允许你限制这种流量。
┌─────────────────────────────────────────────────────────────────────────┐
│ No Network Policy (Default State) │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Pod A │◀──────▶│ Pod B │◀──────▶│ Pod C │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ ▲ ▲ ▲ │
│ │ │ │ │
│ └──────────────────┴──────────────────┘ │
│ Free communication between all Pods │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ With Network Policy Applied │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Pod A │───────▶│ Pod B │ │ Pod C │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ ▲ │
│ │ Allowed │
│ ┌────┴────┐ │
│ │Controlled│ │
│ │by Policy │ │
│ └─────────┘ │
└─────────────────────────────────────────────────────────────────────────┘Network Policy 特性
| 属性 | 描述 |
|---|---|
| Namespace 作用域 | NetworkPolicy 应用于 namespace 内的资源 |
| 累加式 | 当存在多个策略时,所有策略的并集生效 |
| 选择性应用 | 通过 podSelector 指定目标 Pods |
| 方向性控制 | 对 Ingress(入站)和 Egress(出站)分别控制 |
| 依赖 CNI | CNI plugin 必须支持 NetworkPolicy |
CNI NetworkPolicy 支持
| CNI | 基础 NetworkPolicy | 扩展 | L7 Policy |
|---|---|---|---|
| Cilium | ✓ | CiliumNetworkPolicy, CiliumClusterwideNetworkPolicy | ✓ |
| Calico | ✓ | GlobalNetworkPolicy, NetworkSet | ✓(Enterprise) |
| Weave Net | ✓ | 有限 | ✗ |
| Flannel | ✗ | ✗ | ✗ |
| Amazon VPC CNI | ✗(需要单独安装) | Security Groups for Pods | ✗ |
Kubernetes NetworkPolicy 规范
基本结构
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: example-policy
namespace: default
spec:
# Select Pods to apply policy
podSelector:
matchLabels:
app: web
# Policy types (auto-inferred if omitted)
policyTypes:
- Ingress
- Egress
# Ingress rules (inbound traffic)
ingress:
- from:
- podSelector:
matchLabels:
role: frontend
- namespaceSelector:
matchLabels:
project: myproject
- ipBlock:
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24
ports:
- protocol: TCP
port: 80
- protocol: TCP
port: 443
# Egress rules (outbound traffic)
egress:
- to:
- podSelector:
matchLabels:
role: database
ports:
- protocol: TCP
port: 5432podSelector
选择策略适用的 Pods。
# Apply to Pods with specific labels
spec:
podSelector:
matchLabels:
app: api
version: v1
# Apply to all Pods (empty selector)
spec:
podSelector: {}
# Using matchExpressions
spec:
podSelector:
matchExpressions:
- key: app
operator: In
values:
- api
- web
- key: environment
operator: NotIn
values:
- developmentnamespaceSelector
选择其他 namespaces 中的 Pods。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-monitoring
namespace: production
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
ingress:
- from:
# Allow all Pods from monitoring namespace
- namespaceSelector:
matchLabels:
name: monitoring
# Allow specific Pods from production namespace
- namespaceSelector:
matchLabels:
name: production
podSelector:
matchLabels:
role: frontend注意: 同时使用 namespaceSelector 和 podSelector 时,需要区分 AND 与 OR:
# OR condition (two separate rules)
ingress:
- from:
- namespaceSelector: # Rule 1
matchLabels:
name: team-a
- podSelector: # Rule 2
matchLabels:
role: frontend
# AND condition (single rule)
ingress:
- from:
- namespaceSelector: # Both conditions must be met
matchLabels:
name: team-a
podSelector:
matchLabels:
role: frontendipBlock
允许或阻止特定 IP 范围。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-external-traffic
namespace: default
spec:
podSelector:
matchLabels:
app: public-api
policyTypes:
- Ingress
- Egress
ingress:
- from:
# Allow external load balancer IP range
- ipBlock:
cidr: 10.0.0.0/8
# Allow specific external IP
- ipBlock:
cidr: 203.0.113.0/24
egress:
- to:
# Allow external API server access
- ipBlock:
cidr: 0.0.0.0/0
except:
- 10.0.0.0/8 # Exclude internal networks
- 172.16.0.0/12
- 192.168.0.0/16
ports:
- protocol: TCP
port: 443ports
指定允许的端口和协议。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: port-specific-policy
namespace: default
spec:
podSelector:
matchLabels:
app: web
policyTypes:
- Ingress
ingress:
- ports:
# Specific ports
- protocol: TCP
port: 80
- protocol: TCP
port: 443
# Port range (Kubernetes 1.25+)
- protocol: TCP
port: 8000
endPort: 8080
# Named port
- protocol: TCP
port: http默认拒绝策略
默认拒绝 Ingress
阻止所有入站流量的默认策略:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: production
spec:
podSelector: {} # Apply to all Pods
policyTypes:
- Ingress
# No ingress rules = block all inbound traffic默认拒绝 Egress
阻止所有出站流量的默认策略:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-egress
namespace: production
spec:
podSelector: {}
policyTypes:
- Egress
# No egress rules = block all outbound traffic全部拒绝(Ingress + Egress)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress允许 DNS 的默认拒绝
在阻止 egress 时允许 DNS 查询的常见模式:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-egress-allow-dns
namespace: production
spec:
podSelector: {}
policyTypes:
- Egress
egress:
# Allow kube-dns/CoreDNS access
- to:
- namespaceSelector: {}
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53Zero Trust Architecture 默认策略
---
# 1. Default deny all traffic
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: zero-trust-default
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
# 2. Allow DNS only
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
namespace: production
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
---
# 3. Explicitly allow only required communication
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-api
namespace: production
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080策略顺序与评估
策略评估规则
NetworkPolicy 按照以下规则进行评估:
┌─────────────────────────────────────────────────────────────────┐
│ NetworkPolicy Evaluation Flow │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. Are there policies that apply to the Pod? │
│ │ │
│ ├─ No → Allow all traffic (default behavior) │
│ │ │
│ └─ Yes → Start policy evaluation │
│ │ │
│ ▼ │
│ 2. Is there a policy for this direction (Ingress/Egress)? │
│ │ │
│ ├─ No → Allow traffic in that direction │
│ │ │
│ └─ Yes → Start rule matching │
│ │ │
│ ▼ │
│ 3. Does traffic match one or more rules? │
│ │ │
│ ├─ Matched → Allow traffic │
│ │ │
│ └─ Not matched → Block traffic │
│ │
└─────────────────────────────────────────────────────────────────┘组合多个策略
当多个 NetworkPolicies 应用于同一个 Pod 时,所有策略规则会合并(并集):
---
# Policy 1: Allow traffic from frontend
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend
namespace: production
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
---
# Policy 2: Allow traffic from monitoring
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-monitoring
namespace: production
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: monitoring
ports:
- protocol: TCP
port: 8080
- protocol: TCP
port: 9090结果: app: api Pod 同时允许 frontend Pod 访问 8080,以及 monitoring namespace 访问 8080 和 9090。
策略评估顺序
NetworkPolicy 没有优先级概念。所有策略都被同等对待:
┌─────────────────────────────────────────────────────────────────┐
│ │
│ Policy A Policy B Policy C │
│ (allow X) (allow Y) (allow Z) │
│ │ │ │ │
│ └───────────┼───────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ Union │ │
│ │ (X OR Y OR Z) │ │
│ └───────────────┘ │
│ │ │
│ ▼ │
│ Final allowed traffic: │
│ X, Y, Z all allowed │
│ │
└─────────────────────────────────────────────────────────────────┘Cilium Network Policy 扩展
CiliumNetworkPolicy
Cilium 使用更强大的功能扩展了基础 NetworkPolicy。
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: cilium-l7-policy
namespace: production
spec:
# Endpoint selection
endpointSelector:
matchLabels:
app: api
# L3/L4 rules (similar to basic NetworkPolicy)
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8080"
protocol: TCP
# L7 rules (Cilium extension)
rules:
http:
- method: GET
path: "/api/v1/.*"
- method: POST
path: "/api/v1/users"
headers:
- 'Content-Type: application/json'L7 HTTP Policy
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: http-api-policy
namespace: production
spec:
endpointSelector:
matchLabels:
app: api-server
ingress:
- fromEndpoints:
- matchLabels:
app: web-frontend
toPorts:
- ports:
- port: "8080"
protocol: TCP
rules:
http:
# Allow only GET requests
- method: GET
path: "/api/v1/products"
# Allow specific path patterns
- method: GET
path: "/api/v1/products/[0-9]+"
# POST only allowed with specific headers
- method: POST
path: "/api/v1/orders"
headers:
- "X-API-Key: .*"
- "Content-Type: application/json"
# PUT/DELETE only for admin
- method: "PUT|DELETE"
path: "/api/v1/.*"
headers:
- "X-User-Role: admin"L7 Kafka Policy
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: kafka-policy
namespace: data
spec:
endpointSelector:
matchLabels:
app: kafka
ingress:
- fromEndpoints:
- matchLabels:
app: producer
toPorts:
- ports:
- port: "9092"
protocol: TCP
rules:
kafka:
# Allow produce only to specific topics
- role: produce
topic: "orders"
- role: produce
topic: "events"
- fromEndpoints:
- matchLabels:
app: consumer
toPorts:
- ports:
- port: "9092"
protocol: TCP
rules:
kafka:
# Allow consume only from specific topics
- role: consume
topic: "orders"
clientID: "order-processor-.*"L7 DNS Policy
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: dns-policy
namespace: production
spec:
endpointSelector:
matchLabels:
app: web
egress:
# Allow DNS lookups
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: UDP
rules:
dns:
# Allow only specific domain lookups
- matchPattern: "*.amazonaws.com"
- matchPattern: "api.example.com"
- matchName: "database.production.svc.cluster.local"
# Allow connections to looked up domains
- toFQDNs:
- matchPattern: "*.amazonaws.com"
- matchName: "api.example.com"
toPorts:
- ports:
- port: "443"
protocol: TCPCiliumClusterwideNetworkPolicy
集群范围策略:
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
name: cluster-default-deny
spec:
# Apply to all endpoints
endpointSelector: {}
ingress:
- fromEntities:
- cluster # Allow only internal cluster traffic
egress:
- toEntities:
- cluster
- world # Allow external traffic (if needed)
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
toPorts:
- ports:
- port: "53"
protocol: UDPCilium 基于实体的策略
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: entity-based-policy
namespace: production
spec:
endpointSelector:
matchLabels:
app: web
ingress:
- fromEntities:
- world # Outside cluster
- cluster # Inside cluster
egress:
- toEntities:
- world # Internet
toPorts:
- ports:
- port: "443"
protocol: TCP
- toEntities:
- host # Node itself
toPorts:
- ports:
- port: "10250" # kubelet
protocol: TCP
- toEntities:
- kube-apiserver # API serverCalico Network Policy 扩展
Calico NetworkPolicy
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
name: calico-policy
namespace: production
spec:
# Policy order (lower = evaluated first)
order: 100
selector: app == 'api'
types:
- Ingress
- Egress
ingress:
- action: Allow
protocol: TCP
source:
selector: app == 'frontend'
destination:
ports:
- 8080
egress:
- action: Allow
protocol: TCP
destination:
selector: app == 'database'
ports:
- 5432GlobalNetworkPolicy
适用于整个集群的 Calico 策略:
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: default-deny-all
spec:
# Full selector instead of namespace
selector: all()
order: 1000 # Low priority (other policies evaluated first)
types:
- Ingress
- Egress
# No rules = block all traffic
---
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: allow-dns
spec:
selector: all()
order: 100
types:
- Egress
egress:
- action: Allow
protocol: UDP
destination:
selector: k8s-app == 'kube-dns'
namespaceSelector: projectcalico.org/name == 'kube-system'
ports:
- 53
- action: Allow
protocol: TCP
destination:
selector: k8s-app == 'kube-dns'
namespaceSelector: projectcalico.org/name == 'kube-system'
ports:
- 53NetworkSet
定义可复用的 IP 集合:
apiVersion: projectcalico.org/v3
kind: NetworkSet
metadata:
name: external-apis
namespace: production
spec:
nets:
- 203.0.113.0/24 # External API servers
- 198.51.100.10/32 # Specific service
---
apiVersion: projectcalico.org/v3
kind: GlobalNetworkSet
metadata:
name: blocked-ips
spec:
nets:
- 192.0.2.0/24 # IP range to block
- 10.0.0.5/32 # Specific blocked IP使用 NetworkSet:
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
name: allow-external-apis
namespace: production
spec:
selector: app == 'web'
types:
- Egress
egress:
- action: Allow
destination:
selector: projectcalico.org/name == 'external-apis'
namespaceSelector: projectcalico.org/name == 'production'基于 Tier 的策略
Calico Enterprise 支持的分层策略:
apiVersion: projectcalico.org/v3
kind: Tier
metadata:
name: security
spec:
order: 100
---
apiVersion: projectcalico.org/v3
kind: Tier
metadata:
name: platform
spec:
order: 200
---
apiVersion: projectcalico.org/v3
kind: Tier
metadata:
name: application
spec:
order: 300
---
# Security Tier policy (evaluated first)
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: security.block-known-threats
spec:
tier: security
order: 100
selector: all()
types:
- Ingress
ingress:
- action: Deny
source:
selector: global(name == 'blocked-ips')
---
# Platform Tier policy
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: platform.allow-dns
spec:
tier: platform
order: 100
selector: all()
types:
- Egress
egress:
- action: Allow
protocol: UDP
destination:
ports:
- 53设计模式
微分段
分别隔离每个服务:
---
# 1. Namespace default deny
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
# 2. Allow DNS
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
namespace: production
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
---
# 3. Frontend -> API
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: frontend-to-api
namespace: production
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
---
# 4. API -> Database
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-to-database
namespace: production
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
---
# 5. API external access (if needed)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-external-access
namespace: production
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
ports:
- protocol: TCP
port: 443Namespace 隔离
---
# 1. Set namespace labels
apiVersion: v1
kind: Namespace
metadata:
name: team-a
labels:
team: team-a
environment: production
---
# 2. Allow communication only within same team
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-same-team
namespace: team-a
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
team: team-a
---
# 3. Allow access to specific services from other teams
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-shared-services
namespace: team-a
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
shared-services: "true"
podSelector:
matchLabels:
exposed: "true"数据库保护
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: database-protection
namespace: database
spec:
podSelector:
matchLabels:
app: postgresql
policyTypes:
- Ingress
- Egress
ingress:
# Allow access only from application
- from:
- namespaceSelector:
matchLabels:
environment: production
podSelector:
matchLabels:
database-access: "true"
ports:
- protocol: TCP
port: 5432
# Allow monitoring access
- from:
- namespaceSelector:
matchLabels:
name: monitoring
podSelector:
matchLabels:
app: prometheus
ports:
- protocol: TCP
port: 9187 # postgres_exporter
egress:
# Access other DB instances for replication
- to:
- podSelector:
matchLabels:
app: postgresql
ports:
- protocol: TCP
port: 5432
# DNS
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 533-Tier Architecture 策略
---
# Web Tier
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: web-tier-policy
namespace: production
spec:
podSelector:
matchLabels:
tier: web
policyTypes:
- Ingress
- Egress
ingress:
# Allow access from external (Ingress Controller)
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
ports:
- protocol: TCP
port: 80
egress:
# Communicate only with App Tier
- to:
- podSelector:
matchLabels:
tier: app
ports:
- protocol: TCP
port: 8080
# DNS
- to:
- namespaceSelector: {}
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
---
# App Tier
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: app-tier-policy
namespace: production
spec:
podSelector:
matchLabels:
tier: app
policyTypes:
- Ingress
- Egress
ingress:
# Allow access only from Web Tier
- from:
- podSelector:
matchLabels:
tier: web
ports:
- protocol: TCP
port: 8080
egress:
# Communicate only with Data Tier
- to:
- podSelector:
matchLabels:
tier: data
ports:
- protocol: TCP
port: 5432
- protocol: TCP
port: 6379
# DNS
- to:
- namespaceSelector: {}
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
---
# Data Tier
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: data-tier-policy
namespace: production
spec:
podSelector:
matchLabels:
tier: data
policyTypes:
- Ingress
- Egress
ingress:
# Allow access only from App Tier
- from:
- podSelector:
matchLabels:
tier: app
ports:
- protocol: TCP
port: 5432
- protocol: TCP
port: 6379
egress:
# Replication communication within same tier
- to:
- podSelector:
matchLabels:
tier: data测试 Network Policies
使用 netshoot 测试
# Deploy netshoot Pod
kubectl run netshoot --image=nicolaka/netshoot -it --rm -- /bin/bash
# Connection tests
curl -v http://api-service:8080/health
nc -zv database-service 5432
nslookup api-service.production.svc.cluster.local
# TCP connection test
curl --connect-timeout 5 http://target-service:8080使用 kubectl exec 测试
# Test connection from Pod to another service
kubectl exec -it frontend-pod -- curl -v http://api-service:8080
# DNS verification
kubectl exec -it frontend-pod -- nslookup api-service
# Port scan
kubectl exec -it frontend-pod -- nc -zv api-service 8080Cilium 连接性测试
# Run Cilium connectivity test
cilium connectivity test
# Run specific tests only
cilium connectivity test --test pod-to-pod
cilium connectivity test --test pod-to-service
# Policy tests
cilium connectivity test --test to-entities-world
cilium connectivity test --test to-cidr-external自动化测试脚本
#!/bin/bash
# network-policy-test.sh
echo "=== Network Policy Test Suite ==="
# Create test Pod
kubectl run test-pod --image=nicolaka/netshoot --restart=Never --labels="app=test" -- sleep 3600
# Wait for Pod to be ready
kubectl wait --for=condition=Ready pod/test-pod --timeout=60s
# Run test cases
run_test() {
local name=$1
local command=$2
local expected=$3
echo -n "Testing: $name... "
result=$(kubectl exec test-pod -- timeout 5 sh -c "$command" 2>&1)
if [[ "$expected" == "success" && $? -eq 0 ]]; then
echo "PASS"
elif [[ "$expected" == "fail" && $? -ne 0 ]]; then
echo "PASS (correctly blocked)"
else
echo "FAIL"
echo " Result: $result"
fi
}
# Test cases
run_test "DNS resolution" "nslookup kubernetes.default" "success"
run_test "API server access" "curl -k https://kubernetes.default/healthz" "success"
run_test "External access blocked" "curl -s --connect-timeout 3 http://example.com" "fail"
run_test "Database access" "nc -zv database-service 5432" "success"
# Cleanup
kubectl delete pod test-pod --force --grace-period=0EKS 注意事项
Amazon VPC CNI 与 NetworkPolicy
Amazon VPC CNI 默认不支持 NetworkPolicy。若要使用 NetworkPolicy,需要额外配置:
# Option 1: Enable VPC CNI NetworkPolicy support (v1.14.0+)
kubectl set env daemonset aws-node -n kube-system ENABLE_NETWORK_POLICY=true
# Check VPC CNI version
kubectl describe daemonset aws-node -n kube-system | grep Image
# Option 2: Install Calico policy engine separately
kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/master/config/master/calico-operator.yaml
kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/master/config/master/calico-crs.yamlEKS Enhanced Network Security Policies(2025 年 12 月)
发布: December 15, 2025 · 来源
EKS 在 namespace 作用域的 NetworkPolicy 之上新增了两项能力:
- ClusterNetworkPolicy: 一种新资源,允许你从中心位置在整个集群范围内应用一致的网络策略,而不是逐个 namespace 管理策略。
- 基于 DNS (FQDN) 的 egress 控制: 允许或阻止基于域名而不是目标 IP 的 egress 流量。对于 IP 经常变化的目标(例如 SaaS APIs 或外部 endpoints),这比基于 IP 的
ipBlock规则更可靠。
要求:
- 可用于新的 Kubernetes 1.29+ clusters
ClusterNetworkPolicy在 VPC CNI v1.21.0+ 上支持所有启动模式- 基于 DNS 的策略仅支持在 EKS Auto Mode 创建的 EC2 nodes 上使用
- 无额外费用
# ClusterNetworkPolicy example: cluster-wide default deny + allow DNS
apiVersion: policy.networking.k8s.io/v1alpha1
kind: ClusterNetworkPolicy
metadata:
name: cluster-default-deny
spec:
priority: 100
subject:
namespaces: {}
egress:
- name: allow-dns
action: Allow
to:
- namespaces:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53# DNS (FQDN)-based egress policy example: allow only specific SaaS domains
apiVersion: policy.networking.k8s.io/v1alpha1
kind: ClusterNetworkPolicy
metadata:
name: allow-saas-fqdn-egress
spec:
priority: 200
subject:
namespaces:
matchLabels:
team: payments
egress:
- name: allow-external-api
action: Allow
to:
- fqdns:
- "api.stripe.com"
- "*.datadoghq.com"
ports:
- protocol: TCP
port: 443Security Groups for Pods
在 EKS 中,你可以直接将 Security Groups 应用于 Pods:
# SecurityGroupPolicy definition
apiVersion: vpcresources.k8s.aws/v1beta1
kind: SecurityGroupPolicy
metadata:
name: database-sg-policy
namespace: production
spec:
podSelector:
matchLabels:
app: database
securityGroups:
groupIds:
- sg-0123456789abcdef0 # Database Security Group
---
# Pod automatically gets Security Group applied
apiVersion: v1
kind: Pod
metadata:
name: database-pod
namespace: production
labels:
app: database
spec:
containers:
- name: postgres
image: postgres:15Security Group 示例配置:
# Define Security Group with Terraform
resource "aws_security_group" "database_pods" {
name_prefix = "database-pods-"
vpc_id = module.vpc.vpc_id
ingress {
from_port = 5432
to_port = 5432
protocol = "tcp"
security_groups = [aws_security_group.app_pods.id]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}将 VPC 级控制与 NetworkPolicy 结合
# NetworkPolicy (Pod level)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: database-policy
namespace: production
spec:
podSelector:
matchLabels:
app: database
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
database-access: "true"
ports:
- protocol: TCP
port: 5432# Security Group (VPC level)
# Provides additional network isolation
resource "aws_security_group" "database_pods" {
# ... (see example above)
}
# NACL (Subnet level)
# Controls traffic between subnets
resource "aws_network_acl_rule" "database_subnet" {
network_acl_id = aws_network_acl.database.id
rule_number = 100
egress = false
protocol = "tcp"
rule_action = "allow"
cidr_block = "10.0.0.0/16"
from_port = 5432
to_port = 5432
}在 EKS 上使用 Cilium
# Remove VPC CNI (optional)
kubectl delete daemonset aws-node -n kube-system
# Install Cilium
helm repo add cilium https://helm.cilium.io/
helm install cilium cilium/cilium --version 1.15.0 \
--namespace kube-system \
--set eni.enabled=true \
--set ipam.mode=eni \
--set egressMasqueradeInterfaces=eth0 \
--set routingMode=native可视化工具
Cilium Network Policy Editor
Cilium 提供基于 Web 的策略编辑器:
# Enable Cilium Hubble UI
cilium hubble enable --ui
# Access Hubble UI
cilium hubble ui
# Or port forward
kubectl port-forward -n kube-system svc/hubble-ui 12000:80Cilium Policy Verdict Check
# Check real-time policy decisions
hubble observe --verdict DROPPED
hubble observe --verdict FORWARDED
# Check traffic for specific Pod
hubble observe --pod production/api-server
# Output in JSON format
hubble observe --output json | jq '.flow.verdict'Calico Enterprise UI
Calico Enterprise 提供策略可视化 UI:
# Access Calico Enterprise dashboard
kubectl port-forward -n calico-system svc/cnx-manager 9443:443Network Policy 可视化工具
# Install kubectl-np-viewer
kubectl krew install np-viewer
# Visualize policies
kubectl np-viewer -n production
# Check policies for specific Pod
kubectl np-viewer -n production --pod api-server使用 Kube-hunter 进行安全测试
# Cluster security scan
kubectl run kube-hunter --image=aquasec/kube-hunter --restart=Never -- --pod
# Check results
kubectl logs kube-hunter最佳实践
1. 应用默认拒绝策略
# Apply to all production namespaces
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress2. 最小权限原则
仅显式允许必需流量:
# Explicit and specific rules
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-minimal-access
spec:
podSelector:
matchLabels:
app: api
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- port: 8080
protocol: TCP3. 记录策略文档
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-ingress
namespace: production
annotations:
description: "Allow traffic from frontend to API on port 8080"
owner: "platform-team"
last-reviewed: "2026-02-21"
spec:
# ...4. 定期策略审计
#!/bin/bash
# audit-network-policies.sh
echo "=== Network Policy Audit ==="
# Find namespaces without policies
for ns in $(kubectl get namespaces -o jsonpath='{.items[*].metadata.name}'); do
policies=$(kubectl get networkpolicies -n "$ns" --no-headers 2>/dev/null | wc -l)
if [[ $policies -eq 0 ]]; then
echo "WARNING: No NetworkPolicy in namespace: $ns"
fi
done
# Check for default deny policies
for ns in $(kubectl get namespaces -o jsonpath='{.items[*].metadata.name}'); do
deny_policy=$(kubectl get networkpolicies -n "$ns" -o json | jq -r '.items[] | select(.spec.podSelector == {} and .spec.ingress == null) | .metadata.name')
if [[ -z "$deny_policy" ]]; then
echo "INFO: No default-deny policy in namespace: $ns"
fi
done总结
Kubernetes Network Policies 是控制集群内 Pod 通信的核心安全机制:
- 基础 NetworkPolicy: namespace 作用域,支持 podSelector/namespaceSelector/ipBlock
- Cilium 扩展: L7 policies、基于 DNS FQDN 的 policies、集群范围 policies
- Calico 扩展: GlobalNetworkPolicy、NetworkSet、基于 Tier 的 policies
- EKS 注意事项: 启用 VPC CNI NetworkPolicy、Security Groups for Pods、ClusterNetworkPolicy 和基于 DNS (FQDN) 的 egress 控制
建议
- 对所有生产 namespaces 应用默认拒绝策略
- 按照最小权限原则仅允许必需流量
- 定期进行策略审计和测试
- 当需要 L7 policies 时考虑使用 Cilium