容器介绍
容器按照持续运行的时间可分为两类:服务类容器和工作类容器
服务类容器通常持续提供服务,需要一直运行,比如HTTPServer、Daemon等。工作类容器则是一次性任务,比如批处理程序,完成后容器就退出
Kubernetes的Deployment、ReplicaSet和DaemonSet都用于管理服务类容器;对于工作类容器,我们使用Job
客户端配置
- maven依赖
<dependency>
<groupId>io.kubernetes</groupId>
<artifactId>client-java</artifactId>
<version>7.0.0</version>
</dependency>
- k8s工具类封装
/**
* @author: lizhi
* @Date: 2021/4/14 20:39
* @Description: k8s调度工具类
*/
public class K8sUtilsNew {
private static final Logger logger = LoggerFactory.getLogger(K8sUtilsNew.class);
private static CoreV1Api coreV1Api = null;
private static AppsV1Api appsV1Api = null;
private static BatchV1Api batchV1Api = null;
static {
String separator = File.separator;
ApiClient client = null;
try {
//加载k8s config配置
client = Config.fromConfig(ResourceUtils.getFile("classpath:")+separator+"productconfig");
client.setDebugging(true);
//将加载config的client设置为默认的client
Configuration.setDefaultApiClient(client);
//创建api
coreV1Api = new CoreV1Api();
appsV1Api = appsV1Api;
batchV1Api = new BatchV1Api();
} catch (Exception e) {
logger.error("K8S config client error: {}",e);
}
}
/**
* 加载yaml配置文件
*
* @param path
* @throws IOException
*/
public static Object loadYaml(String path) throws IOException {
Reader reader = new FileReader(path);
return Yaml.load(reader);
}
/**
* 创建pod
*
* @param nameSpace :名称空间
* @param body :pod
* @return
* @throws ApiException
*/
public static V1Pod createPod(String nameSpace, V1Pod body) throws ApiException {
return coreV1Api.createNamespacedPod(nameSpace, body, "true", "true", null);
}
/**
* 删除pod
*
* @param nameSpace
* @param podName
* @throws Exception
*/
public static void deletePod(String nameSpace, String podName) throws Exception {
coreV1Api.deleteNamespacedPod(podName, nameSpace, "true", null, null, null, null, null);
}
/**
* 创建service
*
* @param nameSpace
* @param sv
* @throws ApiException
*/
public static void createService(String nameSpace, V1Service sv) throws ApiException {
coreV1Api.createNamespacedService(nameSpace, sv, "true", "true", null);
}
/**
* 删除service
*
* @param nameSpace
* @param serviceName
* @throws Exception
*/
public static void deleteService(String nameSpace, String serviceName) throws Exception {
coreV1Api.deleteNamespacedService(serviceName, nameSpace, null, null, null, null, null, null);
}
/**
* 创建deployment
*
* @param nameSpace
* @param body
* @throws ApiException
*/
public static void createDeployment(String nameSpace, V1Deployment body) throws ApiException {
appsV1Api.createNamespacedDeployment(nameSpace, body, "true", "true", null);
}
/**
* 刪除namespace
*
* @param nameSpace
* @param deployeName
* @throws ApiException
*/
public static void deleteDeployment(String nameSpace, String deployeName) throws ApiException {
appsV1Api.deleteNamespacedDeployment(deployeName, nameSpace, "true", null, null, null, null, null);
}
/**
* 创建job
*
* @param nameSpace
* @param body
* @throws ApiException
*/
public static void createJob(String nameSpace, V1Job body) throws ApiException {
batchV1Api.createNamespacedJob(nameSpace, body, "true", null, null);
}
/**
* 删除job
*
* @param nameSpace
* @param jobName,
* @throws ApiException
*/
public static void deleteJob(String nameSpace, String jobName) throws Exception {
try {
batchV1Api.deleteNamespacedJob(jobName, nameSpace, "true", null, null, null, "Foreground", null);
} catch (Exception e) {
if (e.getCause() instanceof IllegalStateException) {
IllegalStateException ise = (IllegalStateException) e.getCause();
if (ise.getMessage() != null && ise.getMessage().contains("Expected a string but was BEGIN_OBJECT")) {
logger.info("Catching exception because of issue https://github.com/kubernetes/kubernetes/issues/65121");
} else {
throw new Exception(e.toString());
}
} else {
throw new Exception(e.toString());
}
}
}
/**
* @Description 获取命名空间
* @Author lizhi
* @Date 2021/4/15 13:40
* @Param
* @Return
* @Exception
*
*/
public static V1NamespaceList listNamespaces(String label) throws ApiException {
V1NamespaceList v1NamespaceList = coreV1Api.listNamespace(null, null, null, null,
label, null, null, null, null);
return v1NamespaceList;
}
/**
* @Description 获取命名空间job
* @Author lizhi
* @Date 2021/4/15 13:40
* @Param
* @Return
* @Exception
*
*/
public static V1JobList listNamespacesJob(String namespace, String jobName) throws Exception {
V1JobList v1JobList = null;
try {
v1JobList = batchV1Api.listNamespacedJob(namespace, "true", null, null, "metadata.name=" + jobName, null, null, null, 5000, null);
} catch (Exception e) {
if (e.getCause() instanceof IllegalStateException) {
IllegalStateException ise = (IllegalStateException) e.getCause();
if (ise.getMessage() != null && ise.getMessage().contains("Expected a string but was BEGIN_OBJECT")) {
logger.info("Catching exception because of issue https://github.com/kubernetes/kubernetes/issues/65121");
return v1JobList;
} else {
throw new Exception(e.toString());
}
} else {
throw new Exception(e.toString());
}
}
return v1JobList;
}
/**
* @Description 创建命名空间
* @Author lizhi
* @Date 2021/4/15 13:49
* @Param
* @Return
* @Exception
*
*/
public static V1Namespace createNamespace(V1Namespace body) throws ApiException {
V1Namespace v1Namespace = coreV1Api.createNamespace(body, "false", null, null);
return v1Namespace;
}
}
- 创建job
生成创建job yaml模板方法:
/**
* @author: lizhi
* @Date: 2021/4/15 10:18
* @Description: 创建job模板body
*/
private V1Job K8sJobTemplate() {
//参数组装
String jobName = "testJob";
String image = "test:1.0";
//job执行脚本
String cmd = "echo 'hello k8s job'";
List<String> cmds = Arrays.asList(cmd);
//job调度策略:pod非亲和策略
V1LabelSelector v1LabelSelector = new V1LabelSelector().matchExpressions(Arrays.asList(new V1LabelSelectorRequirement().key("security").operator("In").values(Arrays.asList(jobName))));
V1PodAntiAffinity v1PodAntiAffinity = new V1PodAntiAffinity().requiredDuringSchedulingIgnoredDuringExecution(Arrays.asList(new V1PodAffinityTerm().topologyKey("kubernetes.io/hostname").labelSelector(v1LabelSelector)));
V1Affinity v1Affinity = new V1Affinity().podAntiAffinity(v1PodAntiAffinity);
V1Job jobTemplate = new V1Job()
.kind("Job")
.metadata(new V1ObjectMeta().name(jobName).namespace("test").putLabelsItem("security", jobName))
.spec(new V1JobSpec()
.ttlSecondsAfterFinished(100) //job执行完成100秒清除
.backoffLimit(4) //job重启次数
.template(new V1PodTemplateSpec().metadata(new V1ObjectMeta().putLabelsItem("security", jobName))
.spec(new V1PodSpec()
.affinity(v1Affinity)
.containers(Arrays.asList(new V1Container()
.imagePullPolicy("IfNotPresent")
.image(image)
.name(jobName)
.command(Arrays.asList("/bin/bash","-c"))
.args(cmds)))
.restartPolicy("OnFailure"))));
return jobTemplate;
}
调用api创建job
V1Job jobTemplate = K8sJobTemplate();
K8sUtilsNew.createJob("test", jobTemplate);
- 删除job
//删除执行中job
V1JobList v1JobList = K8sUtilsNew.listNamespacesJob("test", "testJob");
if (v1JobList.getItems().size() != 0) {
K8sUtilsNew.deleteJob("test", "testJob");
}
备注
具体生成job模板方法需要自行配置相关yaml参数,依赖具体需求创建job配置