首页 > 其他分享 >当创建statefulset资源后,k8s组件如何协作

当创建statefulset资源后,k8s组件如何协作

时间:2023-12-08 14:56:14浏览次数:41  
标签:负载 statefulset 创建 condemned 更新 StatefulSet 组件 Pod k8s

本文分享自华为云社区《当创建StatefulSet后,k8s会发生什么?》,作者:可以交个朋友 。

一、StatefulSet介绍

StatefulSet 是用来管理有状态应用的工作负载对象,StatefulSet 管理基于相同容器规约的一组 Pod,使用持久标识符为工作负载Pod提供持久存储。和Deployment 类似,也属于副本控制器,但和Deployment不同的是, StatefulSet 为它们的每个 Pod 维护了一个有粘性的 ID。无论该类Pod的生命周期如何变化,每个 Pod 的标识符ID不会变化。另外还支持服务实例有序部署和扩展,并提供有状态应用程序所需的有序启动和终止策略。

StatefulSet工作负载之间使用Headless Service来定义Pod网路标识,生成可解析的DNS域名名称记录,用于同一StatefulSet工作负载彼此Pod之间的通信。

二、StatefulSet工作负载访问方式

与其他的工作负载(如Deployment)的对外访问方式相似,但有所区别。Deployent工作负载使用service(带有IP地址的服务)提供对外服务访问,但在一些特殊场景中,客户端访问不需要kubernetes中service实现的负载均衡功能,而是由客户端直接去发现/选择服务端的后端实例访问,就需要一种特殊的服务“Headless service”。这是一种没有访问入口(即service没有IP地址)的service。kube-proxy不会为这种类型的service(Headless service)创建iptables/ipvs转发规则。

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx # 必须匹配 .spec.template.metadata.labels
  serviceName: "nginx"
  replicas: 3 # 默认值是 1
  minReadySeconds: 10 # 默认值是 0
  template:
    metadata:
      labels:
        app: nginx # 必须匹配 .spec.selector.matchLabels
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: registry.k8s.io/nginx-slim:0.8
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "my-storage-class"
      resources:
        requests:
          storage: 1Gi

其中StatefulSet关联的pod与pvc、pv的关系如下图:

三、StatefulSet工作负载创建流程

  1. 用户使用通过kubectl客户端发起创建StatefulSet资源对象请求至api-server。

  2. api-server对请求用户鉴权、准入控制操作,然后将该请求事件写入到etcd存储中。

  3. 考虑到StatefulSet-controller采用非阻塞式长连接watch机制实时获取StatefulSet资源对象信息,一旦集群中有StatefulSet变化(包括创建、更新、删除),则通过api-server获取etcd中相关StatefulSet资源对象。

  4. api-server将StatefulSet资源返回给StatefulSet-controller的watch接口长连接。

  5. StatefulSet-controller维护StatefulSet的生命周期状态,并通过StatefulSet的模板确定副本数量,根据副本数量依序(0、1....N-1)创建Pod副本。

  6. api-server接收到StatefulSet-controller创建结果后,更新etcd存储中的StatefulSet状态信息和Pod创建事件。

四、StatefulSet-Controller工作原理

在StatefulSet中,Informer和Event Handler是两个重要的组件

  • informer:是一个Kubernetes API客户端,用于监视Kubernetes API中的资源对象的变化并更新到本地缓存中。当资源对象的状态发生变化时,Informer会触发Event Handler。
  • Event Handler:是一个回调函数,用于处理Informer发出的事件,Event Handler会根据事件的类型,执行相应的操作。
  • Manage Revision:用于标识StatefulSet的每个更新版本,通过Manage Revision,可以查看StatefulSet的更新历史,以便在需要时回滚到先前的版本。
  • Manger pods in order: 管理StatefulSet中pod的启动顺序,
  • Update in order: 有序的更新Pod。查看 Pod 期望的状态是否符合要求,不满足则删除重建,
  • Update Status:管理StatefulSet对象的更新状态。
  • replicas数组:存放可用Pod的ord值(Pod名称中ID标识符),(0 <= ord < Spec.replicas)
  • condemned数组:存放需要删除pod的ord值(Pod名称中ID标识符),(ord >= Spec.replicas)
  • 创建StatefulSet工作负载Pod实例

判断StatefulSet的管理策略:

  1. 若实例管理策略为并行策略,则遍历replicas数组,所有Pod同步创建,不区分启动先后顺序。
  2. 若实例管理策略为有序策略,遍历replicas数组,依序(0、1....N-1)创建Pod。需确保replicas数组中的前一个Pod处于runing或ready状态。方可创建下一个Pod。
  3. 最后检查Pod的信息是否与StatefulSet匹配,若不匹配则更新Pod的状态。如当前StatefulSet已关联Pod,但是Pod标签不匹配则释放Pod,重新新建Pod副本关联。

4.1 更新StatefulSet工作负载Pod实例

  1. 判断statefulset的更新策略:

  2. 如果更新策略为OnDelete,则不会自动触发更新行为,需要手动删除Pod,系统对其进行重建更新。

  3. 如果更新策略为RollingUpdate,则不再关注实例管理策略。都是按顺序进行处理且等待当前Pod删除成功后才继续小于上一个Pod顺序号的Pod。

  4. 最后检查Pod的信息是否与StatefulSet匹配,若不匹配则更新Pod的状态。如当前StatefulSet已关联Pod,但是Pod标签不匹配则释放Pod,重新新建Pod副本关联。

4.2 扩缩容StatefulSet工作负载Pod实例

扩容操作:

  1. 更新statefulset的状态信息,将新建Pod的信息写入到replicas队列和condemned队列中。

  2. 遍历replicas数组,确保replicas数组中的Pod处于runing或ready状态。发现faild状态的Pod删除重建,对未创建的Pod则直接创建。

  3. 最后检查Pod的信息是否与StatefulSet匹配,若不匹配则更新Pod的状态。如当前StatefulSet已关联Pod,但是Pod标签不匹配则释放Pod,重新新建Pod副本关联。

缩容操作:

  1. 更新statefulset的状态信息。

  2. 遍历condemned数组,确保replicas数组中的Pod处于runing或ready状态。发现faild状态的Pod删除重建,对未创建的Pod则直接创建。然后按Pod名称标识符由大至小逆序删除condemned数组中若干个Pod

  3. 最后检查Pod的信息是否与StatefulSet匹配,若不匹配则更新Pod的状态。如当前StatefulSet已关联Pod,但是Pod标签不匹配则释放Pod,重新新建Pod副本关联。

4.3 删除StatefulSet工作负载Pod实例

如下processCondemned函数主要介绍删除StatefulSet工作负载Pod
func (ssc *defaultStatefulSetControl) processCondemned(ctx context.Context, set *apps.StatefulSet, firstUnhealthyPod *v1.Pod, monotonic bool, condemned []*v1.Pod, i int) (bool, error) {
    logger := klog.FromContext(ctx)
    if isTerminating(condemned[i]) {
        if monotonic {
            logger.V(4).Info("StatefulSet is waiting for Pod to Terminate prior to scale down",
                "statefulSet", klog.KObj(set), "pod", klog.KObj(condemned[i]))
            return true, nil
        }
        return false, nil
    }
    if !isRunningAndReady(condemned[i]) && monotonic && condemned[i] != firstUnhealthyPod {
        logger.V(4).Info("StatefulSet is waiting for Pod to be Running and Ready prior to scale down",
            "statefulSet", klog.KObj(set), "pod", klog.KObj(firstUnhealthyPod))
        return true, nil
    }
    if !isRunningAndAvailable(condemned[i], set.Spec.MinReadySeconds) && monotonic && condemned[i] != firstUnhealthyPod {
        logger.V(4).Info("StatefulSet is waiting for Pod to be Available prior to scale down",
            "statefulSet", klog.KObj(set), "pod", klog.KObj(firstUnhealthyPod))
        return true, nil
    }

    logger.V(2).Info("Pod of StatefulSet is terminating for scale down",
        "statefulSet", klog.KObj(set), "pod", klog.KObj(condemned[i]))
    return true, ssc.podControl.DeleteStatefulPod(set, condemned[i])
}
  1. 该函数首先判断需要删除的 Pod 是否正在终止中,如果是,则根据是否为Pod管理策略进行不同的处理。如果是有序策略,则会阻塞等待终止的 Pod 完全消失。如果不是有序策略,则直接返回,不做任何操作。

  2. 如果需要删除的 Pod 不是第一个不健康的 Pod,且当前Pod管理策略是有序策略,则会阻塞等待其他不健康 Pod 变为 Running 和 Ready 状态或者变为 Available 状态。如果不是有序策略,则直接返回,不做任何操作。

  3. 最后,如果需要删除的 Pod 不处于终止中,且满足删除条件,则会执行删除操作,并返回 true。否则,直接返回 false。

点击关注,第一时间了解华为云新鲜技术~

 

标签:负载,statefulset,创建,condemned,更新,StatefulSet,组件,Pod,k8s
From: https://www.cnblogs.com/huaweiyun/p/17887155.html

相关文章

  • el-collapse 组件回车键会触发显隐,如何去掉回车出发显隐
    el-collapse组件回车键会触发显隐(第一次手动触发后)因为change方法原因可以把事件放到title插槽上面<template><divclass="coordination-communication"><el-collapsev-model="activeNames"class="lh-collapse"><el-collapse-itemnam......
  • ACPM高效C++组件管理让音视频终端SDK性能更好、稳定性更高
    本专栏将分享阿里云视频云MediaBox系列技术文章,深度剖析音视频开发利器的技术架构、技术性能、开发能效和最佳实践,一起开启音视频的开发之旅。本文为MediaBox技术架构篇,重点从 ACPM介绍、技术架构以及高效管理等方面,介绍如何通过MediaBoxACPM的高效组件管理,来提升音视频终端SDK......
  • 界面控件DevExpress中文教程 - 如何用Office File API组件填充PDF表单
    DevExpressOfficeFileAPI是一个专为C#,VB.NET和ASP.NET等开发人员提供的非可视化.NET库。有了这个库,不用安装MicrosoftOffice,就可以完全自动处理Excel、Word等文档。开发人员使用一个非常易于操作的API就可以生成XLS,XLSx,DOC,DOCx,RTF,CSV和SnapReport等企业级文......
  • OpenTiny Vue 3.12.0 发布:文档大优化!增加水印和二维码两个新组件
    你好,我是Kagol。非常高兴跟大家宣布,2023年11月30日,OpenTinyVue发布了v3.12.0......
  • antd Pro组件ProFormList实现自定义action
    antdPro组件ProFormList实现自定义actionProFormList是antdesignpro的结构化数据组件,通常用来实现动态表单。现在有个需求,除了组件自带的删除和复制,还需要增加两个按钮来实现每个item位置的上下移动,如图所示:查看官方文档,组件有提供自定义action的API--actionRender,介绍如下......
  • 隐藏组件,但保留 ref
    需求背景已知:二次封装el-upload为Import导入组件,点击A或B,都弹出文件选择框。显示如下图所示:父组件:模板代码<el-col:span="1.5"class="import-btn"><importref="importRef":file-lab......
  • vue3视频播放器组件vue-video-player
    1、安装npmivue3-video-play--save2、全局注册importvue3videoPlayfrom'vue3-video-play'//引入组件import'vue3-video-play/dist/style.css'//引入cssapp.use(vue3videoPlay)3、使用<vue3VideoPlaywidth="1210px"......
  • vue3组件通信Props()
    vue3组件通信父传子defineProps()在使用 <scriptsetup> 的单文件组件中,props可以使用 defineProps() 宏来声明://父<HelloWorldmsg="Youdidit!"/><!--根据一个变量的值动态传入-->//<BlogPost:title="post.title"/>//子<scriptsetup>//写法1......
  • vue中孙子调用爷爷组件的方法怎么调用?
    使用Vue的provide和inject来实现跨层级的组件通信。provide允许一个祖先组件(爷爷组件)提供数据,而inject允许子孙组件(孙子组件)在任意层级注入这个数据。通过这种方式,你可以在孙子组件中访问到爷爷组件提供的方法。以下是一个简单的例子://在爷爷组件中提供方法exportdefault......
  • 开发者的福音:TinyVue 组件库文档大优化!类型更详细,描述更清晰!
    你好,我是Kagol。前言从今年2月份开源以来,有不少朋友给我们TinyVue组件库提了文档优化的建议,这些建议都非常中肯,我们也在持续对文档进行优化,并且从中总结出了大家对于文档优化的一些共性问题,形成了一份《组件demo和api文档编写规范》为了提升开发者阅读文档的体验,从9月......