前言
写程序难免经历要很多调试,对于 K8S 开发,如果需要和集群内的其它服务进行交互,要么需要用 VPN 连接到集群内部,要么就需要打包 Docker 镜像,然后更新集群内的版本,就我来说,不是很喜欢前种方法,因为连到集群之后查资料就不是很方便,另外每次发版也是要走 CI 流程的,不妨做下 Golang 的 CI
公司技术栈是 Java + SpringBoot ,基本上没啥 Golang 的项目,自然也没有 Golang 的 CI 脚本,所以需要自己做,之前我弄过不少 CI ,不过是 Github Action 和 Gitea + Drone 之类的,需要写一个 yaml 文件,同时有很多可以用的组件 (use:xxx 这样的),是基于 Docker 的流水线,很方便,而公司使用的是 Jenkins ,而且是非常老版的 Jenkins ,所以只能写 Shell 脚本来打包
编写 Shell 脚本
虽然我很不喜欢 Shell 脚本,不愿意写这玩意儿,不过还好不需要从零开始,找隔壁组大佬要到了 Java 的 CI 脚本,可以在它的基础上简单改改就行
之前我做了套 Gitea + Drone 的 CI,那边主推是 Docker 流水线,不依赖宿主机环境,而 Jenkins 多是依赖宿主机环境,因为 Jenkins 太老装不上 Golang 插件,加上之前用的是 Docker 流水线,所以这次上 Jenkins 也仍然使用 Docker 来进行构建
来看脚本(部分敏感信息删改)
Jenkins 到 k8s 集群的 master 需要做 ssh 免密
#!/usr/bin/env bash
IMAGE=yunzainfo.com/project
REMOTE_YAML_DIR=/opt/work/project/
LOG_PREFIX="【MARS-Golang-Builder】---> " LOG_SUCCESS="【SUCCESS】" LOG_FAIL="【FAIL】"
DEVP_HARBOR="xxx"
PROD_HARBOR="yunzainfo.com"
ORACLE_SERVER="xxx.xxx.xxx.xxx"
POSTGRESQL_SERVER="xxx.xxx.xxx.xxx"
VERSION_DEVP=devp VERSION_TAG=${VERSION_DEVP}
printVersion(){ echo "${LOG_PREFIX} Golang 项目 jenkins 构建脚本 (2023-11-08) Powered by Luckykeeper <luckykeeper@luckykeeper.site | https://luckykeeper.site | https://github.com/luckykeeper>" }
printHelp(){ echo "${LOG_PREFIX}用法: /opt/tools/build-mars-go.sh <IMAGE> <REMOTE_YAML_DIR> [DEPLOY_TARGET]" echo "${LOG_PREFIX}示例1: /opt/tools/build-mars-go.sh yunzainfo.com/cloud/project /opt/work/project/" echo "${LOG_PREFIX}示例2: /opt/tools/build-mars-go.sh yunzainfo.com/cloud/project /opt/work/project/ oracle" }
build(){ A_IMAGE=$1
devp_image="${A_IMAGE/${PROD_HARBOR}/${DEVP_HARBOR}}" echo "${LOG_PREFIX}docker开发版本构建开始... ($devp_image:$VERSION_DEVP)" echo "${LOG_PREFIX}docker build -t $devp_image:$VERSION_DEVP ." docker build -t "$devp_image:$VERSION_DEVP" . > /dev/null
if [ $? -ne 0 ]; then echo "${LOG_PREFIX}${LOG_FAIL}docker开发版本构建失败!($devp_image:$VERSION_DEVP)" exit 1 fi echo "${LOG_PREFIX}docker开发版本构建完成. ($devp_image:$VERSION_DEVP)" echo "${LOG_PREFIX}docker开发版本推送开始... ($devp_image:$VERSION_DEVP)" docker push "$devp_image:$VERSION_DEVP" > /dev/null if [ $? -ne 0 ]; then echo "${LOG_PREFIX}${LOG_FAIL}docker开发版本推送失败!($devp_image:$VERSION_DEVP)" exit 1 fi echo "${LOG_PREFIX}${LOG_SUCCESS}docker开发版本推送完成. ($devp_image:$VERSION_DEVP)"
gitLastTag=$(git describe --tags $(git rev-list --tags --max-count=1)) if [[ ! -n ${gitLastTag} ]]; then echo "${LOG_PREFIX}该项目尚未打过标签" else echo "${LOG_PREFIX}所有分支最后一个标签: ${gitLastTag}" hashTag=$(git describe --tags "${gitLastTag}") currentHeadTag=$(git describe --tags HEAD) if [[ ${hashTag} == "${currentHeadTag}" ]]; then echo "${LOG_PREFIX}当前节点标签: ${currentHeadTag}" VERSION_TAG=$currentHeadTag echo "${LOG_PREFIX}docker标签版本构建开始... ($A_IMAGE:$VERSION_TAG)" echo "${LOG_PREFIX}docker build -t $A_IMAGE:$VERSION_TAG" docker build -t "$A_IMAGE:$VERSION_TAG" . > /dev/null if [ $? -ne 0 ]; then echo "${LOG_PREFIX}${LOG_FAIL}docker标签版本构建失败!" exit 1 fi echo "${LOG_PREFIX}docker标签版本构建完成.($A_IMAGE:$VERSION_TAG)" echo "${LOG_PREFIX}docker标签版本推送开始... ($A_IMAGE:$VERSION_TAG)" docker push "$A_IMAGE:$VERSION_TAG" > /dev/null if [ $? -ne 0 ]; then echo "${LOG_PREFIX}${LOG_FAIL}docker标签版本推送失败!($A_IMAGE:$VERSION_TAG)" exit 1 fi echo "${LOG_PREFIX}${LOG_SUCCESS}docker标签版本推送完成.($A_IMAGE:$VERSION_TAG)" else echo "${LOG_PREFIX}当前节点未打标签" fi fi
}
deployDevpServer() { A_REMOTE_YAML_DIR=$1 host=$2 databaseType=$3 echo "${LOG_PREFIX}部署到 $host ..." echo "${LOG_PREFIX}创建目录" ssh root@$host << EOF mkdir -p $A_REMOTE_YAML_DIR EOF
echo "${LOG_PREFIX}拷贝istio配置文件" scp istio/istio-*.yaml root@$host:$A_REMOTE_YAML_DIR scp istio/configmap-$databaseType.yaml root@$host:$A_REMOTE_YAML_DIR
echo "${LOG_PREFIX}执行远程命令" ssh root@$host << EOF cd $A_REMOTE_YAML_DIR # kubectl delete -f configmap-$databaseType.yaml # kubectl delete -f istio-gateway.yaml # kubectl delete -f istio-svc-dpt.yaml kubectl apply -f configmap-$databaseType.yaml kubectl apply -f istio-gateway.yaml sed -i "s/${PROD_HARBOR}/${DEVP_HARBOR}/g" istio-svc-dpt.yaml kubectl apply -f istio-svc-dpt.yaml exit EOF echo "${LOG_PREFIX}${LOG_SUCCESS}部署到 $host 完成." }
deploy() { A_REMOTE_YAML_DIR=$1 target=$2 if [[ "$target" ]];then if [ "$target" = "oracle" ]; then deployDevpServer "$A_REMOTE_YAML_DIR" $ORACLE_SERVER oracle elif [ "$target" = "postgresql" ]; then deployDevpServer "$A_REMOTE_YAML_DIR" $POSTGRESQL_SERVER postgresql else echo "${LOG_PREFIX}不进行部署." fi else deployDevpServer "$A_REMOTE_YAML_DIR" $ORACLE_SERVER oracle deployDevpServer "$A_REMOTE_YAML_DIR" $POSTGRESQL_SERVER postgresql fi }
if [[ ! "$1" ]];then echo "${LOG_PREFIX}-----------------[ 参数错误 ]-----------------" 1>&2; printHelp exit 1; fi if [[ ! "$2" ]];then echo "${LOG_PREFIX}-----------------[ 参数错误 ]-----------------" 1>&2; printHelp exit 1; fi
A_IMAGE=$1
A_REMOTE_YAML_DIR=$2
A_TARGET=$3
printVersion echo "调用方法: build ${A_IMAGE}" build "${A_IMAGE}" echo "调用方法: deploy ${A_REMOTE_YAML_DIR} ${A_TARGET}" deploy "${A_REMOTE_YAML_DIR}" "${A_TARGET}" echo "${LOG_PREFIX}脚本执行完毕."
|
Jekins 配置
选择 freeStyle 项目,进行如下配置,下面第二张图里面没有特殊配置,之前有别的下面有特殊配置,需要执行的特殊 shell 脚本可以写在这里
效果
每次提交之后,自动触发构建,推送到开发仓并重启 pod,如果发版,git 打上 tag,能够自动推送到公司仓