• 【博客542】k8s使用EndpointSlices扩展大规模service后端服务数量


    k8s使用EndpointSlices扩展大规模service后端服务数量

    EndpointSlices

    端点切片(EndpointSlices) 提供了一种简单的方法来跟踪 Kubernetes 集群中的网络端点(network endpoints)。 它们为 Endpoints 提供了一种可扩缩和可拓展的替代方案。

    出现背景:Endpoint API在大规模service后端的情况下存在较大限制

    Endpoint API 可伸缩性限制:

    如果使用 Endpoint API,Service 只有一个 Endpoint 资源。这意味着它需要为 Service 的每个 Pod 都存储好 IP 地址和端口(网络端点),这需要大量的 API 资源。另外,kube-proxy 会在每个节点上运行,并监控 Endpoint 资源的任何更新。如果 Endpoint 资源中有一个端口发生更改,那么整个对象都会分发到 kube-proxy 的每个实例。

    Endpoint API 另一个局限:

    它会限制跟踪 Service 的网络端点数量。一般存储在 etcd 中的对象默认大小限制为 1.5MB。在某些情况下,它会将 Endpoint 资源限制为 5000 个 Pod IP。对于大多数用户而言,这没什么关系,但是对于接近这个大小的 Service 而言,就有大问题了。

    举例:

    如果一个 Service 有 5000 个 Pod,它如果有 1.5MB 的 Endpoint 资源。当该列表中的某个网络端点发生了变化,那么就要将完整的 Endpoint 资源分发给集群中的每个节点。在具有 3000 个节点的大型集群中,这会是个很大的问题。每次更新将跨集群发送 4.5GB 的数据(1.5MB3000,即 Endpoint 大小 节点个数),并且每次端点更新都要发送这么多数据。想象一下,如果进行一次滚动更新,共有 5000 个 Pod 全部被替换,那么传输的数据量将超过 22 TB。

    EndpointSlice API 拆分 Endpoint

    ndpointSlice API 旨在通过类似于分片的方法来解决该问题。我们不跟踪 Service Pod IP 的单个 Endpoint 资源,而是将它们拆分为多个较小的 EndpointSlice。

    举个例子,现在有 15 个 Pod 在支持一个 Service,那么就有跟踪这些的一个 Endpoint 资源。如果将 EndpointSlice 配置为每个 EndpointSlice 存储 5 个端点,就得到了 3 个不同的 EndpointSlice:在这里插入图片描述默认情况下,EndpointSlice 每个存储能多达 100 个端点,我们可以使用 kube-controller-manager 的 --max-endpoints-per-slice 标签进行配置。

    EndpointSlice优势

    EndpointSlice API 大大提高了网络的可伸缩性:

    因为现在添加或删除 Pod 时,只需更新 1 个小的 EndpointSlice。尤其是成百上千个 Pod 支持单个 Service 时,差异将非常明显。更重要的是,既然 Service 的所有 Pod IP 都不需要存储在单个资源中,那么我们就不必担心 etcd 中存储对象的大小限制。EndpointSlice 可以用于扩展到超过 10 万个网络端点的 Service。

    EndpointSlice 相关新功能

    • Dual-stack Service:是一项与 EndpointSlice 一起开发的新功能。它们利用 IPv4 和 IPv6 地址提供 Service,并依靠 EndpointSlice 上的 addressType 字段按 IP 系列跟踪这些地址。
    • Topology aware routing: 会更新 kube-proxy 以 prefer 同一区域或区域内的路由请求。这使用了为 EndpointSlice 端点存储的拓扑字段。另外,目前还在探索 endpoint subsetting 的潜力,未来 kube-proxy 将只允许观察 EndpointSlice 的子集。这可以与 topology aware routing 结合使用,这样 kube-proxy 只需要监控包含同一区域内端点的 EndpointSlice,这将提供另一个非常显着的可伸缩性改进。

    属主关系

    在大多数场合下,EndpointSlice 都由某个 Service 所有, (因为)该端点切片正是为该服务跟踪记录其端点。这一属主关系是通过为每个 EndpointSlice 设置一个属主(owner)引用,同时设置 kubernetes.io/service-name 标签来标明的, 目的是方便查找隶属于某 Service 的所有 EndpointSlice。

    不同控制器对端点切片的管理

    控制面(尤其是端点切片的控制器) 会创建和管理 EndpointSlice 对象。EndpointSlice 对象还有一些其他使用场景, 例如作为服务网格(Service Mesh)的实现。这些场景都会导致有其他实体 或者控制器负责管理额外的 EndpointSlice 集合。

    为了确保多个实体可以管理 EndpointSlice 而且不会相互产生干扰,Kubernetes 定义了标签 endpointslice.kubernetes.io/managed-by,用来标明哪个实体在管理某个 EndpointSlice。端点切片控制器会在自己所管理的所有 EndpointSlice 上将该标签值设置 为 endpointslice-controller.k8s.io。 管理 EndpointSlice 的其他实体也应该为此标签设置一个唯一值。

    拓扑信息

    EndpointSlice 中的每个端点都可以包含一定的拓扑信息。 拓扑信息包括端点的位置,对应节点、可用区的信息。 这些信息体现为 EndpointSlices 的如下端点字段:

    nodeName - 端点所在的 Node 名称;
    zone - 端点所处的可用区。
    
    • 1
    • 2

    这些拓扑信息可以成为流量转发时的优先匹配依据,也成为了kube-proxy组件生成流量转发拓扑的iptables的依据

    端点切片中的每个端点信息

    我们知道 Endpoint 通常情况下是由 Service 资源自动创建和管理的,但是随着 Kubernetes 集群的规模越来越大和管理的服务越来越多,Endpoint API 的局限性变得越来越明显。 端点切片(EndpointSlices)提供了一种简单的方法来跟踪 Kubernetes 集群中的网络端点。它们为 Endpoint 提供了一种可伸缩和可拓展的替代方案,同时还可以被用到拓扑感知路由中。

    EndpointSlices 示例如下:

    apiVersion: discovery.k8s.io/v1
    kind: EndpointSlice
    metadata:
      name: example-hints
      labels:
        kubernetes.io/service-name: example-svc
    addressType: IPv4
    ports:
      - name: http
        protocol: TCP
        port: 80
    endpoints:
      - addresses:
          - "10.127.2.3"
        conditions:
          ready: true
        hostname: pod-1
        nodename: node-a
        zone: zone-a
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    EndpointSlice 中的每个端点都可以包含一定的拓扑信息。 拓扑信息包括端点的位置,对应节点、可用区的信息。 这些信息体现为 EndpointSlices 的如下端点字段:

    nodeName - 端点所在的 Node 名称
    zone - 端点所处的可用区
    hostname - 端点的 pod 名称
    
    • 1
    • 2
    • 3

    拓扑感知

    启用 kube-apiserver、kube-controller-manager、和 kube-proxy 的特性门控 TopologyAwareHints。通过把 Service 中的注解 service.kubernetes.io/topology-aware-hints 的值设置为 auto, 来激活服务的拓扑感知提示功能。 这告诉 EndpointSlice 控制器在它认为安全的时候来设置拓扑提示。kube-proxy 组件依据 EndpointSlice 控制器设置的提示,过滤由它负责路由的端点。

    由 EndpointSlice 控制器提供提示信息后 EndpointSlice 的示例如下:

    apiVersion: discovery.k8s.io/v1
    kind: EndpointSlice
    metadata:
      name: example-hints
      labels:
        kubernetes.io/service-name: example-svc
    addressType: IPv4
    ports:
      - name: http
        protocol: TCP
        port: 80
    endpoints:
      - addresses:
          - "10.1.2.3"
        conditions:
          ready: true
        hostname: pod-1
        zone: zone-a
        hints:
          forZones:
            - name: "zone-a"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    我们看到其中已注入了 hints 信息,对于上面这个示例,zone-a 的客户端访问会优先路由到该端点上。

    示例:为nginx service生成endpointslice,包含三个后端pod,带有hostname的topo键

    addressType: IPv4
    apiVersion: discovery.k8s.io/v1beta1
    endpoints:
    - addresses:
      - 10.244.1.45
      conditions:
        ready: true
      targetRef:
        kind: Pod
        name: nginx-deployment-pdhhz
        namespace: default
      topology:
        kubernetes.io/hostname: 10.1.2.20
    - addresses:
      - 10.244.2.51
      conditions:
        ready: true
      targetRef:
        kind: Pod
        name: nginx-deployment-j5wfx
        namespace: default
        resourceVersion: "15352701"
        uid: 67b97b7a-7829-420b-b5e3-2182c2ebd785
      topology:
        kubernetes.io/hostname: 10.1.2.21
    - addresses:
      - 10.244.5.70
      conditions:
        ready: true
      targetRef:
        kind: Pod
        name: nginx-deployment-x2fgf
        namespace: default
        resourceVersion: "15352705"
        uid: 7332ace0-c080-4570-8f8e-c8e114aad287
      topology:
        kubernetes.io/hostname: 10.1.2.22
    kind: EndpointSlice
    metadata:
      labels:
        app: nginx
        endpointslice.kubernetes.io/managed-by: endpointslice-controller.k8s.io
        kubernetes.io/service-name: nginx
      name: nginx-ncf2b
      namespace: default
      ownerReferences:
      - apiVersion: v1
        blockOwnerDeletion: true
        controller: true
        kind: Service
        name: nginx
    ports:
    - name: ""
      port: 80
      protocol: TCP
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    默认情况下,控制面创建和管理的 EndpointSlice 将包含不超过 100 个端点。 你可以使用 kube-controller-manager 的 --max-endpoints-per-slice 标志设置此值,最大值为 1000。
    当涉及如何路由内部流量时,EndpointSlice 可以充当 kube-proxy 的决策依据。

  • 相关阅读:
    Rust GUI 库的状态
    Vue项目文件导入、导出
    AD7606模块
    Linux设置定时任务
    Explain 关键字
    SQL中的单行注释,多行注释
    Ubuntu上安装配置Nginx
    .NET 8 RC 2 发布,将在11月14日发布正式版
    SQL Server进阶教程读书笔记
    Selenium 与(Firefox、GeckoDriver)和(Chrome、ChromeDriver)版本对应关系
  • 原文地址:https://blog.csdn.net/qq_43684922/article/details/128052375