> For the complete documentation index, see [llms.txt](https://atomoh.gitbook.io/kubernetes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://atomoh.gitbook.io/kubernetes/es/an-quan-yu-ce-le/04-network-policies.md).

# 网络策略

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

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

## 目录

1. [Network Policy 概述](#network-policy-overview)
2. [Kubernetes NetworkPolicy 规范](#kubernetes-networkpolicy-spec)
3. [默认拒绝策略](#default-deny-policies)
4. [策略顺序与评估](#policy-order-and-evaluation)
5. [Cilium Network Policy 扩展](#cilium-network-policy-extensions)
6. [Calico Network Policy 扩展](#calico-network-policy-extensions)
7. [设计模式](#design-patterns)
8. [测试 Network Policies](#testing-network-policies)
9. [EKS 注意事项](#eks-considerations)
10. [可视化工具](#visualization-tools)

***

## 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 规范

### 基本结构

```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
```

**注意：** 同时使用 `namespaceSelector` 和 `podSelector` 时，需要区分 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 · [来源](https://aws.amazon.com/about-aws/whats-new/2025/12/amazon-eks-enhanced-network-security-policies/)

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

***

## 参考资料

* [Kubernetes Network Policies 官方文档](https://kubernetes.io/docs/concepts/services-networking/network-policies/)
* [Cilium Network Policy 文档](https://docs.cilium.io/en/stable/security/policy/)
* [Calico Network Policy 文档](https://docs.tigera.io/calico/latest/network-policy/)
* [EKS 安全最佳实践 - 网络安全](https://aws.github.io/aws-eks-best-practices/security/docs/network/)
* [Amazon EKS Enhanced Network Security Policies (2025-12-15)](https://aws.amazon.com/about-aws/whats-new/2025/12/amazon-eks-enhanced-network-security-policies/)
