?
前言
之前在團隊中分享了qiankun微服務的單鏡像的部署方案, 詳細決議了單鏡像部署的好處,但由于單鏡像部署在構建時比較復雜,如果在上線時人工地去構建鏡像,將是一個非常復雜,且容易出錯的事情,所以本篇文章會介紹一種使用GitLab CI/CD來構建一個微服務單鏡像的流水線,并應用于生產, 我稱之為 aio 方案 all in one ,五個應用構建到一個docker鏡像中,
?
方案探索
部署檔案目錄
之前分享的單鏡像部署是在根目錄創建一個child,將子應用的編譯的靜態資源都存放其中, 目錄大致是這樣的
└── daas-web/ # 根檔案夾
|
├── child/ # 存放所有微應用的檔案夾
| ├── app1/ # 存放微應用 app1 的檔案夾
| ├── app2/ # 存放微應用 app2 的檔案夾
| ├── app3/ # 存放微應用 app3 的檔案夾
| ├── app4/ # 存放微應用 app4 的檔案夾
├── index.html # mainApp的index.html
├── css/ # 主應用mainApp的css檔案夾
├── js/ # 主應用mainApp的js檔案夾
├── Dockerfile # 鏡像構建Dockerfile檔案
├── default.conf # nginx組態檔
但為了兼容現有的多鏡像部署方案,并將改動降到最小,所以直接將子應用的構建目錄放到根目錄,于是目錄就變成了這樣
└── daas-web/ # 根檔案夾
|
├── app1/ # 存放微應用 app1 的檔案夾
├── app2/ # 存放微應用 app2 的檔案夾
├── app3/ # 存放微應用 app3 的檔案夾
├── app4/ # 存放微應用 app4 的檔案夾
├── index.html # mainApp的index.html
├── css/ # 主應用mainApp的css檔案夾
├── js/ # 主應用mainApp的js檔案夾
├── Dockerfile # 鏡像構建Dockerfile檔案
├── default.conf # nginx組態檔
這種檔案組織結構不用修改原有專案的 publicPath
有關這兩種的檔案組織方式可以查看一下qiankun的部署檔案
?
GitLab CI/CD方案
基本思路是這樣的
在主應用(基座)創建tag來觸發流水線
首先進行流水線的初始化作業,清慷訓創建存放制品的目錄
接著觸發自身和其他應用的相同tag的流水線,并行執行多條跨專案流水線
然后將每個應用編譯出來的制品dist目錄都存放到制品目錄
最后在制品目錄中構建鏡像,最后推送到harbor
?
拆分來講:
在構建aio鏡像時,首先需要在其他子應用創建一個相同的tag,最后在主應用創建一個相同名稱的tag,
這里的順序不能錯,因為創建了主應用就會觸發流水線,如果其他子應用沒有相同的tag則會報錯,先創建子應用tag,再創建主應用tag,并且tag名稱必須保持一致,最終的鏡像版本會從tag中決議出來,
由于目前已經有幾個子應用使用了gitlab ci/cd來發布研發和集成環境,之前的流水線觸發條件是
workflow:
rules:
- if: $CI_COMMIT_BRANCH == 'develop'
這種寫法已經不滿足現有要求,因為在aio方案中主應用的流水線是由tag觸發,子應用的流水線是有主應用來觸發的,
于是拆分出二個配置模版,模版中會配置job所用的runner,觸發條件,
一個(.release_aio_config)用于aio方案,
一個(.develop_config)用于研發集成環境的發布,
在job中可以使用關鍵詞extends 來繼承模版,使用此方法在job中也可以覆寫模版的配置,
由于在aio的流水線中,存在制品依賴的關系,在構建docker鏡像的job中,需要獲取到所有應用的制品,gitlab ci/cd提供了need關鍵詞來是實作制品依賴–跨專案流水線中的制品,在一個job中,可以配置依賴當前流水線中的那些制品,其原理是通過web api來下載制品到當前的作業目錄,順便提下,制品都是上傳到gitlab,在嘗試了幾次后,我發現這是一個付費版本的功能,😄😄,,,,俗話說,上帝給你關了一扇窗,必定會給你打開一扇門,于是我思考片刻,決定從物理層面“暴力突破”付費的限制,該方案就是 基于shell執行器,將各個應用的制品存放在本地,
具體做法是在服務器本地安裝gitlab-runner的rpm或deb包,然后注冊一個shell執行器的runner,使用該runner編譯前端專案,并將各個應用的制品按照規定的目錄結構存放到一個固定的“制品匯總目錄”,
?
直接在服務器本地進行構建的,作業目錄,檔案都存放在本地,所以想把使用容器構建,速度更快,
唯一的缺點是依賴本地的環境(如nodejs,git),遷移麻煩,
最終的流水線概覽圖是這樣的

?
由于每個子應用都是一個專案,所以這里的流水線必須要使用跨專案流水線, 這種需求在gitlab ci/cd有多種方式實作,使用api,或者使用 trigge 關鍵詞,這里使用的是 trigge 來觸發其他專案的,
有關trigger 關鍵詞的使用可以查看該鏈接
以下是一個job示例
build_other_job:
stage: build
variables:
UPSTREAM_BUILD_TAG: $CI_COMMIT_TAG
trigger:
project: a/b/main-app
branch: $CI_COMMIT_TAG
strategy: depend
該job會觸發專案a/b/main-app 的流水線,branch限定了觸發的分支,strategy限定了必須等待跨專案流水線完成后,再執行下一階段,不加strategy限定,默認是創建了跨專案流水線就執行下一階段,這里使用variables向跨專案流水線傳遞了一個變數,以備后用,
流水線撰寫
下面開始流水線的撰寫
首先定義流水線的階段,變數與快取,
目錄 /home/gitlab-runner/web 用于存放所有應用編譯出的制品
stages:
- prebuild
- build
- build_docker
- track
variables:
# 所有制品應該存放的目錄
ALL_ARTIFACTS_PATH: '/home/gitlab-runner/web'
default:
cache:
key: $CI_PROJECT_NAME
paths:
- node_modules
定義二個模板,一個是aio模板,一個是 觸發其他專案流水線的模板,使用模板可以幫我節省很多代碼,將公共部分提取出來,統一管理,這里的runner 的tag使用 shell-dass 只在創建了tag時觸發,
?
定義模板
# 默認配置模板
.release_aio_config:
tags:
- shell-dass
only:
- tags
.build_other_config:
stage: build
variables:
UPSTREAM_BUILD_TAG: $CI_COMMIT_TAG
trigger:
project: a/b/c
branch: $CI_COMMIT_TAG
strategy: depend
only:
- tags
可以在跨專案的流水線中 傳遞引數 UPSTREAM_BUILD_TAG,
預編譯作業,與主應用的編譯作業
ready_job:
extends: .release_aio_config
stage: prebuild
script:
# 清空用于存放制品的目錄
- rm -rf $ALL_ARTIFACTS_PATH
- mkdir -p $ALL_ARTIFACTS_PATH
build_base_job:
extends: .release_aio_config
stage: build
script:
- yarn
- yarn build
- cp -rf dist/* $ALL_ARTIFACTS_PATH
預編譯清空存放制品的目錄, 主應用編譯完成后直接將dist下的所有檔案拷貝到 ALL_ARTIFACTS_PATH 目錄,二個作業都繼承 .release_aio_config 模板,都是用 shell-dass 這個 runner,并且都是在創建tag時觸發
?
編譯子應用的作業
build_model_job:
extends: .build_other_config
trigger:
project: a/b/c
build_service_job:
extends: .build_other_config
trigger:
project: a/b/d
build_management_job:
extends: .build_other_config
trigger:
project: a/b/e
build_dev_job:
extends: .build_other_config
trigger:
project: a/b/f
編譯自定義的作業都繼承.build_other_config 模板,只需要覆寫 專案地址即可,
?
構建docker鏡像,推送到harbor,并使用釘釘通知將構建出的鏡像推送給釘釘群,
creat_app:
extends: .release_aio_config
stage: build_docker
script:
- echo 'creat_app'
- cp -rf Dockerfile-AIO nginx-config.conf $ALL_ARTIFACTS_PATH
- cd $ALL_ARTIFACTS_PATH
- ls -l
- docker build -f Dockerfile-AIO -t web-aio:$CI_COMMIT_TAG .
- docker tag web-aio:$CI_COMMIT_TAG $PUSH_IMAGE_PATH:$CI_COMMIT_TAG
- docker login -u $HARBOR_USERNAME -p $HARBOR_PWD $HARBOR_SERVER
- docker push $PUSH_IMAGE_PATH:$CI_COMMIT_TAG
- docker rmi $PUSH_IMAGE_PATH:$CI_COMMIT_TAG
- echo '構建aio鏡像成功 鏡像地址 $PUSH_IMAGE_PATH:$VERSION '
after_script:
- echo '$PUSH_IMAGE_PATH:$VERSION'
- 'curl -H ''Content-type: application/json'' -d ''{"msgtype":"text", "text": {"content":"$PUSH_IMAGE_PATH:$VERSION"}}'' $DING_WEBHOOK'
when: on_success
到了這一步,所有的子應用構建物都已放到了 ALL_ARTIFACTS_PATH 中,只需要進入該目錄構建docker鏡像即可,
這些需要注意一下,鏡像的 Dockerfile 與 nginx 組態檔可能要使用新建的,構建完成后,改成對應的版本號,推送到harbor中,harbor相關變數 以及鏡像相關變數是定義在專案的 CI/CD變數中,
最后再撰寫一個處理流水線失敗的job,,當流水線報錯時,及時使用釘釘通知告知用戶處理,這里注意
when: on_failure 當做之前的job有報錯的,才會執行該job,
track_fail:
extends: .release_aio_config
stage: track
variables:
CONTENT: '@$GITLAB_USER_NAME構建aio鏡像錯誤$CI_PIPELINE_URL'
DING_WEBHOOK: 'https://oapi.dingtalk.com/robot/send?access_token=$DING_ACCESS_TOKEN'
script:
- echo $CONTENT
- 'curl -H ''Content-type: application/json'' -d ''{"msgtype":"text", "text": {"content":"部署 $CONTENT"}}'' $DING_WEBHOOK'
when: on_failure
遇到的問題
安裝gitlab-runner后,需要將用戶gitlab-runner 加入到docker用戶組中,
sudo usermod -aG docker gitlab-runner
?
git報錯
fatal: git fetch-pack: expected shallow list
fatal: The remote end hung up unexpectedly

升級git版本即可解決,升級到 2.13
限定跨專案流水線
使用strategy: depend 來等待其他專案流水線運行完成,
使用branch 來限定觸發子專案的那個分支流水線,
?
nginx 配置
原有的nginx配置無法使用,需要修改,aio方案的nginx配置為,
server {
listen 80;
listen [::]:80;
server_name localhost;
gzip on;
gzip_buffers 32 4K;
gzip_comp_level 6;
gzip_min_length 100;
gzip_types application/javascript text/css text/xml;
gzip_disable "MSIE [1-6]\.";
gzip_vary on;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
error_page 500 502 503 504 404 /index.html;
location = /index.html {
root /usr/share/nginx/html;
}
}
特別注意 404 轉發到index.html 這條規則,
tag轉為版本號的處理
將tag中的 tags/tag_ 洗掉掉 如tag為 tags/tag_v2.7.x.20210908 ,鏡像版本為 v2.7.x.20210908
${tags/tags\/tag_/}
部署完成后的網路拓撲圖

http://topology.le5le.com/preview/?id=6143f2278672cb00018b9ff4&r=1
結語
吾山拔地三千尺,凌空聳翠一萬年
?
?
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/301477.html
標籤:其他
上一篇:Linux下rpm打包
下一篇:WebSocket服務端訊息推送
