llhuii / dive-into-k8s

Apache License 2.0
0 stars 0 forks source link

Pod 原地升级原理 #5

Open llhuii opened 3 years ago

llhuii commented 3 years ago

待整理:

原地升级的好处:

  1. 节省调度的耗时, 对apiserver/scheduler的开销, pod的位置\资源都不用发生变化
  2. 节省网络分配的耗时, pod的ip不变
  3. 节省了分配\挂载pv的耗时
  4. 节省了大部分拉取镜像的耗时, 只需很少几层镜像
  5. sidecar容器(日志采集/监控), 不希望干扰业务容器的运行
  6. 给集群带来稳定性和确定性, 大量应用触发pod升级时, 大规模的pod漂移, 对Node优先级pod造成抢占迁移. 重建造成对api/scheduler/网络/磁盘分配等中心组件造成较大的压力. 这些组件的延迟也会给pod重建带来恶行循环.

https://developer.aliyun.com/article/765421

https://www.infoq.cn/article/gifpiyxpvrbmzrxmofpk

llhuii commented 3 years ago

技术:

  1. kubelet会对每个container计算哈希值, 并放到容器的.info.config.annotations的key "io.kubernetes.container.hash", 当我们修改某个container的image字段时, kubelet会发现container的hash发生了变化, 会停掉旧容器, 创建新容器
  2. Pod更新限制: 只能更新以下pod字段, 见https://code.k8s.io/pkg/apis/core/validation/validation.go#L4050

    • spec.containers[*].image
    • spec.initContainers[*].image
    • spec.activeDeadlineSeconds

      // ValidatePodUpdate tests to see if the update is legal for an end user to make. newPod is updated with fields
      // that cannot be changed.
      func ValidatePodUpdate(newPod, oldPod *core.Pod, opts PodValidationOptions) field.ErrorList {
      fldPath := field.NewPath("metadata")
      allErrs := ValidateObjectMetaUpdate(&newPod.ObjectMeta, &oldPod.ObjectMeta, fldPath)
      allErrs = append(allErrs, validatePodMetadataAndSpec(newPod, opts)...)
      allErrs = append(allErrs, ValidatePodSpecificAnnotationUpdates(newPod, oldPod, fldPath.Child("annotations"), opts)...)
      specPath := field.NewPath("spec")
      
      // validate updateable fields:
      // 1.  spec.containers[*].image
      // 2.  spec.initContainers[*].image
      // 3.  spec.activeDeadlineSeconds
      // 4.  spec.terminationGracePeriodSeconds
  3. pod.status.containerStatuses, 保存前后状态根据imageID是否变化判断升级成功:
     status:
      containerStatuses:
      - name: bash
        image: bash:latest
        imageID: docker-pullable://nginx@sha256:xxxxx
  4. controller更新pod的readinessGate控制Pod是否ready, 流量无损
     spec:
       readinessGates:
       - conditionType: MyDemo
     status:
      conditions:
      - type: MyDemo
        status: "True"