开源工具专题-01 Superset的CICD流程构建
- Superset
- 2024-03-19
- 105热度
- 0评论
开源工具专题
注
:
- 本教程由羞涩梦整理同步发布,本人技术分享站点:blog.hukanfa.com
- 转发本文请备注原文链接,本文内容整理日期:2024-01-28
- csdn 博客名称:五维空间-影子,欢迎关注
-
说明
- 此搭建场景主要用于公司内部需要对superset进行二次开发来满足内部的使用需求
- 需频繁提交代码并进行功能验证,效果图如下
1 代码拉取
- 操作如下
superset
托管地址如下
# github 外网拉取可能会超时 https://github.com/apache/superset # gitee 码云国内 https://gitee.com/mirrors/Superset # 克隆操作,http方式需输入gitee账号密码、ssh方式请在gitee上配置好机器公钥信息 git clone -b 3.1.1 https://gitee.com/mirrors/Superset.git
- 提供本人对该项目做一些调整后的托管地址
# gitee 调整的内容在本文后续章节会提到 源 3.1.1 分支 https://gitee.com/hukanfa/superset
2 修改 Dockerfile
- 操作如下
- 修改内容:去掉前端代码的编译环节,只编译后端代码、去掉生成dev环境的步骤
FROM hukanfa/python:3.9-superset-v1.0 AS lean WORKDIR /app ENV LANG=C.UTF-8 \ LC_ALL=C.UTF-8 \ SUPERSET_ENV=production \ FLASK_APP="superset.app:create_app()" \ PYTHONPATH="/app/pythonpath" \ SUPERSET_HOME="/app/superset_home" \ SUPERSET_LOG="superset.log" \ SUPERSET_PORT=8088 RUN mkdir -p {PYTHONPATH} superset-frontend apache_superset.egg-info requirements \ && useradd --user-group -d{SUPERSET_HOME} -m --no-log-init --shell /bin/bash superset \ && touch {SUPERSET_HOME}/{SUPERSET_LOG} \ && chown -R superset:superset ./* COPY --chown=superset:superset setup.py MANIFEST.in README.md ./ COPY --chown=superset:superset ./requirements/*.txt ./requirements/ COPY --chown=superset:superset ./superset superset COPY ./docker/run-server.sh /usr/bin/ COPY --chown=superset:superset superset-frontend/package.json superset-frontend/ ADD superset_static_3_1_1.tar.gz /app/superset/ RUN mkdir ~/.pip/ \ && echo '[global]' > ~/.pip/pip.conf \ && echo 'index-url = https://mirrors.aliyun.com/pypi/simple/' >> ~/.pip/pip.conf \ && echo 'trusted-host = mirrors.aliyun.com' >> ~/.pip/pip.conf \ && pip install --no-cache -r requirements/local.txt # COPY --chown=superset:superset --from=superset-node /app/superset/static/assets superset/static/assets RUN pip install --no-cache -e . \ && flask fab babel-compile --target superset/translations \ && chown -R superset:superset superset/translations \ && chmod +x /usr/bin/run-server.sh USER superset HEALTHCHECK CMD curl -f "http://localhost:{SUPERSET_PORT}/health" EXPOSE{SUPERSET_PORT} ###################################################################### # CI image... ###################################################################### FROM lean AS ci COPY --chown=superset:superset ./docker/*.sh /app/docker/ RUN chmod -R 755 /app/docker/*.sh CMD ["/app/docker/docker-ci.sh"]
- Dockerfile 文件中
superset_static_3_1_1.tar.gz
前端编译文件的获取方式如下
# 拉取官方对应版本的镜像 docker pull apache/superset:3.1.1 # 运行镜像 docker run -d --name superset_temp apache/superset:3.1.1 # 进入镜像中将静态文件打包 docker exec -it 2b6d1d5f3006 /bin/bash superset@2b6d1d5f3006:/app cd superset superset@2b6d1d5f3006:/app/supersettar -zcvf superset_static_3_1_1.tar.gz ./static/ # 拷贝压缩包到宿主机保存 [hukanfa@hukanfa ~] docker cp 2b6d1d5f3006:/app/superset/superset_static_3_1_1.tar.gz ./
- Dockerfile 文件中,
python:3.9-superset-v1.0
基础镜像的 Dockerfile 文件如下
ARG PY_VER=3.9-slim-bookworm FROM python:${PY_VER} COPY ./debian.sources / RUN cp -ar /etc/apt/sources.list.d/debian.sources /etc/apt/sources.list.d/debian.sources.bak \ && mv -f /debian.sources /etc/apt/sources.list.d/ \ && apt-get install apt-transport-https ca-certificates \ && apt-get update \ && apt-get install -y --no-install-recommends \ build-essential \ curl \ default-libmysqlclient-dev \ libsasl2-dev \ libsasl2-modules-gssapi-mit \ libpq-dev \ libecpg-dev \ libldap2-dev \ sudo \ inetutils-ping \ # 增加 ping 命令 telnet \ # 增加 telnet 命令 net-tools \ # 增加网络这块的查看命令 && rm -rf /var/lib/apt/lists/*
- 对应的
debian.sources
内容如下
# 改成国内源 Types: deb URIs: https://mirrors.huaweicloud.com/debian Suites: bookworm bookworm-updates Components: main Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg Types: deb URIs: https://mirrors.huaweicloud.com/debian-security Suites: bookworm-security Components: main Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
3 修改 config.py
- 操作如下
- 路径:
superset/config.py
- 修改内容如下,mysql 请事先准备好
### 注释superset自带的数据库配置 #SQLALCHEMY_DATABASE_URI = ( # f"""sqlite:///{os.path.join(DATA_DIR, "superset.db")}?check_same_thread=false""" #) ### 打开mysql配置 SQLALCHEMY_DATABASE_URI = 'mysql://superset:jNaCDgHcJ6zQzy@192.168.26.21:3307/superset' ### 修改默认语言为中文,并只保留中英文语言切换 BABEL_DEFAULT_LOCALE = "zh" LANGUAGES = { "zh": {"flag": "cn", "name": "Chinese"}, "en": {"flag": "us", "name": "English"}, } ### 注释掉默认配置,直接指定key。如果不注释也可以docker-compose文件中指定成环境变量 # SECRET_KEY = os.environ.get("SUPERSET_SECRET_KEY") or CHANGE_ME_SECRET_KEY SECRET_KEY = 'oCghysSLvk2BSa9bPEOz6avKzjLHYkedO6ztCZ/sv5j3pwuIg63wVLeY'
- 提前创建好mysql的
supertset
数据库,项目运行起来后初始化操作会自行创建表
create database if not exists superset character set utf8mb4 collate utf8mb4_bin;
- 路径:
4 修改 docker-ci.sh
- 操作如下
- 路径:
docker/docker-ci.sh
- 此部署脚本会先启动初始化脚本,主要是生成表及相关表的数据初始化。之后再执行服务运行脚本
- 当第一次部署superset且初始化完成之后,需要将此脚本中的初始化步骤注释掉
- 防止后续部署过程中每次都会执行初始化的操作,这样会将配置好的一些数据给删掉的
### 特别提示:一定要等第一次初始化完成后再注释掉,不要一开始就注释 # /app/docker/docker-init.sh
- 路径:
5 pipeline 脚本
- 操作步骤
- 配置在 jenkins 对应项目的 pipeline 脚本框中
pipeline{ agent any options { timestamps() } stages{ stage('初始化'){ steps{ script { wrap([class: 'BuildUser']) { env.buildUserTmp="BUILD_USER" currentBuild.description = "构建人:({env.BUILD_USER})动作:({env.action_choice})环境:({env.env_choice})版本号:({env.version})分支:({env.branch})" } } } } stage('代码拉取'){ steps{ git branch: "{env.branch}", credentialsId: 'c5xxxx93-ad21-4cdd-9c03-dxxxxxx6e15', url: 'git@gitee.com:hukanfa/superset.git' } } stage('打包编译'){ steps{ sh "/bin/bash /root/jenkins_shell/newBackend/{pname}/build.sh{env.env_choice} {BUILD_NUMBER}{pname} {env.action_choice}{env.version} {env.branch}{WORKSPACE}" } } stage('部署上线'){ steps{ sh "/bin/bash /root/jenkins_shell/newBackend/{pname}/deploy.sh{env.env_choice} {BUILD_NUMBER}{pname} {env.version}{env.action_choice}" } } } }
- 流程图如下所示
6 build.sh
- 操作如下
- 脚本内容
#!/bin/bash ### 接收的传参 envType=1 buildNumber=2 pName=3 actionType=4 pVersion=5 codeBranch=6 workspace=7 ### 变量定义区 # 注意,远程机需事先把前端文件传到对应的项目路径下 fontTar="/root/other_data/superset_static_3_1_1.tar.gz" # 定义镜像名称 imageName="registry-vpc.cn-guangzhou.aliyuncs.com/hukanfa/{pName}:{buildNumber}" # version对应的包名称,非0值表示需要回滚 if [pVersion -gt 0 -a actionType == 'roolback' ];then imageName="registry-vpc.cn-guangzhou.aliyuncs.com/hukanfa/{pName}:{pVersion}" fi # 检查目录是否存在的函数,如果目录不存在则创建 checkDirExit(){ if [ -d1 ];then echo "1目录存在" else mkdir -p1 echo "1 目录不存在,已创建" fi } # 判断命令执行状态 function checkStatus(){ if [? -ne 0 ];then echo "执行异常退出,请核查" exit 1 else echo "执行成功" fi } #判断是部署还是回滚操作 if [ actionType == 'deploy' -apVersion -eq 0 ];then cp -ar fontTar ./ checkStatus DOCKER_BUILDKIT=1 docker build -timageName . checkStatus docker push imageName checkStatus elif [actionType == 'roolback' -a pVersion -gt 0 ];then echo "本次将执行回滚操作,镜像版本为:imageName" else echo "部署动作或部署版本值有误,请检查" exit 1 fi
7 deploy.sh
- 操作如下
- 脚本内容
#!/bin/sh ###【1】变量区 # 分支 envType=1 # 构建ID buildNumber=2 # 项目名称 pName=3 # 回滚版本号 pVersion=4 # 部署动作类型 actionType=5 # 定义镜像名称 imageName="registry-vpc.cn-guangzhou.aliyuncs.com/hukanfa/{pName}:{buildNumber}" # version对应的包名称,非0值表示需要回滚 if [pVersion -gt 0 -a actionType == 'roolback' ];then imageName="registry-vpc.cn-guangzhou.aliyuncs.com/hukanfa/{pName}:{pVersion}" fi # 部署的机器 targetHost=(192.168.26.22) # 远程用户名称 remoteUser="hukanfa" # 远程demo目录 remoteScriptsDir="newBackendItem/pName" # 项目远程运行目录 remoteItemDir="/data/{pName}" ###【2】函数区 # 判断命令执行状态 function checkCmdStatus(){ if [? -ne 0 ];then echo "{1}执行异常退出,请核查" exit 1 fi } ###【3】逻辑区 for i in{targetHost[@]} ; do # 先执行检测脚本,判断对应的远程目录是否存在 ssh -l remoteUseri "cd ~ && if [ -d "{remoteScriptsDir}" ];then echo "{remoteScriptsDir} 存在"; else mkdir -p {remoteScriptsDir} && echo "{remoteScriptsDir} 不存在已创建"; fi" checkCmdStatus "远程目录检测" echo "开始调用远程脚本执行部署操作" # 执行远程脚本,传递本次构建的包名称 ssh -l remoteUseri "/bin/bash {remoteScriptsDir}/run.shpName imageNamebuildNumber $pVersion" done
8 远程机脚本
- 操作如下
- 以下脚本或文件在远程机,路径:
/home/hukanfa/newBackendItem/superset
[hukanfa@hukanfa superset]$ docker-compose.yml run.sh
run.sh
#!/bin/bash # 接收传参 pName=1 imageName=2 buildNumber=3 pVersion=4 # 项目远程运行目录 remoteItemDir="/data/{pName}" scriptsDir="/home/hukanfa/newBackendItem/{pName}" backupDir="/data/{pName}/bak" cTime=`date +'%Y%m%d%H%M%S'` dfile="docker-compose.yml" # 前端压缩包文件名称 fronPack="superset_static_3_1_1.tar.gz" # 定义服务运行端口,需和docker-compose.yml中映射的一致 srvPort=8088 # 定义服务状态,默认2 运行中 1 srvStatus=2 # 判断命令执行状态 function checkStatus(){ if [? -ne 0 ];then echo "执行异常退出,请核查" exit 1 else echo "执行成功" fi } # 检查目录是否存在的函数,如果目录不存在则创建 checkDirExit(){ if [ -d 1 ];then echo "1目录存在" else mkdir -p 1 echo "1 目录不存在,已创建" fi } checkDirExit "backupDir" # 判断是否在运行,运行则先停掉,备份相关文件 pidNum=`docker ps -a | grep superset | wc -l` if [pidNum -ge 1 ];then cd remoteItemDir docker-compose down checkStatus sleep 3 mv -fdfile {backupDir}/{dfile}.bak{cTime} checkStatus cp -ar{scriptsDir}/{dfile} ./ checkStatus sed -i 's#ImagesName#'"{imageName}"'#g' ./{dfile} checkStatus # 启动 docker-compose up -d checkStatus sleep 2 elif [pidNum -eq 0 ];then cd remoteItemDir if [ -fdfile ];then mv -f dfile{backupDir}/{dfile}.bak{cTime} checkStatus fi cp -ar {scriptsDir}/{dfile} ./ checkStatus sed -i 's#ImagesName#'"{imageName}"'#g' ./{dfile} checkStatus # 启动 docker-compose up -d checkStatus sleep 2 fi for (( i=1 ; i<=30 ; i++ ));do # 检测启动状态 srvTag=`docker ps | grep superset | awk -F"(" '{print 2}' | awk -F")" '{print1}' | awk '{print 1}'` if [ "srvTag" == "healthy" ];then srvStatus=1 break else echo "################### 状态检查中,请稍等 ####################" docker ps | grep superset sleep 5 fi done # 检查循环结束返回检查结果 if [ $srvStatus -eq 1 ];then echo "本次服务部署运行正常" exit 0 else echo "状态检查超过150s,本次服务部署异常,请核查!" exit 1 fi
docker-compose.yml
模板文件
version: '3' services: superset: image: ImagesName container_name: superset hostname: superset restart: always ports: - 8088:8088 environment: - TZ=Asia/Shanghai
- 以下脚本或文件在远程机,路径: