Skip to content

Kubernetes-NetworkPolicy

Kubernetes NetworkPolicy 是 Kubernetes 中用于控制 Pod 间网络通信的核心安全机制,它通过声明式规则实现精细的网络流量控制。

核心概念与工作原理

定义与功能

NetworkPolicy 是 Kubernetes 中定义网络流量规则的资源对象,它能够在 IP 地址或端口级别(OSI 第 3 层或第 4 层)精细控制 Pod 之间的网络通信。

  • 流量控制:限制哪些 Pod 允许与其他 Pod 通信,或者限制外部访问 Pod
  • 增强安全性:通过定义网络策略,减少潜在的攻击面
  • 多租户支持:在多租户环境中隔离不同租户的流量

默认行为与隔离模型

Kubernetes 网络策略遵循特定的默认行为和隔离原则:

  • 默认允许:未定义任何策略时,所有 Pod 可自由通信(取决于网络插件实现)

  • 默认拒绝:一旦为 Pod 创建 NetworkPolicy:

    • 若定义了 policyTypes: ["Ingress"] 且无 ingress 规则,则所有入站流量被拒绝
    • 若定义了 policyTypes: ["Egress"] 且无 egress 规则,则所有出站流量被拒绝
  • 叠加原则:多个策略的效果是叠加的,不会互相覆盖

  • 双向验证:连接必须同时满足源 Pod 的出口策略和目标 Pod 的入口策略

实现机制与前提条件

  • 网络插件要求:集群必须使用支持 NetworkPolicy 的 CNI 插件(如 Calico、Cilium、Weave Net 等),Flannel 不支持此功能

  • 策略执行流程

    • 标签匹配:根据 podSelector 确定策略作用的 Pod

    • 流量分类:区分入站(进入目标 Pod)和出站(从目标 Pod 发出)流量

    • 规则评估:按顺序匹配 ingress 或 egress 规则,首个匹配规则决定流量命运

资源清单结构

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: my-app-network-policy  # 策略名称
  namespace: production        # 应用的目标命名空间

spec:
  podSelector:
    matchLabels:
      app: my-app              # 选择要应用策略的Pod标签
  
  policyTypes:
  - Ingress                    # 控制入站流量
  - Egress                     # 控制出站流量(可选)

  ingress:
  - from:                      # 允许的入站流量来源
    - podSelector:             # 来自同一命名空间的特定Pod
        matchLabels:
          role: frontend
    - namespaceSelector:       # 来自特定命名空间
        matchLabels:
          env: staging
    - ipBlock:                 # 来自特定IP段
        cidr: 192.168.1.0/24
        except:                # 排除的IP
        - 192.168.1.100/32
    
    ports:                     # 允许的端口和协议
    - protocol: TCP
      port: 80
    - protocol: UDP
      port: 53

  egress:                      # 出站规则(可选)
  - to:                        # 允许的出站目标
    - ipBlock:
        cidr: 10.0.0.0/8
    ports:
    - protocol: TCP
      port: 443

NetworkPolicy 规则类型

策略方向类型

  1. 入口隔离(Ingress Isolation):控制哪些流量可以进入 Pod
    • 默认情况下,Pod 允许所有入站连接
    • 当有 NetworkPolicy 选择 Pod 并包含 "Ingress" policyType 时,Pod 被隔离为入口
  2. 出口隔离(Egress Isolation):控制 Pod 可以发出哪些流量
    • 默认情况下,Pod 允许所有出站连接
    • 当有 NetworkPolicy 选择 Pod 并包含 "Egress" policyType 时,Pod 被隔离为出口

选择器类型

Pod 选择器

匹配当前命名空间中的特定 Pod

yaml
podSelector:
  matchLabels:
    app: backend

命名空间选择器

匹配特定命名空间中的所有 Pod

yaml
namespaceSelector:
  matchLabels:
    env: production

IP 块选择器

匹配特定的 CIDR 范围

yaml
ipBlock:
  cidr: 192.168.1.0/24

组合选择器

同时使用命名空间和 Pod 选择器

yaml
- namespaceSelector:
    matchLabels:
      user: alice
  podSelector:
    matchLabels:
      role: client

经典案例

NetworkPolicy 在 Kubernetes 集群中有多种应用场景,以下是生产环境中常见的用例和对应配置。

默认网络隔离策略

场景:实现集群级别的默认拒绝策略,然后逐步开放必要通信

yaml
# 拒绝所有入站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
spec:
  podSelector: {}
  policyTypes:
  - Ingress

# 拒绝所有出站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-egress
spec:
  podSelector: {}
  policyTypes:
  - Egress

# 允许所有入站流量(恢复默认)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-ingress
spec:
  podSelector: {}
  ingress:
  - {}
  policyTypes:
  - Ingress

微服务间通信控制

场景:在微服务架构中限制服务间的访问权限

yaml
# 只允许前端访问后端服务
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
spec:
  podSelector:
    matchLabels:
      app: backend
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - protocol: TCP
      port: 80

# 允许后端访问数据库
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-backend-to-db
spec:
  podSelector:
    matchLabels:
      app: database
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: backend
    ports:
    - protocol: TCP
      port: 3306

多租户环境隔离

场景:在共享集群中隔离不同团队或环境(如 dev/prod)

yaml
# 禁止开发环境访问生产环境
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-dev-to-prod
  namespace: prod
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          environment: dev

敏感服务保护

场景:对数据库、密钥管理等敏感服务进行严格隔离

yaml
# 只允许特定应用访问数据库
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: protect-db
spec:
  podSelector:
    matchLabels:
      role: database
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: payment
    ports:
    - protocol: TCP
      port: 5432

出站流量控制

场景:限制 Pod 只能访问特定的外部服务或网络

yaml
# 限制Pod只能访问特定CIDR
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: restrict-egress
spec:
  podSelector:
    matchLabels:
      app: external-service
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 443

跨命名空间通信

场景:控制不同命名空间间的 Pod 通信

yaml
# 允许monitoring命名空间访问app命名空间的应用
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-monitoring-to-app
  namespace: app
spec:
  podSelector:
    matchLabels:
      app: myapp
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: monitoring