Commit 83aa284d authored by 黎博's avatar 黎博

k8s controller全面优化

parent 6d85852e
......@@ -16,6 +16,7 @@ import com.tencentcloudapi.tcr.v20190924.models.TagInfo;
import io.fabric8.kubernetes.api.model.*;
import io.fabric8.kubernetes.api.model.apps.Deployment;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
......@@ -32,6 +33,9 @@ import java.util.*;
@RequestMapping("/k8s")
public class K8sController {
@Autowired
TkeService tkeService;
@Autowired
K8sService k8sService;
......@@ -68,7 +72,7 @@ public class K8sController {
*/
@GetMapping("/namespace/list")
public JsonResult getNamespaceList(String env) {
return JsonResult.buildSuccessResult(k8sService.getNamespaceList(env));
return JsonResult.buildSuccessResult(tkeService.getNamespaceList(env));
}
/**
......@@ -78,7 +82,7 @@ public class K8sController {
*/
@GetMapping("/service/list")
public JsonResult getServiceList(@RequestParam String namespace) {
List<Map<String, Object>> podList = k8sService.getPodListNew(namespace);
List<Map<String, Object>> podList = tkeService.getPodList(namespace);
return JsonResult.buildSuccessResult(podList);
}
......@@ -86,7 +90,7 @@ public class K8sController {
public JsonResult getServiceDetail(@RequestParam String namespace,
@RequestParam String serviceType,
@RequestParam String serviceName) {
return JsonResult.buildSuccessResult(k8sService.getPodAndServiceInfo(namespace, serviceType, serviceName));
return JsonResult.buildSuccessResult(tkeService.getPodAndServiceInfo(namespace, serviceType, serviceName));
}
/**
......@@ -107,145 +111,31 @@ public class K8sController {
@PostMapping("/service/create")
public JsonResult createPod(@RequestBody ServiceCreateVo serviceCreateVo) {
try {
String serviceName = serviceCreateVo.getServiceName();
String type = serviceCreateVo.getType();
String label = serviceCreateVo.getLabel();
String namespace = serviceCreateVo.getNamespace();
String image = serviceCreateVo.getImage();
// 如果Deployment已存在,则不重新添加
if (k8sService.queryIfDeploymentExistByName(namespace, serviceName)) {
return JsonResult.buildErrorStateResult("服务已存在,无法重复添加!", false);
String serviceName = serviceCreateVo.getServiceName();
String serviceType = serviceCreateVo.getType();
if (tkeService.checkPvcExistence(namespace, serviceName)) {
return JsonResult.buildErrorStateResult("服务已存在", false);
}
QueryWrapper<DockerProject> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("project_name", serviceName);
if (label.equals("base")) {
// 如果有Service,则首先删除Service
if (k8sService.queryIfServiceExistByName(namespace, serviceName)) {
k8sService.deleteService(namespace, serviceName);
}
// 重新创建Service
switch (serviceName) {
case "mysql":
k8sService.createMysqlService(namespace);
break;
case "redis":
k8sService.createRedisService(namespace);
break;
case "redis5":
k8sService.createRedis5Service(namespace);
break;
case "redis-sentinel":
k8sService.createRedisSentinelService(namespace);
break;
case "mongodb":
k8sService.createMongodbService(namespace);
break;
case "zookeeper":
k8sService.createZookeeperService(namespace);
break;
case "rabbitmq":
k8sService.createRabbitmqService(namespace);
break;
case "kafka":
k8sService.createKafkaService(namespace);
break;
default:
break;
}
// Pvc不存在则创建,已存在无需重新创建
if (!k8sService.queryIfPvcExistByName(namespace, serviceName)) {
switch (serviceName) {
case "mysql":
k8sService.createMysqlPvc(namespace);
break;
case "mongodb":
k8sService.createMongodbPvc(namespace);
break;
case "zookeeper":
k8sService.createZookeeperPvc(namespace);
break;
case "rabbitmq":
k8sService.createRabbitmqPvc(namespace);
break;
case "kafka":
k8sService.createKafkaPvc(namespace);
break;
default:
break;
}
// 新增Service
tkeService.createServiceByYaml(serviceCreateVo);
// 新增Deployment
tkeService.createDeploymentByYaml(serviceCreateVo);
if (StringUtils.equals(serviceType, "base")) {
// 基础服务,如果没有PVC则创建
if (!tkeService.checkPvcExistence(namespace, serviceName)) {
tkeService.createPvcByYaml(serviceCreateVo);
}
// 创建Deployment
switch (serviceName) {
case "mysql":
k8sService.createMysqlDeployment(namespace, image);
// 手动删除namespace缓存,刷新调/k8s/namespace/list获取到的mysql地址
k8sService.deleteNamespaceCache();
break;
case "redis":
k8sService.createRedisDeployment(namespace, image);
break;
case "redis5":
k8sService.createRedis5Deployment(namespace, image);
break;
case "redis-sentinel":
k8sService.createRedisSentinelDeployment(namespace, image);
break;
case "mongodb":
k8sService.createMongoDbDeployment(namespace, image);
break;
case "zookeeper":
k8sService.createZookeeperDeployment(namespace, image);
break;
case "rabbitmq":
k8sService.createRabbitmqDeployment(namespace, image);
break;
case "kafka":
k8sService.createKafkaDeployment(namespace, image);
break;
default:
break;
}
} else if (label.equals("java")) {
DockerProject dockerProject = dockerProjectService.getOne(queryWrapper);
// 如果存在Service,则首先删除,再创建新的
if (k8sService.queryIfServiceExistByName(namespace, serviceName)) {
k8sService.deleteService(namespace, serviceName);
}
k8sService.createJavaService(namespace, serviceName, serviceCreateVo.getDebug());
// 直接创建Java Deployment
k8sService.createJavaDeployment(serviceCreateVo, dockerProject);
// 如果存在Ingress,则首先删除Ingress,再创建新的
if (k8sService.queryIfIngressExistByName(namespace, serviceName)) {
k8sService.deleteIngress(namespace, serviceName);
}
k8sService.createIngress(namespace, serviceName, serviceCreateVo.getDomain());
} else if (label.equals("ui") || label.equals("node")) {
DockerProject dockerProject = dockerProjectService.getOne(queryWrapper);
// 如果存在Service,则首先删除,再创建新的
if (k8sService.queryIfServiceExistByName(namespace, serviceName)) {
k8sService.deleteService(namespace, serviceName);
}
k8sService.createUIAndNodeService(namespace, serviceName, type, label);
// 如果存在Ingress,则首先删除Ingress,再创建新的
if (k8sService.queryIfIngressExistByName(namespace, serviceName)) {
k8sService.deleteIngress(namespace, serviceName);
}
k8sService.createIngress(namespace, serviceName, serviceCreateVo.getDomain());
k8sService.createUIAndNodeDeployment(serviceCreateVo, dockerProject);
} else {
return JsonResult.buildErrorStateResult("服务类型暂不支持!", false);
// 非基础服务,创建Ingress
tkeService.createIngressByYaml(serviceCreateVo);
}
return JsonResult.buildSuccessResult("pod创建成功!");
} catch (Exception e) {
log.info("服务创建异常.", e);
e.printStackTrace();
return JsonResult.buildErrorStateResult("pod创建失败!", false);
return JsonResult.buildErrorStateResult("服务创建异常", false);
}
return JsonResult.buildSuccessResult("服务创建成功");
}
/**
......@@ -256,7 +146,7 @@ public class K8sController {
*/
@PostMapping("/service/redeploy")
public JsonResult resetPodByName(String namespace, String podName) {
return JsonResult.buildSuccessResult(k8sService.resetPod(namespace, podName));
return JsonResult.buildSuccessResult(tkeService.resetPod(namespace, podName));
}
/**
......@@ -268,76 +158,41 @@ public class K8sController {
public JsonResult modifyPod(@RequestBody ServiceCreateVo serviceCreateVo) {
log.info("接口/k8s/service/modify收到请求,请求参数为:{}", JSON.toJSONString(serviceCreateVo));
String serviceName = serviceCreateVo.getServiceName();
String type = serviceCreateVo.getType();
String label = serviceCreateVo.getLabel();
String namespace = serviceCreateVo.getNamespace();
// 默认mock为0
if (serviceCreateVo.getMock() == null) {
serviceCreateVo.setMock(0);
}
// 默认设置debug为0
// 默认debug为0
if (serviceCreateVo.getDebug() == null) {
serviceCreateVo.setDebug(0);
}
QueryWrapper<DockerProject> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("project_name", serviceName);
if (label.equals("java")) {
// JAVA
DockerProject dockerProject = dockerProjectService.getOne(queryWrapper);
// 如果不存在Service,则重新创建Service
if (!k8sService.queryIfServiceExistByName(namespace, serviceName)) {
k8sService.createJavaService(namespace, serviceName, serviceCreateVo.getDebug());
}
// 创建Deployment
if (k8sService.queryIfDeploymentExistByName(namespace, serviceName)) {
Deployment deployment = k8sService.getDeployment(namespace, serviceName);
List<Container> containers = deployment.getSpec().getTemplate().getSpec().getContainers();
if (containers != null && containers.size() > 0) {
List<EnvVar> envVarList = containers.get(0).getEnv();
// 根据原来的debug和mock值,来设置debug和mock
for (EnvVar envVar: envVarList) {
if (envVar.getName().equals("DEBUG")) {
serviceCreateVo.setDebug(Integer.valueOf(envVar.getValue()));
}
if (envVar.getName().equals("MOCK")) {
serviceCreateVo.setMock(Integer.valueOf((envVar.getValue())));
}
// 创建或替换Service
tkeService.createServiceByYaml(serviceCreateVo);
// 如果原来服务已存在,则按照原debug和mock的值,设置serviceCreateVo
if (tkeService.checkDeploymentExistence(namespace, serviceName)) {
Deployment deployment = tkeService.getDeployment(namespace, serviceName);
List<Container> containers = deployment.getSpec().getTemplate().getSpec().getContainers();
if (containers != null && containers.size() > 0) {
List<EnvVar> envVarList = containers.get(0).getEnv();
// 根据原来的debug和mock值,来设置debug和mock
for (EnvVar envVar: envVarList) {
if (envVar.getName().equals("DEBUG")) {
serviceCreateVo.setDebug(Integer.valueOf(envVar.getValue()));
}
if (envVar.getName().equals("MOCK")) {
serviceCreateVo.setMock(Integer.valueOf((envVar.getValue())));
}
}
log.info("{}环境{}服务的Deployment已存在,首先删除该Deployment.", namespace, serviceName);
k8sService.deleteDeployment(namespace, serviceName);
}
k8sService.createJavaDeployment(serviceCreateVo, dockerProject);
// 如果不存在ingress则创建ingress
if (!k8sService.queryIfIngressExistByName(namespace, serviceName)) {
k8sService.createIngress(namespace, serviceName, serviceCreateVo.getDomain());
}
} else if (label.equals("ui") || label.equals("node")) {
// UI
DockerProject dockerProject = dockerProjectService.getOne(queryWrapper);
// 如果不存在Service,则重新创建Service
if (!k8sService.queryIfServiceExistByName(namespace, serviceName)) {
k8sService.createUIAndNodeService(namespace, serviceName, type, label);
}
}
// 创建Deployment
if (k8sService.queryIfDeploymentExistByName(namespace, serviceName)) {
log.info("{}环境{}服务的Deployment已存在,首先删除该Deployment.", namespace, serviceName);
k8sService.deleteDeployment(namespace, serviceName);
}
k8sService.createUIAndNodeDeployment(serviceCreateVo, dockerProject);
// 创建或替换Deployment
tkeService.createDeploymentByYaml(serviceCreateVo);
// 创建或替换Ingress
tkeService.createIngressByYaml(serviceCreateVo);
// 如果不存在ingress则创建ingress
if (!k8sService.queryIfIngressExistByName(namespace, serviceName)) {
k8sService.createIngress(namespace, serviceName, serviceCreateVo.getDomain());
}
} else {
return JsonResult.buildErrorStateResult("暂不支持!", false);
}
return JsonResult.buildSuccessResult("镜像部署成功");
}
......@@ -348,46 +203,14 @@ public class K8sController {
*/
@PostMapping("/service/update")
public JsonResult updatePod(@RequestBody ServiceCreateVo serviceCreateVo) {
String namespace = serviceCreateVo.getNamespace();
String serviceName = serviceCreateVo.getServiceName();
String label = serviceCreateVo.getLabel();
String type = serviceCreateVo.getType();
// 获取dockerProject
QueryWrapper<DockerProject> dockerProjectQueryWrapper = new QueryWrapper<>();
dockerProjectQueryWrapper
.eq("project_name", serviceName)
.eq("project_type", type);
DockerProject dockerProject = dockerProjectService.getOne(dockerProjectQueryWrapper);
// 先删除原有pod
if (!k8sService.deleteDeployment(namespace, serviceName)) {
return JsonResult.buildErrorStateResult("更新服务失败!", false);
}
// 再创建新pod
Deployment deployment = null;
// 删除原来的Service
if (k8sService.queryIfServiceExistByName(namespace, serviceName)) {
k8sService.deleteService(namespace, serviceName);
}
// 类型为Java
if (label.equals("java")) {
k8sService.createJavaService(namespace, serviceName, serviceCreateVo.getDebug());
deployment = k8sService.createJavaDeployment(serviceCreateVo, dockerProject);
}
// 类型为UI或Node
if (label.equals("ui") || label.equals("node")) {
k8sService.createUIAndNodeService(namespace, serviceName, type, label);
deployment = k8sService.createUIAndNodeDeployment(serviceCreateVo, dockerProject);
}
// 删除原有Ingress
if (k8sService.queryIfIngressExistByName(namespace, serviceName)) {
k8sService.deleteIngress(namespace, serviceName);
}
// 创建新的Ingress
k8sService.createIngress(namespace, serviceName, serviceCreateVo.getDomain());
if (deployment != null) {
try {
tkeService.createServiceByYaml(serviceCreateVo);
tkeService.createDeploymentByYaml(serviceCreateVo);
tkeService.createIngressByYaml(serviceCreateVo);
return JsonResult.buildSuccessResult("更新成功!", true);
} else {
} catch (Exception e) {
e.printStackTrace();
log.info("更新服务失败: {}", serviceCreateVo);
return JsonResult.buildErrorStateResult("更新失败", false);
}
}
......@@ -399,8 +222,22 @@ public class K8sController {
* @return
*/
@PostMapping("/service/delete")
public JsonResult deletePodByName(String namespace, String serviceName) {
return JsonResult.buildSuccessResult(k8sService.deleteDeployment(namespace, serviceName));
public JsonResult deletePodByName(String namespace, String serviceName, String serviceType) {
try {
// 删除Service
tkeService.deleteService(namespace, serviceName);
// 删除Deployment
tkeService.deleteDeployment(namespace, serviceName);
if (!StringUtils.equals("base", serviceType)) {
// 非基础服务,删除Ingress
tkeService.deleteIngress(namespace, serviceName);
}
return JsonResult.buildSuccessResult("服务删除成功!");
} catch (Exception e) {
e.printStackTrace();
log.info("删除服务异常:namespace: {}, serviceName: {}, serviceType: {}", namespace, serviceName, serviceType);
return JsonResult.buildErrorStateResult("服务删除失败!", false);
}
}
/**
......@@ -469,7 +306,7 @@ public class K8sController {
@PostMapping("/redis/flush")
public JsonResult flushRedis(@RequestParam String namespace) {
try {
Map<String, Object> redisInfo = k8sService.getPodAndServiceInfo(namespace, "base", "redis");
Map<String, Object> redisInfo = tkeService.getPodAndServiceInfo(namespace, "base", "redis");
String lanIp = redisInfo.get("lanIp").toString();
List<Map<String, Object>> portMappings = (List<Map<String, Object>>) redisInfo.get("portMappings");
for (Map<String, Object> portMap: portMappings) {
......@@ -483,14 +320,14 @@ public class K8sController {
}
/**
* 创建新的namespace
* 创建新的namespace,同时需要根据模板构建对应服务
*/
@PostMapping("/namespace/create")
public JsonResult createNewNamespace(@RequestParam String name,
@RequestParam String desc,
@RequestParam String owner,
@RequestParam String templateId) {
boolean createNamespace = k8sService.createNewNamespace(name, desc, owner);
boolean createNamespace = tkeService.createNewNamespace(name, desc, owner);
if (!createNamespace) {
return JsonResult.buildErrorStateResult("环境创建失败!", false);
}
......@@ -499,91 +336,27 @@ public class K8sController {
List<EnvTemplateDetail> envTemplateDetailList = envTemplateDetailService.list(queryWrapper);
for (EnvTemplateDetail envTemplateDetail: envTemplateDetailList) {
String label = envTemplateDetail.getLabel();
String image = envTemplateDetail.getTag();
String serviceName = envTemplateDetail.getServiceName();
String serviceType = envTemplateDetail.getServiceType();
String domain = envTemplateDetail.getDomain();
ServiceCreateVo serviceCreateVo = new ServiceCreateVo();
serviceCreateVo.setServiceName(envTemplateDetail.getServiceName());
serviceCreateVo.setNamespace(name);
serviceCreateVo.setImage(envTemplateDetail.getTag());
serviceCreateVo.setType(envTemplateDetail.getServiceType());
serviceCreateVo.setDebug(0);
serviceCreateVo.setMock(0);
serviceCreateVo.setLabel(envTemplateDetail.getLabel());
serviceCreateVo.setDomain(envTemplateDetail.getDomain());
// 处理基础服务
if (label.equals("base")) {
switch (serviceType) {
case "mysql":
k8sService.createMysqlPvc(name);
k8sService.createMysqlDeployment(name, image);
k8sService.createMysqlService(name);
break;
case "mongodb":
k8sService.createMongodbPvc(name);
k8sService.createMongoDbDeployment(name, image);
k8sService.createMongodbService(name);
break;
case "redis":
k8sService.createRedisDeployment(name, image);
k8sService.createRedisService(name);
break;
case "rabbitmq":
k8sService.createRabbitmqPvc(name);
k8sService.createRabbitmqDeployment(name, image);
k8sService.createRabbitmqService(name);
break;
case "zookeeper":
k8sService.createZookeeperPvc(name);
k8sService.createZookeeperDeployment(name, image);
k8sService.createZookeeperService(name);
break;
default:
break;
}
}
if (label.equals("java")) {
ServiceCreateVo serviceCreateVo = new ServiceCreateVo();
serviceCreateVo.setServiceName(serviceName);
serviceCreateVo.setNamespace(name);
serviceCreateVo.setImage(image);
serviceCreateVo.setType(serviceType);
serviceCreateVo.setDebug(0);
serviceCreateVo.setMock(0);
serviceCreateVo.setLabel(label);
serviceCreateVo.setDomain(domain);
QueryWrapper<DockerProject> dockerProjectQueryWrapper = new QueryWrapper<>();
dockerProjectQueryWrapper
.eq("project_name", serviceName)
.eq("project_type", serviceType)
.eq("is_active", 1)
.eq("deploy_to_docker", 1);
DockerProject dockerProject = dockerProjectService.getOne(dockerProjectQueryWrapper);
dockerProjectQueryWrapper.clear();
if (dockerProject != null) {
k8sService.createJavaDeployment(serviceCreateVo, dockerProject);
k8sService.createJavaService(name, serviceName, serviceCreateVo.getDebug());
k8sService.createIngress(name, serviceName, domain);
}
}
if (label.equals("ui") || label.equals("node")) {
ServiceCreateVo serviceCreateVo = new ServiceCreateVo();
serviceCreateVo.setServiceName(serviceName);
serviceCreateVo.setNamespace(name);
serviceCreateVo.setImage(image);
serviceCreateVo.setType(serviceType);
serviceCreateVo.setDebug(0);
serviceCreateVo.setMock(0);
serviceCreateVo.setLabel(label);
serviceCreateVo.setDomain(domain);
QueryWrapper<DockerProject> dockerProjectQueryWrapper = new QueryWrapper<>();
dockerProjectQueryWrapper
.eq("project_name", serviceName)
.eq("project_type", serviceType)
.eq("is_active", 1)
.eq("deploy_to_docker", 1);
DockerProject dockerProject = dockerProjectService.getOne(dockerProjectQueryWrapper);
dockerProjectQueryWrapper.clear();
if (dockerProject != null) {
k8sService.createUIAndNodeDeployment(serviceCreateVo, dockerProject);
k8sService.createUIAndNodeService(name, serviceName, serviceType, label);
k8sService.createIngress(name, serviceName, domain);
}
tkeService.createPvcByYaml(serviceCreateVo);
tkeService.createServiceByYaml(serviceCreateVo);
tkeService.createDeploymentByYaml(serviceCreateVo);
} else {
// 业务服务
tkeService.createServiceByYaml(serviceCreateVo);
tkeService.createDeploymentByYaml(serviceCreateVo);
tkeService.createIngressByYaml(serviceCreateVo);
}
}
// 删除相关缓存
......@@ -601,12 +374,12 @@ public class K8sController {
UserInfoVo userInfoVo = tokenService.getUserInfoFromCache(token);
Integer roleId = userInfoVo.getRoleIds().get(0);
List<String> nsStrList = new ArrayList<>();
List<Map> nsMapList = new ArrayList<>();
List<Map<String, Object>> nsMapList = new ArrayList<>();
if (roleId == 1 || roleId == 2) {
nsMapList = k8sService.getNamespaceList("all");
nsMapList = tkeService.getNamespaceList("all");
}
if (roleId == 3) {
nsMapList = k8sService.getNamespaceList("dev");
nsMapList = tkeService.getNamespaceList("dev");
}
for (Map map: nsMapList) {
nsStrList.add(map.get("name").toString());
......@@ -621,9 +394,9 @@ public class K8sController {
*/
@GetMapping("/get_namespace_for_jenkins")
public String getNamespaceForJenkins(@RequestParam String env) {
List<Map> mapList = k8sService.getNamespaceList(env);
List<Map<String, Object>> mapList = tkeService.getNamespaceList(env);
List<String> resultList = new ArrayList<>();
for (Map map: mapList) {
for (Map<String, Object> map: mapList) {
resultList.add(map.get("name").toString());
}
resultList.sort(String::compareTo);
......@@ -702,7 +475,7 @@ public class K8sController {
@RequestParam String serviceType,
@RequestParam String serviceName,
@RequestParam String key) {
List<ServicePort> servicePortList = k8sService.getServiceDetail(namespace, serviceName).getSpec().getPorts();
List<ServicePort> servicePortList = tkeService.getServiceDetail(namespace, serviceName).getSpec().getPorts();
Map<String, Object> serviceMap = new HashMap<>();
List<Map<String, Object>> portMappingList = new ArrayList<>();
if (servicePortList.size() > 0) {
......@@ -729,20 +502,6 @@ public class K8sController {
}
}
/**
* 获取k8s环境变量
* @param namespace 环境
* @return
*/
@GetMapping("/listEnvVars")
public Map getListEnvVars(@RequestParam String namespace) {
Map<String, Object> detailMap = k8sService.getListEnvVars(namespace);
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("details", detailMap);
resultMap.put("success", true);
return resultMap;
}
/**
* 删除namespace缓存
* @return
......
......@@ -44,10 +44,10 @@ public class K8sService {
public K8sService() {
try {
String configYAML = String.join("\n", readConfigFile("kube-config.yml"));
String configYAML = String.join("\n", readConfigFile("tke/kube-config.yml"));
Config config = Config.fromKubeconfig(configYAML);
kubernetesClient = new DefaultKubernetesClient(config);
String configCrt = String.join("\n", readConfigFile("tke-cluster-ca.crt"));
String configCrt = String.join("\n", readConfigFile("tke/tke-cluster-ca.crt"));
config.setCaCertData(configCrt);
log.info("k8s连接初始化成功!");
} catch (Exception e) {
......@@ -718,7 +718,7 @@ public class K8sService {
.withPath("/actuator/health/readiness")
.withPort(httpPort)
.build();
s
Probe livenessProbe = new ProbeBuilder()
.withHttpGet(httpGetAction)
.withInitialDelaySeconds(600)
......@@ -2735,62 +2735,6 @@ s
return kubernetesClient.apps().deployments().inNamespace(namespace).withName(serviceName).get();
}
/**
* 获取环境的所有k8s变量
*
* @param namespace 环境
*/
public Map<String, Object> getListEnvVars(String namespace) {
Map<String, Object> envMap = new TreeMap<>();
List<Pod> podList = kubernetesClient.pods().inNamespace(namespace).list().getItems();
List<Service> serviceList = kubernetesClient.services().inNamespace(namespace).list().getItems();
// 遍历Pod列表
for (Pod pod : podList) {
if (!pod.getStatus().getPhase().equals("Failed")) {
String serviceName = pod.getMetadata().getLabels().get("qcloud-app");
serviceName = serviceName.replace("-", "_").toUpperCase();
envMap.put(serviceName + "_SERVICE_HOST", pod.getStatus().getHostIP());
// MYSQL需要额外加个参数
if (serviceName.equals("MYSQL")) {
envMap.put("DB_SERVICE_HOST", pod.getStatus().getHostIP());
}
}
}
// 遍历Service列表
for (Service service : serviceList) {
String serviceName = service.getMetadata().getName().toUpperCase().replaceAll("-", "_");
List<ServicePort> servicePortList = service.getSpec().getPorts();
if (service.getMetadata().getLabels().get("type").equals("base")) {
if (servicePortList.get(0).getPort() != null) {
envMap.put(serviceName + "_SERVICE_PORT", servicePortList.get(0).getNodePort());
// MYSQL需要额外加个参数
if (serviceName.equals("MYSQL")) {
envMap.put("DB_SERVICE_PORT", servicePortList.get(0).getNodePort());
}
}
for (ServicePort servicePort : servicePortList) {
envMap.put(serviceName + "_SERVICE_PORT_" + servicePort.getPort(), servicePort.getNodePort());
// MYSQL需要额外加个参数
if (serviceName.equals("MYSQL")) {
envMap.put("DB_SERVICE_PORT_" + servicePort.getPort(), servicePort.getNodePort());
}
}
} else {
if (servicePortList.get(0).getNodePort() != null) {
envMap.put(serviceName + "_SERVICE_PORT", servicePortList.get(0).getNodePort());
}
for (ServicePort servicePort : servicePortList) {
if (service.getSpec().getType().equals("NodePort")) {
envMap.put(serviceName + "_SERVICE_PORT_" + servicePort.getPort(), servicePort.getNodePort());
} else if (service.getSpec().getType().equals("ClusterIP")) {
envMap.put(serviceName + "_SERVICE_PORT_" + servicePort.getName(), servicePort.getPort());
}
}
}
}
return envMap;
}
/**
* 删除namespace列表缓存
*/
......
package cn.qg.holmes.service.k8s;
import cn.qg.holmes.entity.k8s.DockerProject;
import cn.qg.holmes.entity.k8s.ServiceCreateVo;
import cn.qg.holmes.utils.DateUtils;
import cn.qg.holmes.utils.FileUtils;
import cn.qg.holmes.utils.TkeUtils;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.fabric8.kubernetes.api.model.*;
import io.fabric8.kubernetes.api.model.apps.Deployment;
import io.fabric8.kubernetes.api.model.extensions.Ingress;
import io.fabric8.kubernetes.client.Config;
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClient;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.HttpGet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import java.io.IOException;
import java.util.*;
/**
* TKE集群k8s相关操作
*/
@Slf4j
@Component
public class TkeService {
@Value("${no.healthcheck.service}")
private String noHealthCheckService;
@Value("${no.healthcheck.service}")
private String gylHealthCheckService;
@Autowired
DockerProjectService dockerProjectService;
private KubernetesClient kubernetesClient;
public TkeService() {
try {
String configYAML = FileUtils.readFileFromClassPathResource("tke/kube-config.yml");
Config config = Config.fromKubeconfig(configYAML);
kubernetesClient = new DefaultKubernetesClient(config);
String configCrt = FileUtils.readFileFromClassPathResource("tke/tke-cluster-ca.crt");
config.setCaCertData(configCrt);
log.info("TKE qa集群k8s连接成功!");
} catch (Exception e) {
log.info("TKE qa集群k8s连接失败!");
e.printStackTrace();
}
}
/**
* 创建新的namespace
*
* @param name namespace名称
* @param desc dev/test
* @param owner
* @return
*/
public boolean createNewNamespace(String name, String desc, String owner) {
try {
ObjectMeta objectMeta = new ObjectMeta();
Map<String, String> annotations = new HashMap<>();
annotations.put("description", desc);
annotations.put("owner", owner);
objectMeta.setAnnotations(annotations);
objectMeta.setName(name);
NamespaceSpec namespaceSpec = new NamespaceSpec();
List<String> finalizers = new ArrayList<>();
finalizers.add("kubernetes");
namespaceSpec.setFinalizers(finalizers);
NamespaceStatus namespaceStatus = new NamespaceStatus();
namespaceStatus.setPhase("Active");
Namespace namespace = new NamespaceBuilder()
.withApiVersion("v1")
.withKind("Namespace")
.withMetadata(objectMeta)
.withSpec(namespaceSpec)
.withStatus(namespaceStatus)
.build();
log.info("开始创建新的环境: {}", namespace.toString());
Namespace namespaceResponse = kubernetesClient.namespaces().create(namespace);
log.info("创建环境返回结果:{}", namespaceResponse.toString());
createQcloudRegistryKeySecret(name);
createTencenthHubKeySecret(name);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
public Secret createQcloudRegistryKeySecret(String namespace) {
Map<String, String> labels = new HashMap<>();
labels.put("qcloud-app", "qcloudregistrykey");
ObjectMeta objectMeta = new ObjectMetaBuilder()
.withLabels(labels)
.withName("tencenthubkey")
.withNamespace(namespace)
.build();
Map<String, String> data = new HashMap<>();
data.put(".dockercfg", "eyJjY3IuY2NzLnRlbmNlbnR5dW4uY29tIjp7InVzZXJuYW1lIjoiMTAwMDA4NjMyMjY5IiwicGFzc3dvcmQiOiJ7QXBwbGljYXRpb25Ub2tlbjo0MTM1NWY2OWQyY2U3ZWUyYmE2YjQxZmMxNzJlNzM0MH0iLCJlbWFpbCI6IjEwMDAwODYzMjI2OUBxcS5jb20iLCJhdXRoIjoiTVRBd01EQTROak15TWpZNU9udEJjSEJzYVdOaGRHbHZibFJ2YTJWdU9qUXhNelUxWmpZNVpESmpaVGRsWlRKaVlUWmlOREZtWXpFM01tVTNNelF3ZlE9PSJ9fQ==");
Secret secret = new SecretBuilder()
.withApiVersion("v1")
.withKind("Secret")
.withType("kubernetes.io/dockercfg")
.withMetadata(objectMeta)
.withData(data)
.build();
log.info("{}环境,创建新的secret:qcloudregistrykey", namespace);
return kubernetesClient.secrets().inNamespace(namespace).create(secret);
}
public Secret createTencenthHubKeySecret(String namespace) {
Map<String, String> labels = new HashMap<>();
labels.put("qcloud-app", "tencenthubkey");
ObjectMeta objectMeta = new ObjectMetaBuilder()
.withLabels(labels)
.withName("tencenthubkey")
.withNamespace(namespace)
.build();
Map<String, String> data = new HashMap<>();
data.put(".dockercfg", "eyJodWIudGVuY2VudHl1bi5jb20iOnsidXNlcm5hbWUiOiIxMDAwMDg2MzIyNjkiLCJwYXNzd29yZCI6ImV5SmhiR2NpT2lKSVV6STFOaUlzSW5SNWNDSTZJa3BYVkNKOS5leUpsZUhBaU9qRTROell5T1RFME9EVXNJbXAwYVNJNklqVTVPVGRqTmpkaExUWmpaV1l0TkRGbE55MDVPRGsyTFdGaE16TTFPRGRpWW1ReE1TSXNJbWxoZENJNk1UVTJNRGt6TVRRNE5Td2libUptSWpveE5UWXdPVE14TkRnMUxDSnpkV0lpT2lJeE1EQXdNRGcyTXpJeU5qa2lmUS5ZWEl4TzBaWTg3QmNzSktLdW9lQ3gzYllLZ1RzMktNVElSeDd5dWVRdDZNIiwiZW1haWwiOiIxMDAwMDg2MzIyNjlAcXEuY29tIiwiYXV0aCI6Ik1UQXdNREE0TmpNeU1qWTVPbVY1U21oaVIyTnBUMmxLU1ZWNlNURk9hVWx6U1c1U05XTkRTVFpKYTNCWVZrTktPUzVsZVVwc1pVaEJhVTlxUlRST2VsbDVUMVJGTUU5RVZYTkpiWEF3WVZOSk5rbHFWVFZQVkdScVRtcGthRXhVV21wYVYxbDBUa1JHYkU1NU1EVlBSR3N5VEZkR2FFMTZUVEZQUkdScFdXMVJlRTFUU1hOSmJXeG9aRU5KTmsxVVZUSk5SR3Q2VFZSUk5FNVRkMmxpYlVwdFNXcHZlRTVVV1hkUFZFMTRUa1JuTVV4RFNucGtWMGxwVDJsSmVFMUVRWGROUkdjeVRYcEplVTVxYTJsbVVTNVpXRWw0VHpCYVdUZzNRbU56U2t0TGRXOWxRM2d6WWxsTFoxUnpNa3ROVkVsU2VEZDVkV1ZSZERaTiJ9fQ==");
Secret secret = new SecretBuilder()
.withApiVersion("v1")
.withKind("Secret")
.withType("kubernetes.io/dockercfg")
.withMetadata(objectMeta)
.withData(data)
.build();
log.info("{}环境,创建新的secret:tencenthubkey", namespace);
return kubernetesClient.secrets().inNamespace(namespace).create(secret);
}
/**
* 获取namespace列表
* @param env all-所有,dev-开发环境,test-测试环境
* @return
*/
public List<Map<String, Object>> getNamespaceList(String env) {
List<Map<String, Object>> resultList = new ArrayList<>();
List<Namespace> allNamespaceList = kubernetesClient.namespaces().list().getItems();
List<Namespace> namespaceList = new ArrayList<>();
if (StringUtils.equals(env, "all")) {
for (Namespace namespace: allNamespaceList) {
// 剔除一些系统创建的namespace
if (namespace.getMetadata().getAnnotations() != null) {
namespaceList.add(namespace);
}
}
} else {
for (Namespace namespace: allNamespaceList) {
if (namespace.getMetadata().getAnnotations() != null && namespace.getMetadata().getAnnotations().get("description").equals(env)) {
namespaceList.add(namespace);
}
}
}
for (Namespace namespace : namespaceList) {
String name = namespace.getMetadata().getName();
// 获取Service
Service service = kubernetesClient.services().inNamespace(name).withName("mysql").get();
// 获取Pod
Map<String, String> labels = TkeUtils.StringArrayToMap(new String[]{"qcloud-app", "mysql", "type", "base"});
List<Pod> podList = kubernetesClient.pods().inNamespace(name).withLabels(labels).list().getItems();
Integer port = null;
String host = null;
if (service != null) {
port = service.getSpec().getPorts().get(0).getNodePort();
}
for (Pod pod : podList) {
if (StringUtils.equals(pod.getStatus().getPhase(), "Running")) {
host = podList.get(0).getStatus().getHostIP();
}
}
Map<String, Object> map = new HashMap<>();
map.put("name", name);
map.put("description", namespace.getMetadata().getAnnotations().get("description"));
map.put("owner", namespace.getMetadata().getAnnotations().get("owner"));
map.put("status", namespace.getStatus().getPhase());
map.put("mysqlHost", host);
map.put("mysqlPort", port);
try {
map.put("createdAt", DateUtils.convertTZStr(namespace.getMetadata().getCreationTimestamp(), "yyyy-MM-dd HH:mm:ss"));
} catch (Exception e) {
log.info("时间解析异常!");
e.printStackTrace();
map.put("createdAt", namespace.getMetadata().getCreationTimestamp());
}
resultList.add(map);
}
return resultList;
}
/**
* 获取pod列表
* @param namespace
* @return
*/
public List<Map<String, Object>> getPodList(String namespace) {
// 获取Pod列表
List<Pod> podList = kubernetesClient.pods().inNamespace(namespace).list().getItems();
// 获取Service列表
List<Service> serviceList = kubernetesClient.services().inNamespace(namespace).list().getItems();
// 获取ingress列表
List<Ingress> ingressList = kubernetesClient.extensions().ingresses().inNamespace(namespace).list().getItems();
Map<String, Map<String, Object>> podServiceMap = new HashMap<>();
// 遍历Pod列表
for (Pod pod: podList) {
if (!pod.getStatus().getPhase().equals("Failed")) {
String serviceName = pod.getMetadata().getLabels().get("qcloud-app");
podServiceMap.put(serviceName, formatPodInfo(pod));
}
}
// 遍历Service列表
for (Service service: serviceList) {
String serviceName = service.getMetadata().getName();
podServiceMap = assign(serviceName, podServiceMap, formatServiceInfo(service));
}
// 遍历Ingress列表
for (Ingress ingress: ingressList) {
String serviceName = ingress.getMetadata().getName();
podServiceMap = assign(serviceName, podServiceMap, formatIngressInfo(ingress));
}
// 对象转列表
List<Map<String, Object>> resultList = new ArrayList<>();
for (Map<String, Object> map: podServiceMap.values()) {
if ((map != null) && (map.get("serviceName") != null)) {
resultList.add(map);
}
}
// 根据serviceName对列表进行排序
Collections.sort(resultList, (m1, m2) -> {
String serviceName1 = m1.get("serviceName").toString();
String serviceName2 = m2.get("serviceName").toString();
return serviceName1.compareTo(serviceName2);
});
return resultList;
}
public Map<String, Map<String, Object>> assign(String serviceName, Map<String, Map<String, Object>> podServiceMap, Map<String, Object> otherMap) {
Map<String, Object> podService = podServiceMap.get(serviceName);
for (Map.Entry<String, Object> entry: otherMap.entrySet()) {
if (podService != null) {
podService.put(entry.getKey(), entry.getValue());
}
}
podServiceMap.put(serviceName, podService);
return podServiceMap;
}
/**
* 处理pod相关信息
* @param pod
* @return
*/
public Map<String, Object> formatPodInfo(Pod pod) {
Map<String, Object> podMap = new HashMap<>();
String serviceName = pod.getMetadata().getLabels().get("qcloud-app");
podMap.put("serviceName", serviceName);
podMap.put("podName", pod.getMetadata().getName());
podMap.put("status", getPodStatus(pod));
podMap.put("podIp", pod.getStatus().getPodIP());
podMap.put("lanIp", pod.getStatus().getHostIP());
// 特殊处理,格式化创建时间
try {
if (pod.getStatus().getStartTime() != null) {
podMap.put("createdAt", DateUtils.convertTZStr(pod.getStatus().getStartTime(), "yyyy-MM-dd HH:mm:ss"));
} else {
podMap.put("createdAt", DateUtils.convertDate(new Date(), "yyyy-MM-dd HH:mm:ss"));
}
} catch (Exception e) {
e.printStackTrace();
log.info("时间转换异常!");
podMap.put("createdAt", pod.getStatus().getStartTime());
}
if (pod.getStatus().getContainerStatuses().size() > 0) {
podMap.put("image", pod.getStatus().getContainerStatuses().get(0).getImage());
podMap.put("imageId", pod.getStatus().getContainerStatuses().get(0).getImageID());
} else {
podMap.put("image", null);
podMap.put("imageId", null);
}
if (pod.getMetadata().getLabels() != null) {
podMap.put("labels", pod.getMetadata().getLabels());
// 对于非基础服务,新增服务描述,方便前端展示
if (!StringUtils.equals(pod.getMetadata().getLabels().get("type"), "base")) {
QueryWrapper<DockerProject> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("project_name", serviceName);
DockerProject dockerProject = dockerProjectService.getOne(queryWrapper);
if (dockerProject != null) {
podMap.put("desc", dockerProject.getDesc());
}
}
}
return podMap;
}
/**
* 格式化pod状态
* @param pod
* @return
*/
public String getPodStatus(Pod pod) {
if (pod.getMetadata().getDeletionTimestamp() != null) {
return "Terminating";
} else {
String status = "";
List<ContainerStatus> containerStatuses = pod.getStatus().getContainerStatuses();
if (containerStatuses.size() == 0) {
status = "Pending";
} else {
if (containerStatuses.get(0).getState().getWaiting() != null) {
status = "ContainerCreating";
}
if (containerStatuses.get(0).getState().getRunning() != null && !containerStatuses.get(0).getReady()) {
status = "Waiting";
}
if (containerStatuses.get(0).getState().getRunning() != null && containerStatuses.get(0).getReady()) {
status = "Normal";
}
}
return status;
}
}
/**
* 格式化k8s Service
* @param service
* @return
*/
public Map<String, Object> formatServiceInfo(Service service) {
Map<String, Object> serviceMap = new HashMap<>();
serviceMap.put("serviceType", service.getSpec().getType());
List<Map<String, Object>> portMappingList = new ArrayList<>();
List<ServicePort> servicePortList = service.getSpec().getPorts();
if (servicePortList.size() > 0) {
for (ServicePort servicePort : servicePortList) {
if (servicePort.getNodePort() != null) {
serviceMap.put("port_" + servicePort.getName(), servicePort.getNodePort());
}
Map<String, Object> portMap = new HashMap<>();
portMap.put("name", servicePort.getName());
portMap.put("nodePort", servicePort.getNodePort());
portMap.put("port", servicePort.getPort());
portMap.put("protocol", servicePort.getProtocol());
portMap.put("targetPort", servicePort.getTargetPort());
portMappingList.add(portMap);
}
}
if (portMappingList.size() > 0) {
serviceMap.put("portMappings", portMappingList);
}
return serviceMap;
}
/**
* 格式化k8s Ingress
* @param ingress
* @return
*/
public Map<String, Object> formatIngressInfo(Ingress ingress) {
Map<String, Object> ingressMap = new HashMap<>();
if (ingress.getSpec().getRules() != null && ingress.getSpec().getRules().size() > 0) {
ingressMap.put("host", ingress.getSpec().getRules().get(0).getHost());
} else {
ingressMap.put("host", "");
}
return ingressMap;
}
/**
* 获取Service详情
* @param namespace 环境
* @param serviceName service名称
* @return
*/
public Service getServiceDetail(String namespace, String serviceName) {
return kubernetesClient.services().inNamespace(namespace).withName(serviceName).get();
}
/**
* 获取pod和service的一些信息
* @param namespace
* @param serviceType
* @param serviceName
* @return
*/
public Map<String, Object> getPodAndServiceInfo(String namespace, String serviceType, String serviceName) {
Service service = kubernetesClient.services().inNamespace(namespace).withName(serviceName).get();
Pod pod = getPodDetail(namespace, serviceType, serviceName);
Map<String, Object> map = new HashMap<>();
if (pod != null && pod.getStatus().getPhase().equals("Running")) {
// 端口映射
List<Map<String, Object>> portMappingList = new ArrayList<>();
ObjectMeta podMetadata = pod.getMetadata();
if (service != null) {
List<ServicePort> servicePortList = service.getSpec().getPorts();
if (servicePortList.size() > 0) {
for (ServicePort servicePort : servicePortList) {
if (servicePort.getNodePort() != null) {
map.put("port_" + servicePort.getName(), servicePort.getNodePort());
}
Map<String, Object> portMap = new HashMap<>();
portMap.put("name", servicePort.getName());
portMap.put("nodePort", servicePort.getNodePort());
portMap.put("port", servicePort.getPort());
portMap.put("protocol", servicePort.getProtocol());
portMap.put("targetPort", servicePort.getTargetPort());
portMappingList.add(portMap);
}
}
if (portMappingList.size() > 0) {
map.put("portMappings", portMappingList);
}
}
map.put("createdAt", podMetadata.getCreationTimestamp());
map.put("serviceName", serviceName);
map.put("podName", podMetadata.getName());
map.put("labels", podMetadata.getLabels());
List<ContainerStatus> containerStatuses = pod.getStatus().getContainerStatuses();
map.put("image", pod.getStatus().getContainerStatuses().get(0).getImage());
map.put("imageId", pod.getStatus().getContainerStatuses().get(0).getImageID());
map.put("lanIp", pod.getStatus().getHostIP());
map.put("podIp", pod.getStatus().getPodIP());
map.put("startTime", pod.getStatus().getStartTime());
map.put("status", containerStatuses.get(0).getReady());
Ingress ingress = kubernetesClient.extensions().ingresses().inNamespace(namespace).withName(serviceName).get();
if (ingress != null) {
if (ingress.getSpec().getRules() != null && ingress.getSpec().getRules().size() > 0) {
map.put("host", ingress.getSpec().getRules().get(0).getHost());
} else {
map.put("host", "");
}
}
}
return map;
}
public Pod getPodDetail(String namespace, String serviceType, String serviceName) {
Map<String, String> labelMap = TkeUtils.StringArrayToMap(new String[] {"type", serviceType, "qcloud-app", serviceName});
LabelSelector labelSelector = new LabelSelectorBuilder().withMatchLabels(labelMap).build();
List<Pod> podList = kubernetesClient.pods().inNamespace(namespace).withLabelSelector(labelSelector).list().getItems();
for (Pod pod: podList) {
// pod可能有多个,返回Running状态的pod
if (pod.getStatus().getPhase().equals("Running")) {
return pod;
}
}
return null;
}
/**
* 重置pod
* @param namespace 环境
* @param podName podName
* @return
*/
public boolean resetPod(String namespace, String podName) {
return kubernetesClient.pods().inNamespace(namespace).withName(podName).delete();
}
/**
* 获取Deployment
*
* @param namespace
* @param serviceName
* @return
*/
public Deployment getDeployment(String namespace, String serviceName) {
return kubernetesClient.apps().deployments().inNamespace(namespace).withName(serviceName).get();
}
/**
* 删除一个Deployment
*
* @param namespace 环境
* @param serviceName 服务名
* @return
*/
public boolean deleteDeployment(String namespace, String serviceName) {
log.info("删除{}环境{}的deployment.", namespace, serviceName);
return kubernetesClient.apps().deployments().inNamespace(namespace).withName(serviceName).delete();
}
public boolean deleteService(String namespace, String serviceName) {
return kubernetesClient.services().inNamespace(namespace).withName(serviceName).delete();
}
public boolean deleteIngress(String namespace, String serviceName) {
return kubernetesClient.extensions().ingresses().inNamespace(namespace).withName(serviceName).delete();
}
/**
* 通过.yml文件创建Deployment
* @param serviceCreateVo
* @return
*/
public Deployment createDeploymentByYaml(ServiceCreateVo serviceCreateVo) {
String serviceType = serviceCreateVo.getType();
String serviceName = serviceCreateVo.getServiceName();
String namespace = serviceCreateVo.getNamespace();
String deploymentYaml;
try {
switch (serviceType) {
case "base":
String yamlFilePath = "tke/template/" + StringUtils.capitalize(serviceName) + "-Deployment.yml";
deploymentYaml = FileUtils.readFileFromClassPathResource(yamlFilePath);
deploymentYaml = TkeUtils.replaceBasicYaml(deploymentYaml, serviceCreateVo);
// kafka还需替换下zookeeper地址和本身的Service port
if (StringUtils.equals(serviceName, "kafka")) {
Map<String, Object> zookeeperInfo = getPodAndServiceInfo(namespace, "base", "zookeeper");
deploymentYaml = deploymentYaml.replaceAll("\\{\\{ZOOKEEPER_HOST}", zookeeperInfo.get("lanIp").toString());
deploymentYaml = deploymentYaml.replaceAll("\\{\\{ZOOKEEPER_PORT}}", zookeeperInfo.get("port_2181").toString());
int count = 10;
Service kafkaService;
while (count > 0) {
try {
kafkaService = getServiceDetail(namespace, "kafka-" + namespace);
if (kafkaService != null) {
deploymentYaml.replaceAll("\\{\\{KAFKA_SERVICE_PORT}}", String.valueOf(kafkaService.getSpec().getPorts().get(0).getNodePort()));
break;
}
Thread.currentThread().sleep(1000);
} catch (Exception e) {
e.printStackTrace();
break;
}
count -= 1;
}
}
break;
case "java":
DockerProject javaProject = dockerProjectService.getOne(Wrappers.lambdaQuery(DockerProject.class)
.eq(DockerProject::getProjectName, serviceCreateVo.getServiceName()));
if (javaProject == null) {
log.info("该项目未在后台配置,暂不创建Java Deployment:{}", JSON.toJSONString(serviceCreateVo));
return null;
}
deploymentYaml = FileUtils.readFileFromClassPathResource("tke/template/Java-Deployment.yml");
deploymentYaml = TkeUtils.replaceBusinessYaml(deploymentYaml, serviceCreateVo, javaProject);
break;
case "ui":
case "node":
DockerProject uiOrNodeProject = dockerProjectService.getOne(Wrappers.lambdaQuery(DockerProject.class)
.eq(DockerProject::getProjectName, serviceCreateVo.getServiceName()));
if (uiOrNodeProject == null) {
log.info("该项目未在后台配置,暂不创建UI Deployment:{}", JSON.toJSONString(serviceCreateVo));
return null;
}
deploymentYaml = FileUtils.readFileFromClassPathResource("tke/template/UI-Node-Deployment.yml");
deploymentYaml = TkeUtils.replaceBusinessYaml(deploymentYaml, serviceCreateVo, uiOrNodeProject);
break;
default:
log.info("暂不支持{}类型的deployment", serviceType);
return null;
}
Yaml yaml = new Yaml(new Constructor(Deployment.class));
Deployment deployment = yaml.load(deploymentYaml);
// 健康检查白名单里的,去掉健康检查
List<String> noHealthCheckServiceList = Arrays.asList(noHealthCheckService.split(","));
if (noHealthCheckServiceList.contains(serviceName)) {
deployment.getSpec().getTemplate().getSpec().getContainers().forEach(container -> container.setReadinessProbe(null));
deployment.getSpec().getTemplate().getSpec().getContainers().forEach(container -> container.setLivenessProbe(null));
}
// 供应链健康检查单独处理下
List<String> gylHealthCheckServiceList = Arrays.asList(gylHealthCheckService.split(","));
if (gylHealthCheckServiceList.contains(serviceName)) {
Probe readinessProbe = createHttpReadinessProbe("/actuator/health/readiness", 80);
Probe livelinessProbe = createHttpLivenessProbe("/actuator/health/readiness", 80);
deployment.getSpec().getTemplate().getSpec().getContainers().forEach(container -> container.setReadinessProbe(readinessProbe));
deployment.getSpec().getTemplate().getSpec().getContainers().forEach(container -> container.setLivenessProbe(livelinessProbe));
}
return kubernetesClient.apps().deployments().inNamespace(namespace).createOrReplace(deployment);
} catch (IOException e) {
log.info("创建Deployment失败!");
e.printStackTrace();
return null;
}
}
/**
* 通过.yml文件创建Service
* @param serviceCreateVo
* @return
*/
public Service createServiceByYaml(ServiceCreateVo serviceCreateVo) {
String serviceType = serviceCreateVo.getType();
String serviceName = serviceCreateVo.getServiceName();
String namespace = serviceCreateVo.getNamespace();
String serviceYaml;
try {
switch (serviceType) {
case "base":
String yamlFilePath = "tke/template/" + StringUtils.capitalize(serviceName) + "-Service.yml";
serviceYaml = FileUtils.readFileFromClassPathResource(yamlFilePath);
serviceYaml = TkeUtils.replaceBasicYaml(serviceYaml, serviceCreateVo);
break;
case "java":
serviceYaml = FileUtils.readFileFromClassPathResource("tke/template/Java-Service.yml");
serviceYaml = TkeUtils.replaceBusinessYaml(serviceYaml, serviceCreateVo, null);
break;
case "node":
case "ui":
serviceYaml = FileUtils.readFileFromClassPathResource("tke/template/UI-Node-Service.yml");
serviceYaml = TkeUtils.replaceBusinessYaml(serviceYaml, serviceCreateVo, null);
break;
default:
log.info("暂不支持创建{}类型的k8s Service.", serviceType);
return null;
}
Yaml yaml = new Yaml(new Constructor(Service.class));
Service service = yaml.load(serviceYaml);
return kubernetesClient.services().inNamespace(namespace).createOrReplace(service);
} catch (IOException e) {
log.info("Service创建失败.");
e.printStackTrace();
return null;
}
}
/**
* 通过.yml文件创建PVC
* @param serviceCreateVo
* @return
*/
public PersistentVolumeClaim createPvcByYaml(ServiceCreateVo serviceCreateVo) {
String namespace = serviceCreateVo.getNamespace();
String serviceName = serviceCreateVo.getServiceName();
if (serviceName.contains("redis")) {
log.info("redis不需要创建pvc.");
return null;
}
try {
String pvcFilePath = "tke/template/" + StringUtils.capitalize(serviceName) + "-Pvc.yml";
String pvcYaml = FileUtils.readFileFromClassPathResource(pvcFilePath);
pvcYaml = TkeUtils.replaceBasicYaml(pvcYaml, serviceCreateVo);
log.info("开始创建Pvc:\n{}", pvcYaml);
Yaml yaml = new Yaml(new Constructor(PersistentVolumeClaim.class));
PersistentVolumeClaim persistentVolumeClaim = yaml.load(pvcYaml);
return kubernetesClient.persistentVolumeClaims().inNamespace(namespace).create(persistentVolumeClaim);
} catch (IOException e) {
log.info("PVC创建失败!");
e.printStackTrace();
return null;
}
}
/**
* 通过Yaml文件创建Ingress
* @param serviceCreateVo
* @return
*/
public Ingress createIngressByYaml(ServiceCreateVo serviceCreateVo) {
try {
String ingressYaml = FileUtils.readFileFromClassPathResource("tke/template/Ingress.yml");
ingressYaml = TkeUtils.replaceBusinessYaml(ingressYaml, serviceCreateVo, null);
log.info("\n开始创建Ingress:\n{}", ingressYaml);
Yaml yaml = new Yaml(new Constructor(Ingress.class));
Ingress ingress = yaml.load(ingressYaml);
IntOrString servicePort = new IntOrStringBuilder().withIntVal(80).build();
ingress.getSpec().getRules().get(0).getHttp().getPaths().get(0).getBackend().setServicePort(servicePort);
return kubernetesClient.extensions().ingresses().inNamespace(serviceCreateVo.getNamespace()).createOrReplace(ingress);
} catch (IOException e) {
log.info("Ingress 创建失败!");
e.printStackTrace();
return null;
}
}
/**
* 查看某个namespace中Deployment是否已存在
* @param namespace 环境名
* @param serviceName 服务名
* @return
*/
public boolean checkDeploymentExistence(String namespace, String serviceName) {
return kubernetesClient.apps().deployments().inNamespace(namespace).withName(serviceName).get() != null;
}
/**
* 查看某个namespace中pvc是否已存在
* @param namespace 环境名
* @param serviceName 服务名
* @return
*/
public boolean checkPvcExistence(String namespace, String serviceName) {
return kubernetesClient.persistentVolumeClaims().inNamespace(namespace).withName(serviceName + "-" + namespace).get() != null;
}
/**
* 创建Http类型的存活检查
* @param path
* @param port
* @return
*/
public Probe createHttpLivenessProbe(String path, Integer port) {
HTTPGetAction httpGetAction = new HTTPGetActionBuilder()
.withPath("/")
.withPort(new IntOrStringBuilder().withIntVal(80).build())
.build();
Probe livenessProbe = new ProbeBuilder()
.withHttpGet(httpGetAction)
.withInitialDelaySeconds(600)
.withTimeoutSeconds(5)
.withPeriodSeconds(60)
.withSuccessThreshold(1)
.withFailureThreshold(3)
.build();
return livenessProbe;
}
/**
* 创建Http类型的就绪检查
* @param path
* @param port
* @return
*/
public Probe createHttpReadinessProbe(String path, Integer port) {
HTTPGetAction httpGetAction = new HTTPGetActionBuilder()
.withPath(path)
.withPort(new IntOrStringBuilder().withIntVal(port).build())
.build();
Probe readinessProbe = new ProbeBuilder()
.withHttpGet(httpGetAction)
.withInitialDelaySeconds(10)
.withTimeoutSeconds(5)
.withPeriodSeconds(10)
.withSuccessThreshold(1)
.withFailureThreshold(3)
.build();
return readinessProbe;
}
}
......@@ -3,10 +3,12 @@ package cn.qg.holmes.utils;
import org.apache.commons.lang3.time.FastDateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
/**
* 日期格式化工具类
......@@ -34,6 +36,21 @@ public class DateUtils {
.parse(date);
}
/**
* 将带T和Z的字符串日期格式化
* @param tzDate
* @param pattern
* @return
* @throws ParseException
*/
public static String convertTZStr(String tzDate, String pattern) throws ParseException {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
return FastDateFormat
.getInstance(pattern)
.format(simpleDateFormat.parse(tzDate));
}
public static long betweenDays(Date dateBefore, Date dateAfter) {
return Duration.between(toLocalDate(dateBefore).atStartOfDay(), toLocalDate(dateAfter).atStartOfDay())
.toDays();
......
package cn.qg.holmes.utils;
import org.springframework.core.io.ClassPathResource;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class FileUtils {
/**
* 从resources目录下读取文件内容
* @param file 配置文件名
*/
public static String readFileFromClassPathResource(String file) throws IOException {
String str = "";
ClassPathResource resource = new ClassPathResource(file);
InputStream in = resource.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
List<String> result = new ArrayList<>();
while ((str = br.readLine()) != null) {
result.add(str);
}
return String.join("\n", result);
}
}
package cn.qg.holmes.utils;
import cn.qg.holmes.entity.k8s.DockerProject;
import cn.qg.holmes.entity.k8s.ServiceCreateVo;
import org.apache.commons.lang3.StringUtils;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
public class TkeUtils {
/**
* 替换业务yaml文件
* @param sourceString
* @param serviceCreateVo
* @param dockerProject
* @return
*/
public static String replaceBusinessYaml(String sourceString, ServiceCreateVo serviceCreateVo, DockerProject dockerProject) {
if (!Objects.isNull(serviceCreateVo)) {
sourceString = sourceString.replaceAll("\\{\\{serviceName}}", serviceCreateVo.getServiceName());
sourceString = sourceString.replaceAll("\\{\\{namespace}}", serviceCreateVo.getNamespace());
sourceString = sourceString.replaceAll("\\{\\{mock}}", String.valueOf(serviceCreateVo.getMock()));
sourceString = sourceString.replaceAll("\\{\\{debug}}", String.valueOf(serviceCreateVo.getDebug()));
sourceString = sourceString.replaceAll("\\{\\{label}}", serviceCreateVo.getLabel());
sourceString = sourceString.replaceAll("\\{\\{image}}", serviceCreateVo.getImage());
sourceString = sourceString.replaceAll("\\{\\{domain}}", serviceCreateVo.getDomain());
sourceString = sourceString.replaceAll("\\{\\{type}}", serviceCreateVo.getType());
}
if (!Objects.isNull(dockerProject)) {
sourceString = sourceString.replaceAll("\\{\\{resources.cpuRequest}}", dockerProject.getCpuRequest());
sourceString = sourceString.replaceAll("\\{\\{resources.memRequest}}", dockerProject.getMemRequest());
sourceString = sourceString.replaceAll("\\{\\{resources.cpuLimit}}", dockerProject.getCpuLimit());
sourceString = sourceString.replaceAll("\\{\\{resources.memLimit}}", dockerProject.getMemLimit());
}
return sourceString;
}
/**
* 替换基础服务yaml文件
* @param sourceString
* @param serviceCreateVo
* @return
*/
public static String replaceBasicYaml(String sourceString, ServiceCreateVo serviceCreateVo) {
String namespace = serviceCreateVo.getNamespace();
String image = serviceCreateVo.getImage();
if (!StringUtils.isEmpty(namespace)) {
sourceString = sourceString.replaceAll("\\{\\{namespace}}", namespace);
}
if (!StringUtils.isEmpty(image)) {
sourceString = sourceString.replaceAll("\\{\\{image}}", image);
}
return sourceString;
}
/**
* 字符串数组转Map
* @param strArray 字符串数组
* @return
*/
public static Map<String, String> StringArrayToMap(String[] strArray) {
// 字符串数组长度必须大于0且为偶数个
if (strArray.length == 0 || strArray.length % 2 != 0) {
return null;
}
Map<String, String> resultMap = new HashMap<>();
for (int i=0; i < strArray.length; i=i+2) {
resultMap.put(strArray[i], strArray[i+1]);
}
return resultMap;
}
}
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: traefik
name: {{serviceName}}
namespace: {{namespace}}
spec:
rules:
- host: {{domain}}-{{namespace}}.xrtan.com
http:
paths:
- backend:
serviceName: {{serviceName}}
servicePort: 80
path: /
pathType: ImplementationSpecific
\ No newline at end of file
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{serviceName}}
namespace: {{namespace}}
labels:
type: {{label}}
qcloud-app: {{serviceName}}
spec:
replicas: 1
revisionHistoryLimit: 1
selector:
matchLabels:
qcloud-app: {{serviceName}}
strategy:
type: Recreate
template:
metadata:
labels:
qcloud-app: {{serviceName}}
type: {{label}}
mock: {{mock}}
spec:
terminationGracePeriodSeconds: 0
containers:
- name: {{serviceName}}
image: ccr.ccs.tencentyun.com/{{image}}
imagePullPolicy: IfNotPresent
# command: [ "/bin/bash", "-ce", "tail -f /dev/null" ]
# args: [ "while true; do sleep 30; done;" ]
volumeMounts:
- mountPath: /home/logs
name: filelog
env:
- name: NAMESPACE
value: {{namespace}}
- name: SYSTEM_NAME
value: {{serviceName}}
- name: HOSTS
value: 192.168.4.50=>eos.quantgroups.com&172.17.1.7=>apollo-dev.quantgroups.com&172.20.3.11=>sentry.quantgroups.com&
- name: DEBUG
value: {{debug}}
- name: MOCK
value: {{mock}}
# - name: DUBBO_PORT_TO_BIND
# value: '80'
# - name: DUBBO_PORT_TO_REGISTRY
# value: '80'
- name: DUBBO_IP_TO_REGISTRY
valueFrom:
fieldRef:
fieldPath: status.hostIP
resources:
requests:
cpu: {{resources.cpuRequest}}m
memory: {{resources.memRequest}}Mi
limits:
cpu: {{resources.cpuLimit}}m
memory: {{resources.memLimit}}Mi
livenessProbe:
exec:
command:
- /home/quant_group/readyCheck.sh
# 启动延时,容器延时启动健康检查的时间
initialDelaySeconds: 600
# 间隔时间,进行健康检查的时间间隔
periodSeconds: 60
# 响应超时,每次健康检查响应的最大超时时间
timeoutSeconds: 5
# 健康阈值,表示后端容器从失败到成功的连续健康检查成功次数
successThreshold: 1
# 不健康阈值
failureThreshold: 3
readinessProbe:
exec:
command:
- /home/quant_group/readyCheck.sh
initialDelaySeconds: 15
timeoutSeconds: 3
periodSeconds: 10
successThreshold: 1
failureThreshold: 3
volumes:
- name: filelog
hostPath:
path: /var/log/containers2/{{namespace}}/{{serviceName}}
restartPolicy: Always
dnsPolicy: ClusterFirst
imagePullSecrets:
- name: qcloudregistrykey
- name: tencenthubkey
\ No newline at end of file
apiVersion: v1
kind: Service
metadata:
labels:
type: java
qcloud-app: {{serviceName}}
name: {{serviceName}}
namespace: {{namespace}}
spec:
# 默认为ClusterIP
type: ClusterIP
ports:
- name: '80'
port: 80
- name: '5005'
port: 5005
- name: '20880'
port: 20880
selector:
qcloud-app: {{serviceName}}
\ No newline at end of file
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
type: base
qcloud-app: kafka
name: kafka
namespace: {{namespace}}
spec:
replicas: 1
selector:
matchLabels:
qcloud-app: kafka
template:
metadata:
labels:
qcloud-app: kafka
type: base
spec:
containers:
- name: kafka
image: ccr.ccs.tencentyun.com/{{image}}
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9092
livenessProbe:
tcpSocket:
port: 9092
env:
- name: KAFKA_ZOOKEEPER_CONNECT
value: {{ZOOKEEPER_HOST}}:{{ZOOKEEPER_PORT}}/kafka
- name: KAFKA_BROKER_ID
value: "1"
- name: KAFKA_ADVERTISED_LISTENERS
value: PLAINTEXT://172.17.5.5:{{KAFKA_SERVICE_PORT}}
- name: KAFKA_LISTENERS
value: "PLAINTEXT://0.0.0.0:9092"
- name: KAFKA_ADVERTISED_PORT
value: "30901"
- name: KAFKA_ADVERTISED_HOST_NAME
valueFrom:
fieldRef:
fieldPath: status.hostIP
volumeMounts:
- name: datadir
mountPath: /var/lib/kafka
volumes:
- name: datadir
persistentVolumeClaim:
claimName: kafka-{{namespace}}
\ No newline at end of file
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: kafka-{{namespace}}
namespace: {{namespace}}
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
\ No newline at end of file
apiVersion: v1
kind: Service
metadata:
name: kafka-{{namespace}}
namespace: {{namespace}}
labels:
type: base
qcloud-app: kafka
spec:
type: NodePort
ports:
- port: 9092
name: kafka-9092-9092
targetPort: 9092
protocol: TCP
selector:
qcloud-app: kafka
\ No newline at end of file
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
qcloud-app: mongodb
type: base
name: mongodb
namespace: {{namespace}}
spec:
replicas: 1
revisionHistoryLimit: 1
selector:
matchLabels:
qcloud-app: mongodb
strategy:
type: Recreate
template:
metadata:
labels:
qcloud-app: mongodb
type: base
spec:
containers:
- env:
- name: MONGO_INITDB_ROOT_USERNAME
value: qa
- name: MONGO_INITDB_ROOT_PASSWORD
value: qatest
image: ccr.ccs.tencentyun.com/{{image}}
imagePullPolicy: Always
livenessProbe:
exec:
command:
- mongo
- -uqa
- -pqatest
- admin
failureThreshold: 3
initialDelaySeconds: 100
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
name: mongodb
readinessProbe:
exec:
command:
- mongo
- -uqa
- -pqatest
- admin
failureThreshold: 3
initialDelaySeconds: 5
periodSeconds: 5
successThreshold: 1
timeoutSeconds: 1
resources:
requests:
cpu: 256m
memory: 256Mi
limits:
cpu: 512m
memory: 512Mi
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/lib/mongo
name: mongodb
dnsPolicy: ClusterFirst
imagePullSecrets:
- name: qcloudregistrykey
- name: tencenthubkey
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
volumes:
- name: mongodb
persistentVolumeClaim:
claimName: mongodb-{{namespace}}
\ No newline at end of file
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: mongodb-{{namespace}}
namespace: {{namespace}}
spec:
# storageClassName: cbs-3
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
\ No newline at end of file
apiVersion: v1
kind: Service
metadata:
labels:
qcloud-app: mongodb
type: base
name: mongodb
namespace: {{namespace}}
spec:
ports:
- port: 27017
selector:
qcloud-app: mongodb
type: NodePort
status:
loadBalancer: {}
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
qcloud-app: mysql
type: base
name: mysql
namespace: {{namespace}}
spec:
replicas: 1
revisionHistoryLimit: 1
selector:
matchLabels:
qcloud-app: mysql
strategy:
type: Recreate
template:
metadata:
labels:
qcloud-app: mysql
type: base
spec:
containers:
- env:
- name: MYSQL_DATABASE
value: db
- name: MYSQL_PASSWORD
value: qatest
- name: MYSQL_ROOT_PASSWORD
value: Quantgroup2017
- name: MYSQL_USER
value: qa
image: ccr.ccs.tencentyun.com/{{image}}
imagePullPolicy: Always
livenessProbe:
exec:
command:
- mysql
- -uqa
- -pqatest
- -e
- SELECT 1
failureThreshold: 3
initialDelaySeconds: 100
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
name: mysql
readinessProbe:
exec:
command:
- mysql
- -uqa
- -pqatest
- -e
- SELECT 1
failureThreshold: 3
initialDelaySeconds: 5
periodSeconds: 5
successThreshold: 1
timeoutSeconds: 1
resources:
requests:
cpu: 200m
memory: 200Mi
limits:
cpu: 2048m
memory: 2Gi
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/lib/mysql
name: mysql
dnsPolicy: ClusterFirst
imagePullSecrets:
- name: qcloudregistrykey
- name: tencenthubkey
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
volumes:
- name: mysql
persistentVolumeClaim:
claimName: mysql-{{namespace}}
\ No newline at end of file
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-{{namespace}}
namespace: {{namespace}}
spec:
# storageClassName: cbs-3
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 50Gi
\ No newline at end of file
apiVersion: v1
kind: Service
metadata:
labels:
type: base
qcloud-app: mysql
name: mysql
namespace: {{namespace}}
spec:
type: NodePort
ports:
- port: 3306
selector:
qcloud-app: mysql
\ No newline at end of file
apiVersion: apps/v1beta1
kind: Deployment
metadata:
labels:
type: base
qcloud-app: rabbitmq
name: rabbitmq
namespace: {{namespace}}
spec:
replicas: 1
revisionHistoryLimit: 1
selector:
matchLabels:
qcloud-app: rabbitmq
strategy:
type: Recreate
template:
metadata:
labels:
qcloud-app: rabbitmq
type: base
spec:
# hostname固定,容器重置后数据持久化才能正常
hostname: rabbitmq-{{namespace}}
containers:
- image: ccr.ccs.tencentyun.com/{{image}}
imagePullPolicy: IfNotPresent
name: rabbitmq
resources:
requests:
cpu: 100m
memory: 100Mi
limits:
cpu: 500m
memory: 500Mi
env:
- name: RABBITMQ_DEFAULT_USER
value: qa
- name: RABBITMQ_DEFAULT_PASS
value: qatest
livenessProbe:
exec:
command:
- /opt/readyCheck.sh
initialDelaySeconds: 100
successThreshold: 1
readinessProbe:
exec:
command:
- /opt/readyCheck.sh
initialDelaySeconds: 30
timeoutSeconds: 2
periodSeconds: 5
successThreshold: 1
# 数据持久化
volumeMounts:
- name: rabbitmq
mountPath: "/var/lib/rabbitmq"
volumes:
- name: rabbitmq
persistentVolumeClaim:
claimName: rabbitmq-{{namespace}}
imagePullSecrets:
- name: qcloudregistrykey
- name: tencenthubkey
restartPolicy: Always
terminationGracePeriodSeconds: 30
status: {}
\ No newline at end of file
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: rabbitmq-{{namespace}}
namespace: {{namespace}}
spec:
# storageClassName: cbs-3
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
\ No newline at end of file
apiVersion: v1
kind: Service
metadata:
labels:
type: base
qcloud-app: rabbitmq
name: rabbitmq
namespace: {{namespace}}
spec:
type: NodePort
# 保留客户端源 IP 地址, 方便调试连接
# externalTrafficPolicy: Local
ports:
- name: tcp-5672-5672
port: 5672
- name: tcp-15672-15672
port: 15672
selector:
qcloud-app: rabbitmq
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
type: base
qcloud-app: redis
name: redis
namespace: {{namespace}}
spec:
replicas: 1
revisionHistoryLimit: 1
selector:
matchLabels:
qcloud-app: redis
strategy:
type: Recreate
template:
metadata:
labels:
type: base
qcloud-app: redis
spec:
containers:
- image: ccr.ccs.tencentyun.com/{{image}}
imagePullPolicy: IfNotPresent
name: redis-6379
command: ["redis-server", "--port", "6379"]
resources:
requests:
cpu: 100m
memory: 400Mi
limits:
cpu: 1000m
memory: 4000Mi
livenessProbe:
exec:
command: ["redis-cli", "-p", "6379","info"]
initialDelaySeconds: 100
successThreshold: 1
readinessProbe:
exec:
command: ["redis-cli", "-p", "6379","info"]
initialDelaySeconds: 5
timeoutSeconds: 1
periodSeconds: 5
- image: ccr.ccs.tencentyun.com/{{image}}
imagePullPolicy: IfNotPresent
name: redis-6380
command: ["redis-server", "--port", "6380"]
resources:
requests:
cpu: 100m
memory: 200Mi
limits:
cpu: 512m
memory: 1024Mi
livenessProbe:
exec:
command: ["redis-cli", "-p", "6380","info"]
initialDelaySeconds: 100
successThreshold: 1
readinessProbe:
exec:
command: ["redis-cli", "-p", "6380","info"]
initialDelaySeconds: 5
timeoutSeconds: 1
periodSeconds: 5
- image: ccr.ccs.tencentyun.com/{{image}}
imagePullPolicy: IfNotPresent
name: redis-6381
command: ["redis-server", "--port", "6381"]
resources:
requests:
cpu: 100m
memory: 100Mi
limits:
cpu: 200m
memory: 200Mi
livenessProbe:
exec:
command: ["redis-cli", "-p", "6381","info"]
initialDelaySeconds: 100
successThreshold: 1
readinessProbe:
exec:
command: ["redis-cli", "-p", "6381","info"]
initialDelaySeconds: 5
timeoutSeconds: 1
periodSeconds: 5
- image: ccr.ccs.tencentyun.com/{{image}}
imagePullPolicy: IfNotPresent
name: redis-6382
command: ["redis-server", "--port", "6382"]
resources:
requests:
cpu: 100m
memory: 100Mi
limits:
cpu: 200m
memory: 200Mi
livenessProbe:
exec:
command: ["redis-cli", "-p", "6382","info"]
initialDelaySeconds: 100
successThreshold: 1
readinessProbe:
exec:
command: ["redis-cli", "-p", "6382","info"]
initialDelaySeconds: 5
timeoutSeconds: 1
periodSeconds: 5
- image: ccr.ccs.tencentyun.com/{{image}}
imagePullPolicy: IfNotPresent
name: redis-6383
command: ["redis-server", "--port", "6383"]
resources:
requests:
cpu: 100m
memory: 100Mi
limits:
cpu: 200m
memory: 200Mi
livenessProbe:
exec:
command: ["redis-cli", "-p", "6383","info"]
initialDelaySeconds: 100
successThreshold: 1
readinessProbe:
exec:
command: ["redis-cli", "-p", "6383","info"]
initialDelaySeconds: 5
timeoutSeconds: 1
periodSeconds: 5
dnsPolicy: ClusterFirst
imagePullSecrets:
- name: qcloudregistrykey
- name: tencenthubkey
restartPolicy: Always
terminationGracePeriodSeconds: 30
status: {}
\ No newline at end of file
apiVersion: v1
kind: Service
metadata:
labels:
type: base
qcloud-app: redis
name: redis
namespace: {{namespace}}
spec:
type: NodePort
ports:
- name: '6379'
port: 6379
- name: '6380'
port: 6380
- name: '6381'
port: 6381
- name: '6382'
port: 6382
- name: '6383'
port: 6383
selector:
qcloud-app: redis
\ No newline at end of file
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{serviceName}}
namespace: {{namespace}}
labels:
type: {{label}}
qcloud-app: {{serviceName}}
spec:
replicas: 1
revisionHistoryLimit: 1
selector:
matchLabels:
qcloud-app: {{serviceName}}
strategy:
type: Recreate
template:
metadata:
labels:
qcloud-app: {{serviceName}}
type: {{label}}
spec:
terminationGracePeriodSeconds: 0
containers:
- name: {{serviceName}}
image: ccr.ccs.tencentyun.com/{{image}}
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /home/logs
name: filelog
env:
- name: NAMESPACE
value: {{namespace}}
- name: SYSTEM_NAME
value: {{serviceName}}
- name: DEBUG
value: {{debug}}
- name: HOSTS
value: 192.168.4.50=>eos.quantgroups.com&172.17.1.7=>apollo-dev.quantgroups.com&172.20.3.11=>sentry.quantgroups.com&
- name: NODE_ENV
value: test
resources:
requests:
cpu: {{resources.cpuRequest}}m
memory: {{resources.memRequest}}Mi
limits:
cpu: {{resources.cpuLimit}}m
memory: {{resources.memLimit}}Mi
livenessProbe:
exec:
command:
- /home/quant_group/readyCheck.sh
# 启动延时,容器延时启动健康检查的时间
initialDelaySeconds: 600
# 间隔时间,进行健康检查的时间间隔
periodSeconds: 60
# 响应超时,每次健康检查响应的最大超时时间
timeoutSeconds: 5
# 健康阈值,表示后端容器从失败到成功的连续健康检查成功次数
successThreshold: 1
# 不健康阈值
failureThreshold: 3
readinessProbe:
exec:
command:
- /home/quant_group/readyCheck.sh
initialDelaySeconds: 15
timeoutSeconds: 3
periodSeconds: 10
successThreshold: 1
failureThreshold: 3
volumes:
- name: filelog
hostPath:
path: /var/log/containers2/{{namespace}}/{{serviceName}}
restartPolicy: Always
dnsPolicy: ClusterFirst
imagePullSecrets:
- name: qcloudregistrykey
- name: tencenthubkey
apiVersion: v1
kind: Service
metadata:
labels:
type: {{label}}
qcloud-app: {{serviceName}}
name: {{serviceName}}
namespace: {{namespace}}
spec:
type: ClusterIP
ports:
- port: 80
selector:
qcloud-app: {{serviceName}}
\ No newline at end of file
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
qcloud-app: zookeeper
type: base
name: zookeeper
namespace: {{namespace}}
spec:
replicas: 1
revisionHistoryLimit: 1
selector:
matchLabels:
qcloud-app: zookeeper
strategy:
type: Recreate
template:
metadata:
labels:
qcloud-app: zookeeper
type: base
name: zookeeper
namespace: {{namespace}}
spec:
containers:
- env:
- name: ZOO_USER
value: zookeeper
image: ccr.ccs.tencentyun.com/{{image}}
imagePullPolicy: Always
livenessProbe:
exec:
command:
- /zookeeper-3.4.13/readyCheck.sh
failureThreshold: 3
initialDelaySeconds: 100
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
name: zookeeper
readinessProbe:
exec:
command:
- /zookeeper-3.4.13/readyCheck.sh
failureThreshold: 3
initialDelaySeconds: 5
periodSeconds: 5
successThreshold: 1
timeoutSeconds: 1
resources:
requests:
cpu: 100m
memory: 300Mi
limits:
cpu: 200m
memory: 600Mi
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/lib/zookeeper
name: zookeeper
dnsPolicy: ClusterFirst
imagePullSecrets:
- name: qcloudregistrykey
- name: tencenthubkey
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
volumes:
- name: zookeeper
persistentVolumeClaim:
claimName: zookeeper-{{namespace}}
\ No newline at end of file
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: zookeeper-{{namespace}}
namespace: {{namespace}}
spec:
# storageClassName: cbs-3
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
\ No newline at end of file
apiVersion: v1
kind: Service
metadata:
labels:
type: base
qcloud-app: zookeeper
name: zookeeper
namespace: {{namespace}}
spec:
type: NodePort
ports:
- name: '2181'
port: 2181
selector:
qcloud-app: zookeeper
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment