Skip to content

网络策略

概述

NetworkPolicy是Kubernetes中用于控制Pod之间网络流量的资源对象。它允许你定义细粒度的网络访问规则,实现Pod级别的网络隔离和安全控制。NetworkPolicy通过标签选择器来选择Pod,并定义允许的入站和出站流量规则。

NetworkPolicy核心功能

1. Pod网络隔离

  • 基于标签选择器隔离Pod
  • 控制入站流量(Ingress)
  • 控制出站流量(Egress)
  • 实现多租户网络隔离

2. 流量控制

  • 基于Pod标签的访问控制
  • 基于命名空间的访问控制
  • 基于IP地址段的访问控制
  • 基于端口的访问控制

3. 安全增强

  • 实现零信任网络模型
  • 限制横向移动攻击
  • 保护敏感应用
  • 满足合规要求

NetworkPolicy架构

┌─────────────────────────────────────────────────────────┐
│                    NetworkPolicy                         │
│  ┌──────────────────────────────────────────────────┐  │
│  │  Pod Selector: app=web                           │  │
│  │  Policy Types: Ingress, Egress                   │  │
│  └──────────────────────────────────────────────────┘  │
└────────────────────┬────────────────────────────────────┘

        ┌────────────┴────────────┐
        │                         │
        ▼                         ▼
┌───────────────┐         ┌──────────────┐
│    Ingress    │         │    Egress    │
│  (入站规则)   │         │  (出站规则)  │
└───────┬───────┘         └──────┬───────┘
        │                        │
        │                        │
        ▼                        ▼
┌────────────────┐      ┌────────────────┐
│  允许的来源     │      │  允许的目标     │
│  - Pod选择器   │      │  - Pod选择器   │
│  - 命名空间    │      │  - 命名空间    │
│  - IP地址段    │      │  - IP地址段    │
│  - 端口       │      │  - 端口       │
└────────────────┘      └────────────────┘
        │                        │
        │                        │
        ▼                        ▼
┌────────────────┐      ┌────────────────┐
│   受保护的Pod   │      │   受保护的Pod   │
│   (app=web)    │◄─────┤   (app=web)    │
└────────────────┘      └────────────────┘

NetworkPolicy配置详解

1. 基本NetworkPolicy

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: basic-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: web
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - protocol: TCP
      port: 80
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: database
    ports:
    - protocol: TCP
      port: 3306

2. 完整NetworkPolicy配置

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: complete-network-policy
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: api
      tier: backend
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: frontend
      podSelector:
        matchLabels:
          app: web
    - ipBlock:
        cidr: 192.168.1.0/24
        except:
        - 192.168.1.100/32
    - namespaceSelector:
        matchLabels:
          name: monitoring
    ports:
    - protocol: TCP
      port: 8080
    - protocol: TCP
      port: 8443
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: database
    ports:
    - protocol: TCP
      port: 3306
  - to:
    - namespaceSelector:
        matchLabels:
          name: external-services
    - ipBlock:
        cidr: 10.0.0.0/8
    ports:
    - protocol: TCP
      port: 443
  - to:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          k8s-app: kube-dns
    ports:
    - protocol: UDP
      port: 53

3. 默认拒绝所有流量

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

4. 默认拒绝入站流量

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

5. 默认拒绝出站流量

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

6. 允许所有流量

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

NetworkPolicy规则详解

1. Pod选择器

yaml
spec:
  podSelector:
    matchLabels:
      app: web
      tier: frontend
    matchExpressions:
    - key: environment
      operator: In
      values:
      - production
      - staging

2. 命名空间选择器

yaml
spec:
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: production
          environment: prod

3. IP地址段选择器

yaml
spec:
  ingress:
  - from:
    - ipBlock:
        cidr: 192.168.0.0/16
        except:
        - 192.168.1.0/24
        - 192.168.2.100/32

4. 组合选择器

yaml
spec:
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: production
      podSelector:
        matchLabels:
          app: frontend

5. 端口配置

yaml
spec:
  ingress:
  - ports:
    - protocol: TCP
      port: 80
      endPort: 8080
    - protocol: UDP
      port: 53

操作命令

创建和管理NetworkPolicy

bash
# 创建NetworkPolicy
kubectl apply -f network-policy.yaml

# 查看NetworkPolicy
kubectl get networkpolicy
kubectl get netpol

# 查看详细信息
kubectl describe networkpolicy <policy-name>

# 查看YAML格式
kubectl get networkpolicy <policy-name> -o yaml

# 删除NetworkPolicy
kubectl delete networkpolicy <policy-name>

# 删除所有NetworkPolicy
kubectl delete networkpolicy --all -n <namespace>

测试NetworkPolicy

bash
# 测试Pod间连接
kubectl run test --image=busybox --rm -it --restart=Never -- wget -O- http://<service-name>:<port>

# 测试特定Pod连接
kubectl exec -it <source-pod> -- wget -O- http://<target-service>:<port>

# 测试DNS解析
kubectl run test --image=busybox --rm -it --restart=Never -- nslookup kubernetes

# 测试外部连接
kubectl run test --image=curlimages/curl --rm -it --restart=Never -- curl http://example.com

调试NetworkPolicy

bash
# 查看NetworkPolicy日志
kubectl logs -n kube-system -l k8s-app=<network-plugin>

# 查看网络插件状态
kubectl get pods -n kube-system -l k8s-app=<network-plugin>

# 检查NetworkPolicy是否生效
kubectl describe networkpolicy <policy-name>

# 查看Pod标签
kubectl get pods --show-labels

# 查看命名空间标签
kubectl get namespace --show-labels

实践示例

示例1:多层应用网络隔离

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: frontend-policy
  namespace: production
spec:
  podSelector:
    matchLabels:
      tier: frontend
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: ingress-nginx
    ports:
    - protocol: TCP
      port: 8080
  egress:
  - to:
    - podSelector:
        matchLabels:
          tier: backend
    ports:
    - protocol: TCP
      port: 8080
  - to:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          k8s-app: kube-dns
    ports:
    - protocol: UDP
      port: 53
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: backend-policy
  namespace: production
spec:
  podSelector:
    matchLabels:
      tier: backend
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          tier: frontend
    ports:
    - protocol: TCP
      port: 8080
  egress:
  - to:
    - podSelector:
        matchLabels:
          tier: database
    ports:
    - protocol: TCP
      port: 3306
  - to:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          k8s-app: kube-dns
    ports:
    - protocol: UDP
      port: 53
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database-policy
  namespace: production
spec:
  podSelector:
    matchLabels:
      tier: database
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          tier: backend
    ports:
    - protocol: TCP
      port: 3306
  egress:
  - to:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          k8s-app: kube-dns
    ports:
    - protocol: UDP
      port: 53

示例2:命名空间隔离

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: namespace-isolation
  namespace: production
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: production
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          name: production
  - to:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          k8s-app: kube-dns
    ports:
    - protocol: UDP
      port: 53

示例3:允许外部访问特定服务

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-external-access
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: web
      expose: external
  policyTypes:
  - Ingress
  ingress:
  - from:
    - ipBlock:
        cidr: 0.0.0.0/0
        except:
        - 10.0.0.0/8
        - 192.168.0.0/16
    ports:
    - protocol: TCP
      port: 80
    - protocol: TCP
      port: 443

示例4:数据库访问控制

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database-access-control
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: mysql
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: production
      podSelector:
        matchLabels:
          tier: backend
    - namespaceSelector:
        matchLabels:
          name: staging
      podSelector:
        matchLabels:
          tier: backend
    ports:
    - protocol: TCP
      port: 3306
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: redis-access-control
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: redis
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: api
    - podSelector:
        matchLabels:
          app: web
    ports:
    - protocol: TCP
      port: 6379

示例5:监控和日志访问

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-monitoring
  namespace: production
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: monitoring
      podSelector:
        matchLabels:
          app: prometheus
    ports:
    - protocol: TCP
      port: 9090
    - protocol: TCP
      port: 8080
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-logging
  namespace: production
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          name: logging
      podSelector:
        matchLabels:
          app: elasticsearch
    ports:
    - protocol: TCP
      port: 9200
  - to:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          k8s-app: kube-dns
    ports:
    - protocol: UDP
      port: 53

示例6:多租户隔离

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tenant-a-isolation
  namespace: tenant-a
spec:
  podSelector:
    matchLabels:
      tenant: tenant-a
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          tenant: tenant-a
  egress:
  - to:
    - podSelector:
        matchLabels:
          tenant: tenant-a
  - to:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          k8s-app: kube-dns
    ports:
    - protocol: UDP
      port: 53
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tenant-b-isolation
  namespace: tenant-b
spec:
  podSelector:
    matchLabels:
      tenant: tenant-b
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          tenant: tenant-b
  egress:
  - to:
    - podSelector:
        matchLabels:
          tenant: tenant-b
  - to:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          k8s-app: kube-dns
    ports:
    - protocol: UDP
      port: 53

故障排查

常见问题

1. NetworkPolicy不生效

bash
# 检查网络插件是否支持NetworkPolicy
kubectl get pods -n kube-system -l k8s-app=<network-plugin>

# 检查NetworkPolicy是否创建
kubectl get networkpolicy -n <namespace>

# 检查NetworkPolicy配置
kubectl describe networkpolicy <policy-name> -n <namespace>

# 检查Pod标签
kubectl get pods -n <namespace> --show-labels

# 检查命名空间标签
kubectl get namespace --show-labels

# 查看网络插件日志
kubectl logs -n kube-system -l k8s-app=<network-plugin>

2. Pod无法访问

bash
# 检查NetworkPolicy规则
kubectl describe networkpolicy -n <namespace>

# 测试Pod连接
kubectl run test --image=busybox --rm -it --restart=Never -- wget -O- http://<service-name>:<port>

# 检查Pod标签是否匹配
kubectl get pods -n <namespace> -l <label-key>=<label-value>

# 检查命名空间标签
kubectl get namespace <namespace> --show-labels

# 临时删除NetworkPolicy测试
kubectl delete networkpolicy <policy-name> -n <namespace>

3. DNS解析失败

bash
# 检查DNS NetworkPolicy
kubectl get networkpolicy -n <namespace> -o yaml | grep -A 10 kube-dns

# 测试DNS解析
kubectl run test --image=busybox --rm -it --restart=Never -- nslookup kubernetes

# 检查DNS Pod标签
kubectl get pods -n kube-system -l k8s-app=kube-dns --show-labels

# 添加DNS允许规则
# 在NetworkPolicy的egress中添加:
# - to:
#   - namespaceSelector: {}
#     podSelector:
#       matchLabels:
#         k8s-app: kube-dns
#   ports:
#   - protocol: UDP
#     port: 53

4. 外部访问被阻止

bash
# 检查egress规则
kubectl describe networkpolicy <policy-name> -n <namespace>

# 测试外部连接
kubectl run test --image=curlimages/curl --rm -it --restart=Never -- curl http://example.com

# 检查IP地址段配置
kubectl get networkpolicy <policy-name> -n <namespace> -o yaml | grep ipBlock -A 5

# 添加外部访问规则
# 在NetworkPolicy的egress中添加:
# - to:
#   - ipBlock:
#       cidr: 0.0.0.0/0
#       except:
#       - 10.0.0.0/8
#       - 192.168.0.0/16

5. 跨命名空间访问失败

bash
# 检查命名空间标签
kubectl get namespace --show-labels

# 添加命名空间标签
kubectl label namespace <namespace> name=<namespace-name>

# 检查NetworkPolicy中的namespaceSelector
kubectl get networkpolicy <policy-name> -n <namespace> -o yaml | grep namespaceSelector -A 5

# 测试跨命名空间连接
kubectl exec -it <pod-name> -n <source-namespace> -- wget -O- http://<service-name>.<target-namespace>:<port>

6. 性能问题

bash
# 检查NetworkPolicy数量
kubectl get networkpolicy --all-namespaces | wc -l

# 检查NetworkPolicy复杂度
kubectl get networkpolicy -n <namespace> -o yaml

# 查看网络插件性能
kubectl top pods -n kube-system -l k8s-app=<network-plugin>

# 检查网络插件日志
kubectl logs -n kube-system -l k8s-app=<network-plugin> --tail=100

# 简化NetworkPolicy规则
# 避免过于复杂的选择器和规则

最佳实践

1. 网络隔离策略

  • 默认拒绝所有流量
  • 显式允许必要的流量
  • 使用最小权限原则
  • 定期审计网络策略

2. 命名空间规划

  • 为命名空间添加标签
  • 使用命名空间隔离不同环境
  • 合理规划命名空间结构
  • 文档化命名空间用途

3. 标签管理

  • 使用一致的标签规范
  • 为所有Pod添加必要标签
  • 定期检查标签一致性
  • 避免标签冲突

4. DNS访问

  • 始终允许DNS访问
  • 使用命名空间选择器
  • 监控DNS查询
  • 配置DNS缓存

5. 监控和日志

  • 监控NetworkPolicy效果
  • 记录网络访问日志
  • 设置异常告警
  • 定期审计策略

6. 测试和验证

  • 测试所有网络策略
  • 验证隔离效果
  • 测试故障场景
  • 文档化测试结果

7. 安全增强

  • 实施零信任网络
  • 限制横向移动
  • 保护敏感应用
  • 满足合规要求

8. 性能优化

  • 简化NetworkPolicy规则
  • 避免过于复杂的选择器
  • 监控网络性能
  • 优化规则顺序

NetworkPolicy支持的网络插件

1. Calico

  • 完整的NetworkPolicy支持
  • 支持高级网络策略
  • 性能优秀
  • 提供网络可视化和策略管理

2. Cilium

  • 基于eBPF的高性能网络
  • 完整的NetworkPolicy支持
  • 支持七层网络策略
  • 提供网络可视化和监控

3. Weave Net

  • 完整的NetworkPolicy支持
  • 简单易用
  • 支持多主机网络
  • 自动网络配置

4. Flannel

  • 基本NetworkPolicy支持
  • 需要配合Calico使用
  • 简单轻量
  • 适合小型集群

5. Kube-router

  • 完整的NetworkPolicy支持
  • 基于IPVS
  • 性能良好
  • 支持网络策略可视化

总结

NetworkPolicy是Kubernetes中实现网络安全隔离的关键组件。通过合理配置NetworkPolicy,可以实现细粒度的网络访问控制,保护应用安全,满足合规要求。理解NetworkPolicy的工作原理和最佳实践,对于构建安全的Kubernetes集群至关重要。

下一步学习