这篇文章为大家提供一种在多k8s集群中部署一套xxl-job的方案。
问题背景:
- 公司生产环境有多套k8s集群,为保证服务可用,容器需要部署到不同集群中。单集群中容器间可直接通过本地ip访问,跨集群容器间调用需通过宿主ip+映射端口访问。
- 由于k8s部署容器时不一定会在哪台宿主机,我们设定xxl-job执行器注册的ip为自动获取的本地ip,端口固定。admin使用的数据库为同一套,导致在跨集群情况下admin调度另一个k8s集群的executor会失败。
如下图:
目标:
- admin与executor能在所有集群中部署
- 不同集群中的admin能够调度所有的executor
- 保证任务调度策略(如轮询,第一个,故障转移,最近最久未使用,admin管理端指定ip调用)不受影响。
解决思路
在admin中添加调度代理接口,利用不同k8s集群配置的ip网段差异,在admin调度时判断与executor网段是否一致,如果一致则直接调度,不一致则将调度请求(通过调度代理接口)交给与executor同集群的admin,由同集群admin调用执行器。
具体开发:
- 在admin中创建调度代理接口
如上面架构图展示的,调度器通过http请求执行器接口完成调度,源码:
com.xxl.job.core.biz.client.ExecutorBizClient
public class ExecutorBizClient implements ExecutorBiz {
.......
private String addressUrl ;
private String accessToken;
private int timeout = 3;
@Override
public ReturnT<String> beat() {
return XxlJobRemotingUtil.postBody(addressUrl+"beat", accessToken, timeout, "", String.class);
}
@Override
public ReturnT<String> idleBeat(IdleBeatParam idleBeatParam){
return XxlJobRemotingUtil.postBody(addressUrl+"idleBeat", accessToken, timeout, idleBeatParam, String.class);
}
@Override
public ReturnT<String> run(TriggerParam triggerParam) {
return XxlJobRemotingUtil.postBody(addressUrl + "run", accessToken, timeout, triggerParam, String.class);
}
...........
所以先在xxl-job-admin中创建接收调度请求的代理接口:
package com.xxl.job.admin.controller;
@Controller
public class ProxyController {
@RequestMapping(value = "health",method = RequestMethod.POST)
@ResponseBody
@PermissionLimit(limit = false)
public ReturnT health(@RequestHeader(XxlJobRemotingUtil.XXL_JOB_ACCESS_TOKEN) String accessTokenReq,@RequestBody HealthParam healthParam) throws Exception {
String accessToken = Config().getAccessToken();//这里是获取配置的accesstoken,请根据您自身获取accesstoken的方式进行修改
if (accessToken != null
&& accessToken.trim().length() > 0
&& !accessToken.equals(accessTokenReq)) {
return new ReturnT<String>(ReturnT.FAIL_CODE, "The access token is wrong.");
}
if(StringUtils.isBlank(healthParam.getAddressUrl())) return new ReturnT<String>(ReturnT.FAIL_CODE, "The addressUrl is wrong.");
ExecutorBiz executorBiz = XxlJobScheduler.getExecutorBiz(healthParam.getAddressUrl());
return executorBiz.health();
}
@RequestMapping(value = "beat",method = RequestMethod.POST)
@ResponseBody
@PermissionLimit(limit = false)
public ReturnT beat(@Reque