CI/CD筆記-gitLab之ci/cdhtml
1、概念普及python
1、概念普及
1. CI/CDmysql
CI(continuous integration):持續集成,即在代碼構建過程當中持續地進行代碼的集成、構建、以及自動化測試等;有了 CI 工具,咱們能夠在代碼提交的過程當中經過單元測試等儘早地發現引入的錯誤。 CD(continuous Deployment):持續交付,在代碼構建完畢後,能夠方便地將新版本部署上線,這樣有利於快速迭代並交付產品。
2. gitlab CI/CDlinux
GitLab CI/CD(後簡稱 GitLab CI)是一套基於 GitLab 的 CI/CD 系統,可讓開發人員經過 .gitlab-ci.yml 在項目中配置 CI/CD 流程,在提交後,系統能夠自動/手動地執行任務,完成 CI/CD 操做。並且,它的配置很是簡單,CI Runner 由 Go 語言編寫,最終打包成單文件,因此只須要一個 Runner 程序、以及一個用於運行 jobs 的執行平臺(如裸機+SSH,Docker 或 Kubernetes 等,我推薦用 Docker,由於搭建至關容易)便可運行一套完整的 CI/CD 系統。
3. gitlab-Jobgit
Job 爲任務,是 GitLab CI 系統中能夠獨立控制並運行的最小單位。在提交代碼後,開發者能夠針對特定的 commit完成一個或多個 job,從而進行 CI/CD 操做。 做業就是運行器(Runner)要執行的指令集合,Job 能夠被關聯到一個 Stage。當一個 Stage 執行的時候,與其關聯的全部 Job 都會被執行。在有足夠運行器的前提下,同一階段的全部做業會併發執行。做業狀態與階段狀態是同樣的,實際上,階段的狀態就是繼承自做業的。 做業必須包含script(由Runner執行的shell腳本),隨着項目愈來愈大,Job 愈來愈多,Job 中包含的重複邏輯可能會讓配置文件臃腫不堪。.gitlab-ci.yml 中提供了 before_script 和 after_script 兩個全局配置項。這兩個配置項在全部 Job 的 script 執行前和執行後調用。 Job 的執行過程當中每每會產生一些數據,默認狀況下 GitLab Runner 會保存 Job 生成的這些數據,而後在下一個 Job 執行以前(甚至不侷限於當次 CI/CD)將這些數據恢復。這樣即使是不一樣的 Job 運行在不一樣的 Runner 上,它也能看到彼今生成的數據。
4. gitlab-Pipelineweb
Pipeline 即流水線,能夠像流水線同樣執行多個 Job. 在代碼提交或 被合併時,GitLab 能夠在最新生成的 commit上創建一個 pipeline,在同一個 pipeline 上產生的多個任務中,所用到的代碼版本是一致的。
5. gitlab-Stage
通常的流水線一般會分爲幾段;在 pipeline中,能夠將多個任務劃分在多個階段中,只有當前一階段的全部任務都執行成功後,下一階段的任務纔可被執行。
注:若是某一階段的任務均被設定爲「容許失敗」,那這個階段的任務執行狀況,不會影響到下一階段的執行。sql
CI Pipelinedocker
上圖中,整條流水線從左向右依次執行,每一列均爲一個階段,而列中的每一個可操控元素均爲任務。左邊兩個階段的任務是自動執行的任務,在commit提交後便可自動開始運行,執行成功或失敗後,能夠點擊任務右邊的按鈕重試;而右邊兩個是手動觸發任務,須要人工點擊右邊的「播放」按鈕來手動運行。shell
6. 什麼是.gitlab-ci.yml文件
官方文檔:https://docs.gitlab.com/ee/ci/yaml/README.html#parameter-detailsjson
GitLab CI使用YAML文件(.gitlab-ci.yml)來管理項目配置。該文件存放於項目倉庫的根目錄,而且包含了你的項目如何被編譯的描述語句,YAML文件使用一系列約束敘述定義了Job啓動時所要作的事情。
Job是.gitlab-ci.yml文件中最基本的元素,由一系列參數定義了任務啓動時所要作的事情,用戶能夠建立任意個任務;每一個任務必須有一個獨一無二的名字,但有一些保留keywords不能用於Job名稱,image,services,stages,types,before_script,after_script,variables,cache,include。
Job被定義爲頂級元素,而且至少包括一條script語句,若是一個 Job 沒有顯式地關聯某個 Stage,則會被默認關聯到 test 階段。
job1: # 關聯到bulid階段 stage: build # 所需執行的腳本 script: - execute-script-for-job1
7. .gitlab-ci.yml文件介紹
variables
用於自定義可用於全部job的全局變量,這個關鍵字也能夠在每一個job中單獨定義,相同變量名時,優先級是先job再全局
variables: SERVICE_ENV: R1 APPNAME: AI-DATA
default
全局默認值,即爲了簡便不用重複設置每一個任務中相同關鍵字對應的相同的值,如每一個job應用相同的鏡像名,就能夠在default下配置,則若是job中沒有配置本身的鏡像則使用default中的,default中支持如下關鍵字
image,services,before_script,after_script,tags,cache,artifacts,retry,timeout,interruptible
default: image: base-python2:v1 stages: - build - deploy build-app-job: stage: build script: "run build script file" only: - branches build-mysql-job: stage: build image: mysql6:v1 script: "do something" stages
用於定義全部做業job可使用的全局階段,gitlab-ci.yml容許定義多個階段,stages元素的順序定義了做業執行的順序。Job關聯的stage名相同時,該多個Job將並行執行(在擁有足夠Runner狀況下),下一個階段的Job將會在前一個階段的job都完成的狀況下執行。
若是沒有定義stages,那麼默認包含build,test,deploy 三個stage,stage中並不能直接配置任何具體的執行邏輯,具體的執行邏輯應該在Job中配置。
stages: - build - test - deploy
stage
爲每一個任務Job指定其屬於那個階段,其依賴stages中定義好的階段
script
script 是一系列經過Runner來執行的shell腳本,也能夠直接執行shell命令
有些時候,script命令須要被單引號或者雙引號所包裹。舉個例子,命令中包涵冒號的時候,該命令須要被引號所包裹,這樣YAML解析器才知道該命令語句不是「key: value」語法的一部分。當命令中包涵如下字符時須要注意打引號:: { } [ ] , & * #? | - < > = ! % @
test-job1: # 每一個任務必須指定階段(stage)和對應要作的任務(script) stage: test script: - ehco "執行對應寫好的須要runner執行的命令或腳本,多個命令這樣寫" - uname -a - echo "hello,$GITLAB_USER_LOGIN" test-job2: stage: test script: echo "若是隻是一條命令能夠直接在這個後面寫"
這兩個關鍵字定義運行時,docker的鏡像名和須要用到的已經存在運行的服務名,前提是註冊runner時選擇的是docker而不是shell
build-job: image:access-web:v1 services: # 定義構建access-web鏡像時能夠訪問服務名 - mysql:v1
before_script 和after_script
定義一些在全部任務Job執行前或以後須要執行的命令,每一個任務Job中若是定義了,就執行本身的,全局的就不會執行
# 定義全局before_script default: before_script: - global before script # 覆蓋全局的before_script test-job1: before_script: - 執行本身的在本任務執行前要作的事 script: - uname -a after_script: - 執行命令等等
only 和 except
更多參考官方文檔:https://docs.gitlab.com/ee/ci/yaml/README.html#onlyexcept-basic
若是任務job沒有指定only關鍵字,默認是全部的分支push或標籤建立時當作觸發條件,except默認爲空即不過濾
only和except都是定義job何時會被觸發建立,only和except可使用正則,能夠指定倉庫地址,能夠同時用;
only定義了job是以分支仍是標籤提交時被觸發;
except定義了job在某個分支或標籤提交時不會被執行;
only和except可使用的一些關鍵字:
job1: stage: test script: echo "do something" only: # 僅以開頭以issue-的引用的時候被觸發,而全部分支均被過跳過 # 經過正則默認區分大小寫,若是想不區分須要後面加i,即/^issue-.*$/i - /^issue-.*$/ except: - branches job2: stage: test script: echo "do something" only: # 僅爲分支標記了標籤、或者經過api請求、或者定時任務時纔會運行次job - tags - triggers - schedules job3: stage: test script: echo "do anything" only: # 指定倉庫全部的分支都會被觸發 - branches@倉庫地址 except: # master分支不會被觸發本任務 - master@倉庫地址 # 以release開頭的命名的也不會被觸發 - /^release/.*$/@倉庫地址
tags
用於指定註冊的某個runner來運行任務,註冊runner時有爲每一個runner設置標籤,這裏就是匹配那個的
job: tags: # 若是指定多個標籤,那麼那些標籤必須某個running都有關聯纔會調用 - python-runner
allow_failure
容許某個任務失敗不影響CI的其餘任務執行結果,默認是false即不容許失敗
job1: stage: test script: "本任務執行成功與否不影響job2的執行" allow_failure: true job2: stage: test script: "本人必須運行成功後面的任務纔會被執行"
when
用於實現發生故障或發生故障時運行的做業
when支持的值以下:
on_success(默認) 早期全部的做業都成功或者視爲成功的all_failure:true
on_failure僅在早期至少一個做業失敗時運行
always 不管早期做業結果如何都執行
manual 手動執行
delayed 延遲指定的時間再執行,gitlab11.14中新增
job: stage: deploy script: - make deploy when:manual
gitlab預設變量
官方文檔:https://docs.gitlab.com/ee/ci/variables/predefined_variables.html#predefined-environment-variables-reference
用於獲取gitlab用於ci/cd 預設的一些環境變量如獲取分支名CI_COMMIT_BRANCH
docker build: script: docker build -t my-image:$CI_COMMIT_REF_SLUG . rules: - if: '$CI_COMMIT_BRANCH == "master"' when: delayed start_in: '3 hours' allow_failure: true
gitlab-runner安裝在服務部署的機器上,其自動根據你在gitlab-ci.yml中規定的觸發條件如某個分支提交後執行,其首先會自動從gitlab倉庫上拉取倉庫代碼到服務器本地,而後根據gitlab-ci文件定義的job執行,如打包文件構建鏡像,而後部署服務【多臺能夠經過創建docker swarm集羣的模式,在本地部署一個,會自動分佈到多臺】
2、實驗環境
系統:centos8.0_x64
gitlab: 192.168.0.152:8888
docker-swarm集羣:192.168.0.150【master】192.168.0.153【slave】
docker倉庫:192.168.0.150:5000
3、前期準備
搭建gitlab:請參考:https://mp.weixin.qq.com/s/amWWG34BXoTAumy1p4SnvA
搭建docker集羣請參考:https://mp.weixin.qq.com/s/cIkPOnna9u0h1AMbz4aOjw
搭建docker私有倉庫請參考:https://mp.weixin.qq.com/s/4KI3fqyJFv5yJI_H_HK0RA
# 1. 直接重docker-hub上拉取centos系統 docker pull centos # 2. 構建一個容器 docker run --name=genPython -it centos /bin/bash # 3. 換yum倉庫 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak && curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-8.repo && yum clean all && yum makecache # 4. 安裝python3 yum -y install python38 # 5. 查看Python安裝 whereis python python3 --version pip3 list # 6. 退出容器,將剛纔改變的容器生成新的鏡像`docker commit 容器id 倉庫/新的鏡像名:標籤` docker commit 0426a83fc666 192.168.0.150:5000/python3:v1 # 7. 推送到私有倉庫,須要先配置本地docker配置文件指定倉庫地址 vim /etc/docker/daemon.json { "registry-mirrors": ["192.168.0.150:5000"], # 加速的地址 "insecure-registries" : ["192.168.0.150:5000"] } systemctl daemon-reload && systemctl restart docker docker push 192.168.0.150:5000/python3:v1 注爲了方便也將其推送到dockerhub上 docker login docker tag 192.168.0.150:5000/python3:v1 addmoney2018/python3:v1 docker push addmoney2018/python3:v1
四. 配置Runner
1. 安裝runner
官方文檔:https://docs.gitlab.com/runner/install/
### 在192.168.0.150上,只有安裝在集羣管理節點上,才能經過docker swarm集羣部署到多臺上 # 下載二進制文件並寫入文件gitlab-runner # Linux x86-64 curl -L --output /usr/local/bin/gitlab-runner "https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64" # 授予其執行權限 chmod +x /usr/local/bin/gitlab-runner # 建立一個GitLab CI用戶 useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash # 修改gitlab-runner密碼 echo "gitlab-runner" | passwd --stdin gitlab-runner # 安裝並做爲服務運行 gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner # 將服務添加到開啓啓動 chkconfig gitlab-runner on # 啓動 gitlab-runner start # 通過實踐發現runner執行docker命令時會報權限不夠,所以須要加權 usermod -aG docker gitlab-runner # 測試下 sudo -u gitlab-runner -H docker info 注:以後想修改上面指定的用戶或工做目錄 修改這個文件便可:/etc/systemd/system/gitlab-runner.service
2. 獲取runner須要的gitlab地址及gitlab之CI的token
登錄gitlab---選擇對應的倉庫---選擇倉庫的setting---選擇CI/CD---選擇Runners的expand----複製下圖中地址和token
注意:
若是選擇的runner執行模式是docker,則runner中的job會在指定的基礎鏡像中執行,所以須要你指定的鏡像裏能夠執行ci文件中定義的命令,如docker build
若是選擇的runner執行模式是shell,即在runner服務安裝的物理機執行,所以你若是不是經過容器安裝runner,而想經過runner打鏡像,建議經過shell模式
# 執行以下命令 gitlab-runner register [root@gitlab bin]# gitlab-runner register Runtime platform arch=amd64 os=linux pid=10254 revision=943fc252 version=13.7.0 Running in system-mode. # 輸入gitlab實例地址 Enter the GitLab instance URL (for example, https://gitlab.com/): http://192.168.0.152:8888/ # 輸入runner的token Enter the registration token: WecGC7zY9otwQgdss7yZ # 輸入這個runner的描述 Enter a description for the runner: [gitlab.example.com]: try to run a python service # 輸入這個runner的標籤,每一個標籤用逗號隔開【用於區分不一樣類型的 Runner,使不一樣階段的 job 在不一樣的 Runner 中運行】 Enter tags for the runner (comma-separated): Python3-runner Registering runner... succeeded runner=WecGC7zY # 選擇執行runner的方式 Enter an executor: docker-ssh, parallels, docker-ssh+machine, custom, shell, ssh, virtualbox, docker+machine, kubernetes, docker: docker Enter the default Docker image (for example, ruby:2.6): # 指定基礎鏡像,注意本地你須要先下載docker鏡像,將其推進到你得私有倉庫,由於你本地daemon.json配置了本地倉庫,runner就是在指定得鏡像中構建得 192.168.0.150:5000/docker Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded! # 重啓下runner gitlab-runner restart # 注 若是想更改上面得配置 vi /etc/gitlab-runner/config.toml
4. gitlab上查看是否註冊成功
5. 寫一個測試項目及相關的Dockerfile與gitlabci.yml文件
test-runner
docker-compose.yml
FROM 192.168.0.150:5000/python3:v1 # 建立容器中的服務根目錄 RUN mkdir -p /app/code/ # 拷貝代碼到容器中 COPY . /app/code/test-gitlab01 # 指定工做目錄 WORKDIR /app/code/test-gitlab01 # 安裝依賴 RUN pip3 install --no-cache-dir -r /app/code/test-gitlab01/requirements.txt -i http://pypi.douban.com/simple --trusted-host pypi.douban.com # 映射端口 EXPOSE 8100 # 啓動 CMD ["python3","main.py"]
variables: SERVICE_ENV: R1 IMAGE_NAME: python-test-app:v3 DOCKER_FILE_PATH: . DOCKER_HUB: 192.168.0.150:5000/ stages: - build - test - deploy build-app: stage: build only: # 僅當什麼事件發生就觸發本任務: 發生推送 - master script: - echo "開始執行構建app的階段" - echo "環境爲:$SERVICE_ENV" - echo "runner爲shell模式就在物理機上執行下面得命令" - echo "當前位置:$(pwd),當前的主機名:$(hostname)" - echo "當前目錄下的文件:$(ls -lrt)" - docker build -t $IMAGE_NAME $DOCKER_FILE_PATH - docker tag $IMAGE_NAME $DOCKER_HUB$IMAGE_NAME - docker push $DOCKER_HUB$IMAGE_NAME - echo "構建鏡像成功!" tags: # 指定某個runner執行本任務 - python-shell-runner test-app: stage: test only: - master script: - echo "開始測試階段" - echo "查看鏡像是否推送到倉庫:$(curl http://192.168.0.150:5000/v2/_catalog)" - export TEST_PORT=$RANDOM - docker run -d -p $TEST_PORT:8100 $DOCKER_HUB$IMAGE_NAME - sleep 3 - curl http://192.168.0.150:$TEST_PORT - echo "測試階段完成!" tags: - python-shell-runner deploy-app: stage: deploy only: - master script: - echo "開始部署服務階段" - echo "當前位置:$(pwd)" - echo "當前目錄下的文件:$(ls -lrt)" - docker stack deploy -c docker-compose.yml web - sleep 3 - docker service ls - docker service ps web_python-test-web - curl http://192.168.0.150:8100 - echo "部署階段完成" tags: - python-shell-runner
version: '3' services: python-test-web: image: 192.168.0.150:5000/python-test-app:v3 ports: - 8100:8100 restart: always deploy: replicas: 2 restart_policy: condition: on-failure volumes: - /etc/localtime:/etc/localtime networks: - python-net networks: python-net:
# _*_ coding:utf-8 _*_ # DevVersion: Python3.6.8 # Date: 2021-01-01 18:10 # Author: Sun # PyCharm|main from flask import Flask app = Flask(__name__) @app.route("/") def index(): return {"message": "happy new year 2021"} if __name__ == '__main__': app.run("0.0.0.0", "8100")
click==7.1.2
Flask==1.1.2
itsdangerous==1.1.0
Jinja2==2.11.2
MarkupSafe==1.1.1
Werkzeug==1.0.1
     **5、卸載gitlab-runner**
gitlab-runner stop
chkconfig gitlab-runner off
gitlab-runner uninstall
rm -rf /etc/gitlab-runner/rm -rf /usr/local/bin/gitlab-runneruserdel -r gitlab-runner