大家好, 今天我将分享通联数据使用 Docker 和 Rancher 构建自动化发布管道的经验, 我会介绍通联数据自动化发布的流程及方案设计, 我们从踩过的一些坑中总结出来的经验, 以及我们的自动化发布管道的系统运行现状
一通联数据的需求及选择 Rancher 的原因
通联数据是一家这几年新崛起的金融科技公司, 主要目标是致力于将大数据云计算人工智能等技术和专业投资理念相结合, 打造国际一流的具有革命性意义的金融服务平台这里面涉及到几个关键词: 大数据云计算人工智能, 这些热词已经有很多企业提及过, 因此我也不赘述了
通联数据作为一家创业公司, 也会遇到很多创业公司都会遇到的问题, 比如产品太多, 而且每年很多产品都会推翻重来, 就会遇到各种各样的问题比如, 应用在开发时, 涉及到需要多少 CPU 需要用什么语言去编程等问题, 开发人员不会与后台人员事先沟通, 出来一个产品, 直接让运维人员上线
基于这样一个背景, 我们迫切需要打通上线这条管道, 因为在可预见的将来, 通联数据每年将会有大量的新应用出现, 如何打通上线这条管道亟待解决
我们做的第一件事, 就是做持续集成由于我们公司每年会有上百个新的项目产生, 每个项目的语言框架部署方法都不尽相同, 发布流程也是比较冗长低效的, 部署应用占用了运维人员大量时间
我们决定用容器解决这个问题, 评估了多家供应商后选择了 Rancher, 主要原因在于:
首先, Rancher 的操作界面非常简单, 相信用过 Rancher 的人都会有这种感受, 它不需要太多专业的知识, 很容易上手; 其次, Rancher 在部署时也非常简单, 可以一键式部署, Rancher 还提供了良好的 API 支持, 方便集成
二自动化发布的流程
随后, 我们开始搭建自己的 CI/CD 当时我们在流程方面遇到了很多困境, 下图已经是简化制作后的了, 实际上还有更多各种各样的分杈和分枝:
就我们原来的流程来说, 流程最开始的部分是研发; 随后进入 QA 环境部署, 这时候就需要人去部署, 通常是运维人员, 但是运维一般不愿意做这个事情; 部署完成后, 进入 QA 环境测试阶段, 通知开发和测试人员进行测试, 过程中可能会出现延迟, 因为测试人员可能正忙于其它的事情, 不能马上进行测试; QA 环境测试通过后, 进入 STG 环境部署; 随后再进行 STG 环境测试, 这几个过程可能会循环很多次跟着进入安全测试阶段; 测试通过后, 还有一个正式包的一个准备过程, 最后才能上生产部署即使是这个简化后的流程也是非常复杂的, 而且其中涉及到很多线下的沟通, 效率不可能高得起来
在使用 Rancher 之后, 原本的流程大大简化了, 改进后的简化流程如下图:
流程的第一步即持续集成, 意味着开发人员写好代码后可以直接通过 CI,CI 触发自动编译, 随后自动部署脚本, 测试环境已经就绪简单来说, 每次开发人员提交代码之后, 测试环境就始终处一个就绪的状态, 这时候就可以直接进入测试阶段, 整个过程都处于线下, 不需要走任何流程, 全部实现自动化了
测试人员完成测试后, 再进行 STG 环境测试, 因为后台已经跟 Rancher 完成对接并实现自动化, 这赋予了 QA 环境测试从未有过的强大的自动化能力, 意味着 QA 环境测试可以自动对接到 STG 环境测试测试通过后, 进入安全测试阶段, 这个阶段是公司要求的, 无法避免, 安全测试通过后就进入到生产部署以前绕不开的线下沟通那些步骤和一些部署就可以省去了, 整个流程优化并且简洁, 效率也提升了
CI/CD 说起来可能很简单, 比如 PUSH 代码 QA 环境自动就绪但是实际操作起来并非如此, 仍然存在很多需要解决的问题比如开发的分支模型就涉及到在开发代码的时, 要 PUSH 什么分支才能部署, 还是 PUSH 所有的分支都能部署?
三开发分支模型
当时我们想到最好就是 PUSH 任意分支都能部署, 这样就非常方便但随后就发现这方法行不通, 会造成混乱, 而且难以管理此前我们 Git 的一个 The Successful Branch Modeling 分支模型就类似于此, 此模型规定了一个 develop 分支一个 feature 类型的分支一个 release 类型的分支一个 hotfixes 类型的分支和一个 master 分支
在平时开发时, 开发人员常常会在 develop 分支上切出一个 feature 的分支, 比如, 开发一个包含很多功能的 story, 那么所有人切一个 story, 这边 story 有自己的 ID, 然后再去开发, 把 story 开发完之后, 再把它 merge 过来最终, 我们只选择了一条线做 CI, 当代码 PUSH 或者合并到 develop 分支时, 我们帮你去做这个, 而在这个 feature 分支的时候, 我们另作处理
feature 分支意味着当用户提交一个 feature 分支之后, 我们会另外帮你部署一套, 每一个 feature 分支部署一套, 相当于每一个 story 都可以分开独立去测试, 最后把它合并到 develop 分支那么测试的时候, 测试可以根据自己的需求来决定它到底在哪一条分支线上去测试
比如, A 测试中如果用户只关心 story A, 那就在 story A 这个分支测试环境去测, 这些 story 全部合并进来之后, 再进行一次集中测试, 测试通过后, 在发布时把这个分支切到 release 的一个分支上来, 然后, 在 release 上发布正式包, 让 QA 在 STG 环境继续进行测试, 就如前面看的那个流程图分支模型非常混乱, 为了做 CI, 我们会跟开发人员定义好每一条分支, 每个分支对应的每个不同行为也定义好, 这在混乱的分支模型下非常有用
四版本号规则
为了做 CI, 版本号的规则必须一致, 如果每个团队版本号命名不一样的话, 匹配规则就会非常麻烦和混乱后来, 我们选择了 Semantic Versioning 的一个版本号的规则, 就是几点几点 X, 这是一种常见的版本号命名方法, 此版本号包含标准的一个文档, 文档描述了此版本号的具体定义, 第一个叫 MAJOR, 第二个叫 MINOR, 第三个叫 PATCH, 后面还可以加各种自己的版本号
五 CI 触发路径
下面我将介绍我们的 CI 的触发路径 Git push,push 到 develop 分支, Git push 就会 push 到 Gitlab 的 server 上, 随后通过 webhook 去调用 Jenkins,Jenkins 会把这个包 bulid 出来原本我们是想通过 Jenkins 调用 Rancher 的 API, 后来发现直接调用 Rancher 有差距, 过程进行的也不那么顺利, 为了解决 Jenkins 和 Rancher 之间的 gap 这一问题, 我们在它们之间装了一个 Ponyes 的软件
为什么需要 Ponyes 这一中间层? 它到底提供了哪些价值?
(1)动态修改版本号
首先, 它可以解决动态修改版本号的问题, 大家用 Rancher 的时候, 发现 Rancher 的商店非常好用, 我们可以在商店里把一些东西定义好, 接着 QA 只要填几个参数, 就可以把一个应用部署起来了, 没有 Ponyes 这一中间层之前, 必须找运维人员去做, 过程也比较复杂
为了用起来 Rancher 应用商店, 我们还定义了一个应用商店的模板, 这样我们就可以在每次 PUSH 代码的时候, 把这个模板生成一个真正可以部署的应用但是, 版本号还是存在一些问题, 我们每次 PUSH 代码的时候, 到 Jenkins, 我们会根据阅览数给 Jenkins 升级一次版本号, 比如说 1.0.1.0-1, 第一次阅览是 - 1, 第二次阅览即 - 2,Jenkins 的版本号根据阅览次数相应变化这时候应用商店也要随之而变
因此, 我们做了这样一个模板, 通过这样一种方式, 在 Ponyes 中, 每个 Jenkins 可以获得对应的版本号, 然后把这个版本号通过变量把它注入进去:
- sample:
- image: {{ REGISTRY }}/automation/auto-sample:{{ m[auto-sample]}}
这一过程还涉及到 registry, 因为 QA 环境和 STG 环境是完全分开的, 在进行模板渲染时, 我们需要知道到底是发到 QA 环境还是 STG 环境, 从而对 registry 的地址做出相应改变, 这样的话, 上面说的修改版本号的问题就解决了
(2)多 service 管理
还有一个比较棘手的问题, 即一个 stack 中有多个服务怎么办? 比如, 一个比较小的团队可能总共就几个人, 每个人负责好几个项目, 与微服务的关系有些相似, 那么一个 stack 可能有好几个服务, 最典型的就是前端后端, 或者是其他的一些中间件, 每一项是一个服务
开始部署时, Rancher 里面的这些服务也要用一个 stack 来管理, 有多个服务就会面临怎样管理的问题比如, 一个 stack 有 ABC 三个服务, 服务 C 更新时, 整个 stack 也应该更新版本号, 因为在 Rancher 里面, stack 被部署出来之后, 有个 update available 的黄色按钮, 如果有新版本, 点这个按钮, 就可以升级这个 stack, 而且必须升级整个 stack, 而不是只升级某个服务, 这时候就需要管理多个服务 Ponyes 记录了服务和 stack 之间的关系, 任意一个服务更新, 也会触发 stack 的更新, 更新的方法就是每个服务每次更新, stack 的版本号 + 1
(3)多版本并行发布
接下来还有一个更严重的问题, 如果多版本并行发布, 我们应该怎么去处理? 比如说我们 ABC 三个模块, A 发布过 1.0 和 2.0,B 发布过 3.04.0,C 发布过 5.0 和 6.0 如果发布一个 C 应用的 5.0.2, 那么对应的 AB 模块号应该选什么, 这个问题困扰了我们很久
有好几种方法可以解决, 比如用某个东西记录 C5.0 和 AB 的一个版本号之间的关系, 这表示用户可以自定义但也存在一个问题, 用户需要自己去管理它们之间的版本号关系, 时间长了, 可能会弄乱或弄错版本号, 或者弄错版本号之间的关系, 随后上线到生产环境, 后果更严重
还有一种方法, 就是将用户的 C 版本号最后一次发布到 5.0 时 AB 是什么版本静态地记录下来但这样的话系统会变得相当复杂, 很容易出错
最后, 我们选择去除多版本并行发布的能力, 只支持单个版本的发布, 意味着如果要发布, 必须是最新版本, 历史版本可以用另外的方法进行人工处理, 这样的话, 系统会更简单, 而且不容易出错, 也不需要用户去维护一个版本号之间的关系以上这些功能都是借助我们自己写的 Ponyes 解决的
Rancher 2.0 也提到了 CI/CD 这样一个功能, 在实际过程中, 会遇到一个非常现实的问题, 从代码研发到整个生产环境部署有许多环节, 具体情况也非常复杂, 而 CI 的作用可能仅止于 QA, 后面的环节还会有新的难题, 这时就需要一个体系把整个生命周期贯穿起来管理, Rancher 承担的作用就在于此
六肉身踩坑总结的三条经验
(1)部署几套 Rancher 环境?
这问题看似很小, 最初也在我们内部也引发过不少讨论最初我们只部署了一套 Rancher, 在 Rancher 里面用环境去区分 QA 或 production 部署一套 Rancher 的方式最简单, 但是有一个严重的问题: Rancher 升级了怎么办? 这套 Rancher 既管了 QA, 又管了 production, 升级的时候需要把生产环境也升级, 此刻如果出现 bug, 问题将非常严重
后来我们把它拆成四套, Rancher 平台本身也得有一个升级的环境建议大家在前期部署 Rancher 的时候要部署多套环境(至少两套), 我们实际上是 devQAstagingproduction 每个环境都有一套, 总共四套
(2)配置项爆炸
第二个问题是关于配置项我们最开始是使用 Rancher compose 的, 它非常简单强大, 我们在 Rancher Catalog 里点一下部署, 配置选项全弹出来, 我们只需要点选一些东西, 就可以部署一个很复杂的应用后来我们却发现, 应用的配置项越来越多 (甚至多达上百个) 这导致它们难以在一个页面里展现, 同时上百项的配置让我们无从填写, 运维也无法成功部署, 我们从而面临了配置项爆炸的问题
我们的解决经验是, 在容器平台里面, 配置项一定要集中管理我们把配置项全部用 consul 管理, 每次容器启动时到 consul 里把配置拉到对应的容器里来如此一来, 容器可以在任意平台漂移另外配置项本身在原 server 存有副本, 我们 copy 原配置项加以修改, 就可以部署另一个实例了所以说, 配置项一定要全部集中管理起来
(3)泛域名 + Rancher LB
我们每一个业务都有一个 web 服务, 要申请自己的域名每年我们有上百个项目上线, 这意味着有上百个域名要申请加上这些域名都分别需要在开发测试生产环境中使用, 所以我们每年要申请将近五百个域名这是一件恐怖的事情
后来我们就用了泛域名的方法比如用. sub.example.com 的域名, 直接 CNM 到 Rancher 环境中的其中一台主机然后在 Rancher 上设置它的 LB,LB 就可以分布在所有的主机上, 每个主机上都会有同样的 LB 这个域名任意指向一台主机, 它都可以工作
比如说, 在 QA 环境, 这个 LB 上 serve 了如下这些域名, 若主机坏掉了, 容器本身会启动, 入口问题则可以很简单地通过修改量来搞定如果是生产环境则可以在上面再加层 nginx, 配三个 upstream, 死掉任意一台, 还可以通过另外两个入口进来
使用泛域名的方法, 在配置好泛域名之后, 在 Rancher LB 上再加任意域名都不用再去申请新的域名, 而是可以直接写 123.sub.example.com, 然后直接在 LB 上配置, 配完之后域名即可用, 无须再走申请的流程了
来源: http://www.bubuko.com/infodetail-2494800.html