基于K8s的自定义控制器Enhanced Statefulset怎么用

这期内容当中小编将会给大家带来有关基于K8s的自定义控制器Enhanced Statefulset怎么用,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

下面要讲的产品——Enhanced statefulset。

顾名思义,Enhanced statefulset就是我们在statefulset的基础上对控制器做了进一步的扩展。它主要解决Pod绑定静态IP问题,同时也解决了statefulset在升级过程中不允许同时升级多个实例的限制。另外,它还可以在节点故障时支持Pod和IP的迁移。

前面已经提到了静态IP的重要场景是业务依赖的周边组件都以IP作为实例唯一标识,所以上到Kubernetes后仍然需要Pod实例保持IP不变。相信很多用户也面临着类似的问题,下面就来分享一下实现原理。

我们主要是通过对Enhanced Statefulset Controller 、 Scheduler、CNI这几个模块扩展来支持Enhanced Statefulset的Pod绑定静态IP。

Enhanced Statefulset Controller 对静态IP的管理主要是维护更新Static IP CR来实现的。当Controller收到创建请求时,会首先检查要创建的实例是否已经有对应的static IP CR记录,若记录不存在则会创建一个新的记录。在稍后scheduler完成调度,CNI完成静态IP分配后,controller会监听Pod信息并将其更新到Static IP CR中。反之若创建实例时,对应的static IP CR记录已经存在则表示这个Pod是删除重建,Controller会将static IP CR中的信息更新到Pod上,scheduler和CNI根据pod上的配置进行亲和性调度和IP分配。

StaticIP CRD中记录了负载类型、负载名称、节点、IP和Pod信息。其中IP信息在Pod实例上以annotation

  • 新增缓存:原有 Node 缓存基础上新增 staticIPNode 缓存,用于计算和缓存 staticIPPod 资源占用情况、缓存 IP 数量、Pod cpu/内存 使用量;

  • 新增predicate :

    • PodFitsResourcesWithStaticIPPodPred Node 现有资源基础上基于 staticIPPod 占用资源再次过滤,达到资源预占目的;

    • CheckPodAnnotationWithStaticIPPred 检查pod 是否包含 static ip 的指定 node annotation, 并仅保留指定 node 结果只 fit node 列表。

    概括起来核心思路就是将静态IP Pod所占用的资源作为一种特殊资源单独标识,在调度时进行匹配调度达到资源预占目的。

    CNI 在静态IP场景下主要实现以下三个功能:

    1. 按照Pod annotation上指定的IP分配,若无IP则从IP池中随机分配一个IP并将此记录更新到Pod中 ;

    2. IP地址预留,当绑定静态IP的Pod删除重建时,CNI会检查static IP CR记录,如果记录未删除则IP地址不释放,确保重建的Pod能够拿到绑定的IP;

    3. 在大规模集群场景下,为了提高SDN网络性能,我们要求CNI必须使用IP range模式。在这种模式下,弹性网卡上绑定的是IP CIDR,例如10.0.0.0/24,而不是某一个具体IP。IP迁移,释放和申请都是以CIDR的形式进行。

    最后,我们通过一个创建流程来展示一下Enhanced statefulset对象如何绑定静态IP:

    1. 用户创建一个enhanced statefulset对象,该请求首先发送到API server;

    2. enhanced statefulset controller监听到该请求,首先查询是否有该Pod对应的CR记录,若没有则创建新的CR,若已经有CR,则将CR中的信息更新的新建的Pod中;

    3. enhanced statefulset controller开始创建Pod;

    4. Scheduler根据Pod的affinity信息将其调度到相应的节点上,若无affinity信息则是新建pod正常调度。同时调度时会触发资源预留逻辑确保已有的静态IP Pod的资源不被占用;

    5. CNI查看Pod静态IP记录,如无记录则随机分配IP并将IP信息更新到Pod上,若有记录则按记录分配;

    6. StaticIP controller监听到Pod上静态IP信息变更,并将此信息更新到CR中。

    除了支持静态IP这个强需求,我们考虑的第二个重点就是尽可能将Kubernetes的DevOps能力赋能给业务场景。社区原生的 StatefulSet 在升级过程中不允许同时升级多个实例,这主要是为了某些有状态应用需要依次按序升级的需求。但这样带来的问题是效率太低,而集团业务对升级失败和顺序有一定容忍度,为了提升升级效率,我们定义了MaxUnavailable 参数,它允许应用实例被并行升级,且始终保持最大不可用的实例数不超过 MaxUnavailable 的限制数。

    此外,为了保证升级足够可控,Enhanced Statefulset可以通过Partitions进行分批升级。每个批次升级完成后通过再次更新Partitions触发下一次升级,如果发现升级过程中遇到问题也可以进行Rollback回滚或Paused暂停。

    通过这些优化,Enhanced Statefulset具备更好了灵活性,既可以兼容原生Statefulset规则严格按照实例顺序升级,确保有状态服务的可靠性。又可以兼具类似Deployment的能力,以更高效的方式并发升级。同时还可以分批手工触发,基本覆盖了集团业务的绝大部分场景。

    下面通过一个示例来具体了解下:

    用户创建了一个Enhanced Statefulset的应用,副本数为6,应用从staticip-example-0到staticip-example-5,Partitions设置为3, MaxUnavailable设置为2。

     1apiVersion: jke.jdcloud.com/v1alpha1
    2kind: EnhancedStatefulSet
    3metadata:
    4  name: staticip-example
    5  annotations:
    6    staticip.jke.jdcloud.com/enable: "true"    #打开静态IP功能
    7spec:
    8  serviceName: enhanced-sts-service-example
    9  replicas: 6
    10  selector:
    11    matchLabels:
    12      apps: staticip-example
    13  updateStrategy:
    14    rollingUpdate:
    15      maxUnavailable: 2                       #最大不可用数量,允许并行升级,并且容忍副本不可用
    16      partition: 3                            #enhanced statefulset创建的Pod都有index,命名从0开始,例如pod-0 pod-1  所有index大于等于partition值的实例升级,通过变更partition值来实现分批升级
    17      paused: false
    18      podUpdatePolicy: ReCreate
    19    type: RollingUpdate
    20  template:
    21    metadata:
    22      labels:
    23        apps: staticip-example
    24    spec:
    25      containers:
    26        - image: nginx:v1                    # nginx:v1 变更为 nginx:v2 触发升级

    当用户将镜像从v1升级到v2时,升级流程如下:

    1. Enhanced Statefulset Controller将staticip-example-3到staticip-example-5这3个副本并发升级到v2版本,其中staticip-example-4不可用,因为MaxUnavailable当前值为2,不影响应用继续升级;

    2. 用户将Partitions设置为0,enhanced statefulset controller将剩余3个副本staticip-example-0到staticip-example-2并发升级到v2版本,其中staticip-example-2不可用;

    3. 随后用户对不可用Pod进行手工修复,所有实例均恢复正常。

    在执行第二步时,如果第一步升级有两个实例不可用触发MaxUnavailable阈值,则用户在第二步即使将Partitions设置为0也不会触发再次升级。

    最后,再和大家聊一下故障迁移功能。静态IP为业务上Kubernetes带来便利的同时也带来了问题,其中一个比较突出的问题就是故障迁移场景。故障迁移有几个前提条件:

    1. 静态IP Pod和其所绑定的IP需要迁移到同一个目标节点上,这样才能保证Pod迁移后IP不变;

    2. 前面已经提到在大规模集群下我们要求CNI必须配置成IP Range模式,这种模式下IP CIDR不能拆分到更细粒度迁移,一个节点绑定的一个IP CIDR只能迁移到一个目标节点。这就意味着,所有绑定静态IP的Pod也必须迁移到同一个目标。这样就带来了一个问题,怎样才能保证目标节点有足够的资源;

    3. 故障迁移后,业务希望最大程度保留原来的物理拓扑,虚机配置与规格;

    针对这些问题,我们当前给出的方案是node migration。基本流程如下:

    1. 当节点处于失联状态超过容忍的时间窗口后(用户可根据业务情况配置时间窗口阈值),node operator会将此节点禁用;

    2. node operator会创建一台与故障节点同规格同AZ的目标节点;

    3. node operator将故障节点的IP和Pod 指定迁移到新节点重新创建,并更新元数据信息;

    4. 将故障节点删除。

上述就是小编为大家分享的基于K8s的自定义控制器Enhanced Statefulset怎么用了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注亿速云行业资讯频道。

原创文章,作者:kirin,如若转载,请注明出处:https://blog.ytso.com/225688.html

(0)
上一篇 2022年1月8日
下一篇 2022年1月8日

相关推荐

发表回复

登录后才能评论