美文网首页
node not ready时如何迁移有状态pod

node not ready时如何迁移有状态pod

作者: wwq2020 | 来源:发表于2024-01-12 14:33 被阅读0次

    背景

    由于pv attach到对应的节点,就算是我们删除了pod,pod也无法调度到其他节点上(如果pvc的volume.kubernetes.io/selected-node有值,调度器根据它过滤节点,也就是只有这个注解对应的值的节点能满足)
    这个时候就需要利用controller manager的自动detach能力

    总结

    1 删除pod
    2 添加污点自动detach pv
    ···
    kubectl taint node ${yournodename} node.kubernetes.io/out-of-service=nodeshutdown:NoExecute
    ···
    3 自动调度到其他节点

    源码

    pkg/controller/volume/attachdetach/reconciler/reconciler.go中

    func (rc *reconciler) reconcile(ctx context.Context) {
    ...
    是否超时
                timeout := elapsedTime > rc.maxWaitForUnmountDuration
    
    节点是否健康
                isHealthy, err := rc.nodeIsHealthy(attachedVolume.NodeName)
                if err != nil {
    ...
                }
    
    ...
    是否强制detach
                forceDetach := !isHealthy && timeout
    是否有对应污点
                hasOutOfServiceTaint, err := rc.hasOutOfServiceTaint(attachedVolume.NodeName)
                if err != nil {
                    logger.Error(err, "Failed to get taint specs for node", "node", klog.KRef("", string(attachedVolume.NodeName)))
                }
    ...
    判断是否需要detach
                if attachedVolume.MountedByNode && !forceDetach && !hasOutOfServiceTaint {
                    logger.V(5).Info("Cannot detach volume because it is still mounted", "node", klog.KRef("", string(attachedVolume.NodeName)), "volumeName", attachedVolume.VolumeName)
                    continue
                }
    ...
    执行detach
                err = rc.attacherDetacher.DetachVolume(logger, attachedVolume.AttachedVolume, verifySafeToDetach, rc.actualStateOfWorld)
    ...
    }
    
    判断是否有node.kubernetes.io/out-of-service这个污点
    func (rc *reconciler) hasOutOfServiceTaint(nodeName types.NodeName) (bool, error) {
        node, err := rc.nodeLister.Get(string(nodeName))
        if err != nil {
            return false, err
        }
        return taints.TaintKeyExists(node.Spec.Taints, v1.TaintNodeOutOfService), nil
    }
    

    pkg/volume/util/operationexecutor/operation_executor.go中

    detach volume
    func (oe *operationExecutor) DetachVolume(
        logger klog.Logger,
        volumeToDetach AttachedVolume,
        verifySafeToDetach bool,
        actualStateOfWorld ActualStateOfWorldAttacherUpdater) error {
    构建操作对象
        generatedOperations, err :=
            oe.operationGenerator.GenerateDetachVolumeFunc(logger, volumeToDetach, verifySafeToDetach, actualStateOfWorld)
        if err != nil {
            return err
        }
    
        if util.IsMultiAttachAllowed(volumeToDetach.VolumeSpec) {
            return oe.pendingOperations.Run(
                volumeToDetach.VolumeName, "" /* podName */, volumeToDetach.NodeName, generatedOperations)
        }
    执行操作
        return oe.pendingOperations.Run(
            volumeToDetach.VolumeName, "" /* podName */, "" /* nodeName */, generatedOperations)
    
    }
    

    pkg/volume/util/operationexecutor/operation_generator.go中

    func (og *operationGenerator) GenerateDetachVolumeFunc(
    ...
    构建detach方法
        detachVolumeFunc := func() volumetypes.OperationContext {
            var err error
            if verifySafeToDetach {
                err = og.verifyVolumeIsSafeToDetach(volumeToDetach)
            }
            if err == nil {
                err = volumeDetacher.Detach(volumeName, volumeToDetach.NodeName)
            }
    
    ...
        }
    
    ...
        return volumetypes.GeneratedOperations{
            OperationName:     DetachOperationName,
            OperationFunc:     detachVolumeFunc,
            CompleteFunc:      util.OperationCompleteHook(util.GetFullQualifiedPluginNameForVolume(pluginName, volumeToDetach.VolumeSpec), DetachOperationName),
            EventRecorderFunc: nil, // nil because we do not want to generate event on error
        }, nil
    }
    

    pkg/controller/volume/attachdetach/attach_detach_controller.go中

    var DefaultTimerConfig = TimerConfig{
    ...
        ReconcilerMaxWaitForUnmountDuration:               6 * time.Minute,
    ...
    }
    
    

    补充

    对于需要维护的节点,主动进行删除pod,taint node操作
    对于运行期not ready节点,部署巡检服务,进行删除pod和taint node操作

    相关文章

      网友评论

          本文标题:node not ready时如何迁移有状态pod

          本文链接:https://www.haomeiwen.com/subject/fuvxodtx.html