K8S-NetworkPolicy

一、什么是 NetworkPolicy?

NetworkPolicy 是 Kubernetes 中的一种资源对象,用于定义 Pod 之间的网络通信规则。简单来说,它就像集群内部的 "防火墙",可以精确控制:

  • 哪些 Pod 可以访问目标 Pod(入站流量,Ingress)
  • 目标 Pod 可以访问哪些 Pod 或外部网络(出站流量,Egress)
  • 允许通信的协议和端口范围

通过这种细粒度的控制,我们可以有效防止未经授权的访问,减少网络攻击面,提高集群的整体安全性。

二、NetworkPolicy 的核心原理

要理解 NetworkPolicy 的工作机制,需要掌握以下几个核心概念:

  1. Pod 选择器(PodSelector) 通过标签(Label)选择特定的 Pod 群体,作为网络策略的 "作用对象"。例如,matchLabels: {app: backend}表示策略仅作用于带有app=backend标签的 Pod。

  2. 命名空间选择器(namespaceSelector) 通过命名空间的标签选择特定命名空间,用于控制跨命名空间的通信。例如,namespaceSelector: {matchLabels: {project: myproject}}表示仅允许来自带有project=myproject标签的命名空间的流量。

  3. Ingress 规则定义允许进入 "作用对象 Pod" 的流量规则,包括来源(如其他 Pod、IP 网段)、协议和端口。

  4. Egress 规则定义允许 "作用对象 Pod" 发出的流量规则,包括目标(如其他 Pod、IP 网段)、协议和端口。

  5. **Peer Pod(对等 Pod)**规则中定义的通信对方 Pod,通过 PodSelector 或 namespaceSelector 指定,是 NetworkPolicy 规则的核心匹配目标。

三、NetworkPolicy 资源清单详解

一个完整的 NetworkPolicy 资源清单结构如下,我们通过示例解析关键字段:

yaml

复制代码
apiVersion: networking.k8s.io/v1  # 固定API版本
kind: NetworkPolicy  # 资源类型
metadata:
  name: test-network-policy  # 策略名称
  namespace: default  # 策略作用的命名空间(仅对该命名空间有效)
spec:
  podSelector:  # 选择作用对象Pod
    matchLabels:
      app: backend  # 仅作用于带有app=backend标签的Pod
  ingress:  # 入站规则
    - from:  # 允许的来源
        - podSelector:  # 来源为带有app=frontend标签的Pod
            matchLabels:
              app: frontend
        - ipBlock:  # 来源为192.168.1.0/24网段
            cidr: 192.168.1.0/24
      ports:  # 允许的端口和协议
        - protocol: TCP
          port: 8080  # 仅允许访问8080端口
  egress:  # 出站规则
    - to:  # 允许访问的目标
        - podSelector:  # 目标为带有app=database标签的Pod
            matchLabels:
              app: database
      ports:  # 允许的端口和协议
        - protocol: TCP
          port: 3306  # 仅允许通过3306端口访问
  • spec.policyTypes:可选字段,指定策略是否包含 Ingress、Egress 规则(默认根据是否定义 Ingress/Egress 自动推断)。
  • ipBlock:用于指定 IP 网段(支持cidrexcept排除网段),适合控制与集群外部的通信。

四、实用场景示例

以下是几个常见的 NetworkPolicy 配置场景,帮助理解如何在实际环境中应用。

场景 1:允许同一命名空间内的 Pod 通信

当需要限制 Pod 仅与同命名空间内的其他 Pod 通信时,可通过namespaceSelector匹配当前命名空间的标签:

yaml

复制代码
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-same-namespace
spec:
  podSelector:
    matchLabels:
      app: myapp  # 作用于带有app=myapp标签的Pod
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:  # 允许来自带有project=myproject标签的命名空间
        matchLabels:
          project: myproject
  egress:
  - to:
    - namespaceSelector:  # 允许访问带有project=myproject标签的命名空间
        matchLabels:
          project: myproject

注意 :需提前为命名空间添加project=myproject标签(如kubectl label ns default project=myproject)。

场景 2:限制敏感 Pod 的外部访问

对于敏感应用(如数据库),可能需要禁止其与集群外部通信,仅允许 Pod 间内部访问:

yaml

复制代码
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-external-traffic
spec:
  podSelector:
    matchLabels:
      app: sensitive-app  # 作用于敏感应用Pod
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector: {}  # 允许所有内部Pod访问(空选择器匹配所有Pod)
  egress:
  - to:
    - podSelector: {}  # 允许访问所有内部Pod

podSelector: {}表示匹配当前命名空间内的所有 Pod,因此该策略会禁止敏感 Pod 访问集群外部网络。

场景 3:限制特定端口的访问

对于前端服务,可能仅需要开放 80(HTTP)和 53(DNS)端口:

yaml

复制代码
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-specific-ports
spec:
  podSelector:
    matchLabels:
      app: frontend  # 作用于前端Pod
  ingress:
  - ports:  # 仅允许指定端口的入站流量
    - protocol: TCP
      port: 80  # 允许TCP 80端口
    - protocol: UDP
      port: 53  # 允许UDP 53端口(DNS解析)

场景 4:允许访问外部网络但禁止跨命名空间通信

需让myns1命名空间中app=alpine的 Pod 既能与同命名空间 Pod 通信,又能访问外部网络,但禁止与其他命名空间通信:

yaml

复制代码
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: alpine-communication-policy
  namespace: myns1  # 仅作用于myns1命名空间
spec:
  podSelector:
    matchLabels:
      app: alpine  # 作用对象:app=alpine的Pod
  policyTypes:
  - Ingress
  - Egress

  # 入站:仅允许myns1内的Pod访问
  ingress:
  - from:
    - podSelector: {}  # 匹配myns1内所有Pod

  # 出站:允许同命名空间Pod和外部网络,排除其他命名空间
  egress:
  # 允许访问myns1内所有Pod
  - to:
    - podSelector: {}
  # 允许访问外部网络(排除集群内部CIDR)
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0  # 允许所有IPv4地址
        except:  # 排除集群内部网段(需根据实际集群调整)
        - 10.244.0.0/16  # Pod CIDR示例
        - 10.96.0.0/12   # Service CIDR示例
  # 允许DNS解析(否则无法访问外部域名)
  - to:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: kube-system  # kube-dns所在命名空间
      podSelector:
        matchLabels:
          k8s-app: kube-dns  # kube-dns的Pod标签
    ports:
      - protocol: UDP
        port: 53
      - protocol: TCP
        port: 53

五、高级用法

NetworkPolicy 还支持更复杂的配置,满足多样化的网络控制需求:

1. 策略的 "叠加" 效果

Kubernetes 中多个 NetworkPolicy 可以同时作用于同一 Pod,最终规则为所有策略的 "并集"。例如:

  • 一个策略允许来自role=frontend的 Pod 访问
  • 另一个策略允许来自role=middleware的 Pod 访问最终目标 Pod 会允许来自frontendmiddleware的所有访问。

2. 复杂的 Peer 选择器

通过matchExpressions定义更灵活的标签匹配规则,例如允许rolefrontendmiddleware的 Pod 访问:

yaml

复制代码
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: advanced-selector-matching
spec:
  podSelector:
    matchLabels:
      app: backend
  ingress:
  - from:
    - podSelector:
        matchExpressions:
        - key: role
          operator: In
          values: [frontend, middleware]  # 匹配role为frontend或middleware的Pod

六、总结

NetworkPolicy 是 Kubernetes 集群网络安全的核心工具,通过定义精细的 Pod 通信规则,能够有效隔离不同应用、限制访问范围,降低网络攻击风险。在实际使用中,需注意:

  • 策略仅对匹配标签的 Pod 生效,未匹配的 Pod 不受限制(除非有默认拒绝策略)
  • 入站 / 出站规则默认 "拒绝所有",仅允许明确配置的流量
  • 需结合集群实际的 Pod/Service CIDR 配置外部访问规则,避免误阻断内部通信
相关推荐
真上帝的左手2 小时前
3. 代码管理-构建工具-Maven
java·maven
m0_471199632 小时前
【JavaScript】前端如何处理服务端部分接口加解密
开发语言·前端·javascript
stanleyrain2 小时前
c++指针问题
开发语言·c++
北极糊的狐2 小时前
stream.findFirst().get() 报错 NoSuchElementException
开发语言·python
如意.7592 小时前
【C++】从 I0 库到缓冲区,一篇吃透输入输出
开发语言·c++
JIngJaneIL2 小时前
基于Java旅游信息推荐系统(源码+数据库+文档)
java·开发语言·数据库·vue.js·spring boot·旅游
梦未2 小时前
Java多态性与类生命周期
java
黑客思维者2 小时前
Python数据清洗实战:去重/标准化
开发语言·python·数据清洗·数据标准化
CryptoRzz2 小时前
对接印度股票市场数据 (India api) 实时k线图表
java·开发语言·python·区块链·maven