概述
敏捷軟體開發(Agile software development),是一種應對快速變化的需求的一種軟體開發能力。強調開發團隊與業務需求方之間的緊密協作、面對面溝通(認為比書面的文檔更有效)、頻繁交付新的軟體版本、緊湊而自我組織型的團隊、能夠很好地適應需求變化的代碼編寫和團隊組織方法,也更注重軟體開發過程中人的作用。敏捷開發的流程分為幾個階段:編碼 -> 構建 -> 集成 -> 測試 -> 交付 -> 部署。而CI/CD是實現這一理念的方法。
持續集成CI(Continuous integration)
持續集成(Continuous integration),簡稱CI,是一種軟體開發實踐。開發人員提交代碼後,系統自動進行構建、(單元)測試,通過自動化測試保障所有的提交在合併主線之後不會出現質量問題,對可能出現的一些問題進行預警。
需要具備的條件
需要為每個新功能、代碼改進、或者問題修復創建自動化測試用例。你需要一個持續集成伺服器,它可以監控代碼提交情況,對每個新的提交進行自動化測試。儘可能快地提交代碼。帶來的效益
通過自動化測試可以拿到測試結果,避免將一些問題提交到交付生產中。發布編譯將會更加容易,因為合併之初已經將所有問題都規避了。減少工作問題切換,研發可以很快獲得構建失敗的消息,在開始下一個任務之前就可以很快解決。測試成本大幅降低,你的CI伺服器可以在幾秒鐘之內運行上百條測試。團隊花費在測試上面的時間會大幅縮短,將會更加側重於質量方面的提升上面。
持續交付CD(Continuous Delivery)
持續交付(Continuous Delivery),簡稱CD:是一種軟體工程的手法。持續交付在持續集成的基礎上,將集成後的代碼部署到更貼近真實運行環境的「類生產環境」(production-like environments)中,也就是我們通常說的預發布環境。交付給質量團隊或者用戶,以供評審。如果評審通過,代碼就進入生產階段。持續交付並不是指軟體每一個改動都要儘快部署到產品環境中,它指的是任何的代碼修改都可以在任何時候實施部署。
需要具備的條件
需要有強大的持續集成組件和足夠多的測試用例滿足代碼的需求。部署需要自動化。觸發是手動的,但是部署一旦開始,就不能人為幹預。團隊可能需要接受特性開關,沒有完成的功能模塊不會影響到線上產品。帶來的效益
繁瑣的部署工作沒有了。開發團隊不再需要花費幾天的時間去準備一個發布。你可以更快的進行交付,這樣就加快了與需求方之間的反饋環。輕鬆應對小變更,加速迭代。
持續部署CD(Continuous Deploymen)
持續部署(Continuous Deployment),也是簡稱CD:指當交付的代碼通過評審之後,自動部署到生產環境中。持續部署是持續交付的最高階段。開發人員可以專注於構建軟體,他們看到他們的修改在他們完成工作後幾分鐘就上線了。基本上,當開發人員在主分支中合併一個提交時,這個分支將被構建、測試,如果一切順利,則部署到生產環境中。
需要具備的條件
研發團隊測試理念比較完善。測試單元的健壯性直接決定著交付質量。文檔和部署頻率要保持一致。特徵標誌成為發布重大變化過程的固有部分,以確保您可以與其他部門(支持,市場營銷,公關…)協調。帶來的效益
發布頻率更快,因為你不需要停下來等待發布。每一處提交都會自動觸發發布流。在小批量發布的時候,風險降低了,發現問題也可以很輕鬆的修復。客戶每天都可以看到我們的持續改進和提升,而不是每個月或者每季度,或者每年。持續交付與持續部署的關係
持續部署意味著所有的變更都會被自動部署到生產環境中。持續交付意味著所有的變更都可以被部署到生產環境中,但是出於業務考慮,可以選擇不部署。如果要實施持續部署,必須先實施持續交付。
持續交付表示的是一種能力;而持續部署則是一種方式。
Gitlab CI/CD介紹
Gitlab CI/CD是Gitlab一個簡潔好用的的持續集成/持續交付/持續部署的框架。為項目配置一個或者多個 GitLab Runner,然後添加一個
.gitlab-ci.yml
文件到項目根目錄,進行提交或者推送代碼到Gitlab伺服器,就可以很方便地持續集成/部署代碼。
.gitlab-ci.yml
文件會告訴Gitlab Runner做什麼。
Gitlab CI/CD運行原理
開發者推送、提交代碼到Gitlab,Gitlab通過項目的
.gitlab-ci.yml
文件配置,找到指定的項目gitlab runner,runner運行相關的命令,進行編譯、 集成、測試、交付、部署,一切順利地話會分發到各個伺服器(測試伺服器、預發布伺服器、正式伺服器等),此時一個迭代開發上線流程走完。流程圖如下。
GitLab Runner
GitLab Runner是一個開源項目,用於運行項目持續集成、持續部署作業並將結果發送回GitLab,與GitLab CI/CD一起使用。GitLab Runner是用Go編寫的,可以作為單個二進位文件運行,不需要語言特定的要求,運行在Linux,macOS和Windows作業系統上。只要您可以在其上編譯Go二進位文件,其他作業系統可能會起作用,也可以運行在Docker上。
執行流程
默認情況下,它運行有三個流水線階段stage:
build
,
test
,和
deploy
,可以在
.gitlab-ci.yml
的stages自定義,多個階段是按順序執行的,可以修改順序,如果其中一個階段失敗,則後續的階段不會被執行,整個過程被認為失敗。
Stage 在
.gitlab-ci.yml
中通過如下的方式定義:
stages: - build - test - deploy
任務Job可以關聯到一個階段stage,當一個 Stage 執行的時候,與其關聯的所有 Job 都會被執行。一個階段可以有多個任務Job,同個階段的任務直接是可並行執行的。
Job 在
.gitlab-ci.yml
中關聯Stage示例如下:
build:stage: build script: - cd ~/go/src/$CI_PROJECT_NAME/ - go build
至此,執行流程就講完了,接下來就是詳細的配置過程。
具體配置過程
安裝gitlab runner
這裡以安裝到Linux為例,參考官網教程,選用一臺編譯伺服器用root帳號執行。
下載gitlab runner二進位文件放在bin目錄:
wget -O /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-386
賦予它可執行權限
chmod +x /usr/local/bin/gitlab-runner
創建一個gitlab CI用戶:
useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash
安裝並作為服務運行
# 安裝gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner# 運行gitlab-runner start
註冊到gitlab
在gitlab項目獲取URL地址和token令牌,如下:
此時得到
URL地址:https://gitlab.xxxx.comtoken令牌:TOKEN
啟動註冊功能:gitlab-runner register輸入gitlab項目的URL地址,:Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com )https://gitlab.xxxx.com輸入令牌:Please enter the gitlab-ci token for this runnerTOKEN輸入Runner的描述,可以在GitLab修改: Please enter the gitlab-ci description for this runner [hostame] my-runner給Runner添加標籤,這裡我標記為運行goland的:Please enter the gitlab-ci tags for this runner (comma separated):goland.gitlab-ci.yml 中可以設置 tags 欄位來聲明,當前任務只在擁有匹配 Tags 的 Runner 上運行。比如 iOS 編譯階段只能在 Mac Runner 上運行,那麼就可以設置這個 Runner 的 Tags 為 『iOS』,並且在 iOS 工程中在欄位 tags 中,添加『iOS』 值。 Tags 最好不要隨便命名,遵循適當的命名規則會讓後期 CI 的維護輕鬆許多。選擇Runner執行程序,這裡選擇用shell:Please enter the executor: ssh, docker+machine, docker-ssh+machine, kubernetes, docker, parallels, virtualbox, docker-ssh, shell:shell在gitlab項目查看是否允許,或者管理此runner:
runner其它命令
gitlab-runner --debug run,如果你遇到一些錯誤,可以使用這個命令來在前端(控制臺運行),查看loggitlab-runner stop ,停止運行gitlab-runner run --user jafir(普通用戶),如果需要切換用戶可以使用這個gitlab-runner uninstall,如果想卸載從頭再來gitlab-runner status,查看狀態gitlab-runner verify,查看runner是否在運行後gitlab-runner verify --delete,刪除註冊的用戶,如果想要從頭再來刪除 ~/.gitlab-runner/config.toml(註冊的用戶的配置文件),和/etc/gitlab-runner/config.toml,如果想要從頭再來
創建.gitlab-ci.yml文件
這裡用go語言的編譯發版的示例,你可以根據自己的需求配置:
stages: - build - deploybefore_script: - export NOW_DATE_TIME=$CI_PROJECT_NAME$(git show -s --format=%cd --date=format:%m-%d_%H:%M $CI_COMMIT_SHA)variables: SUPERVISORD_WORKER: "ci_cd_test-worker:ci_cd_test-worker_00" FILE_NAME: "meisha_account" TEST_HOST_IP: '127.0.0.1' PROD_HOST_IP: '127.0.0.2'build_stage: stage: build script: - rm -rf ~/go/src/$CI_PROJECT_NAME - cp -r $CI_PROJECT_DIR ~/go/src/ - cd ~/go/src/$CI_PROJECT_NAME/ - go get github.com/jsooo/log - go build tags: - golangdeploy_test: stage: deploy only: refs: - test script: - ssh -T -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o CheckHostIP=false test@$TEST_HOST_IP -p 23 "cd /home/test/projects/go/src/$CI_PROJECT_NAME/ && mv $FILE_NAME $NOW_DATE_TIME" - scp -P 56000 -q ~/go/src/$CI_PROJECT_NAME/$FILE_NAME test@$TEST_HOST_IP:/home/test/projects/go/src/$CI_PROJECT_NAME/ - ssh -T -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o CheckHostIP=false root@$TEST_HOST_IP -p 23 "supervisorctl -c /etc/supervisord/supervisord.conf restart $SUPERVISORD_WORKER" - echo '發到測試了' when: on_success tags: - golangdeploy_master: stage: deploy only: refs: - master script: - ssh -T -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o CheckHostIP=false user_00@$PROD_HOST_IP -p 23 "cd /data/publish/$CI_PROJECT_NAME/ && mv $FILE_NAME $NOW_DATE_TIME" - scp -P 56000 -q ~/go/src/$CI_PROJECT_NAME/$FILE_NAME user_00@PROD_HOST_IP:/data/publish/$CI_PROJECT_NAME/ - ssh -T -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o CheckHostIP=false root@$PROD_HOST_IP -p 23 "supervisorctl -c /etc/supervisord/supervisord.conf restart $SUPERVISORD_WORKER" - echo '發到測試了' when: on_success tags: - golang
配置說明
before_script 這一部分執行階段都會進行,我這執行的是獲取git commit提交的時間,賦值給NOW_DATE_TIME 變量;variables 是定義一些變量,這裡定義了測試、正式的IP位址,打包編譯的文件名,supervisorctl的進程名;build_stage、deploy_test 、deploy_master是一個個任務,可以自定義名稱,它們用stage關聯了某個階段,比如build_stage關聯了build階段,deploy_test關聯了deploy階段,deploy_master也關聯了deploy階段。only 定義哪個分支提交才會執行,我這裡定義了提交到test分支就部署到測試環境,提交到master分支就發布到正式環境。script 是任務的主要內容,需要執行的命令都寫在這。在build階段,用go build命令打包go程序。在deploy階段就把打包後的文件複製到伺服器,然後用supervisorctl重啟進程。when 定義了什麼時候才執行。tags標籤指定gitlab runner。具體配置可以參考gitlab的官網:https://docs.gitlab.com/ee/ci/yaml/README.html