实践005-Gitlab CICD全项目整合
文章目录
- 环境准备
- 环境准备
- 集成Kubernetes
- Gitlab CICD项目整合
- 项目整合
- 整合设计
- 后端Java项目部署
- 后端Java项目静态检查
- 后端Java项目镜像构建
- 创建Java项目部署文件
- 创建完整流水线
- 前端webui项目部署
- 前端webui项目镜像构建
- 创建webui项目部署文件
- 创建完整流水线
- 构建父子类型流水线
- 查看流水线
- 确认验证
- 部署情况确认
- 验证后端应用
- 验证前端应用
- Ddevops梳理
环境准备
环境准备
单独测试前后端项目的时候已成功部署相关应用,为便于后续整合,将已部署的应用进行清理。
root@master01:~# kubectl -n gitlabci delete deployments.apps deploy-apiserver-ci deploy-webui-ci
root@master01:~# kubectl -n gitlabci delete service service-apiserver-ci service-webui-ci
root@master01:~# kubectl delete ns gitlabciroot@master01:~# kubectl get ns
整个环境需要发布镜像至阿里云,需要将应用部署到 Kubernetes 。
因此提前在 gitlab 中创建 ALIYUN_USER 和 ALIYUN_PASSWORD 、KUBE_CONFIG 变量,配置阿里云镜像推送的账号和密码。
集成Kubernetes
当前 Gitlab 的 runner 是基于 helm 部署 gitla 的同时配套部署的,即 runner 是运行在 Kubernetes 中的一个 Pod,runner 类型是 Kubernetes ,如下所示:
root@master01:~# kubectl -n gitlab exec -ti mygitlab-gitlab-runner-798986f578-h2thf -- bash
camygitlab-gitlab-runner-798986f578-h2thf:/$ cat /home/gitlab-runner/.gitlab-runner/config.toml
#……
[[runners]]
#……executor = "kubernetes"
因此该 runner 后续需要直接在 Kubernetes 中部署业务,需要安装 kubectl 命令,以及配置 kubeconfig 上下文。
从而需要提前将 kubeconfig 内容以变量形式引入到 runner Pod 中。
root@master01:~# echo $(cat ~/.kube/config | base64) | tr -d " "
YXBpVmVyc2lvbjogdjEKY2x1c3RlcnM6Ci0gY2x1c3RlcjoKICA……
添加变量 KUBE_CONFIG 。
提示:由于后续流水线中作业有 main 和 tag 两种触发方式,因此建议将变量取消受保护。
同时对于 Kubernetes 的部署可参考: 附042.Kubernetes_v1.33.0生成环境高可用部署方案
Gitlab CICD项目整合
项目整合
整合设计
当前后端 java 和前端 web 的构建、测试、编译基于学习目的,都由独立项目通过 gitlab 验证,基于生产环境需要,现需要整合至一个项目中,从而将多个子项目放在一个项目代码仓中。
gitlab 创建总项目: mycicd 。
由于整合后的新项目为 mycicd ,因此原有部分文件的内容涉及路径部分均需要稍作调整,sonarqube代码检查对接的gitlab项目也需要重新调整。
[root@gitclient ~]# git clone git@gitlab.linuxsb.com:mygroup/mycicd.git
[root@gitclient ~]# cd mycicd/
复制前后端项目至该目录。
[root@gitclient mycicd]# cp -rp ../apiserver .
[root@gitclient mycicd]# cp -rp ../webui .
[root@gitclient mycicd]# tree -L 2 .
.
├── apiserver
│ ├── deployjavaci.yaml
│ ├── deployjavaprod.yaml
│ ├── deployjavatest.yaml
│ ├── Dockerfile
│ ├── HELP.md
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ ├── README.md
│ └── src
├── README.md
└── webui├── babel.config.js├── deploywebuici.yaml├── deploywebuiprod.yaml├── deploywebuitest.yaml├── Dockerfile├── jsconfig.json├── node_modules├── package.json├── package-lock.json├── public├── README.md├── src└── vue.config.js
后端Java项目部署
后端Java项目静态检查
参考实践002-Gitlab CICD静态代码检查 ,重新配置 sonarqube 对 gitlab 新建的 mycicd 项目的检查。
后端Java项目镜像构建
目录有所调整。
[root@gitclient mycicd]# vim apiserver/Dockerfile
FROM uhub.service.ucloud.cn/imxhy/maven:3.8.5-openjdk-17MAINTAINER xhy@itzgr.cnRUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo "Asia/Shanghai" > /etc/timezoneEXPOSE 8080WORKDIR /opt/apiserviceCOPY target/apiservice-0.0.1-SNAPSHOT.jar ./ENTRYPOINT ["java","-jar","/opt/apiservice/apiservice-0.0.1-SNAPSHOT.jar"]
创建Java项目部署文件
调整如下 ci 、 test 、 prod 部署文件。
- ci 部署文件
[root@gitclient mycicd]# vim apiserver/deployjavaci.yaml
---
apiVersion: v1
kind: Namespace
metadata:name: gitlabci---
apiVersion: apps/v1
kind: Deployment
metadata:name: deploy-apiserver-cinamespace: gitlabci
spec:replicas: 2revisionHistoryLimit: 5selector:matchLabels:app: apiserver-cistrategy:type: RollingUpdaterollingUpdate:maxUnavailable: 25%maxSurge: 25%template:metadata:labels:app: apiserver-cispec:containers:- name: apiserver-cienv:- name: TZvalue: Asia/Shanghaiimage: __POD_CONTAINERS_IMAGE__imagePullPolicy: IfNotPresentports:- containerPort: 8080protocol: TCPreadinessProbe:httpGet:path: /demo/helloport: 8080scheme: HTTPinitialDelaySeconds: 30periodSeconds: 10livenessProbe:httpGet:path: /demo/helloport: 8080scheme: HTTPinitialDelaySeconds: 30periodSeconds: 10---
apiVersion: v1
kind: Service
metadata:name: service-apiserver-cinamespace: gitlabci
spec:ports:- nodePort: 32101port: 8080protocol: TCPtargetPort: 8080selector:app: apiserver-cisessionAffinity: ClientIPtype: NodePort
- test 部署文件
[root@gitclient mycicd]# vim apiserver/deployjavatest.yaml
---
apiVersion: v1
kind: Namespace
metadata:name: gitlabtest---
apiVersion: apps/v1
kind: Deployment
metadata:name: deploy-apiserver-testnamespace: gitlabtest
spec:replicas: 2revisionHistoryLimit: 5selector:matchLabels:app: apiserver-teststrategy:type: RollingUpdaterollingUpdate:maxUnavailable: 25%maxSurge: 25%template:metadata:labels:app: apiserver-testspec:containers:- name: apiserver-testenv:- name: TZvalue: Asia/Shanghaiimage: __POD_CONTAINERS_IMAGE__imagePullPolicy: IfNotPresentports:- containerPort: 8080protocol: TCPreadinessProbe:httpGet:path: /demo/helloport: 8080scheme: HTTPinitialDelaySeconds: 30periodSeconds: 10livenessProbe:httpGet:path: /demo/helloport: 8080scheme: HTTPinitialDelaySeconds: 30periodSeconds: 10---
apiVersion: v1
kind: Service
metadata:name: service-apiserver-testnamespace: gitlabtest
spec:ports:- nodePort: 32102port: 8080protocol: TCPtargetPort: 8080selector:app: apiserver-testsessionAffinity: ClientIPtype: NodePort
- prod 部署文件
[root@gitclient mycicd]# vim apiserver/deployjavaprod.yaml
---
apiVersion: v1
kind: Namespace
metadata:name: gitlabprod---
apiVersion: apps/v1
kind: Deployment
metadata:name: deploy-apiserver-prodnamespace: gitlabprod
spec:replicas: 2revisionHistoryLimit: 5selector:matchLabels:app: apiserver-prodstrategy:type: RollingUpdaterollingUpdate:maxUnavailable: 25%maxSurge: 25%template:metadata:labels:app: apiserver-prodspec:containers:- name: apiserver-prodenv:- name: TZvalue: Asia/Shanghaiimage: __POD_CONTAINERS_IMAGE__imagePullPolicy: IfNotPresentports:- containerPort: 8080protocol: TCPreadinessProbe:httpGet:path: /demo/helloport: 8080scheme: HTTPinitialDelaySeconds: 30periodSeconds: 10livenessProbe:httpGet:path: /demo/helloport: 8080scheme: HTTPinitialDelaySeconds: 30periodSeconds: 10---
apiVersion: v1
kind: Service
metadata:name: service-apiserver-prodnamespace: gitlabprod
spec:ports:- nodePort: 32103port: 8080protocol: TCPtargetPort: 8080selector:app: apiserver-prodsessionAffinity: ClientIPtype: NodePort
创建完整流水线
创建如下流水线,并且将后端 Java 项目的编译构建阶段全部整合到一起。并且最后直接使用 git clone 使用 autotest 项目进行最后的测试。
即对于后端 Java 项目,整合 UnitTest+compile+sonarqube-check ----> build ----> deploy_java_ci/deploy_java_test ----> check_java_ci_pod/check_java_test_pod ----> test 全链路流程。
[root@gitclient mycicd]# vim apiserver/.gitlab-ci.yml
stages:- compile- build- deploy- check- testvariables:KUBECONFIG: "/.kube/config"PROJECT_DIR: "${CI_PROJECT_DIR}/apiserver"GITLAB_HOST: gitlab.linuxsb.comGITLAB_PORT: "32222"REPO_URL: git@${GITLAB_HOST}:mygroup/autotest.gitunittest_java:stage: compileimage: maven:3.8.5-openjdk-17script:- cd ${PROJECT_DIR}- mvn verify -Dmaven.test.failure.ignore=true- ls target/surefire-reports/*.xmlrules:- if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_TAGartifacts:when: alwaysreports:junit:- apiserver/target/surefire-reports/TEST-*.xml- apiserver/target/failsafe-reports/TEST-*.xmltags:- study-runnercompile_java:stage: compileimage: uhub.service.ucloud.cn/imxhy/maven:3.8.5-openjdk-17artifacts:paths:- apiserver/target/apiservice-0.0.1-SNAPSHOT.jarscript:- pwd- cd ${PROJECT_DIR}- mvn clean- mvn compile- mvn package -Dmaven.test.skip=true- ls targetrules:- if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_TAGtags:- study-runnersonarqube_check_java:stage: compileimage: maven:3.8.5-openjdk-17variables:SONAR_USER_HOME: "${CI_PROJECT_DIR}/apiserver/.sonar"GIT_DEPTH: "0"cache:key: "${CI_JOB_NAME}"paths:- .sonar/cachescript:- cd ${PROJECT_DIR}- mvn verify sonar:sonar -Dsonar.projectKey=mygroup_mycicd_AZaRvvQBjzPXArMYpIcZallow_failure: truerules:- if: $CI_COMMIT_BRANCH == "main"tags:- study-runnerbuild_java:stage: buildimage: uhub.service.ucloud.cn/imxhy/executor:v1.9.0-debugneeds:- unittest_java- compile_javascript:- cd ${PROJECT_DIR}- ls target- IMAGE_TAG=$(echo "${CI_COMMIT_TIMESTAMP}" | sed 's/T/_/g; s/-//g; s/://g' | cut -c1-15)- IMAGE_TAG_TO_INSTALL=${CI_COMMIT_TAG:-$IMAGE_TAG}- echo ${IMAGE_TAG_TO_INSTALL}- mkdir -p /kaniko/.docker- echo "{\"auths\":{\"registry.cn-hangzhou.aliyuncs.com\":{\"username\":\"${ALIYUN_USER}\",\"password\":\"${ALIYUN_PASSWORD}\"}}}" > /kaniko/.docker/config.json- cat /kaniko/.docker/config.json- echo ${PROJECT_DIR}- echo {\"username\":\"${ALIYUN_USER}\",\"password\":\"${ALIYUN_PASSWORD}\"}- ls ${PROJECT_DIR}/Dockerfile- >/kaniko/executor--context "${PROJECT_DIR}"--dockerfile "${PROJECT_DIR}/Dockerfile"--destination "registry.cn-hangzhou.aliyuncs.com/xhyimages/apiservice:${IMAGE_TAG_TO_INSTALL}"--registry-mirror "https://dbzucv6w.mirror.aliyuncs.com"rules:- if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_TAGtags:- study-runnerdeploy_java_ci:stage: deployimage: uhub.service.ucloud.cn/imxhy/kubectl:1.33.0script:- mkdir -p /.kube- echo $KUBE_CONFIG | base64 -d > $KUBECONFIG- kubectl version- IMAGE_TAG=$(echo "${CI_COMMIT_TIMESTAMP}" | sed 's/T/_/g; s/-//g; s/://g' | cut -c1-15)- IMAGE_TAG_TO_INSTALL=${CI_COMMIT_TAG:-$IMAGE_TAG}- echo $IMAGE_TAG_TO_INSTAL- sed -i "s#__POD_CONTAINERS_IMAGE__#registry.cn-hangzhou.aliyuncs.com/xhyimages/apiservice:${IMAGE_TAG_TO_INSTALL}#g" apiserver/deployjavaci.yaml- kubectl apply -f apiserver/deployjavaci.yaml || exit 1rules:- if: $CI_COMMIT_BRANCH == "main"tags:- study-runnerdeploy_java_test:stage: deployimage: uhub.service.ucloud.cn/imxhy/kubectl:1.33.0when: manualscript:- mkdir -p /.kube- echo $KUBE_CONFIG | base64 -d > $KUBECONFIG- kubectl version- IMAGE_TAG=$(echo "${CI_COMMIT_TIMESTAMP}" | sed 's/T/_/g; s/-//g; s/://g' | cut -c1-15)- IMAGE_TAG_TO_INSTALL=${CI_COMMIT_TAG:-$IMAGE_TAG}- echo $IMAGE_TAG_TO_INSTAL- sed -i "s#__POD_CONTAINERS_IMAGE__#registry.cn-hangzhou.aliyuncs.com/xhyimages/apiservice:${IMAGE_TAG_TO_INSTALL}#g" apiserver/deployjavatest.yaml- kubectl apply -f apiserver/deployjavatest.yaml || exit 1rules:- if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_TAGtags:- study-runnerdeploy_java_prod:stage: deployimage: uhub.service.ucloud.cn/imxhy/kubectl:1.33.0when: manualscript:- mkdir -p /.kube- echo $KUBE_CONFIG | base64 -d > $KUBECONFIG- kubectl version- IMAGE_TAG=$(echo "${CI_COMMIT_TIMESTAMP}" | sed 's/T/_/g; s/-//g; s/://g' | cut -c1-15)- IMAGE_TAG_TO_INSTALL=${CI_COMMIT_TAG:-$IMAGE_TAG}- echo $IMAGE_TAG_TO_INSTAL- sed -i "s#__POD_CONTAINERS_IMAGE__#registry.cn-hangzhou.aliyuncs.com/xhyimages/apiservice:${IMAGE_TAG_TO_INSTALL}#g" apiserver/deployjavaprod.yaml- kubectl apply -f apiserver/deployjavaprod.yaml || exit 1rules:- if: $CI_COMMIT_TAGtags:- study-runnercheck_java_ci_pod:stage: checkimage: uhub.service.ucloud.cn/imxhy/kubectl:1.33.0script:- mkdir -p /.kube- echo $KUBE_CONFIG | base64 -d > $KUBECONFIG- timeout 120 bash -c "until kubectl get pods -n gitlabci -l app=apiserver-ci --field-selector=status.phase=Running --no-headers | grep '1/1'; do sleep 3; done"rules:- if: $CI_COMMIT_BRANCH == "main"needs:- deploy_java_citags:- study-runnercheck_java_test_pod:stage: checkimage: uhub.service.ucloud.cn/imxhy/kubectl:1.33.0script:- mkdir -p /.kube- echo $KUBE_CONFIG | base64 -d > $KUBECONFIG- timeout 120 bash -c "until kubectl get pods -n gitlabtest -l app=apiserver-test --field-selector=status.phase=Running --no-headers | grep '1/1'; do sleep 3; done"rules:- if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_TAGneeds:- deploy_java_testtags:- study-runnercheck_java_prod_pod:stage: checkimage: uhub.service.ucloud.cn/imxhy/kubectl:1.33.0script:- mkdir -p /.kube- echo $KUBE_CONFIG | base64 -d > $KUBECONFIG- timeout 120 bash -c "until kubectl get pods -n gitlabprod -l app=apiserver-prod --field-selector=status.phase=Running --no-headers | grep '1/1'; do sleep 3; done"rules:- if: $CI_COMMIT_TAGneeds:- deploy_java_prodtags:- study-runnertest:stage: testimage: python:3.13.3before_script:- mkdir -p ~/.ssh- chmod 700 ~/.ssh- echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa- chmod 600 ~/.ssh/id_rsa- echo "Host ${GITLAB_HOST}" >> ~/.ssh/config- echo " Port ${GITLAB_PORT}" >> ~/.ssh/config- echo " User git" >> ~/.ssh/config- echo " IdentityFile ~/.ssh/id_rsa" >> ~/.ssh/config- echo " StrictHostKeyChecking no" >> ~/.ssh/config- ssh-keyscan -p ${GITLAB_PORT} ${GITLAB_HOST} >> ~/.ssh/known_hostsscript:- git clone -b main ${REPO_URL}- cd autotest- python -m pip install --no-cache-dir -r requirements.txt- mkdir -p tests/reports- cd tests && pytest -s --junitxml=reports/report.xml || echo "Pytest exited with $?"- pwd- ls -l .- ls -l reportsartifacts:reports:junit: autotest/tests/reports/report.xmlrules:- if: $CI_COMMIT_BRANCH == "main"tags:- study-runner
前端webui项目部署
前端webui项目镜像构建
目录有所调整。
[root@gitclient mycicd]# vim webui/Dockerfile
FROM uhub.service.ucloud.cn/imxhy/node:23.11.0MAINTAINER xhy@itzgr.comRUN npm install -g @vue/cliWORKDIR /opt/webui/COPY . ./RUN npm installENTRYPOINT ["npm","run","serve"]
创建webui项目部署文件
调整如下 ci 、 test 、 prod 部署文件。
- ci 部署文件
[root@gitclient mycicd]# vim webui/deploywebuici.yaml
---
apiVersion: v1
kind: Namespace
metadata:name: gitlabci---
apiVersion: apps/v1
kind: Deployment
metadata:name: deploy-webui-cinamespace: gitlabci
spec:replicas: 2revisionHistoryLimit: 5selector:matchLabels:app: webui-cistrategy:type: RollingUpdaterollingUpdate:maxUnavailable: 25%maxSurge: 25%template:metadata:labels:app: webui-cispec:containers:- name: webui-cienv:- name: TZvalue: Asia/Shanghaiimage: __POD_CONTAINERS_IMAGE__imagePullPolicy: IfNotPresentports:- containerPort: 8080protocol: TCPreadinessProbe:httpGet:path: /port: 8080scheme: HTTPinitialDelaySeconds: 30periodSeconds: 10livenessProbe:httpGet:path: /port: 8080scheme: HTTPinitialDelaySeconds: 30periodSeconds: 10---
apiVersion: v1
kind: Service
metadata:name: service-webui-cinamespace: gitlabci
spec:ports:- nodePort: 32111port: 8080protocol: TCPtargetPort: 8080selector:app: webui-cisessionAffinity: ClientIPtype: NodePort
- test 部署文件
[root@gitclient mycicd]# vim webui/deploywebuitest.yaml
---
apiVersion: v1
kind: Namespace
metadata:name: gitlabtest---
apiVersion: apps/v1
kind: Deployment
metadata:name: deploy-webui-testnamespace: gitlabtest
spec:replicas: 2revisionHistoryLimit: 5selector:matchLabels:app: webui-teststrategy:type: RollingUpdaterollingUpdate:maxUnavailable: 25%maxSurge: 25%template:metadata:labels:app: webui-testspec:containers:- name: webui-testenv:- name: TZvalue: Asia/Shanghaiimage: __POD_CONTAINERS_IMAGE__imagePullPolicy: IfNotPresentports:- containerPort: 8080protocol: TCPreadinessProbe:httpGet:path: /port: 8080scheme: HTTPinitialDelaySeconds: 30periodSeconds: 10livenessProbe:httpGet:path: /port: 8080scheme: HTTPinitialDelaySeconds: 30periodSeconds: 10---
apiVersion: v1
kind: Service
metadata:name: service-webui-testnamespace: gitlabtest
spec:ports:- nodePort: 32112port: 8080protocol: TCPtargetPort: 8080selector:app: webui-testsessionAffinity: ClientIPtype: NodePort
- prod 部署文件
[root@gitclient mycicd]# vim webui/deploywebuiprod.yaml
---
apiVersion: v1
kind: Namespace
metadata:name: gitlabprod---
apiVersion: apps/v1
kind: Deployment
metadata:name: deploy-webui-prodnamespace: gitlabprod
spec:replicas: 2revisionHistoryLimit: 5selector:matchLabels:app: webui-prodstrategy:type: RollingUpdaterollingUpdate:maxUnavailable: 25%maxSurge: 25%template:metadata:labels:app: webui-prodspec:containers:- name: webui-prodenv:- name: TZvalue: Asia/Shanghaiimage: __POD_CONTAINERS_IMAGE__imagePullPolicy: IfNotPresentports:- containerPort: 8080protocol: TCPreadinessProbe:httpGet:path: /port: 8080scheme: HTTPinitialDelaySeconds: 30periodSeconds: 10livenessProbe:httpGet:path: /port: 8080scheme: HTTPinitialDelaySeconds: 30periodSeconds: 10---
apiVersion: v1
kind: Service
metadata:name: service-webui-prodnamespace: gitlabprod
spec:ports:- nodePort: 32113port: 8080protocol: TCPtargetPort: 8080selector:app: webui-prodsessionAffinity: ClientIPtype: NodePort
创建完整流水线
创建如下流水线,并且将前端 webui 项目的构建阶段全部整合到一起。
即对于前端 webui 项目,整合 build ----> deploy_webui_ci/deploy_webui_test ----> check_webui_ci_pod/check_webui_test_pod 全链路流程。
[root@gitclient mycicd]# vim webui/.gitlab-ci.yml
stages:- build- deploy- checkvariables:KUBECONFIG: "/.kube/config"PROJECT_DIR: "${CI_PROJECT_DIR}/webui"build_webui:stage: buildimage: uhub.service.ucloud.cn/imxhy/executor:v1.9.0-debugscript:- cd ${PROJECT_DIR}- IMAGE_TAG=$(echo "${CI_COMMIT_TIMESTAMP}" | sed 's/T/_/g; s/-//g; s/://g' | cut -c1-15)- IMAGE_TAG_TO_INSTALL=${CI_COMMIT_TAG:-$IMAGE_TAG}- echo $IMAGE_TAG_TO_INSTALL- mkdir -p /kaniko/.docker- echo "{\"auths\":{\"registry.cn-hangzhou.aliyuncs.com\":{\"username\":\"${ALIYUN_USER}\",\"password\":\"${ALIYUN_PASSWORD}\"}}}" > /kaniko/.docker/config.json- cat /kaniko/.docker/config.json- echo ${PROJECT_DIR}- echo {\"username\":\"${ALIYUN_USER}\",\"password\":\"${ALIYUN_PASSWORD}\"}- ls ${PROJECT_DIR}/Dockerfile- >/kaniko/executor--context "${PROJECT_DIR}"--dockerfile "${PROJECT_DIR}/Dockerfile"--destination "registry.cn-hangzhou.aliyuncs.com/xhyimages/webui:${IMAGE_TAG_TO_INSTALL}"--registry-mirror "https://dbzucv6w.mirror.aliyuncs.com"rules:- if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_TAGtags:- study-runnerdeploy_webui_ci:stage: deployimage: uhub.service.ucloud.cn/imxhy/kubectl:1.33.0script:- mkdir -p /.kube- echo $KUBE_CONFIG | base64 -d > $KUBECONFIG- kubectl version- IMAGE_TAG=$(echo "${CI_COMMIT_TIMESTAMP}" | sed 's/T/_/g; s/-//g; s/://g' | cut -c1-15)- IMAGE_TAG_TO_INSTALL=${CI_COMMIT_TAG:-$IMAGE_TAG}- sed -i "s#__POD_CONTAINERS_IMAGE__#registry.cn-hangzhou.aliyuncs.com/xhyimages/webui:${IMAGE_TAG_TO_INSTALL}#g" webui/deploywebuici.yaml- kubectl apply -f webui/deploywebuici.yaml || exit 1rules:- if: $CI_COMMIT_BRANCH == "main"tags:- study-runnerdeploy_webui_test:stage: deployimage: uhub.service.ucloud.cn/imxhy/kubectl:1.33.0when: manualscript:- mkdir -p /.kube- echo $KUBE_CONFIG | base64 -d > $KUBECONFIG- kubectl version- IMAGE_TAG=$(echo "${CI_COMMIT_TIMESTAMP}" | sed 's/T/_/g; s/-//g; s/://g' | cut -c1-15)- IMAGE_TAG_TO_INSTALL=${CI_COMMIT_TAG:-$IMAGE_TAG}- sed -i "s#__POD_CONTAINERS_IMAGE__#registry.cn-hangzhou.aliyuncs.com/xhyimages/webui:${IMAGE_TAG_TO_INSTALL}#g" webui/deploywebuitest.yaml- kubectl apply -f webui/deploywebuitest.yaml || exit 1rules:- if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_TAGtags:- study-runnerdeploy_webui_prod:stage: deployimage: uhub.service.ucloud.cn/imxhy/kubectl:1.33.0when: manualscript:- mkdir -p /.kube- echo $KUBE_CONFIG | base64 -d > $KUBECONFIG- kubectl version- IMAGE_TAG=$(echo "${CI_COMMIT_TIMESTAMP}" | sed 's/T/_/g; s/-//g; s/://g' | cut -c1-15)- IMAGE_TAG_TO_INSTALL=${CI_COMMIT_TAG:-$IMAGE_TAG}- sed -i "s#__POD_CONTAINERS_IMAGE__#registry.cn-hangzhou.aliyuncs.com/xhyimages/webui:${IMAGE_TAG_TO_INSTALL}#g" webui/deploywebuiprod.yaml- kubectl apply -f webui/deploywebuiprod.yaml || exit 1rules:- if: $CI_COMMIT_TAGtags:- study-runnercheck_webui_ci_pod:stage: checkimage: uhub.service.ucloud.cn/imxhy/kubectl:1.33.0script:- mkdir -p /.kube- echo $KUBE_CONFIG | base64 -d > $KUBECONFIG- timeout 120 bash -c "until kubectl get pods -n gitlabci -l app=webui-ci --field-selector=status.phase=Running --no-headers | grep '1/1'; do sleep 3; done"rules:- if: $CI_COMMIT_BRANCH == "main"needs:- deploy_webui_citags:- study-runnercheck_webui_test_pod:stage: checkimage: uhub.service.ucloud.cn/imxhy/kubectl:1.33.0script:- mkdir -p /.kube- echo $KUBE_CONFIG | base64 -d > $KUBECONFIG- timeout 120 bash -c "until kubectl get pods -n gitlabtest -l app=webui-test --field-selector=status.phase=Running --no-headers | grep '1/1'; do sleep 3; done"rules:- if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_TAGneeds:- deploy_webui_testtags:- study-runnercheck_webui_prod_pod:stage: checkimage: uhub.service.ucloud.cn/imxhy/kubectl:1.33.0script:- mkdir -p /.kube- echo $KUBE_CONFIG | base64 -d > $KUBECONFIG- timeout 120 bash -c "until kubectl get pods -n gitlabprod -l app=webui-prod --field-selector=status.phase=Running --no-headers | grep '1/1'; do sleep 3; done"rules:- if: $CI_COMMIT_TAGneeds:- deploy_webui_prodtags:- study-runner
构建父子类型流水线
父子类型流水线适用于将多个子项目放在一个项目代码仓中的场景。
该场景中,流水线中存在后端 Java 、前端 webui 两个项目的编译、构建、发布以及集成在一起的测试和部署等。
因此可以使用父子类型的流水线,且配置是如果只修改了Java子项目,则只执行和Java子项目相关的流水线任务即可。
前端子项目的目录为 webui,后端子项目的目录为apiserver,组建父子类型的流水线,就是在项目的根目录创建流水线发布文件.gitlab-ci.yml作为父流水线的配置,各子项目分别创建一个.gitlab-ci.yml作为子流水线的位置。
如上所致 java 后端和 webui 前端流水线均创建完成。
- 父流水线
子流水线不会自动触发,需要项目根目录下的.gitlab-ci.yml文件进行触发。
在父流水线中调用子流水线需要使用关键字 trigger 和 include 。
[root@gitclient mycicd]# vim .gitlab-ci.yml
stages:- triggers- pre-checkverify_files:stage: pre-checkscript:- ls -l apiserver/.gitlab-ci.yml- ls -l webui/.gitlab-ci.ymltrigger_apiserver:stage: triggerstrigger:include: apiserver/.gitlab-ci.ymlforward:pipeline_variables: truevariables:PARENT_TAG: $CI_COMMIT_TAGrules:- if: $CI_COMMIT_BRANCH == "main"changes:- apiserver/*- if: $CI_COMMIT_TAGchanges: []trigger_webui:stage: triggerstrigger:include: webui/.gitlab-ci.ymlforward:pipeline_variables: truevariables:PARENT_TAG: $CI_COMMIT_TAGrules:- if: $CI_COMMIT_BRANCH == "main"changes:- webui/*- if: $CI_COMMIT_TAGchanges: []
如上定义了一个节点, trigger ,然后 trigger 里定义了两个任务,通过 include 关键字将子目录下的 .gitlab-ci.yml 引用。
rules 和 changes 关键字是用来控制 job 触发执行的,指定具体的目录。
如上 trigger_back 的 job 指定了检测目录为 apiserver,即只有当 apiserver 目录中的文件或代码发生了变化,apiserver 目录中的子流水线才会执行。
- 提交流水线
首次提交后,由于前后端都是第一次生成,因此会自动执行完所有任务。
[root@gitclient mycicd]# git add .
[root@gitclient mycicd]# git status [root@gitclient mycicd]# git commit -m "Deploy apiserver and webui cicd"
[root@gitclient mycicd]# git push origin main
查看流水线
查看提交流水线后的作业情况。
确认验证
部署情况确认
查看部署在 Kubernetes 后的应用,
root@master01:~# kubectl -n gitlabci get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
deploy-apiserver-ci-68655894c8-qzcwr 1/1 Running 0 117m 10.10.19.82 worker03 <none> <none>
deploy-apiserver-ci-68655894c8-vrdwd 1/1 Running 0 117m 10.10.5.47 worker01 <none> <none>
deploy-webui-ci-5cfb75dfcf-7zm8w 1/1 Running 0 111m 10.10.19.115 worker03 <none> <none>
deploy-webui-ci-5cfb75dfcf-zncr9 1/1 Running 0 111m 10.10.5.35 worker01 <none> <none>
root@master01:~# kubectl -n gitlabci get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service-apiserver-ci NodePort 10.20.29.161 <none> 8080:32101/TCP 117m app=apiserver-ci
service-webui-ci NodePort 10.20.10.106 <none> 8080:32111/TCP 112m app=webui-ci
root@master01:~# kubectl -n gitlabci get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
deploy-apiserver-ci 2/2 2 2 117m
deploy-webui-ci 2/2 2 2 112m
验证后端应用
浏览器直接访问: http://172.24.8.180:32101/demo/hello 。
验证前端应用
浏览器直接访问: http://172.24.8.180:32111
Ddevops梳理
如上所示为一个包含前后端的完整流水线,其主要包括过程总结如下:
-
当后端研发人员提交代码后,流水线会自动触发。首先执行compile阶段,主要包括unittest_java、compile_java和静态代码检查sonarqube_check_java,这三个认为是并行执行的。而且只要compile阶段执行完成,不论单元测试和静态代码检查是否执行完成,都会执行第二个build镜像构建阶段。当build镜像构建阶段完成后,自动部署到CI环境,CI环境部署完成后,开始检查CI环境中的Pod状态是否正常。检查完成后,开始自动执行自动化测试。当自动化测试执行完成后,根据测试结果及其他需求,计划是否要部署到测试环境,测试环境的部署由手动执行。
-
部署到测试环境后,流水线执行如下,然后测试团队可以对测试环境进行测试:
- 当测试团队测试完成,并对测试结果进行bug修复完成后,可以通过tags部署线上生产环境。
-
打完tag后同样会触发新的流水线,通过打tag触发的流水线有两个选择,即部署测试环境或部署生产环境,同时保留手动执行,即在通过CI环境同时修复bug后打tag,然后人为审核是否发版,然后手动执行。
-
手动部署 test 环境,然后可以通知测试人员对test环境进行测试。
-
测试团队确认后,可以手动开始部署 prod 生产环境。
相关文章:

实践005-Gitlab CICD全项目整合
文章目录 环境准备环境准备集成Kubernetes Gitlab CICD项目整合项目整合整合设计 后端Java项目部署后端Java项目静态检查后端Java项目镜像构建创建Java项目部署文件创建完整流水线 前端webui项目部署前端webui项目镜像构建创建webui项目部署文件创建完整流水线 构建父子类型流水…...

懒人美食帮SpringBoot订餐系统开发实现
概述 快速构建一个订餐系统,今天,我们将通过”懒人美食帮”这个基于SpringBoot的订餐系统项目,为大家详细解析从用户登录到多角色权限管理的完整实现方案。本教程特别适合想要学习企业级应用开发的初学者。 主要内容 1. 用户系统设计与实现…...
css animation 动画属性
animation // 要绑定的关键帧规则名称 animation-name: slidein;// 定义动画完成一个周期所需的时间,秒或毫秒 animation-duration: 3s;// 定义动画速度曲线 animation-timing-function: ease;// 定义动画开始前的延迟时间 animation-delay: 1s;// 定义动画播放次数…...

MySQL 从入门到精通(六):视图全面详解 —— 虚拟表的灵活运用
在数据库开发中,我们经常需要重复执行复杂的多表查询,或是需要限制用户只能访问特定数据。这时候,MySQL 的 视图(View)就能大显身手。作为一种 “虚拟表”,视图不存储实际数据,却能基于 SQL 查询…...

手机隐私数据彻底删除工具:回收或弃用手机前防数据恢复
软件介绍 有这样一款由吾爱网友chenwangjun 原创开发的数据处理软件,名为 AndroidDiskClear。它的核心功能十分强大,能够将你手机里已经删除的各类文件,像图片、普通文件、文字信息等彻底清除干净,有效杜绝数据恢复类软件的二次恢…...

数据压缩实现案例
在driver中修改代码 package com.root.mapreduce.compress; import java.io.IOException; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; import org.apache.…...
python实战项目69:基于Python爬虫的链家二手房数据采集方法研究
python实战项目69:链家二手房数据采集 一、项目需求1.1 房地产数据价值1.2 传统数据获取局限性1.3 技术可行性二、数据采集流程2.1 需求分析2.2 网页结构分析2.3 请求发送与反爬策略2.4 数据解析2.5 数据存储三、结论与展望四、完整代码一、项目需求 本文针对房地产数据分析需…...
xml与注解的区别
功能xml配置注解定义bean bean标签 id属性 class属性 Component Controller Service Repository ComponentScan 设置依赖注入 setter注入(set方法) 构造器注入(构造方法) Autowired Qualifier Value 配置第三方bean bean标签 静…...

FlySecAgent:——MCP全自动AI Agent的实战利器
最近,出于对人工智能在网络安全领域应用潜力的浓厚兴趣,我利用闲暇时间进行了深入研究,并成功开发了一款小型轻量化的AI Agent安全客户端FlySecAgent。 什么是 FlySecAgent? 这是一个基于大语言模型和MCP(Model-Contr…...
利用flask设计接口
Flask 接口设计详尽指南(整合知识库优化版) 目录 基础概念与安装接口设计规范核心功能实现高级特性扩展错误处理与调试部署与优化完整示例 基础概念与安装 安装 Flask pip install Flask项目结构建议 my_flask_api/ ├── app.py # 主…...

ideal创建Springboot项目(Maven,yml)
以下是使用 IntelliJ IDEA 创建基于 Maven 的 Spring Boot 项目并使用 YAML 配置文件的详细步骤: 一、创建 Spring Boot 项目 启动项目创建向导 打开 IntelliJ IDEA,点击“File”->“New”->“Project”。 在弹出的“New Project”窗口中&#…...

Pycharm(十九)深度学习
一、深度学习概述 1.1 什么是深度学习 深度学习是机器学习中的一种特殊方法,它使用称为神经网络的复杂结构,特别是“深层”的神经网络,来学习和做出预测。深度学习特别适合处理大规模和高维度的数据,如图像、声音和文本。深度学习、机器学习和人工智能之间的关系如下图所…...
XSS 攻击:深入剖析“暗藏在网页中的脚本“与防御之道
XSS (Cross-Site Scripting),即跨站脚本攻击,是 Web 安全领域中最常见也最具危害性的漏洞之一。攻击者通过巧妙的手段将恶意的 JavaScript、HTML 或其他脚本代码注入到正常的 Web 页面中。当其他用户浏览这些被注入了恶意脚本的页面时,这些脚…...

Scrapyd 详解:分布式爬虫部署与管理利器
Scrapyd 是 Scrapy 官方提供的爬虫部署与管理平台,支持分布式爬虫部署、定时任务调度、远程管理爬虫等功能。本文将深入讲解 Scrapyd 的核心功能、安装配置、爬虫部署流程、API 接口使用,以及如何结合 Scrapy-Redis 实现分布式爬虫管理。通过本文&#x…...
ai之pdf解析rapidOCR 的两种底层依赖PaddlePaddle 和ONNXRuntime
rapidocr_onnxruntime 与 rapidocr(通常指 rapidocr_paddle 或其他后端实现)的核心区别及使用推荐: 一、核心区别 特性rapidocr_onnxruntimerapidocr(以 rapidocr_paddle 为例)后端引擎基于 ONNXRuntime 推理框架&…...

驱动开发硬核特训 · 专题篇:Vivante GPU 与 DRM 图形显示体系全解析(i.MX8MP 平台实战)
视频教程请关注 B 站:“嵌入式Jerry”。 一、背景导读:GPU 与 DRM 到底谁负责“显示”? 在嵌入式 Linux 图形系统中,“画面怎么显示出来”的问题,表面看似简单,实则涉及多个内核子系统与用户态组件的协同&…...

C——猜数字游戏
前面我们已经学习了C语言常见概念,数据类型和变量以及分置于循环的内容,现在我们可以将这些内容结合起来写一个有趣的小游戏。下面正式开始我们今天的主题——猜数字游戏的实现。 猜数字游戏的要求: 1.电脑自动生成1~100的随机数。 2.玩家…...

C/C++实践(三)深入理解 C++ 三大特性之一:封装
一、封装的概念与核心思想 封装(Encencapsulation)是 C 面向对象编程(OOP)的三大核心特性之一,其本质是将数据(成员变量)和对数据的操作(成员函数)捆绑在一个逻辑单元&a…...
Filecoin存储管理:如何停止Lotus向特定存储路径写入新扇区数据
Filecoin存储管理:如何停止Lotus向特定存储路径写入新扇区数据 引言背景问题场景解决方案步骤1:修改sectorstore.json文件步骤2:重新加载存储配置步骤3:验证更改 技术原理替代方案最佳实践结论 引言 在Filecoin挖矿过程中&#x…...

1、RocketMQ 核心架构拆解
1. 为什么要使用消息队列? 消息队列(MQ)是分布式系统中不可或缺的中间件,主要解决系统间的解耦、异步和削峰填谷问题。 解耦:生产者和消费者通过消息队列通信,彼此无需直接依赖,极大提升系统灵…...

vue3 element-plus 输入框回车跳转页面问题处理
问题描述: 当页面搜索条件只有一个的情况下,输入框不管有没有值,回车后会跳转页面 解决办法,给表单添加 submit.prevent <el-form ref"ruleForm" :model"search" label-width"120px" class&qu…...
常见WEB漏洞----暴力破解
什么是暴力破解 暴力破解 (Brue Force) 是一种攻击方法 (穷举法),简称为“爆破”,黑客通过反复猜解和实验,旨在以暴力手段登入、访问目标主机获取服务,破坏系统安全,其属于 ATT&CK技术中的一种,常利用…...

快速入门深度学习系列(2)----损失函数、逻辑回归、向量化
针对深度学习入门新手目标不明确 知识体系杂乱的问题 拟开启快速入门深度学习系列文章的创作 旨在帮助大家快速的入门深度学习 写在前面: 本系列按照吴恩达系列课程顺序发布(说明一下为什么不直接看原笔记 因为内容太多 没有大量时间去阅读 所有作者需要一次梳理…...

[超详细,推荐!!!]前端性能优化策略详解
学习记录,部分内容版权归妙码学院 1.优化内容包括那些 其实前端的优化,整体粗略概括下来,白话之: 打开速度怎么变快再次打开速度怎么变快操作怎么才顺滑动画怎么保证流畅 2.性能优化 2.1首屏加载优化 在了解优化方法和策略之…...

数据提取之BeautifulSoup4快速使用
文章目录 一、前言二、概述2.1 安装2.2 初始化2.3 对象类型 三、遍历文档树3.1 子节点3.2 父节点3.3 兄弟节点3.4 前后节点3.5 节点内容3.5.1 文本内容3.5.2 属性值3.5.3 标签删除 四、搜索文档树4.1 find_all4.2 find4.3 CSS选择器4.4 更多 一、前言 官方文档:http…...

list类的详细讲解
【本节目标】 1. list的介绍及使用 2. list的深度剖析及模拟实现 3. list与vector的对比 1. list的介绍及使用 1.1 list的介绍 1. list 是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。 2. list 的底层是双向链表结构&a…...

Linux系统下安装mongodb
1. 配置MongoDB的yum仓库 创建仓库文件 sudo vi /etc/yum.repos.d/mongodb-org.repo添加仓库配置 根据系统版本选择配置(以下示例为CentOS 7和CentOS 9的配置): CentOS 7(安装MongoDB 5.0/4.2等旧版本): In…...

kuka, fanuc, abb机器人和移动相机的标定
基础知识 : 一, 9点标定之固定相机标定: 图1: 固定位置相机拍照 因为相机和机器人的基坐标系是固定的, 所以在海康威视相机的9点标定功能栏中, 填上海康使用“圆查找”捕捉到的坐标值, 再将机器人显示的工具坐标系在基坐标系的实时位置pos_act值填入物理坐标X, Y中即可 图2:…...

Android Framework学习四:init进程实现
文章目录 init流程简介init源码执行顺序执行顺序 init进程的具体工作事项挂载文件系统设置 SELinuxSecondStageMaininit.rc启动zygote和serviceManager进程的重要性serviceManager工作原理 Framework学习之系列文章 init流程简介 下面图片主要围绕 Android 系统中init进程的运…...
Linux计划任务与进程
at 命令使用方法 at 命令可在指定时间执行任务,适用于一次性任务调度。以下是基本用法: 安装 atd 服务(如未安装) # Debian/Ubuntu sudo apt-get install at# CentOS/RHEL sudo yum install at启动服务 sudo systemctl start atd…...