多环境下的微服务持续交付实践

2022-12-01 18:12:00 浏览数 (1)

项目背景概述

本文通过部署一个基于Dubbo的微服务项目——Q云书城(QCBM)(图1-1),介绍如何在多环境下部署微服务持续交付项目。通过使用Zadig持续部署工具,展示多环境配置、微服务构建、工作流交付及运行时管理的完整过程,提供一种多环境下持续集成、持续交付及云原生微服务管理能力的解决方案。(图1-2)

图1-1 Q云书城图1-1 Q云书城
图1-2 Zadig持续交付图1-2 Zadig持续交付

Q云书城(下同QCBM)是一个基于腾讯云原生产品,使用Dubbo2.7.8框架开发的一个网上书城 Demo 项目,整体架构采用微服务实现。以下为架构各层服务介绍(图1-3):

图1-3 Q云书城架构图图1-3 Q云书城架构图
  1. 接入层使用腾讯云负载均衡 CLB 结合 K8S Ingress 和 Service 实现流量接入和转发,跨区高可用模式部署。
  2. 数据层使用 腾讯云数据库 MYSQL腾讯云数据库 Redis 搭建,保存书城信息,也采用跨区高可用模式部署,提供灾备切换能力。
  3. 应用层使用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)

图2-1 Zadig云原生环境交付图例图2-1 Zadig云原生环境交付图例

Zadig与其他CICD工具相同,项目中也分工作流、构建、测试和版本等模块,但不同的是:

  • 环境模块,在Zadig里是一组服务集合及其配置、运行环境的总称,与 Kubernetes的NameSpace一一对应,环境间具备隔离性。
  • 服务模块,可以理解为一组 Kubernetes 资源,包括 Ingress、Service、Deployment、ConfigMap 等,也可以是一个完整的 Helm Chart或者主机服务

产品优势

  • 面向开发者的云原生环境,提供微服务 容器的集成交付环境。
  • 高并发工作流部署模式,多服务间可并行构建、部署、测试。
  • 分钟级创建或复制完整的隔离的服务,实现资源托管能力,可进行日志查看,调试管理。
  • 对接Jmeter、Pytest等主流测试框架,可跨项目管理UI、API等测试用例。
  • 提供跨项目共享模板库,如K8S YAML、Helm Chart、构建等,实现模板统一管理。
  • 容器环境实现构建过程,确保每次构建环境上下文一致。

使用场景

  • 云原生场景大规模微服务交付,具备统一管理能力。
  • 高频高并发工作流交付,希望具备并行构建部署能力。
  • 多地域环境下微服务部署,如同城双活,异地多活。
  • 快速配置基线-自测测试环境。

同类型产品对比

组件

Zadig

Jenkins

Argo

开源/商业化

开源/商业化

开源

开源

微服务场景支持

高,项目以微服务为中心展开,可通过控制台调整微服务交付时启动顺序

低,通过脚本管理微服务,并自定义Pipeline,通过脚本顺序控制微服务启动顺序

中,仅提供标准K8S资源方式,通过CRD定义微服务启动顺序

产品易用性

高,控制台操作,方便接入各托管平台

中,控制台操作,方便接入各托管平台

低,通过CRD操作

流水线可维护性

高,控制台操作,流水线保存在数据库中

中,需自行管理Jenkinsfile。在云原生部署场景下,还需额外管理Dockerfile及Yaml文件

中,流水线通过CRD定义,需管理CRD YAML文件;大部分场景下,需用户二次开发上层管理平台

集成环境

内置容器环境

需自行配置

K8S整合性

完整,面向K8S实现

需插件支持

完整,面向K8S实现

权限控制

无,可间接通过K8S权限体系控制

产品优势

配置简单,基本无学习成本;产品微服务及云原生整合度高,并具备模板,自测,联调等特色功能

产品成熟,具备众多的插件和成熟脚本

Pipeline中每个步骤都是容器的工作流,可整合进现有YAML管理方式;通过CRD描述,自定义成都高

项目实践

Zadig安装

  • 确保一台连接集群的主机用于执行安装脚本,并已安装Kubectl客户端,目前Zadig支持Kubernetes1.16-1.22版本,以下实践采用TKE 1.18版本实现。
  • 主机上配置环境变量。
代码语言:javascript复制
export IP=<IP> # 主机 IP,用于访问 Zadig 系统
export PORT=<PORT> # 随机填写 30000 - 32767 区间的任一端口
  • 官网下载Zadig 1.13 安装脚本,为方便实验,本文使用快速安装模式,搭建 Zadig on Kubernetes 环境。(备注:生产环境请选用生产模式部署,持久化MySQL及MongoDB数据)
代码语言:javascript复制
# 快速体验:
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)
控制台配置控制台配置
图3-1 Zadig登录界面图3-1 Zadig登录界面
  • 登录后,通过个人界面,配置项目所需的代码仓库及镜像仓库;本次实践采用腾讯云CODING 作为代码仓库(图3-2),并使用腾讯云TCR对持续集成流程中的镜像进行托管(图3-3);通过【系统设置】界面,可以完成以上两个外部系统进行管理。
图3-2 代码源集成图3-2 代码源集成
图3-3 镜像仓库集成图3-3 镜像仓库集成
  • 在【系统设置】中,通过配置集群属性,安装Zadig Agent,完成K8S集群环境托管。安装后的Zadig Agent负责环境读取、应用交付及运行时管理。(图3-4)
代码语言:javascript复制
kubectl apply -f "http://x.x.x.x:30000/api/aslan/cluster/agent/62cd47b98b49327bcb8a1569/agent.yaml?type=deploy"

图3-4 K8S集群集成图3-4 K8S集群集成
  • 成功后,可以在对应集群Zadig NameSpace里找到如下资源
代码语言:javascript复制
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)

图3-5 部署环境示例图3-5 部署环境示例
  • 进入Zadig项目模块,开始配置环境(图3-6)。因项目从零开始配置,所以这里我们选择【K8S YAML项目】,如果是针对现有服务进行托管及应用交付,可选择【K8S 托管项目】,Zadig会自动读取环境中的资源,自动化环境配置过程。(图3-7)
图3-6 新建项目图3-6 新建项目
图3-7 K8S托管项目图3-7 K8S托管项目
  • 新建项目后,点击【跳过向导】,进入项目页面;项目页面顶部菜单中的【工作流】、【环境】、【服务】和【构建】四个模块,为本次实践配置对象。接下来我们先对【环境】进行配置,选择该环境所对应的集群、命名空间、镜像仓库和托管服务。(图3-8)(备注:因软件限制,配置环境前需至少一个服务项已配置,可先在【服务】配置一个PlaceHolder服务,后期删除)
图3-8 环境配置图3-8 环境配置
  • 环境中一个重要配置项是环境配置。我们将Ingress、ConfigMap和Secret配置在这里,由环境内的服务共享(图3-9)。后期也可以在【环境】界面中,对其他资源进行添加(图3-10)。(备注:项目使用腾讯云 CLB Ingress 进行环境负载均衡接入,具体用法可参考 CLB 类型 Ingress
图3-9 在环境中配置Ingress、ConfigMap和Secret图3-9 在环境中配置Ingress、ConfigMap和Secret
图3-10 在环境中添加Ingress、ConfigMap和Secret图3-10 在环境中添加Ingress、ConfigMap和Secret
  • 在【服务】模块中配置的全局环境变量也会在【环境】模块中显示。(备注:建议将环境中的特性开关配置、业务区域配置、全局注入的Annotation、不适合放在服务配置中的敏感信息,都统一放置在【环境】中的全局变量中)
  • 最后是服务列表,将容器镜像选择,配置为【全容器-智能选择镜像】,会优先选择最新的容器镜像,如果在镜像仓库中不存在该容器镜像,则会选择模板中的默认镜像进行填充。(图3-11)
图3-11 在环境中配置服务镜像图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)

图3-12 同步YAML配置文件图3-12 同步YAML配置文件
  • 接下来我们对QCBM中的6个微服务进行配置,并添加构建步骤。(备注:为了演示【环境】模块配置,上一节中新建了一个PlaceHolder服务,配置完正式服务后,PlaceHolder服务可进行删除)
  • 在【服务】模块中,新建服务,并将YAML文件写入对话框,保存。在【环境】模块配置时,我们已经将Ingress、ConfigMap、Secret进行了配置,此处只需添加Deployment及Service。(图3-13)
图3-13 配置服务图3-13 配置服务
  • 点击服务右侧添加构建。默认右侧镜像显示为Yaml模板里的image,完成持续集成后,服务会使用最新镜像进行环境交付。(图3-14)
图3-14 添加构建图3-14 添加构建
  • 在【系统配置】里,修改Maven仓库源为Maven 镜像源加速-腾讯云,优化软件包下载速度。(图3-15)
图3-15 修改Maven仓库源图3-15 修改Maven仓库源
  • 在构建窗口里,选择先前配置的代码仓库,完善代码仓库,默认分支等信息,并填写构建脚本。其中可根据DEV与QA测试目标的不同,选择feature或master分支。(图3-16)
代码语言:javascript复制
#!/bin/bash
set -e

cd qcbm-backend
mvn clean package -DskipTests

cd qcbm-gateway
docker build -t $IMAGE -f Dockerfile .
docker push $IMAGE
图3-16【构建】模块图3-16【构建】模块
  • 因为下载软件包的原因,第一次构建时间一般比较长,可以配置本地工作空间缓存,加速后期构建速度。(图3-17)
图3-17 模块缓存配置图3-17 模块缓存配置
  • 至此,我们已经配置好一个服务。将配置好的服务加入dev环境。注意,因为线上生产环境我们直接采用镜像部署,这里仅将微服务加入dev和qa环境中。(图3-18)
图3-18 将服务加入环境图3-18 将服务加入环境
  • 按照同样的配置,配置其他5个微服务。如Service需公网访问,可以复用同一个CLB。参考容器服务 Service 使用已有 CLB(备注:Ingress及Service不支持复用CLB,不同Service可复用同样的CLB)
  • 完成后,通过上下拖拽服务名,可以调整持续集成后,服务在集群里的启动顺序。(图3-19)
图3-19 更改服务启动顺序图3-19 更改服务启动顺序
  • 在LENS中查看环境对应的集群命名空间,可以看见服务在加入环境后,已经正确启动。(图3-20)
图3-20 LENS界面查看图3-20 LENS界面查看
  • 如果有服务运行不正常,会显示Unstable状态,在【服务】模块中修改对应服务Yaml配置,【服务】模块会进行提示,可直接点击进行服务更新。(图3-21)
图3-21 服务更新图3-21 服务更新

工作流部署

截止现在,项目中已包含6个微服务、4套环境。接下来我们需要对工作流进行配置。

开发及测试环境采用代码拉取并编译的方式进行构建,开发及测试人员可以快速的在环境里进行单元测试(dev分支)及回归测试(master分支),而生产环境的发布,通过已经测试充分的镜像交付物进⾏发布,不需要再经过⼀轮代码拉取,编译打包的工作流程,直接采用镜像部署。

因此,我们一共需要部署4条流水线,DEV和QA环境,采用Zadig的【构建部署】模式交付;PROD环境采用Zadig的【交付物部署】模式交付。(图3-22)

图3-22 工作流流程图图3-22 工作流流程图
  • 进入【工作流】,选择对应环境。(图3-23)
图3-23 新建工作流图3-23 新建工作流
  • DEV及QA工作流,选择【构建部署】,通过各服务对应的构建配置,进行代码拉取,编译打包,推送镜像仓库,最近进行容器部署。(图3-24)
图3-24 构建部署图3-24 构建部署
  • PROD工作流,选择【交付物部署】,通过各服务对应的镜像仓库,直接进行容器部署。(图3-25)
图3-25 交付物部署图3-25 交付物部署
  • 完成后,在界面上我们可以看到4条工作流,手动运行工作流即可对服务部署更新。(图3-26)
图3-26 项目工作流图3-26 项目工作流

工作流交付

  • 进入项目的工作流页面,点击【执行】,选择环境和服务后启动任务。(图3-27)
图3-27 工作流执行图3-27 工作流执行
  • 在结果界面中,可以查看工作流执行情况以及构建过程中的实时日志。Zadig打包编译都是在自身环境中的 Docker 容器中完成,脱离了对外部物理机环境的依赖,提高环境一致性及交付平台适配性。(图3-28)
图3-28 构建实时日志图3-28 构建实时日志
  • 工作流运行完毕后,在环境可查看到,服务被部署成功,镜像信息已更新为编译后的TAG。(图3-29)
图3-29 环境中镜像信息图3-29 环境中镜像信息
  • 同时在LENS中,也可以查看到Deployment及Service已被更新成功。(备注:Deployment更新策略通过RollingUpdate进行配置,参考容器服务 Deployment 管理)(图3-30)
图3-30 LENS中Deployment信息图3-30 LENS中Deployment信息
  • 通过Ingress公网IP,访问API Gateway,所有服务已经正常启动。(图3-31)
图3-31 API Gateway探活接口图3-31 API Gateway探活接口
  • 开发及测试流程完毕后,通过生产环境绑定的镜像仓库,选择Release版本进行【交付物部署】,完成PROD环境服务更新。(备注:一般来讲,在开发测试完毕后,需进行人工审核后,方可进入生产环境部署)(图3-32)
图3-32 生产环境部署图3-32 生产环境部署

微服务管理

Zadig基于Kubernetes而生,提供了强大的容器服务管理功能,避免来回切换系统,在单个控制面里闭环实现操作。点击具体的服务进入详情页,即可对被托管服务进行更新,如重启实例、切换镜像、调整副本数等。另外,还可以查看服务实时日志、对容器中的服务进行调试。

  • 通过【环境】界面直接对服务进行管理。(图3-33)
图3-33 服务管理图3-33 服务管理
  • 通过【环境】界面查看容器内部日志。(图3-34)
图3-34 日志查看图3-34 日志查看
  • 通过【环境】界面对容器内部服务进行调试。(图3-35)
图3-35 服务调试图3-35 服务调试

同城双活与异地多活部署异同

前述项目以同城双活做为背景实现。对比同城双活共用同一套数据层(或不同数据库逻辑上组成主备),异地多活各环境(SET)采用不同数据层,数据层之间使用双向同步完成数据一致性。(图3-36)下面就异地多活部署模式中接入层、应用层、数据层在Zadig里的方案进行简述:

  • 接入层:和同城双活一致,各环境独立配置不同的CLB Ingress实例
  • 应用层:和同城双活一致,在开发测试过程完毕后,采用【交付物部署】的方式,在不同地域的进行镜像部署。
  • 数据层:在【环境】配置里,ConfigMap及Secret连接字符串和秘钥为各环境独立数据库服务

另外,在不同地域环境下分别配置TCR镜像仓库地址,采用镜像同步的方式提高镜像拉取速度,减少公网流量消耗,参考同实例多地域复制镜像

图3-36 同城双活与异地多活架构对比图3-36 同城双活与异地多活架构对比

总结

传统的持续交付方案中,云原生微服务的集成发布,往往需要⼤量的⼈⼒去维护K8S YAML资源,并编写大量脚本完成服务更新。如果涉及多环境部署,如同城双活或异地多活场景,工作量则会直线翻倍,且难以对差异环境的配置进行管理。

Zadig以微服务为中心,Kubernetes为基座,通过环境间复制保证了开发,测试,多生产环境的一致性;将Ingress,ConfigMap,Secret,PVC等资源与环境绑定,简化差异性维护需求;支持以 GitOps 的模式进行资源同步,保证项目与开发同步;支持高并发工作流能力,具备大规模微服务交付能力。

Zadig学习了Argo的特点,整合了 Kubernetes 面向终态的服务交付模式,以流水线方式配置过程,通过 Kubernetes 终态能力保证流水线执行的正确性与幂等性。本身运行在Kubernetes集群中,可以快速以容器环境进行编译,实现了任何基础设施上应用交付与管理的能力。

0 人点赞