当创建statefulset资源后,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工作负载创建流程

用户使用通过kubectl客户端发起创建StatefulSet资源对象请求至api-server。
api-server对请求用户鉴权、准入控制操作,然后将该请求事件写入到etcd存储中。
考虑到StatefulSet-controller采用非阻塞式长连接watch机制实时获取StatefulSet资源对象信息,一旦集群中有StatefulSet变化(包括创建、更新、删除),则通过api-server获取etcd中相关StatefulSet资源对象。
api-server将StatefulSet资源返回给StatefulSet-controller的watch接口长连接。
StatefulSet-controller维护StatefulSet的生命周期状态,并通过StatefulSet的模板确定副本数量,根据副本数量依序(0、1....N-1)创建Pod副本。
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的管理策略:
- 若实例管理策略为并行策略,则遍历replicas数组,所有Pod同步创建,不区分启动先后顺序。
- 若实例管理策略为有序策略,遍历replicas数组,依序(0、1....N-1)创建Pod。需确保replicas数组中的前一个Pod处于runing或ready状态。方可创建下一个Pod。
- 最后检查Pod的信息是否与StatefulSet匹配,若不匹配则更新Pod的状态。如当前StatefulSet已关联Pod,但是Pod标签不匹配则释放Pod,重新新建Pod副本关联。
4.1 更新StatefulSet工作负载Pod实例
判断statefulset的更新策略:
如果更新策略为OnDelete,则不会自动触发更新行为,需要手动删除Pod,系统对其进行重建更新。
如果更新策略为RollingUpdate,则不再关注实例管理策略。都是按顺序进行处理且等待当前Pod删除成功后才继续小于上一个Pod顺序号的Pod。
最后检查Pod的信息是否与StatefulSet匹配,若不匹配则更新Pod的状态。如当前StatefulSet已关联Pod,但是Pod标签不匹配则释放Pod,重新新建Pod副本关联。
4.2 扩缩容StatefulSet工作负载Pod实例
扩容操作:
更新statefulset的状态信息,将新建Pod的信息写入到replicas队列和condemned队列中。
遍历replicas数组,确保replicas数组中的Pod处于runing或ready状态。发现faild状态的Pod删除重建,对未创建的Pod则直接创建。
最后检查Pod的信息是否与StatefulSet匹配,若不匹配则更新Pod的状态。如当前StatefulSet已关联Pod,但是Pod标签不匹配则释放Pod,重新新建Pod副本关联。
缩容操作:
更新statefulset的状态信息。
遍历condemned数组,确保replicas数组中的Pod处于runing或ready状态。发现faild状态的Pod删除重建,对未创建的Pod则直接创建。然后按Pod名称标识符由大至小逆序删除condemned数组中若干个Pod
最后检查Pod的信息是否与StatefulSet匹配,若不匹配则更新Pod的状态。如当前StatefulSet已关联Pod,但是Pod标签不匹配则释放Pod,重新新建Pod副本关联。
4.3 删除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])
}
该函数首先判断需要删除的 Pod 是否正在终止中,如果是,则根据是否为Pod管理策略进行不同的处理。如果是有序策略,则会阻塞等待终止的 Pod 完全消失。如果不是有序策略,则直接返回,不做任何操作。
如果需要删除的 Pod 不是第一个不健康的 Pod,且当前Pod管理策略是有序策略,则会阻塞等待其他不健康 Pod 变为 Running 和 Ready 状态或者变为 Available 状态。如果不是有序策略,则直接返回,不做任何操作。
最后,如果需要删除的 Pod 不处于终止中,且满足删除条件,则会执行删除操作,并返回 true。否则,直接返回 false。
当创建statefulset资源后,k8s组件如何协作的更多相关文章
- 【Kubernetes】在K8s中创建StatefulSet
在K8s中创建StatefulSet 遇到的问题: 使用Deployment创建的Pod是无状态的,当挂在Volume之后,如果该Pod挂了,Replication Controller会再run一个 ...
- 在K8s中创建StatefulSet
在K8s中创建StatefulSet 遇到的问题: 使用Deployment创建的Pod是无状态的,当挂在Volume之后,如果该Pod挂了,Replication Controller会再run一个 ...
- Kubernetes学习之路(二十)之K8S组件运行原理详解总结
目录 一.看图说K8S 二.K8S的概念和术语 三.K8S集群组件 1.Master组件 2.Node组件 3.核心附件 四.K8S的网络模型 五.Kubernetes的核心对象详解 1.Pod资源对 ...
- k8s 组件介绍__单Master集群部署
参考链接:https://github.com/opsnull/follow-me-install-kubernetes-cluster kubernetes 概述 1.kubernetes 是什么 ...
- php私有组件以及创建自己的composer私有组件(packagist+git+composer)
1.私有组件 大多数时候我们使用的都是公开可用的开源组件,但有时候如果公司使用内部开发的PHP组件,而基于许可证和安全方面的问题不能将其开源,就需要使用私有组件.对Composer而言,这是小菜一碟. ...
- kubernets之statefulset资源
一 了解Statefulset 1.1 对比statefulset与RS以及RC的区别以及相同点 Statefulset是有状态的,而RC以及RS等是没有状态的 Statefulset是有序的,拥 ...
- 二十六、StatefulSet资源控制器
StatefulSet资源控制器 一.statefulset介绍 StatefulSet 是为了解决有状态服务的问题而设计的资源控制器. 匹配 Pod name ( 网络标识 ) 的模式为:(stat ...
- Spring源码学习-容器BeanFactory(一) BeanDefinition的创建-解析资源文件
写在前面 从大四实习至今已一年有余,作为一个程序员,一直没有用心去记录自己工作中遇到的问题,甚是惭愧,打算从今日起开始养成写博客的习惯.作为一名java开发人员,Spring是永远绕不过的话题,它的设 ...
- Mysql创建新用户后无法登录,提示 Access denied for user 'username'@'localhost' (using password: YES)
MySQL创建新用户后无法登录,提示 Access denied for user 'username'@'localhost' (using password: YES) ,多半是因为存在匿名用户, ...
- 自动帮助创建android资源xml文件的网站
自动帮助创建android资源xml文件的网站 http://android-holo-colors.com/ stack overflow上一个seekbar的例子: http://stackove ...
随机推荐
- Java面向对象编程的三大特性:封装、继承、多态。
一.封装 封装的核心在于私有化(private),大部分情况下,来封装对象的属性,很少有封装方法的.通过将对象的属性封装,提供对外的公共方法来访问属性是最常见的方式. public static cl ...
- C#学习笔记--进阶
C#进阶 简单数据结构类 ArrayList 元素类型以Object类型存储,支持增删查改的数组容器. 因而存在装箱拆箱操作,谨慎使用. //ArrayList ArrayList array=new ...
- Python 利用pymysql和openpyxl操作MySQL数据库并插入Excel数据
1. 需求分析 本文将介绍如何使用Python连接MySQL数据库,并从Excel文件中读取数据,将其插入到MySQL数据库中. 2. 环境准备 在开始本文之前,请确保您已经安装好了以下环境: Pyt ...
- 舵机驱动——STM32F407ZGT6探索者——HAL库
舵机驱动--STM32F407ZGT6探索者--HAL库 1.材料准备 开发板:正点原子STM32F407ZGT6探索者 舵机:SG90 舵机线材分辨:褐色 / 红色 / 橘黄色 -- GND / V ...
- JAVA专题1-序列化与反序列化
http://www.cnblogs.com/xdp-gacl/p/3777987.html
- 一个Docker仓库问题的思考
近期项目有云上部署要求,产品要打包成docker镜像.之前产品已经发布过docker版本本次只需要需要更新下,于是交代组内另外一个同学更新下镜像,想着应该很简单: 中间经过熟悉docker知识点搭建环 ...
- 题解 CF690C1
题目大意: 给定一张 \(n\) 个点 \(m\) 条边的无向图,判断这是不是一棵树. 题目分析: 两种思路: 思路一: 不需要建图,直接使用并查集判环即可 最后判断一下图联不联通就行,具体方法就是看 ...
- 26. 干货系列从零用Rust编写正反向代理,如何发布Rust项目到Docker
wmproxy wmproxy已用Rust实现http/https代理, socks5代理, 反向代理, 静态文件服务器,四层TCP/UDP转发,内网穿透,后续将实现websocket代理等,会将实现 ...
- Bean常用的属性
Bean常用的属性介绍 <bean name="xxx" class="指定的bean类" scope="singleton"> ...
- sqlite数据库删除了数据,为什么文件不会变小?
SQLite数据库文件的大小不会自动缩小,即使删除了其中的数据. 这是因为在SQLite中,当数据被删除时,它实际上并没有立即从磁盘上移除,而是被标记为[已删除], 这种处理机制,被删除的数据仍然占用 ...