CI/CD
目前,我们的 CI 过程使用自建的 Jenkins 服务完成。
大致的自动构造流程如下:
在我们的
git项目中添加jenkins的构造脚本,并编写脚本完成“拉代码、编译Dockerfile、上传镜像仓库” 这几个步骤。在
jenkins的可视化界面中添加构造任务构造任务中使用
SCM Pipeline script方式指定我们的git代码仓库地址和登陆的账号密码为了使我们可以在
jenkins可视化页面中每次选择不同分支来构造,需要在构造任务中勾选 “参数化构建过程” 进行配置。完成以上 4 个步骤,我们便可以在
jenkins中启动构造,并得到一个腾讯云的镜像地址在 k8s 中更新镜像文件
ASP.NET Core 项目
增加 dockerfile
小技巧
在传统的项目编译中,我们需要在本地编译源代码,然后将编译好的文件打包,上传到服务器。
这样对于不同类型的项目需要安装不同的依赖,比如:java 需要安装 jdk,maven 等, vue、angular 需要支持不同的 nodejs 版本。
所以,目前主流的构造方案是在 dockerfile 中完成源代码的编译,打包等工作。这样的好处是编译在 docker 内完成,减少了对 docker 宿主机上运行时依赖,不同的编译运行时在源代码的 dockerfile 中指定。其他如 vue、java 等项目请直接 google :
xxx build in dockerfiledotnet 8 dockerfile 示例
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build WORKDIR /build ARG NUGET=/tmp/nuget # copy project file and nuget to build container COPY ["src/Demo.Api.csproj", "src/"] COPY ["src/nuget.config", "src/"] # restore nuget packages RUN mkdir -p ${NUGET} && \ dotnet restore "src/Demo.Api.csproj" --disable-parallel --packages ${NUGET} # Copy everything else and build COPY . . RUN dotnet publish "src/Demo.Api.csproj" -c release -o /dist/publish --packages ${NUGET} FROM mcr.microsoft.com/dotnet/aspnet:8.0 WORKDIR /opt # copy publish files to container COPY --from=build /dist/publish . RUN sed -i 's/MinProtocol = TLSv1.2/MinProtocol = TLSv1/' /etc/ssl/openssl.cnf && \ sed -i 's/CipherString = DEFAULT@SECLEVEL=2/CipherString = DEFAULT@SECLEVEL=1/' /etc/ssl/openssl.cnf # install tools RUN sed -i "s/deb.debian.org/mirrors.aliyun.com/g" /etc/apt/sources.list RUN apt-get update && apt-get install -y curl # set env ENV ASPNETCORE_URLS=http://+:8080 ENV TZ=Asia/Shanghai EXPOSE 8080 ENTRYPOINT ["dotnet", "Demo.Api.dll"]
在项目文件夹下创建构造脚本文件 Jenkinsfile, 并编写构造脚本
podTemplate { node('jenkins-agent') { // 获取分支 parameters { gitParameter branchFilter: 'origin/(.*)', defaultValue: 'main', name: 'BRANCH', type: 'PT_BRANCH' } // 设置环境变量 stage('set env') { script { env.service = 'demo' env.git = 'https://github.com/yoholiao/demo.git' } } // 拉取代码,credentialsId 是在 jenkins 中提前配置好能获取git的账号密码。 stage('git pull') { git branch: "${params.BRANCH}", credentialsId: 'xxx-xxx-xx', url: "${env.git}" } // 获取分支当前 commit id stage('set repo url') { script { // Get the Git commit ID and store it in an environment variable env.GIT_COMMIT_ID = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim() env.CURRENT_DATE_TIME = sh(script: 'date "+%Y%m%d%H%M%S"', returnStdout: true).trim() env.imageUrl = "registry.cn-hangzhou.aliyuncs.com/yxliao/${env.service}:${env.GIT_COMMIT_ID}.${env.CURRENT_DATE_TIME}.${env.BRANCH}.${env.BUILD_ID}" } } stage('docker build and push') { container('jnlp') { docker.withRegistry('https://registry.cn-hangzhou.aliyuncs.com', 'xxx-xxx-xx') { def image = docker.build("${env.imageUrl}") image.push() } } sh "sleep 5 && docker image rm ${env.imageUrl}" } stage('build image info') { ansiColor('xterm') { echo "\033[0;34m imageUrl : ${env.imageUrl}\033[0m" echo "\033[0;34m update cmd : kubectl set image deployment/${env.service} ${env.service}=${env.imageUrl} --record\033[0m" echo "\033[0;31m rollback cmd : kubectl rollout undo deployment ${env.service}\033[0m" } } } }
小技巧
demo:4b21355.20241205091711.develop.290
我们生产的镜像名称是由项目名称:commit id.时间.分支.构建号组成。以方便运维对更新管理和应用回滚 \在 jenkins 中添加构造任务


编辑任务详情,设置 git 地址和登陆账号密码。



注意
jenkins的构造文件Jenkinsfile目前不支持切换分支,所以我们把文件创建在master分支上。 这就变相的要求,其他分支都需要使用同一个构造文件。 如果有分支需要使用不同的构造文件,可临时在jenkins的任务页面修改分支名称。指定 Jenkinsfile 在文件夹位置,及配置分支的参数化构建


执行构建并查看构建过程



VUE 项目
备注
jenkins 上的创建项目的基本操作,参考上面的 ASP.NET Core 的构造过程。其他前端项目过程也大致一致。
如果需要增加多余的参数化构造,参考上面的第 5 步。下面的例子中增加了一个 NPM_SCRIPT 的参数
在项目文件夹下添加
nginx.config并将如下配置保存到此文件events{} http { include /etc/nginx/mime.types; server { listen 80; server_name localhost; root /usr/share/nginx/html; index index.html; location / { try_files $uri $uri/ /index.html; } } }
注意
注意,上面的
nginx的路由配置,是 UI 页面做为主站部署时,既https://xxx.demo.com/即可访问 UI。 如果是子站部署https://xxx.demo.com/eshop, 需要使用下面的配置。events{} http { include /etc/nginx/mime.types; server { listen 80; server_name localhost; root /usr/share/nginx/html; index index.html; location /eshop { try_files $uri $uri/ /eshop/index.html; } } }
在项目文件夹下
Dockerfile,并将如下配置保存到此文件FROM node:14.21.3 as builder # 定义变量此变量可从 jenkins 页面选择传入 ARG NPM_SCRIPT WORKDIR /tmp # 设置淘宝镜像 RUN npm config set registry https://registry.npmmirror.com # 拷贝依赖文件、依赖变更文件到tmp目录下 COPY package.json package-lock.json /tmp/ RUN npm install # 拷贝源代码文件至tmp目录 COPY . /tmp # 执行所定义的变量 RUN npm run ${NPM_SCRIPT} # 运行镜像 FROM nginx:1.16.0 # 创建子目录 RUN mkdir -p /usr/share/nginx/html/eshop # 拷贝 nginx 配置文件 COPY ./nginx.conf /etc/nginx/nginx.conf # 从 builder 镜像复制编译后文件到运行目录 COPY --from=builder /tmp/dist /usr/share/nginx/html/eshop EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]
重要
COPY ./dist /usr/share/nginx/html这里的 dist 文件夹是 vue build 的输出目录。根据自己项目修改!在项目文件夹下增加
Jenkinsfile,并根据自己的项目修改。小技巧
Jenkinsfile 内容参考 ASP.NET Core 项目内容。但是为了给 vue 编译时传递
NPM_SCRIPT参数,需要在jenkins的任务页面中添加参数化构建,并增加如下内容。parameters { // npm run <script> string(name: 'NPM_SCRIPT', defaultValue: '') } stage('docker build and push') { container('jnlp') { // 这里的腾讯镜像仓库配置不需要改动。 docker.withRegistry('https://registry.cn-hangzhou.aliyuncs.com', 'xxx-xxx-xx') { def image = docker.build("${env.imageUrl}" , "--build-arg NPM_SCRIPT=${params.NPM_SCRIPT} .") image.push() } } }
VUE 项目作为子站部署
当我们的 vue 项目需要以子站 https://www.demo.com/eshop 方式访问时,需要针对 vue 、nginx 及 dockerfile 都做出相应的修改,才能使得不同项目的 vue 路由都正常工作。
下面,我们以/eshop子站来简单介绍下 vue 需要子站部署时该如何对接。
修改
vue.config.js1module.exports = { 2 publicPath: '/eshop' 3}
nginx.conf1events{} 2http { 3 include /etc/nginx/mime.types; 4 access_log off; 5 server { 6 listen 80; 7 server_name localhost; 8 root /usr/share/nginx/html; 9 index index.html; 10 location /eshop { 11 try_files $uri $uri/ /eshop/index.html; 12 } 13 } 14}
dockerfile1FROM nginx:1.16.0-alpine 2# copy artifact build from the 'build environment' 3RUN mkdir -p /usr/share/nginx/html/eshop 4COPY ./nginx.conf /etc/nginx/nginx.conf 5COPY ./dist /usr/share/nginx/html/eshop 6# expose port 80 7EXPOSE 80 8# run nginx 9CMD ["nginx", "-g", "daemon off;"]
容器平台 K8S
目前,我们在 IDC 中部署了一套自建的 K8S 集群,用于部署我们企业内部服务。对于 C 端服务,我们使用腾讯云容器服务 TKE 及阿里云的容器服务。
部分外采系统使用 K3S 搭建的小集群。
Dashboard
Dashboard 使用飞致云开源的多集群管理工具 kubepi 作为集群的管理工具。 \
kubepi 支持配置 LDAP、OIDC 等认证方式登录,支持多集群管理,支持多种资源的管理,如:deploy configMap service ingress 等。
发布应用
进入集群

工作负载中 -> Deployment -> YAML -> 从文件读取

预览 yaml 内容,提交。

小技巧
我们可以将 deploy configMap service 相关 yaml 内容合并到同一个 yaml 文件中。
更新应用新版本
在 deployment 中找到需要更新版本的应用并进入查看详情。

在“调整镜像版本”中,更新应用最近的版本号。

危险
我们并不推荐在 jenkins 中增加自动脚本来实现 CI 到 CD 的自动化。
因为当团队的项目较多时,根据 Git 更变自动触发会导致 jenkins 任务过多,持续的 CI、CD 过程会过多消耗集群资源。
所以,我们推荐CI、CD的过程都通过人工操作来完成,按需构建、按需发布!!!
扩容、重启
扩容、缩容、重启应用

查看应用日志、进入容器、查看文件
