Skip to content

Network Policies(网络策略)

支持的版本: Kubernetes 1.31, 1.32, 1.33 最后更新: July 3, 2026

Kubernetes Network Policies 是控制 Pod(容器组)之间流量的防火墙规则。本文档涵盖从基础 NetworkPolicy 到 Cilium 和 Calico 扩展的全部内容。

目录

  1. Network Policy 概述
  2. Kubernetes NetworkPolicy 规范
  3. 默认拒绝策略
  4. 策略顺序与评估
  5. Cilium Network Policy 扩展
  6. Calico Network Policy 扩展
  7. 设计模式
  8. 测试 Network Policies
  9. EKS 注意事项
  10. 可视化工具

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(出站)分别控制
依赖 CNICNI plugin 必须支持 NetworkPolicy

CNI NetworkPolicy 支持

CNI基础 NetworkPolicy扩展L7 Policy
CiliumCiliumNetworkPolicy, CiliumClusterwideNetworkPolicy
CalicoGlobalNetworkPolicy, NetworkSet✓(Enterprise)
Weave Net有限
Flannel
Amazon VPC CNI✗(需要单独安装)Security Groups for Pods

Kubernetes NetworkPolicy 规范

基本结构

yaml
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: 5432

podSelector

选择策略适用的 Pods。

yaml
# 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:
          - development

namespaceSelector

选择其他 namespaces 中的 Pods。

yaml
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

注意: 同时使用 namespaceSelectorpodSelector 时,需要区分 AND 与 OR:

yaml
# 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: frontend

ipBlock

允许或阻止特定 IP 范围。

yaml
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: 443

ports

指定允许的端口和协议。

yaml
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

阻止所有入站流量的默认策略:

yaml
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

阻止所有出站流量的默认策略:

yaml
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)

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: production
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress

允许 DNS 的默认拒绝

在阻止 egress 时允许 DNS 查询的常见模式:

yaml
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: 53

Zero Trust Architecture 默认策略

yaml
---
# 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 时,所有策略规则会合并(并集):

yaml
---
# 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。

yaml
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

yaml
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

yaml
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

yaml
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: TCP

CiliumClusterwideNetworkPolicy

集群范围策略:

yaml
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: UDP

Cilium 基于实体的策略

yaml
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 server

Calico Network Policy 扩展

Calico NetworkPolicy

yaml
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:
          - 5432

GlobalNetworkPolicy

适用于整个集群的 Calico 策略:

yaml
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:
          - 53

NetworkSet

定义可复用的 IP 集合:

yaml
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:

yaml
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 支持的分层策略:

yaml
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

设计模式

微分段

分别隔离每个服务:

yaml
---
# 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: 443

Namespace 隔离

yaml
---
# 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"

数据库保护

yaml
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: 53

3-Tier Architecture 策略

yaml
---
# 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 测试

bash
# 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 测试

bash
# 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 8080

Cilium 连接性测试

bash
# 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

自动化测试脚本

bash
#!/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=0

EKS 注意事项

Amazon VPC CNI 与 NetworkPolicy

Amazon VPC CNI 默认不支持 NetworkPolicy。若要使用 NetworkPolicy,需要额外配置:

bash
# 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.yaml

EKS 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 上使用
  • 无额外费用
yaml
# 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
yaml
# 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: 443

Security Groups for Pods

在 EKS 中,你可以直接将 Security Groups 应用于 Pods:

yaml
# 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:15

Security Group 示例配置:

hcl
# 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 结合

yaml
# 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
hcl
# 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

bash
# 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 的策略编辑器:

bash
# 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:80

Cilium Policy Verdict Check

bash
# 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:

bash
# Access Calico Enterprise dashboard
kubectl port-forward -n calico-system svc/cnx-manager 9443:443

Network Policy 可视化工具

bash
# 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 进行安全测试

bash
# Cluster security scan
kubectl run kube-hunter --image=aquasec/kube-hunter --restart=Never -- --pod

# Check results
kubectl logs kube-hunter

最佳实践

1. 应用默认拒绝策略

yaml
# Apply to all production namespaces
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: production
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress

2. 最小权限原则

仅显式允许必需流量:

yaml
# 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: TCP

3. 记录策略文档

yaml
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. 定期策略审计

bash
#!/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 通信的核心安全机制:

  1. 基础 NetworkPolicy: namespace 作用域,支持 podSelector/namespaceSelector/ipBlock
  2. Cilium 扩展: L7 policies、基于 DNS FQDN 的 policies、集群范围 policies
  3. Calico 扩展: GlobalNetworkPolicy、NetworkSet、基于 Tier 的 policies
  4. EKS 注意事项: 启用 VPC CNI NetworkPolicy、Security Groups for Pods、ClusterNetworkPolicy 和基于 DNS (FQDN) 的 egress 控制

建议

  • 对所有生产 namespaces 应用默认拒绝策略
  • 按照最小权限原则仅允许必需流量
  • 定期进行策略审计和测试
  • 当需要 L7 policies 时考虑使用 Cilium

参考资料