项目背景概述
本文通过部署一个基于Dubbo的微服务项目——Q云书城(QCBM)(图1-1),介绍如何在多环境下部署微服务持续交付项目。通过使用Zadig持续部署工具,展示多环境配置、微服务构建、工作流交付及运行时管理的完整过程,提供一种多环境下持续集成、持续交付及云原生微服务管理能力的解决方案。(图1-2)
Q云书城(下同QCBM)是一个基于腾讯云原生产品,使用Dubbo2.7.8框架开发的一个网上书城 Demo 项目,整体架构采用微服务实现。以下为架构各层服务介绍(图1-3):
接入层使用腾讯云负载均衡 CLB 结合 K8S Ingress 和 Service 实现流量接入和转发,跨区高可用模式部署。 数据层使用 腾讯云数据库 MYSQL 和 腾讯云数据库 Redis 搭建,保存书城信息,也采用跨区高可用模式部署,提供灾备切换能力。 应用层使用Dubbo开发,由以下微服务单元组成: QCBM-Gateway:API 网关,接受前端HTTP REST请求,转化为服务间Dubbo调用。 User-Service:提供用户注册、登录、鉴权等功能。 Favorites-Service :提供用户图书收藏功能。 Order-Service :提供用户订单生成和查询等功能。 Store-Service :提供图书信息的存储等功能。 Seckill-Service:提供图书秒杀功能,提供限流熔断能力。 各微服务单元基于容器部署,运行于腾讯云的 容器服务 TKE 环境上。不同的可用区采用K8S NameSpace模拟,1:1进行应用层部署,通过接入层实现流量切换。
Zadig产品介绍
基本概念 Zadig 是 KodeRover 公司基于 Kubernetes 设计研发的开源分布式持续交付 (Continuous Delivery) 产品,项目包括工作流、环境、服务、构建、测试和版本等模块,面向云原生场景提供高并发部署能力,适用于大规模微服务、多环境部署、高频交付等场景。(图2-1)
Zadig与其他CICD工具相同,项目中也分工作流、构建、测试和版本等模块,但不同的是:
环境模块,在Zadig里是一组服务集合及其配置、运行环境的总称,与 Kubernetes的NameSpace一一对应,环境间具备隔离性。 服务模块,可以理解为一组 Kubernetes 资源,包括 Ingress、Service、Deployment、ConfigMap 等,也可以是一个完整的 Helm Chart或者主机服务
产品优势 面向开发者的云原生环境,提供微服务 + 容器的集成交付环境。 高并发工作流部署模式,多服务间可并行构建、部署、测试。 分钟级创建或复制完整的隔离的服务,实现资源托管能力,可进行日志查看,调试管理。 对接Jmeter、Pytest等主流测试框架,可跨项目管理UI、API等测试用例。 提供跨项目共享模板库,如K8S YAML、Helm Chart、构建等,实现模板统一管理。 容器环境实现构建过程,确保每次构建环境上下文一致。
使用场景 云原生场景大规模微服务交付,具备统一管理能力。 高频高并发工作流交付,希望具备并行构建部署能力。 多地域环境下微服务部署,如同城双活,异地多活。 快速配置基线-自测测试环境。
同类型产品对比
高,项目以微服务为中心展开,可通过控制台调整微服务交付时启动顺序
低,通过脚本管理微服务,并自定义Pipeline,通过脚本顺序控制微服务启动顺序
中,仅提供标准K8S资源方式,通过CRD定义微服务启动顺序
中,需自行管理Jenkinsfile。在云原生部署场景下,还需额外管理Dockerfile及Yaml文件
中,流水线通过CRD定义,需管理CRD YAML文件;大部分场景下,需用户二次开发上层管理平台
配置简单,基本无学习成本;产品微服务及云原生整合度高,并具备模板,自测,联调等特色功能
Pipeline中每个步骤都是容器的工作流,可整合进现有YAML管理方式;通过CRD描述,自定义成都高
项目实践
Zadig安装 确保一台连接集群的主机用于执行安装脚本,并已安装Kubectl客户端,目前Zadig支持Kubernetes1.16-1.22版本,以下实践采用TKE 1.18版本实现。 主机上配置环境变量。 export IP=<IP> # 主机 IP,用于访问 Zadig 系统
export PORT=<PORT> # 随机填写 30000 - 32767 区间的任一端口
官网下载Zadig 1.13 安装脚本,为方便实验,本文使用快速安装模式,搭建 Zadig on Kubernetes 环境。(备注:生产环境请选用生产模式部署,持久化MySQL及MongoDB数据) # 快速体验:
curl -LO https://github.com/koderover/zadig/releases/download/v1.13.0/install_quickstart.sh
chmod +x ./install_quickstart.sh
./install_quickstart.sh
使用环境变量中配置的IP及PORT,访问Zadig控制台;初始管理员密码在安装界面中提供。(图3-1) 登录后,通过个人界面,配置项目所需的代码仓库及镜像仓库;本次实践采用腾讯云CODING 作为代码仓库(图3-2),并使用腾讯云TCR 对持续集成流程中的镜像进行托管(图3-3);通过【系统设置】界面,可以完成以上两个外部系统进行管理。 在【系统设置】中,通过配置集群属性,安装Zadig Agent,完成K8S集群环境托管。安装后的Zadig Agent负责环境读取、应用交付及运行时管理。(图3-4) kubectl apply -f "http://x.x.x.x:30000/api/aslan/cluster/agent/62cd47b98b49327bcb8a1569/agent.yaml?type=deploy"
成功后,可以在对应集群Zadig NameSpace里找到如下资源 namespace/koderover-agent created
serviceaccount/koderover-agent created
clusterrolebinding.rbac.authorization.k8s.io/koderover-agent-admin-binding created
clusterrole.rbac.authorization.k8s.io/koderover-agent-admin created
service/hub-agent created
deployment.apps/koderover-agent-node-agent created
deployment.apps/resource-server created
service/resource-server created
statefulset.apps/dind created
service/dind created
环境配置 本次实践项目,目标为多环境下的微服务持续交付。实验环境采用NameSpace进行多集群模拟,共设置4个环境,分别为DEV(开发环境),QA(测试环境),PROD(线上生产环境,可用区A),PROD-BAK(线上生产环境,可用区B)。(图3-5)
进入Zadig项目模块,开始配置环境(图3-6)。因项目从零开始配置,所以这里我们选择【K8S YAML项目】,如果是针对现有服务进行托管及应用交付,可选择【K8S 托管项目】,Zadig会自动读取环境中的资源,自动化环境配置过程。(图3-7) 新建项目后,点击【跳过向导】,进入项目页面;项目页面顶部菜单中的【工作流】、【环境】、【服务】和【构建】四个模块,为本次实践配置对象。接下来我们先对【环境】进行配置,选择该环境所对应的集群、命名空间、镜像仓库和托管服务。(图3-8)(备注:因软件限制,配置环境前需至少一个服务项已配置,可先在【服务】配置一个PlaceHolder服务,后期删除) 环境中一个重要配置项是环境配置。我们将Ingress、ConfigMap和Secret配置在这里,由环境内的服务共享(图3-9)。后期也可以在【环境】界面中,对其他资源进行添加(图3-10)。(备注:项目使用腾讯云 CLB Ingress 进行环境负载均衡接入,具体用法可参考 CLB 类型 Ingress ) 图3-9 在环境中配置Ingress、ConfigMap和Secret
图3-10 在环境中添加Ingress、ConfigMap和Secret
在【服务】模块中配置的全局环境变量也会在【环境】模块中显示。(备注:建议将环境中的特性开关配置、业务区域配置、全局注入的Annotation、不适合放在服务配置中的敏感信息,都统一放置在【环境】中的全局变量中) 最后是服务列表,将容器镜像选择,配置为【全容器-智能选择镜像】,会优先选择最新的容器镜像,如果在镜像仓库中不存在该容器镜像,则会选择模板中的默认镜像进行填充。(图3-11) 采用同样的方式,配置其他3套环境。其中,DEV、QA、PROD环境中,Ingress及ConfigMap采用各自环境组件,避免出现环境污染。(备注:本实践项目为同城双活架构,应用部署于可用区PROD-AZ3与PROD-AZ4,接入层Ingress采用不同CLB实例,数据层ConfigMap采用同一实例)
服务与构建配置 Zadig产品提供了三种方式管理服务配置(K8S 资源YAML):
手工输入:在创建服务时手动输入配置文件,内容存储在 Zadig 系统中。 从代码库同步:服务的配置文件在代码库中,从代码库中同步服务配置。之后提交到该代码库的 YAML 变更会被自动同步到 Zadig 系统上。 使用模板新建:在 Zadig 平台中创建服务 K8s YAML 模板,创建服务时,在模板的基础上对服务进行重新定义 生产环境中,建议采用从代码库同步的方式,将K8S YAML资源文件(Deployment,Ingress,ConfigMap)通过Git进行版本管理(GitOps),保证每次项目发布过程中,都使用最新版本进行交付。(图3-12)
接下来我们对QCBM中的6个微服务进行配置,并添加构建步骤。(备注:为了演示【环境】模块配置,上一节中新建了一个PlaceHolder服务,配置完正式服务后,PlaceHolder服务可进行删除) 在【服务】模块中,新建服务,并将YAML文件写入对话框,保存。在【环境】模块配置时,我们已经将Ingress、ConfigMap、Secret进行了配置,此处只需添加Deployment及Service。(图3-13) 点击服务右侧添加构建。默认右侧镜像显示为Yaml模板里的image,完成持续集成后,服务会使用最新镜像进行环境交付。(图3-14) 在构建窗口里,选择先前配置的代码仓库,完善代码仓库,默认分支等信息,并填写构建脚本。其中可根据DEV与QA测试目标的不同,选择feature或master分支。(图3-16) #!/bin/bash
set -e
cd qcbm-backend
mvn clean package -DskipTests
cd qcbm-gateway
docker build -t $IMAGE -f Dockerfile .
docker push $IMAGE
因为下载软件包的原因,第一次构建时间一般比较长,可以配置本地工作空间缓存,加速后期构建速度。(图3-17) 至此,我们已经配置好一个服务。将配置好的服务加入dev环境。注意,因为线上生产环境我们直接采用镜像部署,这里仅将微服务加入dev和qa环境中。(图3-18) 按照同样的配置,配置其他5个微服务。如Service需公网访问,可以复用同一个CLB。参考容器服务 Service 使用已有 CLB (备注:Ingress及Service不支持复用CLB,不同Service可复用同样的CLB) 完成后,通过上下拖拽服务名,可以调整持续集成后,服务在集群里的启动顺序。(图3-19) 在LENS中查看环境对应的集群命名空间,可以看见服务在加入环境后,已经正确启动。(图3-20) 如果有服务运行不正常,会显示Unstable状态,在【服务】模块中修改对应服务Yaml配置,【服务】模块会进行提示,可直接点击进行服务更新。(图3-21) 工作流部署 截止现在,项目中已包含6个微服务、4套环境。接下来我们需要对工作流进行配置。
开发及测试环境采用代码拉取并编译的方式进行构建,开发及测试人员可以快速的在环境里进行单元测试(dev分支)及回归测试(master分支),而生产环境的发布,通过已经测试充分的镜像交付物进⾏发布,不需要再经过⼀轮代码拉取,编译打包的工作流程,直接采用镜像部署。
因此,我们一共需要部署4条流水线,DEV和QA环境,采用Zadig的【构建部署】模式交付;PROD环境采用Zadig的【交付物部署】模式交付。(图3-22)
DEV及QA工作流,选择【构建部署】,通过各服务对应的构建配置,进行代码拉取,编译打包,推送镜像仓库,最近进行容器部署。(图3-24) PROD工作流,选择【交付物部署】,通过各服务对应的镜像仓库,直接进行容器部署。(图3-25) 完成后,在界面上我们可以看到4条工作流,手动运行工作流即可对服务部署更新。(图3-26) 工作流交付 进入项目的工作流页面,点击【执行】,选择环境和服务后启动任务。(图3-27) 在结果界面中,可以查看工作流执行情况以及构建过程中的实时日志。Zadig打包编译都是在自身环境中的 Docker 容器中完成,脱离了对外部物理机环境的依赖,提高环境一致性及交付平台适配性。(图3-28) 工作流运行完毕后,在环境可查看到,服务被部署成功,镜像信息已更新为编译后的TAG。(图3-29) 同时在LENS中,也可以查看到Deployment及Service已被更新成功。(备注:Deployment更新策略通过RollingUpdate进行配置,参考容器服务 Deployment 管理 )(图3-30) 通过Ingress公网IP,访问API Gateway,所有服务已经正常启动。(图3-31) 开发及测试流程完毕后,通过生产环境绑定的镜像仓库,选择Release版本进行【交付物部署】,完成PROD环境服务更新。(备注:一般来讲,在开发测试完毕后,需进行人工审核后,方可进入生产环境部署)(图3-32) 微服务管理 Zadig基于Kubernetes而生,提供了强大的容器服务管理功能,避免来回切换系统,在单个控制面里闭环实现操作。点击具体的服务进入详情页,即可对被托管服务进行更新,如重启实例、切换镜像、调整副本数等。另外,还可以查看服务实时日志、对容器中的服务进行调试。
通过【环境】界面直接对服务进行管理。(图3-33) 通过【环境】界面对容器内部服务进行调试。(图3-35) 同城双活与异地多活部署异同 前述项目以同城双活做为背景实现。对比同城双活共用同一套数据层(或不同数据库逻辑上组成主备),异地多活各环境(SET)采用不同数据层,数据层之间使用双向同步完成数据一致性。(图3-36)下面就异地多活部署模式中接入层、应用层、数据层在Zadig里的方案进行简述:
接入层:和同城双活一致,各环境独立配置不同的CLB Ingress实例 应用层:和同城双活一致,在开发测试过程完毕后,采用【交付物部署】的方式,在不同地域的进行镜像部署。 数据层:在【环境】配置里,ConfigMap及Secret连接字符串和秘钥为各环境独立数据库服务 另外,在不同地域环境下分别配置TCR镜像仓库地址,采用镜像同步的方式提高镜像拉取速度,减少公网流量消耗,参考同实例多地域复制镜像
总结
传统的持续交付方案中,云原生微服务的集成发布,往往需要⼤量的⼈⼒去维护K8S YAML资源,并编写大量脚本完成服务更新。如果涉及多环境部署,如同城双活或异地多活场景,工作量则会直线翻倍,且难以对差异环境的配置进行管理。
Zadig以微服务为中心,Kubernetes为基座,通过环境间复制保证了开发,测试,多生产环境的一致性;将Ingress,ConfigMap,Secret,PVC等资源与环境绑定,简化差异性维护需求;支持以 GitOps 的模式进行资源同步,保证项目与开发同步;支持高并发工作流能力,具备大规模微服务交付能力。
Zadig学习了Argo的特点,整合了 Kubernetes 面向终态的服务交付模式,以流水线方式配置过程,通过 Kubernetes 终态能力保证流水线执行的正确性与幂等性。本身运行在Kubernetes集群中,可以快速以容器环境进行编译,实现了任何基础设施上应用交付与管理的能力。