Zadig
是 KodeRover 公司基于 Kubernetes 自主设计、研发的开源分布式持续交付产品,具备灵活易用的高并发工作流、面向开发者的云原生环境、高效协同的测试管理、强大免运维的模板库、客观精确的效能洞察以及云原生 IDE 插件等重要特性,为工程师提供统一的协作平面。Zadig 内置了 K8s YAML、Helm Chart、主机等复杂场景最佳实践,适用大规模微服务、高频高质量交付等场景。
核心概念
在使用 Zadig 之前我们这里先来了解下 Zadig 中的几个核心概念。
- 项目:Zadig 中的项目包括工作流、环境、服务、构建、测试、版本等资源,用户在项目中可以进行服务开发、服务部署、集成测试、版本发布等操作。
- 工作流:典型的软件开发过程一般包括
编写代码 -> 构建 -> 部署 -> 测试 -> 发布
这几个步骤,工作流就是 Zadig 平台对这样一个开发流程的实现,通过工作流来更新环境中的服务或者配置。 - 工作流组成:Zadig 工作流简化示意图如下所示:
目前工作流基本组成部分有:
-
- 构建:拉取代码,执行构建
- 部署:将构建产物部署到测试环境中
- 测试:执行自动化测试,对部署结果进行验证
- 分发:完成测试验证后,将构建产物分发到待发布的仓库
- 环境:Zadig 环境是一组服务集合及其配置、运行环境的总称,与 Kubernetes 的 NameSpace 是一对一的对应关系,使用一套服务模板可以创建多套环境。
- 服务:Zadig 中的服务可以理解为一组 Kubernetes 资源,包括 Ingress、Service、Deployment/Statefulset、ConfigMap 等,也可以是一个完整的 Helm Chart 或者云主机/物理机服务,成功部署后可对外提供服务能力。
- 服务组件:服务组件是 Zadig 中可被更新的最小单元,是使用 Kubernetes 作为基础设施的项目中的概念。一个服务中可包括多个服务组件。不同项目中的服务组件信息如下表:
服务组件是服务构建配置中的一部分,为服务组件配置构建后,运行工作流时可选择对应的服务组件对其进行更新。
- 构建:Zadig 构建属于服务配置的一部分,同时在工作流运行阶段会被调用,与服务是一对多的对应关系,即一套构建可以支持多个服务共享。
- 测试:Zadig 测试属于项目的资源,同时也可以作为一个非必要阶段在工作流中调用,支持跨项目。
- 版本管理:Zadig 版本是一个完整的可靠交付物,比如 Helm Chart,或 K8s YAML 完整配置文件。
安装
我们这里选择使用 Helm 的方式来进行安装。
$ helm repo add koderover-chart https://koderover.tencentcloudcr.com/chartrepo/chart
$ helm repo update
获取 chart 包:
$ helm pull koderover-chart/zadig --untar
创建如下所示的 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 服务,如果你没有外部的服务可用,则可以使用内置的服务,通过 tags
下面的属性来配置是否开启即可,endpoint.FQDN
用来配置 zadig 服务的地址。然后我们就可以使用该 values 文件来部署 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 相关服务状态:
$ 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 的依赖服务还是比较多的,默认情况下 zadig 会使用 gloo
这种 ingress 控制器来暴露服务,会创建一个名为 zadig
的 virtualservices
对象,该对象相当于 Ingress 的一个高级版本。
$ 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
,会自动为 gateway-proxy
服务分配一个 LoadBalancer 类型的 IP 地址,我们只需将 zadig.k8s.local
域名解析到该 IP 地址即可,然后我们就可以在浏览器中访问了。
默认的用户名为 admin
,密码为 zadig
,登录后即可进入首页。
基本使用
Zadig 安装完成后,接下来我们以容器化 Nginx 为例来说明下 Zadig 的基本使用。
集成代码源
首先我们要去添加下代码源,比如常见的 GitHub、GitLab 等。
GitHub
要集成 GitHub 代码源首先需要进入 https://github.com/settings/developers 页面新建一个 OAuth Apps
,其中应用名称可以随便命名,首页 URL 我们这里是 http://zadig.k8s.local
,下面的 callback URL
比较重要,填写 http://zadig.k8s.local/api/directory/codehosts/callback
。
应用创建成功后,GitHub 会返回应用的基本信息,点击 Generate a new client secret
生成 Client Secret。
将生成的 Client ID
与 Client Secret
记录下来,切换到 Zadig 系统,管理员依次点击系统设置 -> 集成管理 -> 代码源集成
页面,然后点击添加按钮,在弹出的对话框中选择 GitHub
代码源,填上上面获取的 Client ID
和 Client Secret
信息。
然后点击前往授权
按钮,点击后会自动跳转到 GitHub 的授权页面,需要我们进行认证授权,授权后会自动跳转回 Zadig 系统页面。
GitLab
如果要集成 GitLab 代码源,同样需要去创建一个认证应用,前往 GitLab 应用管理页面 http://git.k8s.local/-/profile/applications。
这里我们需要新建一个应用,名称为 Zadig
,其中 Redirect URI
为 http://zadig.k8s.local/api/directory/codehosts/callback
,需要勾选 api
、read_user
、read_repository
3个权限。
应用创建成功后,GitLab 会返回应用的相关信息,其中包括 Application ID
、Secret
信息。
然后一样的方式前往 Zadig 添加一个新的代码源,将 GitLab 相关信息填写到对话框中。
然后点击前往授权
按钮会自动跳转到 GitLab 页面进行授权认证。
确认授权后会自动跳转回 Zadig,正常情况下就可以看到添加的代码源了。
集成镜像仓库
代码源集成完成后,接下来我们需要添加镜像仓库到 Zadig 中,支持集成阿里云 ACR、腾讯云 TCR、华为云 SWR、Amazon ECR、DockerHub、Harbor 等镜像仓库,我们这里来集成同 K8s 集群中部署的 Harbor 服务。
首先在 Harbor 中创建一个名为 zadig
的新项目,用来保存 Zadig 中构建的镜像。
在 Zadig 系统 http://zadig.k8s.local/v1/system/registry 页面点击新建
按钮,配置上我们的 Harbor 相关信息。
由于我这里的 Harbor 服务是自签名的服务,为了方便我这里未开启 SSL 校验,然后点击保存
按钮即可。
新建项目
我们这里通过一个简单的 Nginx 应用来进行说明,代码放置在 GitLab 上面,仓库地址为 http://git.k8s.local/course/zadig-nginx-demo,仓库就包含一个 Dockerfile
和 index.html
文件。
from nginx:stable
add index.html /usr/share/nginx/html
代码源准备好后,接下来我们就可以去创建项目了,Zadig 中的项目包括工作流、环境、服务、构建、测试、版本等资源,用户在项目中可以进行服务开发、服务部署、集成测试、版本发布等操作。
前面项目列表开始新建项目,这里我们选择 K8s YAML项目
类型。
点击立即新建
按钮,进入项目初始化向导,点击下一步开始创建服务:
点击下一步
开始新建一个服务,Zadig 中的服务可以理解为一组 Kubernetes 资源,比如 Service、Deployment 等等,也可以是一个 Helm Chart 包。
新建服务提供了3种方式:
- 手工输入:直接配置 K8s 的资源清单文件
- 从代码库导入:从代码仓库中同步服务的 K8s 资源清单文件
- 使用模板新建:基于 K8s YAML 模板或者从 K8s 中导入
由于我们这里的示例非常简单,就直接使用手工输入的方式来新建服务。如下所示,我们新建一个名为 nginx
的服务,在中间的 YAML 区域编写我们服务的资源清单文件。
这里我只需要简单创建一个 Deployment 和 Service 资源即可,对应的资源清单文件如下所示:
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
然后点击保存
按钮,保存后会自动加载除系统变量、YAML 中的自定义变量以及服务组件,上面的 YAML 文件中我们添加了一个 {{.nginxVersion}}
变量,Zadig 会自动读取到该变量。
接下来在变量区域点击添加构建
为我们的服务配置构建方式。
可以根据需要配置构建的环境,同时选择 GitLab 这个代码源,并选择我们前面的项目代码仓库以及分支。
然后在下方可以配置通用构建脚本:
cd $WORKSPACE/zadig-nginx-demo
docker build -t $IMAGE -f Dockerfile .
docker push $IMAGE
其中的 $IMAGE
变量就是前面变量中读取到的当前镜像版本($IMAGE)
,配置后点击保存构建
即可。
可以看到已经关联上了上面创建的构建信息了。
接下来点击下一步
继续,在这一步中,系统会自动创建 2 套环境和 3 条工作流。2 套环境可分别用于日常开发环节和测试验收环节,3 条工作流也会自动绑定对应的环境以达到对不同环境进行持续交付的目的。
Zadig 会在 K8s 集群中创建两个名为 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
继续下一步
进入工作流执行页面,在该页面可以看到创建的3条工作流,分别对应着不同的环境。
比如我们现在选择 nginx-demo-workflow-dev
这条工作流来完成 dev 环境的持续交付,点击后面的点击运行
按钮。
根据实际需求选择要部署的服务以及对应代码分支,然后点击启动任务即可开始执行构建任务。
任务启动后我们也可以看到会去自动启动一个 Pod 来执行构建任务,这点和 Jenkins 的动态 Slave 基本一致的,当任务构建完成后也会自动销毁该 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
# ......
任务执行完成后会使用新构建的镜像 harbor.k8s.local/zadig/nginx:20220711184844-1-main
去替换掉前面我们配置的资源清单中的镜像地址,自动部署到 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
我们可以通过该服务的 NodePort 来访问 nginx 服务。
$ 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 优点知识(youdianzhishi.com)!
</h1>
同时 dev
环境中的镜像信息也自动更新成了上面构建的镜像信息。
触发器
其他环境的服务交付和上面都是类似的,接下来我们来配置自动触发工作流和版本交付。
点击 dev
工作流配置按钮,进入工作流配置页面。
点击左侧的触发器+
按钮开始添加触发器,然后勾选 Webook
来添加一个 Webhook 的触发器。
点击添加配置
添加一个触发器,这里我们为 GitLab 代码库添加一个触发器,选择对应的代码库和分支等信息,添加后记得保存。
现在我们去 GitLab 代码仓库中创建一个 Pull Request,在处理合并的页面中会自动关联上对应的 Zadig 工作流状态。
点击任务链接可以跳转到 Zadig 工作流信息页面。
当然当我们将这个 PR 合并到 main 分支上过后同样也会触发一次新的任务。
到这里我们就使用 Zadig 完成了一个最简单的应用交付,Zadig 还有更多高级功能实践未完待续......