看了就會(huì)的 Zadig 入門教程
Zadig 是 KodeRover 公司基于 Kubernetes 自主設(shè)計(jì)、研發(fā)的開(kāi)源分布式持續(xù)交付產(chǎn)品,具備靈活易用的高并發(fā)工作流、面向開(kāi)發(fā)者的云原生環(huán)境、高效協(xié)同的測(cè)試管理、強(qiáng)大免運(yùn)維的模板庫(kù)、客觀精確的效能洞察以及云原生 IDE 插件等重要特性,為工程師提供統(tǒng)一的協(xié)作平面。Zadig 內(nèi)置了 K8s YAML、Helm Chart、主機(jī)等復(fù)雜場(chǎng)景最佳實(shí)踐,適用大規(guī)模微服務(wù)、高頻高質(zhì)量交付等場(chǎng)景。
核心概念
在使用 Zadig 之前我們這里先來(lái)了解下 Zadig 中的幾個(gè)核心概念。
項(xiàng)目:Zadig 中的項(xiàng)目包括工作流、環(huán)境、服務(wù)、構(gòu)建、測(cè)試、版本等資源,用戶在項(xiàng)目中可以進(jìn)行服務(wù)開(kāi)發(fā)、服務(wù)部署、集成測(cè)試、版本發(fā)布等操作。
工作流:典型的軟件開(kāi)發(fā)過(guò)程一般包括
編寫代碼 -> 構(gòu)建 -> 部署 -> 測(cè)試 -> 發(fā)布這幾個(gè)步驟,工作流就是 Zadig 平臺(tái)對(duì)這樣一個(gè)開(kāi)發(fā)流程的實(shí)現(xiàn),通過(guò)工作流來(lái)更新環(huán)境中的服務(wù)或者配置。工作流組成:Zadig 工作流簡(jiǎn)化示意圖如下所示:
目前工作流基本組成部分有:構(gòu)建:拉取代碼,執(zhí)行構(gòu)建 部署:將構(gòu)建產(chǎn)物部署到測(cè)試環(huán)境中 測(cè)試:執(zhí)行自動(dòng)化測(cè)試,對(duì)部署結(jié)果進(jìn)行驗(yàn)證 分發(fā):完成測(cè)試驗(yàn)證后,將構(gòu)建產(chǎn)物分發(fā)到待發(fā)布的倉(cāng)庫(kù) 環(huán)境:Zadig 環(huán)境是一組服務(wù)集合及其配置、運(yùn)行環(huán)境的總稱,與 Kubernetes 的 NameSpace 是一對(duì)一的對(duì)應(yīng)關(guān)系,使用一套服務(wù)模板可以創(chuàng)建多套環(huán)境。
服務(wù):Zadig 中的服務(wù)可以理解為一組 Kubernetes 資源,包括 Ingress、Service、Deployment/Statefulset、ConfigMap 等,也可以是一個(gè)完整的 Helm Chart 或者云主機(jī)/物理機(jī)服務(wù),成功部署后可對(duì)外提供服務(wù)能力。
服務(wù)組件:服務(wù)組件是 Zadig 中可被更新的最小單元,是使用 Kubernetes 作為基礎(chǔ)設(shè)施的項(xiàng)目中的概念。一個(gè)服務(wù)中可包括多個(gè)服務(wù)組件。不同項(xiàng)目中的服務(wù)組件信息如下表:
服務(wù)組件是服務(wù)構(gòu)建配置中的一部分,為服務(wù)組件配置構(gòu)建后,運(yùn)行工作流時(shí)可選擇對(duì)應(yīng)的服務(wù)組件對(duì)其進(jìn)行更新。構(gòu)建:Zadig 構(gòu)建屬于服務(wù)配置的一部分,同時(shí)在工作流運(yùn)行階段會(huì)被調(diào)用,與服務(wù)是一對(duì)多的對(duì)應(yīng)關(guān)系,即一套構(gòu)建可以支持多個(gè)服務(wù)共享。
測(cè)試:Zadig 測(cè)試屬于項(xiàng)目的資源,同時(shí)也可以作為一個(gè)非必要階段在工作流中調(diào)用,支持跨項(xiàng)目。
版本管理:Zadig 版本是一個(gè)完整的可靠交付物,比如 Helm Chart,或 K8s YAML 完整配置文件。
安裝
我們這里選擇使用 Helm 的方式來(lái)進(jìn)行安裝。
$ helm repo add koderover-chart https://koderover.tencentcloudcr.com/chartrepo/chart
$ helm repo update
獲取 chart 包:
$ helm pull koderover-chart/zadig --untar
創(chuàng)建如下所示的 values 文件(ci/local-values.yaml):
# ci/local-values.yaml
tags:
mongodb: true
minio: true
ingressController: false
mysql: true
endpoint:
type: FQDN
FQDN: zadig.k8s.local
dex:
config:
staticClients:
- id: zadig
redirectURIs:
- 'http://zadig.k8s.local/api/v1/callback'
name: 'zadig'
secret: ZXhhbXBsZS1hcHAtc2VjcmV0
zadig 需要依賴 mongodb、minio 以及 mysql 服務(wù),如果你沒(méi)有外部的服務(wù)可用,則可以使用內(nèi)置的服務(wù),通過(guò) tags 下面的屬性來(lái)配置是否開(kāi)啟即可,endpoint.FQDN 用來(lái)配置 zadig 服務(wù)的地址。然后我們就可以使用該 values 文件來(lái)部署 zadig 了:
$ kubectl create ns zadig
$ helm upgrade --install zadig . -f ci/local-values.yaml --namespace zadig
NAME: zadig
LAST DEPLOYED: Mon Jul 11 14:21:16 2022
NAMESPACE: zadig
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Zadig has been installed successfully.
An initial account has been generated for your first login:
- Login: zadig.k8s.local
- User: admin
- Password: zadig
Add wechat ID "guotimeme": get FREE Zadig Tech Support, and Join our online community.
部署完成后查看 zadig 相關(guān)服務(wù)狀態(tài):
$ kubectl get pods -n zadig
NAME READY STATUS RESTARTS AGE
aslan-69d6759654-rtsrn 2/2 Running 0 155m
config-547fb89564-vkj84 1/1 Running 1 (153m ago) 155m
cron-f8544788c-5b8fl 2/2 Running 1 (143m ago) 155m
dind-0 1/1 Running 0 155m
discovery-74945fc6d4-sn8ws 1/1 Running 0 155m
gateway-6bdf56976-gg4nx 1/1 Running 3 (154m ago) 155m
gateway-proxy-f7d46ccb9-bln5j 1/1 Running 0 155m
gloo-66d69d848f-khvfk 1/1 Running 0 155m
hub-server-7fb68b65cb-4c7lp 1/1 Running 0 155m
nsqlookup-0 1/1 Running 0 155m
opa-b5df66445-stjjp 1/1 Running 0 155m
picket-84d4758c5f-kp88l 1/1 Running 0 155m
podexec-57db555984-tgrk8 1/1 Running 0 155m
policy-67f7d4f744-n9g5l 1/1 Running 0 155m
resource-server-bcd7cd7f8-krpg6 1/1 Running 0 155m
user-5c95bb8fb7-z8wg5 1/1 Running 1 (153m ago) 155m
warpdrive-7ffff47d47-n2vwb 2/2 Running 0 155m
warpdrive-7ffff47d47-rwpq4 2/2 Running 0 155m
zadig-dex-c575978d9-n68q9 1/1 Running 1 (150m ago) 155m
zadig-init--1-f98xb 0/1 Completed 0 155m
zadig-minio-fb7fdd6b6-cfjss 1/1 Running 0 155m
zadig-mongodb-5c59975745-4s24h 1/1 Running 0 155m
zadig-mysql-0 1/1 Running 0 155m
zadig-portal-5cdd6d9fdd-6g8ds 1/1 Running 0 155m
可以看到 zadig 的依賴服務(wù)還是比較多的,默認(rèn)情況下 zadig 會(huì)使用 gloo 這種 ingress 控制器來(lái)暴露服務(wù),會(huì)創(chuàng)建一個(gè)名為 zadig 的 virtualservices 對(duì)象,該對(duì)象相當(dāng)于 Ingress 的一個(gè)高級(jí)版本。
$ kubectl get virtualservices zadig -n zadig
NAME AGE
zadig 171m
$ kubectl get svc -n zadig
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
aslan ClusterIP 10.97.27.165 <none> 25000/TCP 172m
config ClusterIP 10.107.241.188 <none> 80/TCP 172m
dind ClusterIP None <none> 2375/TCP 172m
gateway ClusterIP 10.99.26.142 <none> 443/TCP 172m
gateway-proxy LoadBalancer 10.111.109.206 192.168.0.102 80:31600/TCP,443:31572/TCP 172m
gloo ClusterIP 10.103.178.8 <none> 9977/TCP,9976/TCP,9988/TCP,9979/TCP 172m
hub-server ClusterIP 10.109.70.132 <none> 26000/TCP 172m
nsqlookupd ClusterIP None <none> 4160/TCP,4161/TCP 172m
opa ClusterIP 10.111.93.64 <none> 9191/TCP,8181/TCP 172m
picket ClusterIP 10.97.6.111 <none> 80/TCP 172m
podexec ClusterIP 10.100.251.156 <none> 27000/TCP 172m
policy ClusterIP 10.105.50.162 <none> 80/TCP 172m
resource-server ClusterIP 10.111.41.231 <none> 80/TCP 172m
user ClusterIP 10.106.85.172 <none> 80/TCP 172m
warpdrive ClusterIP 10.107.219.101 <none> 25001/TCP 172m
zadig-dex ClusterIP 10.102.181.112 <none> 5556/TCP,5558/TCP 172m
zadig-minio ClusterIP 10.99.45.95 <none> 9000/TCP 172m
zadig-mongodb ClusterIP 10.98.252.235 <none> 27017/TCP 172m
zadig-mysql ClusterIP 10.101.122.76 <none> 3306/TCP 172m
zadig-mysql-headless ClusterIP None <none> 3306/TCP 172m
zadig-portal ClusterIP 10.104.141.49 <none> 80/TCP 172m
我本地集群部署了 metalb,會(huì)自動(dòng)為 gateway-proxy 服務(wù)分配一個(gè) LoadBalancer 類型的 IP 地址,我們只需將 zadig.k8s.local 域名解析到該 IP 地址即可,然后我們就可以在瀏覽器中訪問(wèn)了。

默認(rèn)的用戶名為 admin,密碼為 zadig,登錄后即可進(jìn)入首頁(yè)。

基本使用
Zadig 安裝完成后,接下來(lái)我們以容器化 Nginx 為例來(lái)說(shuō)明下 Zadig 的基本使用。
集成代碼源
首先我們要去添加下代碼源,比如常見(jiàn)的 GitHub、GitLab 等。
GitHub
要集成 GitHub 代碼源首先需要進(jìn)入 https://github.com/settings/developers 頁(yè)面新建一個(gè) OAuth Apps,其中應(yīng)用名稱可以隨便命名,首頁(yè) URL 我們這里是 http://zadig.k8s.local,下面的 callback URL 比較重要,填寫 http://zadig.k8s.local/api/directory/codehosts/callback。

應(yīng)用創(chuàng)建成功后,GitHub 會(huì)返回應(yīng)用的基本信息,點(diǎn)擊 Generate a new client secret 生成 Client Secret。

將生成的 Client ID 與 Client Secret 記錄下來(lái),切換到 Zadig 系統(tǒng),管理員依次點(diǎn)擊系統(tǒng)設(shè)置 -> 集成管理 -> 代碼源集成頁(yè)面,然后點(diǎn)擊添加按鈕,在彈出的對(duì)話框中選擇 GitHub 代碼源,填上上面獲取的 Client ID 和 Client Secret 信息。

然后點(diǎn)擊前往授權(quán)按鈕,點(diǎn)擊后會(huì)自動(dòng)跳轉(zhuǎn)到 GitHub 的授權(quán)頁(yè)面,需要我們進(jìn)行認(rèn)證授權(quán),授權(quán)后會(huì)自動(dòng)跳轉(zhuǎn)回 Zadig 系統(tǒng)頁(yè)面。

GitLab
如果要集成 GitLab 代碼源,同樣需要去創(chuàng)建一個(gè)認(rèn)證應(yīng)用,前往 GitLab 應(yīng)用管理頁(yè)面 http://git.k8s.local/-/profile/applications。

這里我們需要新建一個(gè)應(yīng)用,名稱為 Zadig,其中 Redirect URI 為 http://zadig.k8s.local/api/directory/codehosts/callback,需要勾選 api、read_user、read_repository3個(gè)權(quán)限。

應(yīng)用創(chuàng)建成功后,GitLab 會(huì)返回應(yīng)用的相關(guān)信息,其中包括 Application ID、Secret 信息。

然后一樣的方式前往 Zadig 添加一個(gè)新的代碼源,將 GitLab 相關(guān)信息填寫到對(duì)話框中。

然后點(diǎn)擊前往授權(quán)按鈕會(huì)自動(dòng)跳轉(zhuǎn)到 GitLab 頁(yè)面進(jìn)行授權(quán)認(rèn)證。

確認(rèn)授權(quán)后會(huì)自動(dòng)跳轉(zhuǎn)回 Zadig,正常情況下就可以看到添加的代碼源了。

集成鏡像倉(cāng)庫(kù)
代碼源集成完成后,接下來(lái)我們需要添加鏡像倉(cāng)庫(kù)到 Zadig 中,支持集成阿里云 ACR、騰訊云 TCR、華為云 SWR、Amazon ECR、DockerHub、Harbor 等鏡像倉(cāng)庫(kù),我們這里來(lái)集成同 K8s 集群中部署的 Harbor 服務(wù)。
首先在 Harbor 中創(chuàng)建一個(gè)名為 zadig 的新項(xiàng)目,用來(lái)保存 Zadig 中構(gòu)建的鏡像。

在 Zadig 系統(tǒng) http://zadig.k8s.local/v1/system/registry 頁(yè)面點(diǎn)擊新建按鈕,配置上我們的 Harbor 相關(guān)信息。

由于我這里的 Harbor 服務(wù)是自簽名的服務(wù),為了方便我這里未開(kāi)啟 SSL 校驗(yàn),然后點(diǎn)擊保存按鈕即可。
新建項(xiàng)目
我們這里通過(guò)一個(gè)簡(jiǎn)單的 Nginx 應(yīng)用來(lái)進(jìn)行說(shuō)明,代碼放置在 GitLab 上面,倉(cāng)庫(kù)地址為 http://git.k8s.local/course/zadig-nginx-demo,倉(cāng)庫(kù)就包含一個(gè) Dockerfile 和 index.html 文件。
from nginx:stable
add index.html /usr/share/nginx/html
代碼源準(zhǔn)備好后,接下來(lái)我們就可以去創(chuàng)建項(xiàng)目了,Zadig 中的項(xiàng)目包括工作流、環(huán)境、服務(wù)、構(gòu)建、測(cè)試、版本等資源,用戶在項(xiàng)目中可以進(jìn)行服務(wù)開(kāi)發(fā)、服務(wù)部署、集成測(cè)試、版本發(fā)布等操作。
前面項(xiàng)目列表開(kāi)始新建項(xiàng)目,這里我們選擇 K8s YAML項(xiàng)目類型。

點(diǎn)擊立即新建按鈕,進(jìn)入項(xiàng)目初始化向?qū)Вc(diǎn)擊下一步開(kāi)始創(chuàng)建服務(wù):

點(diǎn)擊下一步開(kāi)始新建一個(gè)服務(wù),Zadig 中的服務(wù)可以理解為一組 Kubernetes 資源,比如 Service、Deployment 等等,也可以是一個(gè) Helm Chart 包。

新建服務(wù)提供了3種方式:
手工輸入:直接配置 K8s 的資源清單文件 從代碼庫(kù)導(dǎo)入:從代碼倉(cāng)庫(kù)中同步服務(wù)的 K8s 資源清單文件 使用模板新建:基于 K8s YAML 模板或者從 K8s 中導(dǎo)入
由于我們這里的示例非常簡(jiǎn)單,就直接使用手工輸入的方式來(lái)新建服務(wù)。如下所示,我們新建一個(gè)名為 nginx 的服務(wù),在中間的 YAML 區(qū)域編寫我們服務(wù)的資源清單文件。

這里我只需要簡(jiǎn)單創(chuàng)建一個(gè) Deployment 和 Service 資源即可,對(duì)應(yīng)的資源清單文件如下所示:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
app: nginx
version: "{{.nginxVersion}}"
template:
metadata:
labels:
app: nginx
version: "{{.nginxVersion}}"
spec:
containers:
- name: nginx
image: harbor.k8s.local/zadig/nginx:stable
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
version: "{{.nginxVersion}}"
spec:
labelSelector:
app: nginx
type: NodePort
ports:
- name: http
port: 80
targetPort: 80
然后點(diǎn)擊保存按鈕,保存后會(huì)自動(dòng)加載除系統(tǒng)變量、YAML 中的自定義變量以及服務(wù)組件,上面的 YAML 文件中我們添加了一個(gè) {{.nginxVersion}} 變量,Zadig 會(huì)自動(dòng)讀取到該變量。
接下來(lái)在變量區(qū)域點(diǎn)擊添加構(gòu)建為我們的服務(wù)配置構(gòu)建方式。

可以根據(jù)需要配置構(gòu)建的環(huán)境,同時(shí)選擇 GitLab 這個(gè)代碼源,并選擇我們前面的項(xiàng)目代碼倉(cāng)庫(kù)以及分支。

然后在下方可以配置通用構(gòu)建腳本:
cd $WORKSPACE/zadig-nginx-demo
docker build -t $IMAGE -f Dockerfile .
docker push $IMAGE
其中的 $IMAGE 變量就是前面變量中讀取到的當(dāng)前鏡像版本($IMAGE),配置后點(diǎn)擊保存構(gòu)建即可。

可以看到已經(jīng)關(guān)聯(lián)上了上面創(chuàng)建的構(gòu)建信息了。

接下來(lái)點(diǎn)擊下一步繼續(xù),在這一步中,系統(tǒng)會(huì)自動(dòng)創(chuàng)建 2 套環(huán)境和 3 條工作流。2 套環(huán)境可分別用于日常開(kāi)發(fā)環(huán)節(jié)和測(cè)試驗(yàn)收環(huán)節(jié),3 條工作流也會(huì)自動(dòng)綁定對(duì)應(yīng)的環(huán)境以達(dá)到對(duì)不同環(huán)境進(jìn)行持續(xù)交付的目的。

Zadig 會(huì)在 K8s 集群中創(chuàng)建兩個(gè)名為 nginx-demo-env-dev 和 nginx-demo-env-qa 的命名空間。
$ kubectl get ns |grep nginx-demo
nginx-demo-env-dev Active 23s
nginx-demo-env-qa Active 23s
繼續(xù)下一步進(jìn)入工作流執(zhí)行頁(yè)面,在該頁(yè)面可以看到創(chuàng)建的3條工作流,分別對(duì)應(yīng)著不同的環(huán)境。

比如我們現(xiàn)在選擇 nginx-demo-workflow-dev 這條工作流來(lái)完成 dev 環(huán)境的持續(xù)交付,點(diǎn)擊后面的點(diǎn)擊運(yùn)行按鈕。

根據(jù)實(shí)際需求選擇要部署的服務(wù)以及對(duì)應(yīng)代碼分支,然后點(diǎn)擊啟動(dòng)任務(wù)即可開(kāi)始執(zhí)行構(gòu)建任務(wù)。

任務(wù)啟動(dòng)后我們也可以看到會(huì)去自動(dòng)啟動(dòng)一個(gè) Pod 來(lái)執(zhí)行構(gòu)建任務(wù),這點(diǎn)和 Jenkins 的動(dòng)態(tài) Slave 基本一致的,當(dāng)任務(wù)構(gòu)建完成后也會(huì)自動(dòng)銷毀該 Pod。
$ kubectl get pods -n zadig
NAME READY STATUS RESTARTS AGE
dind-0 1/1 Running 0 16m
nginx-demo-workflow-dev-2-buildv2-szhrk--1-mn6dd 1/1 Running 0 8s
# ......
任務(wù)執(zhí)行完成后會(huì)使用新構(gòu)建的鏡像 harbor.k8s.local/zadig/nginx:20220711184844-1-main 去替換掉前面我們配置的資源清單中的鏡像地址,自動(dòng)部署到 nginx-demo-env-dev 命名空間中。
$ kubectl get pods -n nginx-demo-env-dev
NAME READY STATUS RESTARTS AGE
nginx-5d5c7f978-r2vkd 1/1 Running 0 30s
我們可以通過(guò)該服務(wù)的 NodePort 來(lái)訪問(wèn) nginx 服務(wù)。
$ kubectl get svc -n nginx-demo-env-dev
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx NodePort 10.96.32.211 <none> 80:31675/TCP 6m57s
$ curl 192.168.0.106:31675
<h1>
Hello 優(yōu)點(diǎn)知識(shí)(youdianzhishi.com)!
</h1>
同時(shí) dev 環(huán)境中的鏡像信息也自動(dòng)更新成了上面構(gòu)建的鏡像信息。

觸發(fā)器
其他環(huán)境的服務(wù)交付和上面都是類似的,接下來(lái)我們來(lái)配置自動(dòng)觸發(fā)工作流和版本交付。
點(diǎn)擊 dev 工作流配置按鈕,進(jìn)入工作流配置頁(yè)面。

點(diǎn)擊左側(cè)的觸發(fā)器+按鈕開(kāi)始添加觸發(fā)器,然后勾選 Webook 來(lái)添加一個(gè) Webhook 的觸發(fā)器。

點(diǎn)擊添加配置添加一個(gè)觸發(fā)器,這里我們?yōu)?GitLab 代碼庫(kù)添加一個(gè)觸發(fā)器,選擇對(duì)應(yīng)的代碼庫(kù)和分支等信息,添加后記得保存。

現(xiàn)在我們?nèi)?GitLab 代碼倉(cāng)庫(kù)中創(chuàng)建一個(gè) Pull Request,在處理合并的頁(yè)面中會(huì)自動(dòng)關(guān)聯(lián)上對(duì)應(yīng)的 Zadig 工作流狀態(tài)。

點(diǎn)擊任務(wù)鏈接可以跳轉(zhuǎn)到 Zadig 工作流信息頁(yè)面。

當(dāng)然當(dāng)我們將這個(gè) PR 合并到 main 分支上過(guò)后同樣也會(huì)觸發(fā)一次新的任務(wù)。
到這里我們就使用 Zadig 完成了一個(gè)最簡(jiǎn)單的應(yīng)用交付,Zadig 還有更多高級(jí)功能實(shí)踐未完待續(xù)......
