我是靠谱客的博主 玩命信封,最近开发中收集的这篇文章主要介绍k8s构建和发布文件,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

package com.alibaba.security.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.security.entry.BuildStatus;
import com.alibaba.security.entry.Result;
import com.alibaba.security.module.k8s.K8sApi;
import com.alibaba.security.param.BuildParam;
import com.alibaba.security.service.DeployService;
import com.alibaba.security.task.SyncBuildTask;
import com.alibaba.security.util.StringUtils;
import io.kubernetes.client.openapi.models.V1Deployment;
import io.kubernetes.client.openapi.models.V1DeploymentList;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Slf4j
@Service
public class DeployServiceImpl implements DeployService {
public static final ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
public static final Map<String, String> buildDataCache = Collections.synchronizedMap(new LinkedHashMap<>());
@Autowired
private K8sApi k8sApi;
// 缓存最大的容量,超出进行清理
private static Integer cacheSize;
static {
String paramNameCacheSize = "security.deploy.cache.size";
String propertiesCacheSize = System.getProperty(paramNameCacheSize);
if (StringUtils.isNotBlank(propertiesCacheSize)) {
cacheSize = Integer.parseInt(propertiesCacheSize);
}
if (Objects.isNull(cacheSize)) {
String envCacheSize = System.getenv().getOrDefault(paramNameCacheSize, "100");
cacheSize = Integer.parseInt(envCacheSize);
}
}
@Override
public Result deployApp(BuildParam param) throws Exception {
if (Objects.nonNull(param.getIsAsync()) && param.getIsAsync()) {
buildAsync(param);
return Result.success("SUCCESS!");
} else {
return buildSync(param);
}
}
/**
* 异步构建
*/
public void buildAsync(BuildParam param) {
cachedThreadPool.execute(() -> {
String buildKey = param.getEnv() + "-" + param.getAppName() + "-" + param.getVersion();
try {
buildDataCache.put(buildKey, BuildStatus.RUNNING);
buildSync(param);
buildDataCache.put(buildKey, BuildStatus.SUCCESS);
} catch (Exception e) {
log.error("异步构建任务失败,buildKey: " + buildKey + ", exception:", e);
StringWriter sw = new StringWriter();
try (PrintWriter pw = new PrintWriter(sw)) {
e.printStackTrace(pw);
}
buildDataCache.put(buildKey, BuildStatus.FAIL + ":" + sw.toString());
}
});
}
/**
* 同步构建
*/
public Result buildSync(BuildParam param) throws IOException, InterruptedException {
return new SyncBuildTask(param).run();
}
/**
* 获取构建任务状态
*/
public String queryTaskStatus(String buildKey) {
return buildDataCache.getOrDefault(buildKey, "");
}
/**
* 定时清理构建任务缓存
*/
@Scheduled(cron = "0 0 */12 * * ?")
private void cleanDataCache() {
int cleanCount = Math.max(0, buildDataCache.size() - cacheSize);
Iterator<Map.Entry<String, String>> it = buildDataCache.entrySet().iterator();
while (it.hasNext() && cleanCount > 0) {
cleanCount--;
it.next();
it.remove();
}
log.info("dataCache size:{}, content:{}", buildDataCache.size(), JSON.toJSONString(buildDataCache.keySet()));
}
/**
* 发布到k8s
*/
public String deployK8s(String appName, String namespace, String version) {
try {
V1DeploymentList list = k8sApi.listDeployment(namespace);
for (V1Deployment item : list.getItems()) {
//排除接口异常,Metadata为null,status为null等异常情况
if (item.getMetadata() == null || item.getMetadata().getLabels() == null || item.getSpec().getTemplate() == null ){
log.error("namespace:{},appName:{} Metadata error or null", namespace, appName);
return "failed";
}
//获取应用原来的image,并使用新的版本号去替换image中的版本
if (appName.equals(item.getMetadata().getLabels().get("edas.oam.acname")) && item.getStatus().getReplicas() != null) {
String deploymentName = item.getMetadata().getName();
String oldImage = item.getSpec().getTemplate().getSpec().getContainers().get(0).getImage();
String newImage = oldImage.substring(0, oldImage.indexOf(":") + 1) + version;
V1Deployment body = k8sApi.readDeployment(deploymentName, namespace);
body.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(newImage);
//替换镜像后,k8s会自动拉起一个新的pod将旧版本的pod替换掉
k8sApi.replaceDeployment(deploymentName, namespace, body);
log.info("namespace:{}, deployment:{}, {} update success", namespace, deploymentName, newImage);
return "success";
}
}
} catch (Exception e) {
log.error("apply deployment failed", e);
}
return "failed";
}
/**
* 查询k8s的发布状态,通过比较replicas数量是否一致
*/
public String queryK8s(String appName, String namespace) {
try {
V1DeploymentList list = k8sApi.listDeployment(namespace);
for (V1Deployment item : list.getItems()) {
//排除接口异常,Metadata为null,status为null等异常情况
if (item.getMetadata() == null || item.getMetadata().getLabels() == null || item.getMetadata().getLabels().get("edas.oam.acname") == null ){
log.error("namespace:{}, Metadata error or null", namespace);
return "failed";
}
if (appName.equals(item.getMetadata().getLabels().get("edas.oam.acname")) && item.getStatus().getReplicas() != null && item.getStatus().getAvailableReplicas() != null) {
String deploymentName = item.getMetadata().getName();
V1Deployment body = k8sApi.readDeployment(deploymentName, namespace);
if (body == null || body.getStatus() == null ){
log.error("namespace:{}, deployment:{}, Status is null", namespace, deploymentName);
return "failed";
}
Integer availablReplicas = body.getStatus().getAvailableReplicas();
Integer readyReplicas = body.getStatus().getReadyReplicas();
Integer replicas = body.getStatus().getReplicas();
Integer unavailableReplicas = body.getStatus().getUnavailableReplicas();
log.info("availablReplicas:{}, readyReplicas:{}, replicas{}", availablReplicas, readyReplicas, replicas);
//副本总数和可用副本总数一致,并且没有不可用副本,此时发布已经完成,slb流量已经切到新的pod
if (unavailableReplicas == null && availablReplicas !=null && availablReplicas.equals(readyReplicas) && availablReplicas.equals(replicas)) {
log.info("namespace:{}, deployment:{}, update finish", namespace, deploymentName);
return "success";
}
return "failed";
}
}
} catch (Exception e) {
log.error("apply deployment failed", e);
}
return "failed";
}
}

构建脚本

MEM_USAGE=$(df -H | grep vda1 | awk '{print $5}' | awk '{gsub(/%/, ""); print}')
echo "MEM_USAGE: $MEM_USAGE"
if [ $MEM_USAGE -gt 75 ];then
echo "clean docker images starting..."
sudo docker rmi -f `sudo docker images | grep placeholder_app_name_placeholder | awk '{print $3}'`
sudo docker rmi -f `sudo docker images | grep none | awk '{print $3}'`
echo "ean_docker.sh end!"
fi
TAG=placeholder_version_placeholder
cd placeholder_work_home_placeholder
REPOS=placeholder_docker_repos_placeholder
TARGET=$REPOS/placeholder_docker_repos_path_placeholder/placeholder_app_name_placeholder
sudo docker login $REPOS --username=placeholder_docker_username_placeholder --password=placeholder_docker_password_placeholder
sudo docker build -t $TARGET:$TAG . || exit 1;
sudo docker push $TARGET:$TAG

最后

以上就是玩命信封为你收集整理的k8s构建和发布文件的全部内容,希望文章能够帮你解决k8s构建和发布文件所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(40)

评论列表共有 0 条评论

立即
投稿
返回
顶部