OpenKruise入门:原地升级的原理

概要

k8s的哲学是不要把Pod当成宠物,因此每次deployment的更新,都会导致Pod的删除和重建,对于一些场景而言,Pod的重建是完全不必要的,因此需要一种办法,在特定情况,例如只是更新镜像时,让Pod不要重建,而是重启,并且对业务无损,OpenKruise实现了这个功能。

详情

k8s核心原理

原地升级即k8s的Pod重启

每个 Node 上的 Kubelet,会针对本机上所有 Pod.spec.containers 中的每个 container 计算一个 hash 值,当hash变化时,例如image发生了改变,kubelet会重启容器,从而实现Pod的原地升级。

go 复制代码
func HashContainer(container *v1.Container) uint64 {
	hash := fnv.New32a()
	containerJSON, _ := json.Marshal(container)
	hashutil.DeepHashObject(hash, containerJSON)
	return uint64(hash.Sum32())
}

pod spec 修改校验:

go 复制代码
// pkg/apis/core/validation/validation.go
func ValidatePodUpdate(newPod, oldPod *core.Pod, opts PodValidationOptions) field.ErrorList

status上报image

scss 复制代码
func (kl *Kubelet) convertToAPIContainerStatuses(pod *v1.Pod, podStatus *kubecontainer.PodStatus, previousStatus []v1.ContainerStatus, containers []v1.Container, hasInitContainers, isInitContainer bool) []v1.ContainerStatus

func (kl *Kubelet) convertStatusToAPIStatus(pod *v1.Pod, podStatus *kubecontainer.PodStatus, oldPodStatus v1.PodStatus) *v1.PodStatus

func (kl *Kubelet) generateAPIPodStatus(pod *v1.Pod, podStatus *kubecontainer.PodStatus) v1.PodStatus

func (kl *Kubelet) syncPod(ctx context.Context, updateType kubetypes.SyncPodType, pod, mirrorPod *v1.Pod, podStatus *kubecontainer.PodStatus) (isTerminal bool, err error)

kl.statusManager.SetPodStatus(pod, apiPodStatus)

// 更新pod status到apiserver
func (m *manager) syncPod(uid types.UID, status versionedPodStatus) 

newPod, patchBytes, unchanged, err := statusutil.PatchPodStatus(m.kubeClient, pod.Namespace, pod.Name, pod.UID, pod.Status, mergedStatus)

kubelet判断Pod Ready(ReadinessGates)

go 复制代码
func GeneratePodReadyCondition(spec *v1.PodSpec, conditions []v1.PodCondition, containerStatuses []v1.ContainerStatus, podPhase v1.PodPhase) v1.PodCondition {
	unreadyMessages := []string{}
	for _, rg := range spec.ReadinessGates {
		_, c := podutil.GetPodConditionFromList(conditions, rg.ConditionType)
		if c == nil {
			unreadyMessages = append(unreadyMessages, fmt.Sprintf("corresponding condition of pod readiness gate %q does not exist.", string(rg.ConditionType)))
		} else if c.Status != v1.ConditionTrue {
			unreadyMessages = append(unreadyMessages, fmt.Sprintf("the status of pod readiness gate %q is not \"True\", but %v", string(rg.ConditionType), c.Status))
		}
	}
}

Pod 更新限制和校验

func ValidateTolerations(tolerations \[\]core.Toleration, fldPath *field.Path) field.ErrorList

kruise原理

pkg/util/inplaceupdate/inplace_update.go 定义了原地更新的控制面接口和实现,pkg/util/inplaceupdate/inplace_update_defaults.go定义了如何把更新patch到Pod上等方法,例如defaultPatchUpdateSpecToPod

scss 复制代码
// Interface for managing pods in-place update.
type Interface interface {
	CanUpdateInPlace(oldRevision, newRevision *apps.ControllerRevision, opts *UpdateOptions) bool
	Update(pod *v1.Pod, oldRevision, newRevision *apps.ControllerRevision, opts *UpdateOptions) UpdateResult
	Refresh(pod *v1.Pod, opts *UpdateOptions) RefreshResult
}

参考

揭秘:如何为 Kubernetes 实现原地升级

相关推荐
螺蛳粉 螺蛳粉19 小时前
第 02 篇:镜像分层与 containerd 2.x 实战:SystemdCgroup 与 pause 镜像配置踩坑(底座认知 02)
docker·云原生·容器·kubernetes·etcd·containerd·kube-apiserver
小白的码BUG之路1 天前
K8s -- 搭建过程中经常遇到的问题
云原生·容器·kubernetes
螺蛳粉 螺蛳粉1 天前
第 03 篇:为什么 K8s 的最小调度单元是 Pod 而不是容器:pause 容器与边车模式(底座认知 03)
docker·云原生·容器·kubernetes·etcd·运维排障·kube-apiserver
艾伦_耶格宇1 天前
【kubernetes - 1.28版本】-9 K8S-dashbord可视化界面
云原生·容器·kubernetes
无人生还别怕2 天前
如何搭建k8s服务(containerd部署)
linux·云原生·容器·kubernetes·openanolisos
fb_123452 天前
从探针到权限:一篇吃透 Kubernetes 健康检查、RBAC 认证授权与 Dashboard 可视化管理
云原生·容器·kubernetes
mengge.cloud2 天前
10-28-Kubernetes健康检查认证授权与Dashboard
云原生·容器·kubernetes
SatanII2 天前
Kubernetes 认证与授权详解:守护集群API访问安全
安全·贪心算法·kubernetes
闲云野鹤在人间2 天前
头秃修炼手册:StorageClass+StatefulSet+ETCD 全套渡劫笔记
linux·数据库·笔记·云原生·kubernetes·etcd
艾伦_耶格宇2 天前
【kubernetes - 1.28版本】-7 K8S命令
云原生·容器·kubernetes