当前位置: 首页 > article >正文

Kubernetes: NetworkPolicy 的实践应用

一、Network Policy 是什么,在云原生领域有和作用

Network Policy 是 Kubernetes 官方提出来的一种网络策略的规范,用户通过编写符合对应规范的规则来控制 k8s 集群内 L3 和 L4 层的网络流量。

NetworkPolicy 主要的功能就是实现在云原生领域的容器网络管控它给用户提供了几点最常用的能力

  1. 容器网络的出入网管控,最常用的就是控制业务的对公网访问
  2. 不同业务直接的网络资源隔离,随着集群规模的变大,不可避免的会存在多租户的场景,不同租户之间的网络隔离 network policy 可以做到
  3. 云原生领域的安全演练能力,例如模拟某些网络异常,可以直接通过NetworkPolicy 功能实现

二、Network Policy 和容器网络关系

云原生领域经过多年的发展,上层的应用各种服务层出不穷,作为云原生底层的基础服务,容器网络也面临更多安全和网络管控的需求。比如在大规模集群中不同业务希望互相禁止访问,一些内部服务希望禁止公网访问或被公网访问。kubernetes 对应这些类似需求给出的解决方案就是 Network Policy 。Network Policy 的实现依赖于容器网络,但是因为不同的 CNI 技术方案和组网方式的不同,Network Policy 实现方式也是不同的,所以 kubernetes 官方只给出了一个 Network Policy 的格式规范,并没有给出具体的实现方案,示例如下:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6379
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 5978

三、Kubernetes 原生的Network Policy

kubernetes 原生的 Network Policy 功能相对简单只支持 namespace 级别,功能且相对简单,支持 L3 和 L4 基础的网络策略。

3.1 匹配规则

  • Ingress : 顾名思义,外部流量流入 Pod
ingress:
  -from:
    -ipBlock:
cidr: 172.17.0.0/16
except:
        - 172.17.1.0/24
    -namespaceSelector:
matchLabels:
project: myproject
    -podSelector:
matchLabels:
role: frontend
ports:
    -protocol: TCP
port: 6379

Ingress 通过 From 关键字来配置规则,可以通过ipBlocknamespaceSelectorpodSelectorPorts 来选择该策略所使用的对象。

podSelector:此选择器将在与 NetworkPolicy 相同的 namespace 中选择特定的 Pod,应将其允许作为入站流量来源或出站流量目的地。

namespaceSelector:此选择器将选择特定的 namespace,应将所有 Pod 用作其入站流量来源或出站流量目的地。

namespaceSelector 和 podSelector:一个指定 namespaceSelectorpodSelectorto/from 条目选择特定 namespace 中的特定 Pod。

  • Egress: Pod 的出向流量

Egress 匹配策略和 ingress 基本一致,只是from 字段改为to

3.2 官方案例

  1. 默认拒绝所有的入站流量,在 default namespace 下生效
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
spec:
  podSelector: {}
  policyTypes:
  - Ingress

  1. 允许所有入站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-ingress
spec:
  podSelector: {}
  ingress:
  - {}
  policyTypes:
  - Ingress
  1. 默认拒绝所有的出站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-egress
spec:
  podSelector: {}
  policyTypes:
  - Egress

  1. 允许所有出站
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-egress
spec:
  podSelector: {}
  egress:
  - {}
  policyTypes:
  - Egress
  1. 默认拒绝所有的入站和出站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

四、开源组件拓展Network Policy

kubernetes 提供的原生的Network Policy 所能实现的功能相对较少,很难满足日益复杂的容器网络管控需求,所以各家CNI 基本上都有自己标准的Network Policy

4.1 Calico Network Policy

Calico 的Network Policy 相较于Kubernetes 原生的Network Policy 有两点需要特别注意,第一个是增加了集群级别的网络策略,第二个是对于流量的处理处理正常的allow 和 deny 还多了一个log 用来记录被network policy 匹配到的流量 注:这里只介绍Calico 开源版本,企业版本的calico 不在本文的介绍范围内。

  1. 集群级别的网络策略 相较于k8s 原生的namespace 级别的网络策略,集群级别网络策略是一种非namespace 资源,可以应用于独立于命名空间的任何类型的端点(pod、VM、主机接口)。
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
  name: allow-tcp-port-6379
  1. 标准的Calico Network Policy 在以下示例中,传入到应用程序的 TCP 流量被拒绝,并且每个连接尝试都记录到系统日志中
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
  name: allow-tcp-6379
  namespace: production
spec:
  selector: role == 'database'
  types:
    - Ingress
    - Egress
  ingress:
    - action: Log
      protocol: TCP
      source:
        selector: role == 'frontend'
    - action: Deny
      protocol: TCP
      source:
        selector: role == 'frontend'

4.2 Cilium Network Policy

Cilium CNI 提供的Network Policy 的功能相对较多,它不仅支持3层、四层、7层,同时还支持通过自定义实体身份来选择Network Policy 生效位置

4.2.1 三层Network Policy

****Cilium 的 Network Policy 支持多种模式,这里只选两个经典的来介绍

4.2.1.1 基于 ipBlock

此示例显示所有含 app=myservice 的 Pod 访问 20.1.1.1/32 和除了 10.96.0.0/12 所有 10.0.0.0/8 范围的地址

apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "cidr-rule"
spec:
  endpointSelector:
    matchLabels:
      app: myService
  egress:
  - toCIDR:
    - 20.1.1.1/32
  - toCIDRSet:
    - cidr: 10.0.0.0/8
      except:
      - 10.96.0.0/12

4.2.1.2 基于 DNS 下面的示例表示,允许 default namespace 下标签为 app=test-app 的 pod 向 kube-system namespace 下标签为 k8s:k8s-app=kube-dns 的 pod 的 53 端口发送请求”my-remote-service.com“的域名解析请求

apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "to-fqdn"
spec:
  endpointSelector:
    matchLabels:
      app: test-app
  egress:
    - toEndpoints:
      - matchLabels:
          "k8s:io.kubernetes.pod.namespace": kube-system
          "k8s:k8s-app": kube-dns
      toPorts:
        - ports:
           - port: "53"
             protocol: ANY
          rules:
            dns:
              - matchPattern: "*"
    - toFQDNs:
        - matchName: "my-remote-service.com"

4.2.2 四的Cilium Network Policy

四层的网络策略和 K8S 原生的规范除个别字段名称之外基本一致,所以只给出一个基本的例子 以下规则限制所有具有app=myService标签的 pod 只能使用端口 80-444 上的 TCP 向任何第 3 层目的地发送数据包

apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "l4-port-range-rule"
spec:
  endpointSelector:
    matchLabels:
      app: myService
  egress:
    - toPorts:
      - ports:
        - port: "80"
          endPort: 444
          protocol: TCP

4.2.3 七层的Cilium Network Policy

7层的Network Policy 目前支持的有 HTTP 协议,Kafka 相关以及DNS相关

// L7Rules is a union of port level rule types. Mixing of different port
// level rule types is disallowed, so exactly one of the following must be set.
// If none are specified, then no additional port level rules are applied.
type L7Rules struct {
        // HTTP specific rules.
        //
        // +optional
        HTTP []PortRuleHTTP `json:"http,omitempty"`

        // Kafka-specific rules.
        //
        // +optional
        Kafka []PortRuleKafka `json:"kafka,omitempty"`

        // DNS-specific rules.
        //
        // +optional
        DNS []PortRuleDNS `json:"dns,omitempty"`
}

4.2.3.1 HTTP 相关的L7 Network Policy

http 相关的NetworkPolicy 可以匹配path、method、host、headers 等信息,使用起来非常灵活

  • 基于 url& path

下面的例子允许从带有“env=prod”标签的 Pod 到带有“app=service”标签的 Pod 的 GET 请求访问 URL /public,但对其他任何 URL 或使用其他方法的请求将被拒绝。除端口 80 以外的其他端口上的请求将被丢


apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "rule1"
spec:
  description: "Allow HTTP GET /public from env=prod to app=service"
  endpointSelector:
    matchLabels:
      app: service
  ingress:
  - fromEndpoints:
    - matchLabels:
        env: prod
    toPorts:
    - ports:
      - port: "80"
        protocol: TCP
      rules:
        http:
        - method: "GET"
          path: "/public"

  • 基于 path & method & header

下面的例子限制了所有带有标签“app=myService”的 Pod 只能通过 TCP 协议接收端口 80 上的数据包。在使用这个端口进行通信时,仅允许以下两个 API :GET /path1 和 PUT /path2,并且必须在 HTTP 头“X-My-Header”中设置值为 true。

apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "l7-rule"
spec:
  endpointSelector:
    matchLabels:
      app: myService
  ingress:
  - toPorts:
    - ports:
      - port: '80'
        protocol: TCP
      rules:
        http:
        - method: GET
          path: "/path1$"
        - method: PUT
          path: "/path2$"
          headers:
          - 'X-My-Header: true'

4.2.3.2 KafKa相关的L7 Network Policy(beta) • 允许使用“produce” role 创建 topic

apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "rule1"
spec:
  description: "enable empire-hq to produce to empire-announce and deathstar-plans"
  endpointSelector:
    matchLabels:
      app: kafka
  ingress:
  - fromEndpoints:
    - matchLabels:
        app: empire-hq
    toPorts:
    - ports:
      - port: "9092"
        protocol: TCP
      rules:
        kafka:
        - role: "produce"
          topic: "deathstar-plans"
        - role: "produce"
          topic: "empire-announce"

• 允许使用 apiKeys 生成 topic

apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "rule1"
spec:
  description: "enable empire-hq to produce to empire-announce and deathstar-plans"
  endpointSelector:
    matchLabels:
      app: kafka
  ingress:
  - fromEndpoints:
    - matchLabels:
        app: empire-hq
    toPorts:
    - ports:
      - port: "9092"
        protocol: TCP
      rules:
        kafka:
        - apiKey: "apiversions"
        - apiKey: "metadata"
        - apiKey: "produce"
          topic: "deathstar-plans"
        - apiKey: "produce"
          topic: "empire-announce"

4.2.3.3 DNS 相关的L7 Network Policy

下面的示例表示,允许 default namespace 下标签为 org=alliance 的 pod 向 kube-system namespace 下标签为 k8s:k8s-app=kube-dns 的 pod 的 53 端口发送请求”my-remote-service.com“的域名解析请求,允许的域名为 cilium.io *. cilium.io .api.cilium.io 同时允许 cilium.io sub.cilium.io service1.api.cilium.io specialservice.api.cilium.io 的外部请求

apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: "tofqdn-dns-visibility"
spec:
  endpointSelector:
    matchLabels:
      any:org: alliance
  egress:
  - toEndpoints:
    - matchLabels:
       "k8s:io.kubernetes.pod.namespace": kube-system
       "k8s:k8s-app": kube-dns
    toPorts:
      - ports:
         - port: "53"
           protocol: ANY
        rules:
          dns:
            - matchName: "cilium.io"
            - matchPattern: "*.cilium.io"
            - matchPattern: "*.api.cilium.io"

  - toFQDNs:
      - matchName: "cilium.io"
      - matchName: "sub.cilium.io"
      - matchName: "service1.api.cilium.io"
      - matchPattern: "special*service.api.cilium.io"
    toPorts:
      - ports:
         - port: "80"
           protocol: TCP

4.2.4 集群联邦(Cluster Federation)的Cilium Network Policy

kubernetes 在 1.8 版本起就声称单个集群最多可支持 5000 个 node 和 15 万个 Pod,但是实际上我们关注近几年互联网上因为服务崩溃而上的几次热搜就应该明白,大规模集群一旦底层组件出现异常,带来的影响是非常大的。这个时候我们就需要用到集群联邦(Cluster Federation)。有了集群联邦,同样就需要考虑联邦级别的 Network Policy ,恰巧 Cilium 就提供了对应的这一能力。 以下策略说明如何允许特定 pod 在两个集群之间进行通信。

apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "allow-cross-cluster"
spec:
  description: "Allow x-wing in cluster1 to contact rebel-base in cluster2"
  endpointSelector:
    matchLabels:
      name: x-wing
      io.cilium.k8s.policy.cluster: cluster1
  egress:
  - toEndpoints:
    - matchLabels:
        name: rebel-base
        io.cilium.k8s.policy.cluster: cluster2


http://www.kler.cn/a/460514.html

相关文章:

  • 回归预测 | MATLAB实现CNN-SVM多输入单输出回归预测
  • ==和===的区别,被坑的一天
  • CSS 学习之 padding 与图形绘制
  • 矩阵运算提速——玩转opencv::Mat
  • 如何在IDEA一个窗口中导入多个项目
  • Android 系统 AlarmManager 系统层深度定制
  • 航顺芯片推出HK32A040方案,赋能汽车矩阵大灯安全与智能化升级
  • Linux postgresql-15部署文档
  • 音频进阶学习九——离散时间傅里叶变换DTFT
  • 华为仓颉编程语言的函数与结构类型分析
  • Midjourney技术浅析(五):图像细节处理
  • 【大模型实战篇】GLM-Zero模型初代版本的尝鲜
  • SSM-Spring-IOC/DI对应的配置开发
  • 【Win】感觉“ctypes.WinDLL(“user32“)“跟“ctypes.windll.user32“看起来很像呀,它们之间有什么区别呢?
  • UL-SCH 处理函数
  • 关于今天发现的一个bug
  • 深入解析Android JNI:以Visualizer为例
  • Ragas自动化评测整体后端流程
  • 平凡的2024回顾
  • 【每日学点鸿蒙知识】广告ID、NFC手机充值、CSS支持语法、PC与模拟器交互、SO热更新等
  • 前端实现PDF预览的几种选择(pdfjs-dist、react-pdf、pdf-viewer)
  • 嵌入式科普(25)Home Assistant米家集成意味着IOT的核心是智能设备
  • 形象地理解UE4中的数据结构 TLinkedListBase
  • [极客大挑战 2019]LoveSQL 1解题思路
  • Java多线程中,synchronized和ReentrantLock的区别是什么?及使用场景有哪些?
  • html+css网页设计 美食 美食美客模版2个页面