Kubernetes NetworkPolicy 完全指南:从入门到实战
字数:
893
·
阅读:
5 分钟
·
访问:
-
前言
在 Kubernetes 集群中,默认情况下所有 Pod 之间都可以自由通信。但在生产环境中,我们往往需要对网络流量进行精细化控制,这时就需要用到 NetworkPolicy。本文将从基础概念到实际应用,全面介绍 NetworkPolicy 的使用方法。
什么是 NetworkPolicy?
NetworkPolicy 是 Kubernetes 的一种资源对象,用于定义 Pod 之间的网络访问规则。它类似于传统网络中的防火墙规则,可以控制:
- 入站流量(Ingress):哪些来源可以访问目标 Pod
 - 出站流量(Egress):目标 Pod 可以访问哪些目的地
 
前置条件
在开始之前,确保您的集群满足以下条件:
1. CNI 插件支持
NetworkPolicy 需要 CNI 插件的支持,常见支持的插件包括:
- Calico(推荐)
 - Cilium
 - Weave Net
 - Antrea
 
⚠️ 注意:Flannel 默认不支持 NetworkPolicy
2. 验证支持情况
# 检查当前 CNI 插件
kubectl get pods -n kube-system | grep -E "(calico|cilium|weave|antrea)"
# 创建测试策略验证支持
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-policy
  namespace: default
spec:
  podSelector: {}
  policyTypes: []
EOF
# 如果支持,会输出 "networkpolicy/test-policy created"
kubectl get networkpolicies -n default
NetworkPolicy 基础语法
完整结构示例
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: example-policy
  namespace: production
spec:
  # 选择应用此策略的 Pod
  podSelector:
    matchLabels:
      app: web-server
  
  # 策略类型:Ingress(入站)和/或 Egress(出站)
  policyTypes:
    - Ingress
    - Egress
  
  # 入站规则
  ingress:
    - from:
        - podSelector:
            matchLabels:
              role: frontend
        - namespaceSelector:
            matchLabels:
              name: allowed-namespace
        - ipBlock:
            cidr: 192.168.1.0/24
            except:
              - 192.168.1.100/32
      ports:
        - protocol: TCP
          port: 8080
  
  # 出站规则
  egress:
    - to:
        - podSelector:
            matchLabels:
              role: database
      ports:
        - protocol: TCP
          port: 5432
关键字段解析
| 字段 | 说明 | 
|---|---|
podSelector | 选择应用此策略的目标 Pod | 
policyTypes | 策略类型,可以是 Ingress、Egress 或两者 | 
ingress.from | 定义允许的入站来源 | 
egress.to | 定义允许的出站目标 | 
ports | 指定允许的端口和协议 | 
实战案例
案例 1:拒绝所有流量(默认拒绝策略)
首先创建一个拒绝所有流量的基础策略:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all
  namespace: production
spec:
  podSelector: {}  # 选择命名空间中的所有 Pod
  policyTypes:
    - Ingress
    - Egress
  # 没有定义 ingress 和 egress 规则,因此拒绝所有流量
案例 2:Web 应用三层架构
创建一个典型的 Web 应用场景:Frontend → Backend → Database
环境准备
# 创建命名空间和标签
kubectl create namespace webapp
kubectl label namespace webapp name=webapp
# 部署应用(示例)
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
  namespace: webapp
spec:
  replicas: 2
  selector:
    matchLabels:
      app: frontend
      tier: web
  template:
    metadata:
      labels:
        app: frontend
        tier: web
    spec:
      containers:
      - name: frontend
        image: nginx:alpine
        ports:
        - containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
  namespace: webapp
spec:
  replicas: 2
  selector:
    matchLabels:
      app: backend
      tier: api
  template:
    metadata:
      labels:
        app: backend
        tier: api
    spec:
      containers:
      - name: backend
        image: nginx:alpine
        ports:
        - containerPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: database
  namespace: webapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: database
      tier: db
  template:
    metadata:
      labels:
        app: database
        tier: db
    spec:
      containers:
      - name: database
        image: postgres:13
        ports:
        - containerPort: 5432
EOF
网络策略配置
1. Frontend 策略
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: frontend-policy
  namespace: webapp
spec:
  podSelector:
    matchLabels:
      tier: web
  policyTypes:
    - Ingress
    - Egress
  ingress:
    # 允许来自集群外部的流量(通过 Ingress Controller)
    - ports:
      - protocol: TCP
        port: 80
  egress:
    # 允许访问 Backend
    - to:
      - podSelector:
          matchLabels:
            tier: api
      ports:
      - protocol: TCP
        port: 8080
    # 允许 DNS 解析
    - to: []
      ports:
      - protocol: UDP
        port: 53
2. Backend 策略
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: backend-policy
  namespace: webapp
spec:
  podSelector:
    matchLabels:
      tier: api
  policyTypes:
    - Ingress
    - Egress
  ingress:
    # 只允许来自 Frontend 的流量
    - from:
      - podSelector:
          matchLabels:
            tier: web
      ports:
      - protocol: TCP
        port: 8080
  egress:
    # 允许访问 Database
    - to:
      - podSelector:
          matchLabels:
            tier: db
      ports:
      - protocol: TCP
        port: 5432
    # 允许 DNS 解析
    - to: []
      ports:
      - protocol: UDP
        port: 53
3. Database 策略
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database-policy
  namespace: webapp
spec:
  podSelector:
    matchLabels:
      tier: db
  policyTypes:
    - Ingress
    - Egress
  ingress:
    # 只允许来自 Backend 的流量
    - from:
      - podSelector:
          matchLabels:
            tier: api
      ports:
      - protocol: TCP
        port: 5432
  egress:
    # 允许 DNS 解析(如需要)
    - to: []
      ports:
      - protocol: UDP
        port: 53
案例 3:跨命名空间访问控制
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: cross-namespace-policy
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: api-server
  policyTypes:
    - Ingress
  ingress:
    # 允许来自 staging 命名空间的特定 Pod
    - from:
      - namespaceSelector:
          matchLabels:
            name: staging
        podSelector:
          matchLabels:
            app: test-client
      ports:
      - protocol: TCP
        port: 8080
    # 允许来自相同命名空间的所有 Pod
    - from:
      - podSelector: {}
      ports:
      - protocol: TCP
        port: 8080
案例 4:基于 IP 的访问控制
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: ip-allowlist-policy
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: admin-panel
  policyTypes:
    - Ingress
  ingress:
    # 只允许特定 IP 段的流量
    - from:
      - ipBlock:
          cidr: 10.0.0.0/8
          except:
            - 10.0.1.0/24  # 排除特定子网
      - ipBlock:
          cidr: 192.168.1.0/24
      ports:
      - protocol: TCP
        port: 443
测试和验证
1. 创建测试 Pod
# 创建测试客户端
kubectl run test-client --image=busybox -it --rm --restart=Never -- sh
# 在 Pod 内测试连接
wget -qO- --timeout=2 http://frontend-service.webapp.svc.cluster.local
2. 使用 netshoot 进行网络调试
kubectl run netshoot --image=nicolaka/netshoot -it --rm --restart=Never
3. 查看策略状态
# 列出所有网络策略
kubectl get networkpolicy -A
# 查看策略详情
kubectl describe networkpolicy frontend-policy -n webapp
# 查看 Pod 标签
kubectl get pods -n webapp --show-labels
常见问题和最佳实践
问题 1:策略不生效
可能原因:
- CNI 插件不支持 NetworkPolicy
 - Pod 标签选择器错误
 - 策略应用到错误的命名空间
 
解决方法:
# 检查 CNI 插件
kubectl get pods -n kube-system | grep -E "(calico|cilium)"
# 验证标签选择器
kubectl get pods --show-labels -n your-namespace
问题 2:DNS 解析失败
NetworkPolicy 可能会阻止 DNS 查询,需要显式允许:
egress:
  - to: []
    ports:
    - protocol: UDP
      port: 53
    - protocol: TCP
      port: 53
问题 3:服务发现问题
确保允许访问 Kubernetes API Server:
egress:
  - to:
    - ipBlock:
        cidr: 10.96.0.1/32  # API Server IP
    ports:
    - protocol: TCP
      port: 443
最佳实践
- 从拒绝开始:先创建 
deny-all策略,再逐步添加允许规则 - 最小权限原则:只开放必需的端口和协议
 - 使用标签管理:合理设计 Pod 和 Namespace 标签
 - 分层设计:按应用层次设计网络策略
 - 文档化:为每个策略添加清晰的注释说明
 - 定期审计:定期检查和更新网络策略
 
高级功能
1. 命名端口支持
egress:
  - to:
    - podSelector:
        matchLabels:
          app: database
    ports:
    - protocol: TCP
      port: db-port  # 使用命名端口
2. 组合选择器
ingress:
  - from:
    # 必须同时满足命名空间和 Pod 标签条件
    - namespaceSelector:
        matchLabels:
          name: production
      podSelector:
        matchLabels:
          role: api-client
3. 空规则的含义
# 允许所有入站流量
ingress:
  - {}
# 允许所有出站流量  
egress:
  - {}
监控和日志
使用 Calico 查看策略日志
# 启用 Calico 日志记录
kubectl patch felixconfiguration default --type merge --patch '{"spec":{"flowLogsEnableNetworkPolicy":true}}'
# 查看拒绝的连接
kubectl logs -n calico-system -l k8s-app=calico-node | grep "calico-packet"
使用 Cilium Hubble
# 安装 Hubble CLI
hubble observe --type drop
# 查看网络流量
hubble observe --namespace webapp
总结
NetworkPolicy 是 Kubernetes 中实现网络安全的重要工具。通过合理设计和应用网络策略,我们可以:
- 实现零信任网络架构
 - 符合安全合规要求
 - 减少攻击面
 - 提高系统安全性
 
掌握 NetworkPolicy 的使用,是构建安全 Kubernetes 集群的必备技能。在实际应用中,建议从简单的场景开始,逐步构建复杂的网络安全策略。