久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

基于drone如何構建CI

176次閱讀
沒有評論

共計 7139 個字符,預計需要花費 18 分鐘才能閱讀完成。

本篇內容主要講解“基于 drone 如何構建 CI-CD 系統”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓丸趣 TV 小編來帶大家學習“基于 drone 如何構建 CI-CD 系統”吧!

kubernetes 集群三步安裝 CI 概述用一個可描述的配置定義整個工作流

程序員是很懶的動物,所以想各種辦法解決重復勞動的問題,如果你的工作流中還在重復一些事,那么可能就得想想如何優化了

持續集成就是可以幫助我們解決重復的代碼構建,自動化測試,發布等重復勞動,通過簡單一個提交代碼的動作,解決接下來要做的很多事。

容器技術使這一切變得更完美。

!–more–

典型的一個場景:

我們寫一個前端的工程,假設是基于 vue.js 的框架開發的,提交代碼之后希望跑一跑測試用例,然后 build 壓縮一個到 dist 目錄里,再把這個目錄的靜態文件用 nginx 代理一下。最后打成 docker 鏡像放到鏡像倉庫。甚至還可以增加一個在線上運行起來的流程。

現在告訴你,只需要一個 git push 動作,接下來所有的事 CI 工具會幫你解決!這樣的系統如果你還沒用上的話,那請問還在等什么。接下來會系統的向大家介紹這一切。

代碼倉庫管理

首先 SVN 這種渣渣軟件就該盡早淘汰,沒啥好說的,有 git 真的沒有 SVN 存在的必要了我覺得。

所以我們選一個 git 倉庫,git 倉庫比較多,我這里選用 gogs,gitea gitlab 都行,根據需求自行選擇

docker run -d --name gogs-time -v /etc/localtime:/etc/localtime -e TZ=Asia/Shanghai --publish 8022:22 \
 --publish 3000:3000 --volume /data/gogs:/data gogs:latest

訪問 3000 端口,然后就沒有然后了 gogs 功能沒有那么強大,不過占用資源少,速度快,我們穩定運行了幾年了。缺點就是 API 不夠全。

CI 工具

當你用過 drone 之后。。。

裝:

version:  2 
services:
 drone-server:
 image: drone/drone:0.7
 ports:
 - 80:8000
 volumes:
 - /var/lib/drone:/var/lib/drone/
 restart: always
 environment:
 - DRONE_OPEN=true
 - DOCKER_API_VERSION=1.24
 - DRONE_HOST=10.1.86.206
 - DRONE_GOGS=true
 - DRONE_GOGS_URL=http://10.1.86.207:3000/ #  代碼倉庫地址
 - DRONE_SECRET=ok
 drone-agent:
 image: drone/drone:0.7
 command: agent
 restart: always
 depends_on:
 - drone-server
 volumes:
 - /var/run/docker.sock:/var/run/docker.sock
 environment:
 - DOCKER_API_VERSION=1.24
 - DRONE_SERVER=ws://drone-server:8000/ws/broker
 - DRONE_SECRET=ok

docker-compose up -d 然后你懂的,也沒有然后了

用 gogs 賬戶登錄 drone 即可

每個步驟就是個容器,每個插件也是個容器,各種組合,簡直就是活字印刷術

怎么使用這種初級膚淺的內容我就不贅述了,但是有很多坑的地方:

裝 drone 的機器能用 aufs 盡量用,device mapper 有些插件是跑不了的,如一些 docker in docker 的插件,這不算是 drone 的毛病,只能說 docker 對 docker in docker 支持不夠好

centos 對 aufs 支持不夠好,如果想用 centos 支持 aufs,那你可得折騰折騰了,社區方案在此:https://github.com/sealyun/kernel-ml-aufs

最推薦的是 drone 的機器內核升級到 4.9 以上, 然后 docker 使用 overlay2 存儲驅動,高版本內核跑容器筆者也實踐過比較長的時間了,比低內核穩定很多

安裝方式 2,在 k8s 上安裝:

helm install stable/drone

使用篇

首先在你的代碼倉庫主目錄下新建三個文件:

.drone.yml : 描述構建與部署的流程(狹義),流程配置文件(廣義)CI/CD 無本質區別

Dockerfile : 告訴你的應用如何打包成鏡像,當然如果不是容器化交付可以不需要

k8s yaml 配置文件 or docker-compose 文件 or chart 包:告訴你的應用如何部署

其他:如 kube-config 等

用 gogs 賬戶密碼登錄到 drone 頁面上之后同步下項目就可以看到項目列表,打開開關就可以關聯到 git 倉庫, 比較簡單,自行探索

官方事例

pipeline:
 backend: #  一個步驟的名稱,可以隨便全名
 image: golang #  每個步驟的本質都是基于這個鏡像去啟動一個容器
 commands: #  在這個容器中執行一些命令
 - go get
 - go build
 - go test
 frontend:
 image: node:6
 commands:
 - npm install
 - npm test
 publish:
 image: plugins/docker
 repo: octocat/hello-world
 tags: [ 1, 1.1, latest ]
 registry: index.docker.io
 notify:
 image: plugins/slack
 channel: developers
 username: drone

各步驟啟動的容器共享 workdir 這個卷, 這樣 build 步驟的結果產物就可以在 publish 這個容器中使用

結合 Dockerfile 看:

# docker build --rm -t drone/drone .
FROM drone/ca-certs
EXPOSE 8000 9000 80 443
ENV DATABASE_DRIVER=sqlite3
ENV DATABASE_CONFIG=/var/lib/drone/drone.sqlite
ENV GODEBUG=netdns=go
ENV XDG_CACHE_HOME /var/lib/drone
ADD release/drone-server /bin/ #  因為工作目錄共享,所以就可以在 publish 時使用到  build 時的產物,這樣構建和發布就可以分離
ENTRYPOINT [/bin/drone-server]

上面說到構建與發布分離,很有用,如構建 golang 代碼時我們需要 go 環境,但是線上或者運行時其實只需要一個可執行文件即可,

所以 Dockerfile 里就可以不用 FROM 一個 golang 的基礎鏡像,讓你的鏡像更小。又比如 java 構建時需要 maven,而線上運行時不需要,

所以也是可以分離。

用 drone 時要發揮想象,千萬不要用死了,上面每句話都需要仔細讀一遍,細細理解。再總結一下關鍵點:

drone 自身是不管每個步驟是什么功能的,只傻瓜式幫你起容器,跑完正常就執行下個步驟,失敗就終止。

編譯,提交到鏡像倉庫,部署,通知等功能都是由鏡像的功能,容器的功能決定的 drone 里叫插件,插件本質就是鏡像,有一丟丟小區別后面說

這意味著你想干啥就弄啥鏡像,如編譯時需要 maven,那去做個 maven 鏡像,部署時需要對接 k8s,那么搞個有 kubectl 客戶端的鏡像;要物理機部署那么搞個 ansible 的鏡像,等等,發揮想象,靈活使用。

drone 環境變量

有時我們希望 CI 出來的 docker 鏡像 tag 與 git 的 tag 一致,這樣的好處就是知道運行的是哪個版本的代碼,升級等等都很方便,不過每次都去修改 pipeline 文件顯然很煩,那么 drone 就可以有很多環境變量來幫助我們解決這個問題:

pipeline:
 build:
 image: golang:1.9.2 
 commands:
 - go build -o test --ldflags  -linkmode external -extldflags  -static 
 when:
 event: [push, tag, deployment]
 publish:
 image: plugins/docker
 repo: fanux/test
 tags: ${DRONE_TAG=latest}
 dockerfile: Dockerfile
 insecure: true
 when:
 event: [push, tag, deployment]

這個例子 ${DRONE_TAG=latest} 如果 git tag 事件觸發了 pipeline 那就把 git tag 當鏡像 tag,否則就用 latest,這樣我們自己研發過程中就 可以一直用 latest 迭代,覺得版本差不多了,打個 tag,生成一個可以給測試人員測試的鏡像,非常優雅,不需要改什么東西,不容易出錯

同理還有很多其它的環境變量可以用,如 git 的 commitID 分支信息等等, 這里可以查

對接 k8s 實踐

首先得有個 k8s 集群,那么首選:kubernetes 集群三步安裝 廣告,無視就好。。。

有了上面的鋪墊,對接 k8s 就相當簡單了:搞個 kubectl 的鏡像嵌入流程中即可:

把項目的 k8s yaml 文件放到代碼中,然后 pipelie 里直接 apply

 publish:
 image: plugins/docker #  鏡像倉庫, 執行 Dockerfile 插件
 tags:
 - ${DRONE_TAG=latest}
 insecure: true #  照抄
 
 deploy:
 image: kubectl:test #  這個鏡像自己去打即可
 commands:
 - cat test.yaml
 - ls 
 - rm -rf /root/.kube   cp -r .kube /root # k8s  的 kubeconfig 文件,可以有多個,部署到哪個集群就拷貝哪個 kubeconfig 文件
 - kubectl delete -f test.yaml || true
 - kubectl apply -f test.yaml

不過最佳實踐還有幾個細節:

k8s 的 kubeconfig 文件同樣放在了代碼目錄(這個不太安全,不過倉庫私有還好,還可以利用 drone 的 secret,不細展開)

k8s 部署的 yaml 文件里的鏡像怎么配置?每次都修改 test.yaml 多不爽

如果多個集群 yaml 配置有區別怎么辦?寫多個 yaml?造成混亂,非常不優雅

所以我們引入 chart, 用 helm 進行部署:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
 name: test
 namespace: {{ .Values.namespace }}
spec:
 replicas: {{ .Values.replicaCount }}
 template:
 metadata:
 labels:
 name: test
 spec:
 serviceAccountName: test
 containers:
 - name: test
 image:  {{ .Values.image.repository }}:{{ .Values.image.tag }}  # deployment 的 yaml 文件是模板,創建時再傳參進來渲染
 imagePullPolicy: {{ .Values.image.pullPolicy }} 
....

注意,有了模板之后,我們部署 v1 版本和 v2 版本時就不需要改動 yaml 文件,這樣降低出錯風險,pipeline 執行時把環境變量傳進來,完美解決

這樣 git tag 鏡像 tag 與 yaml 里鏡像配置實現了完全的統一:

 deploy_dev: #  部署到開發環境
 image: helm:v2.8.1
 commands:
 - mkdir -p /root/.kube   cp -r .kube/config-test101.194 /root/.kube 
 - helm delete test --purge || true
 - helm install --name test --set image.tag=${DRONE_TAG=latest} Chart
 when:
 event: deployment
 environment: deploy_dev
 deploy_test: #  部署到測試環境
 image: helm:v2.8.1
 commands:
 - mkdir -p /root/.kube   cp -r .kube/config-test101.84 /root/.kube #  兩個環境使用不同的 kubeconfig
 - helm delete test --purge || true
 - helm install --name test --set image.tag=${DRONE_TAG=latest} Chart #  把 git tag 傳給 helm,這樣運行的鏡像就是 publish 時構建的鏡像,tag 一致
 when:
 event: deployment
 environment: deploy_test

以上,優雅的解決了上面問題

細節:event 可以是 git 的事件也可以是手動處罰的事件,類型是 deployment 時就是手動觸發的,drone 支持命令行觸發

我們進行了二次開發,讓 drone 可以在頁面上觸發對應的事件

原理篇

drone 上開通一個倉庫時,會給倉庫設置一個 webhook, 在項目設置里可以看到,這樣 git 的事件就可以通知到 drone,drone 根據事件去拉取代碼走流程

pipeline 基本原理

理解原理對使用這個系統非常重要,否則就會把一個東西用死。

pipeline 就負責起容器而已,容器干啥的系統不關心,用戶決定 這句話本文不止強調過一次,非常重要多讀幾遍

插件原理

鏡像即插件,也就是可能現有很多鏡像都能直接當作插件嵌入到 drone 流程中。

有個小區別是,你會發現 drone 有些插件還帶一些參數,這就是比普通的鏡像多做了一丟丟事,如 publish 時打 docker 的鏡像:

 publish:
 image: plugins/docker
 repo: octocat/hello-world
 tags: [ 1, 1.1, latest ]
 registry: index.docker.io

你會發現它有 repo tags 什么的參數,其實 drone 處理時非常簡單,就是把這些參數轉化成環境變量傳給容器了,然后容器去處理這些參數。本質就是做了這個事情:

docker run --rm \
 -e PLUGIN_TAG=latest \
 -e PLUGIN_REPO=octocat/hello-world \
 -e DRONE_COMMIT_SHA=d8dbe4d94f15fe89232e0402c6e8a0ddf21af3ab \
 -v $(pwd):$(pwd) \
 -w $(pwd) \
 --privileged \
 plugins/docker --dry-run

那我們自定義一個插件就簡單了,只要寫個腳本能處理特定環境變量即可,如一個 curl 的插件:

pipeline:
 webhook:
 image: foo/webhook
 url: http://foo.com
 method: post
 body: |
 hello world

寫個腳本

#!/bin/sh
curl \
 -X ${PLUGIN_METHOD} \ #  處理一個幾個環境變量
 -d ${PLUGIN_BODY} \
 ${PLUGIN_URL}
FROM alpine
ADD script.sh /bin/
RUN chmod +x /bin/script.sh
RUN apk -Uuv add curl ca-certificates
ENTRYPOINT /bin/script.sh
docker build -t foo/webhook .
docker push foo/webhook

打成 docker 鏡像,大功告成

所以大部分情況我們會很懶的什么也不寫,直接在容器里執行命令就是了,同樣是一個 curl 的需求,不寫插件的話

pipeline:
 webhook:
 image: busybox #  直接用 busybox
 command: 
 - curl -X POST -d 123 http://foo.com  完事,插件都懶得開發了 

值得注意的是一些復雜功能還是需要開發插件的,如 publish 鏡像時用的插件。關于該插件我想補充一句 它是 docker 里面起了一個 docker engine,用 docker 內的 docker engine 進行打鏡像的 所以 devicemapper 存儲驅動是支持不了的。請升級內核用 overlay2,或者 ubuntu 用 aufs

到此,相信大家對“基于 drone 如何構建 CI-CD 系統”有了更深的了解,不妨來實際操作一番吧!這里是丸趣 TV 網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-08-04發表,共計7139字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 扎鲁特旗| 萝北县| 石棉县| 江源县| 遵义县| 长兴县| 秦安县| 华阴市| 木兰县| 六安市| 阿拉善左旗| 蓬安县| 嫩江县| 康定县| 定州市| 临澧县| 靖远县| 晋江市| 樟树市| 鄂尔多斯市| 凌源市| 扶绥县| 成安县| 平利县| 高淳县| 巫山县| 湛江市| 达州市| 修武县| 关岭| 马鞍山市| 内江市| 彭泽县| 莱芜市| 皮山县| 象州县| 大理市| 大厂| 敦化市| 秦皇岛市| 萝北县|