k8s statefulset controller源码分析

statefulset controller分析

statefulset简介

statefulset是Kubernetes提供的管理有状态应用的对象,而deployment用于管理无状态应用。

有状态的pod与无状态的pod不一样的是,有状态的pod有时候需要通过其主机名来定位,而无状态的不需要,因为无状态的pod每个都是一样的,随机选一个就行,但对于有状态的来说,每一个pod都不一样,通常希望操作的是特定的某一个。

statefulset适用于需要以下特点的应用:
(1)稳定的网络标志(主机名):Pod重新调度后其PodName和HostName不变;
(2)稳定的持久化存储:基于PVC,Pod重新调度后仍能访问到相同的持久化数据;
(3)稳定的创建与扩容次序:有序创建或扩容,从序号小到大的顺序对pod进行创建(即从0到N-1),且在下一个Pod创建运行之前,所有之前的Pod必须都是Running和Ready状态;
(4)稳定的删除与缩容次序:有序删除或缩容,从序号大到小的顺序对pod进行删除(即从N-1到0),且在下一个Pod终止与删除之前,所有之前的Pod必须都已经被删除;
(5)稳定的滚动更新次序:从序号大到小的顺序对pod进行更新(即从N-1到0),先删除后创建,且需等待当前序号的pod再次创建完成且状态为Ready时才能进行下一个pod的更新处理。

statefulset controller简介

statefulset controller是kube-controller-manager组件中众多控制器中的一个,是 statefulset 资源对象的控制器,其通过对statefulset、pod资源的监听,当资源发生变化时会触发 statefulset controller 对相应的statefulset资源对象进行调谐操作,从而完成statefulset对于pod的创建、删除、更新、扩缩容、statefulset的滚动更新、statefulset状态status更新、旧版本statefulset清理等操作。

statefulset controller架构图

statefulset controller的大致组成和处理流程如下图,statefulset controller对statefulset、pod对象注册了event handler,当有事件时,会watch到然后将对应的statefulset对象放入到queue中,然后syncStatefulSet方法为statefulset controller调谐statefulset对象的核心处理逻辑所在,从queue中取出statefulset对象,做调谐处理。
在这里插入图片描述

statefulset pod的命名规则、pod创建与删除

如果创建一个名称为web、replicas为3的statefulset对象,则其pod名称分别为web-0、web-1、web-2。

statefulset pod的创建按0 - n的顺序创建,且在创建下一个pod之前,需要等待前一个pod创建完成并处于ready状态。

同样拿上面的例子来说明,在web statefulset创建后,3 个 Pod 将按顺序创建 web-0,web-1,web-2。在 web-0 处于 ready 状态之前,web-1 将不会被创建,同样当 web-1 处于ready状态之前 web-2也不会被创建。如果在 web-1 ready后,web-2 创建之前, web-0 不处于ready状态了,这个时候 web-2 将不会被创建,直到 web-0 再次回到ready状态。

statefulset滚动更新或缩容过程中pod的删除按n - 0的顺序删除,且在删除下一个pod之前,需要等待前一个pod删除完成。

另外,当statefulset.Spec.VolumeClaimTemplates中定义了pod所需的pvc时,statefulset controller在创建pod时,会同时创建对应的pvc出来,但删除pod时,不会做对应pvc的删除操作,这些pvc需要人工额外做删除操作。

statefulset更新策略

(1)OnDelete:使用 OnDelete 更新策略时,在更新 statefulset pod模板后,只有当你手动删除老的 statefulset pods 之后,新的 statefulset Pod 才会被自动创建。
(2)RollingUpdate:使用 RollingUpdate 更新策略时,在更新 statefulset pod模板后, 老的 statefulset pods 将被删除,并且将根据滚动更新配置自动创建新的 statefulset pods。滚动更新期间,每个序号的statefulset pod最多只能有一个,且滚动更新下一个pod之前,需等待前一个pod更新完成并处于ready状态。与statefulset pod按0 - n的顺序创建不同,滚动更新时Pod按逆序的方式(即n - 0)删除并创建。

statefulset的滚动升级中还有一个Partition配置,在设置partition后,滚动更新过程中,statefulset的Pod中序号大于或等于partition的Pod会进行滚动升级,而其余的Pod保持不变,不会进行滚动更新。

statefulset controller分析将分为两大块进行,分别是:
(1)statefulset controller初始化与启动分析;
(2)statefulset controller处理逻辑分析。

1.statefulset controller初始化与启动分析

基于tag v1.17.4

https://github.com/kubernetes/kubernetes/releases/tag/v1.17.4

直接看到startStatefulSetController函数,作为statefulset controller初始化与启动分析的入口。

startStatefulSetController

startStatefulSetController主要逻辑:
(1)调用statefulset.NewStatefulSetController新建并初始化StatefulSetController;
(2)拉起一个goroutine,跑StatefulSetController的Run方法。

// cmd/kube-controller-manager/app/apps.go
func startStatefulSetController(ctx ControllerContext) (http.Handler, bool, error) {
	if !ctx.AvailableResources[schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "statefulsets"}] {
		return nil, false, nil
	}
	go statefulset.NewStatefulSetController(
		ctx.InformerFactory.Core().V1().Pods(),
		ctx.InformerFactory.Apps().V1().StatefulSets(),
		ctx.InformerFactory.Core().V1().PersistentVolumeClaims(),
		ctx.InformerFactory.Apps().V1().ControllerRevisions(),
		ctx.ClientBuilder.ClientOrDie("statefulset-controller"),
	).Run(int(ctx.ComponentConfig.StatefulSetController.ConcurrentStatefulSetSyncs), ctx.Stop)
	return nil, true, nil
}
1.1 statefulset.NewStatefulSetController

statefulset.NewStatefulSetController函数代码中可以看到,statefulset controller注册了statefulset、pod对象的EventHandler,也即对这几个对象的event进行监听,把event放入事件队列并做处理,对statefulset controller做了初始化。

// pkg/controller/statefulset/stateful_set.go
func NewStatefulSetController(
	podInformer coreinformers.PodInformer,
	setInformer appsinformers.StatefulSetInformer,
	pvcInformer coreinformers.PersistentVolumeClaimInformer,
	revInformer appsinformers.ControllerRevisionInformer,
	kubeClient clientset.Interface,
) *StatefulSetController {
	eventBroadcaster := record.NewBroadcaster()
	eventBroadcaster.StartLogging(klog.Infof)
	eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")})
	recorder := eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "statefulset-controller"})

	ssc := &StatefulSetController{
		kubeClient: kubeClient,
		control: NewDefaultStatefulSetControl(
			NewRealStatefulPodControl(
				kubeClient,
				setInformer.Lister(),
				podInformer.Lister(),
				pvcInformer.Lister(),
				recorder),
			NewRealStatefulSetStatusUpdater(kubeClient, setInformer.Lister()),
			history.NewHistory(kubeClient, revInformer.Lister()),
			recorder,
		),
		pvcListerSynced: pvcInformer.Informer().HasSynced,
		queue:           workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "st
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值