Kubevirt EvacuationController 流程分析

EvacuationController主要处理 darin 以及 migrate。大体来说会计算出该节点目前的migration创建上限,对于该节点上需要并且可以驱逐的vmi 创建相应migration。informer 有vmiInformer、vmiPodInformer、migrationInformer以及nodeInformer。将obj相关的node加入处理队列。 EvacuationController 总体流程

图1 evacuationController 总体流程
逻辑入口在pkg/virt-controller/watch/drain/evacuation/evacuation.go execute

获取相关 obj

首先确定节点存在以及其上的 migration 已经处理完成。

1
2
3
4
5
6
7
8
	if !exists {
		c.migrationExpectations.DeleteExpectations(key)
		return nil
	}

	if !c.migrationExpectations.SatisfiedExpectations(key) {
		return nil
	}

接着列出节点上的 vmi 以及还没有完成的 migration,然后进入sync流程

1
2
3
4
5
6
7
8
	vmis, err := c.listVMIsOnNode(node.Name)
	if err != nil {
		return fmt.Errorf("failed to list VMIs on node: %v", err)
	}

	migrations := migrationutils.ListUnfinishedMigrations(c.migrationInformer)
	
	return c.sync(node, vmis, migrations)

sync

首先vmisToMigrate找出需要迁移的 vmi,如果 node 包含 taint 则节点上所有 vmi 都需要迁移,否则 vmi 被 Evacuation 且还未开始迁移。

1
vmi.IsMarkedForEviction() && !hasMigratedOnEviction(vmi) && !migrationutils.IsMigrating(vmi)

接着filterRunningNonMigratingVMIs找到 vmi Pod 都停掉,spec 设置了 LiveMigrate 以及 LiveMigratable 为 true 且暂时没有 migrate 的 vmi。将 需要迁移的vmi 分成可迁移和不可迁移的两类;

接着算出source vmi 在此节点上的 migration 的数目;

以及集群中的最大节点并行migtation 数目,以及集群中的最大migration 并行数;

首先计算集群集群中的最大migration 并行数 - 现在active的 migration数freeSpotsPerCluster

其次算出最大节点并行migtation 数目 - source vmi 在此节点上的 migration 的数目 freeSpotsPerThisSourceNode

取两数中较小的作为上限freeSpots

1
2
3
4
5
6
7
8
migrationCandidates, nonMigrateable := c.filterRunningNonMigratingVMIs(vmisToMigrate, activeMigrations)
activeMigrationsFromThisSourceNode := c.numOfVMIMForThisSourceNode(vmisOnNode, activeMigrations)
maxParallelMigrationsPerOutboundNode :=
   int(*c.clusterConfig.GetMigrationConfiguration().ParallelOutboundMigrationsPerNode)
maxParallelMigrations := int(*c.clusterConfig.GetMigrationConfiguration().ParallelMigrationsPerCluster)
freeSpotsPerCluster := maxParallelMigrations - len(activeMigrations)
freeSpotsPerThisSourceNode := maxParallelMigrationsPerOutboundNode - activeMigrationsFromThisSourceNode
freeSpots := int(math.Min(float64(freeSpotsPerCluster), float64(freeSpotsPerThisSourceNode)))

difffreeSpots 和 可迁移vmi 数中的较小值;

remaining为还富余的 migration 数目;

1
2
3
diff := int(math.Min(float64(freeSpots), float64(len(migrationCandidates))))
remaining := freeSpots - diff
remainingForNonMigrateableDiff := int(math.Min(float64(remaining), float64(len(nonMigrateable))))

如果有富余且有不可迁移 的vmi则对这这两个数字中较小的remainingForNonMigrateableDiff 个 vmi 添加 event 。

VirtualMachineInstance is not migrateable

选出 diff个可迁移的 vmi,使用&sync.WaitGroup 创建相应的 migration。

updatedupdated2023-02-272023-02-27