Spring Batch工作Pod仅调度到两个worker节点,如何实现均匀分布?
解决方案
第一步:基础状态校验
先确认第三个worker节点本身符合调度要求:
- 执行
kubectl get nodes确认节点状态为Ready - 执行
kubectl describe node <第三个worker节点名称>检查两项:Taints字段没有NoSchedule/NoExecute类型的污点,如果有需要先移除污点,或者给worker Pod配置对应容忍规则Allocatable对应CPU、内存剩余资源足够容纳worker Pod
第二步:配置Pod调度打散规则
你可以二选一以下两种配置方案,推荐优先用拓扑分布约束,适配100个Pod的大规模均匀调度需求:
方案1:配置拓扑分布约束(K8s 1.21原生支持,效果最优)
拓扑分布约束是K8s专门用于实现Pod跨节点/可用区均匀分布的特性,你可以直接在现有PartitionHandler代码中增加部署属性配置,示例如下:
@Bean public PartitionHandler partitionHandler(TaskLauncher taskLauncher, JobExplorer jobExplorer) { // 原有代码保持不变 Resource resource = this.resourceLoader.getResource(resourceSpec); DeployerPartitionHandler partitionHandler = new DeployerPartitionHandler(taskLauncher, jobExplorer, resource, "worker"); commandLineArgs.add("--spring.profiles.active=worker"); commandLineArgs.add("--spring.cloud.task.initialize.enable=false"); commandLineArgs.add("--spring.batch.initializer.enabled=false"); commandLineArgs.add("--spring.cloud.task.closecontext_enabled=true"); commandLineArgs.add("--logging.level.root=DEBUG"); partitionHandler.setCommandLineArgsProvider(new PassThroughCommandLineArgsProvider(commandLineArgs)); partitionHandler.setEnvironmentVariablesProvider(environmentVariablesProvider()); partitionHandler.setApplicationName(appName + "worker"); partitionHandler.setMaxWorkers(maxWorkers); // 新增以下配置:拓扑分布约束 Map<String, String> deploymentProps = new HashMap<>(); String workerAppLabel = appName + "worker"; deploymentProps.put("spring.cloud.deployer.kubernetes.podTopologySpreadConstraints", String.format("[{\"topologyKey\": \"kubernetes.io/hostname\", \"maxSkew\": 1, \"whenUnsatisfiable\": \"ScheduleAnyway\", \"labelSelector\": {\"matchLabels\": {\"spring-app\": \"%s\"}}}]", workerAppLabel) ); partitionHandler.setDeploymentProperties(deploymentProps); return partitionHandler; }
配置说明:
topologyKey: kubernetes.io/hostname表示按节点维度做分布统计maxSkew: 1表示任意两个节点上的worker Pod数量差值最大为1,实现完全均匀whenUnsatisfiable: ScheduleAnyway表示资源不足时仍允许调度,不会出现Pod pending的情况- 也可以直接把上述配置写在application.yml的
spring.cloud.deployer.kubernetes配置段下,无需修改代码。
方案2:配置Pod软反亲和
如果不需要严格的均匀度,也可以用更简单的软反亲和配置,让调度器优先把Pod打散到不同节点:
// 新增到PartitionHandler的配置中 Map<String, String> deploymentProps = new HashMap<>(); String workerAppLabel = appName + "worker"; deploymentProps.put("spring.cloud.deployer.kubernetes.podAntiAffinity", "preferredDuringSchedulingIgnoredDuringExecution"); deploymentProps.put("spring.cloud.deployer.kubernetes.podAntiAffinityWeight", "100"); deploymentProps.put("spring.cloud.deployer.kubernetes.podAntiAffinityLabelSelector", "spring-app=" + workerAppLabel); partitionHandler.setDeploymentProperties(deploymentProps);
验证效果
重新启动批量任务后,执行kubectl get pods -l spring-app=<你的worker应用名> -o wide,即可看到Pod均匀分配到3个worker节点上。
内容的提问来源于stack exchange,提问作者Abhinav Sharma
相关产品推荐
相关产品推荐

