本文使用「署名 4.0 國際 (CC BY 4.0)」許可協議,歡迎轉載、或從新修改使用,但須要註明來源。 署名 4.0 國際 (CC BY 4.0)html
本文做者: 蘇洋前端
建立時間: 2019年08月24日 統計字數: 5361字 閱讀時間: 11分鐘閱讀 本文連接: soulteary.com/2019/08/24/…git
上一篇文章講了如何搭建高性能的 Composer 服務,本篇來聊聊如何搭配 CI 進行使用,讓研發效率有必定的保障。docker
本文以 GitLab Runner 中最簡單通用的 shell
模式爲例,其餘 CI 系統相似,酌情修改腳本便可。考慮到持續集成過程當中須要進行資源隔離,咱們使用工具容器做爲持續集成環境。shell
在使用 CI 前,咱們須要先拆分階段,通常來講,基於 Composer 的項目存在三個階段:編程
composer install
階段sync release
階段reload/restart service
階段若是寫成 yml 配置,能夠這樣描述:json
stages:
- update
- deploy
- restart
複製代碼
定義完畢階段後,須要詳細描述每階段作的事情。ubuntu
先從 update
階段開始提及。api
爲了方便描述,項目結構簡單定義爲下面這樣。緩存
.
├── composer.lock
└── composer.json
複製代碼
更新代碼最簡單的方案即是進入項目目錄,執行 composer i
,等待項目安裝完畢了。然而這樣會致使兩個問題:
因此若是使用固定配置構建的工具鏡像,搭配「即用即丟」模式來用作構建執行環境,上面的問題就迎刃而解了。
docker run \
--add-host composer.lab.com:192.168.123.234 \
--volume $PWD:/app \
composer /bin/sh -c "composer install && ls -al vendor"
複製代碼
使用上面的方案,搭配 部署令牌
,除了解決常規依賴的獲取外,也不難解決下面這種類型的軟件包的獲取。
"repositories": [
{
"type": "vcs",
"url": "https://gitlab+deploy-token-2:ZeYhk_F7oqtdxXuKsvvr@gitlab.lab.com/forum/session.git"
},
...
]
複製代碼
一切彷佛很美好,可是若是涉及到下面這類倉庫,上面的方案就失靈了。
"repositories": [
{
"type": "vcs",
"url": "ssh://git@gitlab.lab.com/forum/session.git"
},
...
]
複製代碼
使用 Git 獲取 SSH 協議的倉庫數據,須要配置 SSH KEY。解決的方案也不難,爲上面的 docker 命令加一些額外的參數:
docker run \
--add-host composer.lab.com:192.168.123.234 \
--volume $PWD:/app \
--volume /etc/passwd:/etc/passwd:ro \
--volume /etc/group:/etc/group:ro \
--user $(id -u):$(id -g) \
composer /bin/sh -c "composer install && ls -al vendor"
複製代碼
爲了追求簡單優雅,咱們能夠將上面的代碼進一步優化,改成用 docker-compose
,像是下面這樣。
version: '3.6'
services:
composer:
image: composer
volumes:
- ./:/app
- ./known_hosts:/root/.ssh/known_hosts
- $HOME/.ssh/id_rsa:/root/.ssh/id_rsa
command: install
複製代碼
你會發現這裏多映射了一個 known_hosts
文件。因爲 SSH 設計上防止中間人攻擊,須要驗證服務端的指紋,因此,咱們須要將服務端指紋保存下來,不然當 composer
容器訪問代碼倉庫服務器的時候,會由於下面的錯誤而停止倉庫 Clone 。
Could not open a connection to your authentication agent.
複製代碼
這裏經過 ssh-keyscan
來生成簽名文件:ssh-keyscan gitlab.lab.com > known_hosts
,文件內容會相似下面:
ssh-keyscan gitlab.lab.com
# gitlab.lab.com:22 SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.8
gitlab.lab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCyC3qB2M68KeK79op1vdoYYbX+Y3G768DVV+nki0ujUSHsedCo77sfkTIU4ZHAojEn4w/oqAjDcz3bDJNEI/CIO3k1NeiM3tZbkzm8VKTGhXkvxbTYkAud3f/UbXij3LAhsskn8ykoxgl7qqQ4dH2y0v9oBARNh2fRNyENaj4Tvu3Ao8MIh4JWD69u3AcNvQwJWtqphkY7xbvFDb2GNzNrTW+X1R2jHsqCxq8Nuq6tCC9m+JNGtUR6IsZusm5B2/CtamxUSk+1YEtNsWxEJ2qikm7Ud+Ikkak9N+8xZ/Ck6lmjoAxlKwgoP7Tq6cDDfZrQt8drwLE1/j1hzrE7TfoR
# gitlab.lab.com:22 SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.8
gitlab.lab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFzJ/O/QQQ0RsEBALP/UeiZa58IDpI+c4RRjS9Vd1nMFY//xFuS1UF6ml8mpRpaYwSjxgQG9lNbXlL9E9AoAslo=
# gitlab.lab.com:22 SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.8
gitlab.lab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGkm3tji72xkD5ySTJo6NIeaE/zqhedlgkw5Y59quy6X
複製代碼
使用 compose
來描述內容,最後的 CI 腳本能夠簡化爲:
更新代碼:
stage: update
script:
- docker-compose up && ls -al
- chown -R $(id -u):$(id -g) ./vendor
複製代碼
部署代碼能夠作的簡單些,好比直接用 rsync ,能夠開啓 - I
選項保證一致性,或者老老實實 ansible ,若是追求一步到位,把代碼打包鏡像分發也沒有問題。先以 rsync 爲例,ansible 足夠再寫一篇啦。
生成一枚 SSH 密鑰用於部署,而後項目倉庫/代碼主機中配置信任該密鑰,rsync 使用的話,手段就靈活多了:
.ssh
目錄中和上面同樣一樣考慮將工具打包爲鏡像使用:
FROM alpine:3.9
RUN echo '' > /etc/apk/repositories && \
echo "https://mirror.tuna.tsinghua.edu.cn/alpine/v3.9/main" >> /etc/apk/repositories && \
echo "https://mirror.tuna.tsinghua.edu.cn/alpine/v3.9/community" >> /etc/apk/repositories && \
echo "Asia/Shanghai" > /etc/timezone
RUN apk update && \
apk upgrade && \
apk add --no-cache rsync openssh-client && \
rm -rf /var/cache/apk/*
複製代碼
上面的 Dockerfile 演示瞭如何構建一個徹底獨立於系統,大小隻有 10MB
的 Rsync 工具包。
使用命令也很簡單,和傳統的 Rsync 別無二致,只是前面加上了 docker run
命令:
docker run \
--volume $DEPLOY_DIR/ssh.key:/ssh.key \
--volume $PWD:/app \
$RSYNC_TOOL rsync -az --list-only --include='vendor' --exclude='.git*' --timeout=3600 -P --partial --delete -e 'ssh -i /ssh.key -p 22 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' /app/ $DEPLOY_TARGET_01:$PROJECT_WORKDIR
複製代碼
一樣的,若是你願意的話,這個命令也能夠重寫爲更優雅一些的 compose
腳本。
此外,若是你想部署多臺服務器,想將上一步的「過程產物」共享,須要定義緩存目錄,本例中能夠這樣配置:
cache:
paths:
- vendor
複製代碼
重啓/重載服務其實沒有什麼難的,若是業務須要平滑重啓,能夠將腳本配置成串行任務:
前端不管是 Nginx 仍是負載均衡服務,會根據服務可用狀況幫助你平滑更新線上應用。
此外,若是你的服務部署更新後,須要觸發其餘項目的構建過程,可使用 GitLab API:pipeline trigger
,調用手段不少,最簡單的莫過於使用 curl
進行調用,放在當前項目 CI 腳本的合適位置便可:
curl -X POST -F token=$DEP_PROJECT_TOKEN -F ref=$DEP_PROJECT_REF_NAME https://gitlab.lab.com/api/v4/projects/$DEP_PROJECT_ID/trigger/pipeline
複製代碼
上面的變量能夠在 GitLab CI 幫助文檔和項目配置中得到,在此就不贅述了。
這裏給出一套簡單的參考配置,裏面演示瞭如何使用不一樣的命令來進行項目部署:
variables:
RSYNC_TOOL: "docker.lab.com/rsync-tool:1.0.0"
CACHE_DIR: "/data/caches/$CI_PROJECT_ID"
SOURCE_DIR: $CI_PROJECT_DIR
PROJECT_WORKDIR: /data/forum/$CI_PROJECT_NAME
DEPLOY_TARGET_01: $DEPLOY_HOST_01
DEP_PROJECT_TOKEN: cb0550eeaa6c6a696e6ada8b041234
DEP_PROJECT_REF_NAME: master
DEP_PROJECT_ID: 11
stages:
- update
- deploy
- restart
cache:
paths:
- vendor
下載依賴:
stage: update
script:
- docker-compose up && ls -al
- chown -R $(id -u):$(id -g) ./vendor
分發依賴01:
stage: deploy
before_script:
- DEPLOY_DIR=$CACHE_DIR && mkdir -p $DEPLOY_DIR && echo "$DEPLOY_KEY" | tr -d '\r' >$DEPLOY_DIR/ssh.key && chmod 600 $DEPLOY_DIR/ssh.key
script:
- docker run --volume $DEPLOY_DIR/ssh.key:/ssh.key --volume $PWD:/app $RSYNC_TOOL rsync -azi --list-only --include='vendor' --exclude='.git*' --timeout=3600 -P --partial --delete -e 'ssh -i /ssh.key -p 22 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' /app/ $DEPLOY_TARGET_01:$PROJECT_WORKDIR
重啓服務:
stage: restart
script:
- "curl -X POST -F token=$DEP_PROJECT_TOKEN -F ref=$DEP_PROJECT_REF_NAME https://gitlab.lab.com/api/v4/projects/$DEP_PROJECT_ID/trigger/pipeline"
複製代碼
先寫到這裏吧。
—EOF
我如今有一個小小的折騰羣,裏面彙集了一些喜歡折騰的小夥伴。
在不發廣告的狀況下,咱們在裏面會一塊兒聊聊軟件、HomeLab、編程上的一些問題,也會在羣裏不按期的分享一些技術沙龍的資料。
喜歡折騰的小夥伴歡迎掃碼添加好友。(請註明來源和目的,不然不會經過審覈)