部署 请问大家的 CI/CD 方案 (测试 / 部署方案) 使用的是什么流程?Docker+Drone+Swarm?

1c7 · 2019年01月24日 · 最后由 huobazi 回复于 2020年08月04日 · 9101 次阅读

之前的经历

之前用 Rails 做小项目就直接 Rails (puma) + Nginx 扔到服务器上
(是的,安装依赖花了 10-20 分钟)
没有用 Docker/Heroku 或任何其他方便部署的东西。

(非广告)

没怎么写测试(RSpec/单元测试)。
而 0 downtime 要么靠 puma 的 phashed_restart 要么 nginx 的 load balancer。
日志和监控什么的也没有太在意。

这一段的重点是:现有的流程不但原始(只适合小项目),而且也不够方便。这个流程需要改进。

遇到了什么问题

最近在忙的项目,用户逐渐变多,不再是小项目了,在往中小型项目发展。
技术栈:Ruby on Rails 做 JSON API 后端,微信小程序作为前端。(不方便给具体信息,不贴小程序码了,见谅)

一方面希望方便 scale
另一方面希望工作流能方便一些。git push 之后自动部署,或者,在最后一步手动点按钮触发部署。

这一段的重点是:改进流程迫在眉睫,不能再推了

调查后的结果

  • 为了解决环境不一致,以及部署很麻烦需要手动安装软件的问题:Docker
  • 为了方便 Scale:Docker Swarm / Kubenetes
  • 为了 CI/CD:Gitlab CI / Travis CI / Circle CI / Drone.io / 等等

目前在尝试的流程(Workflow)

Gitlab -> Drone.io -> Docker swarm

  • Gitlab 纯粹代码托管,不用它的 CI 功能
  • Drone.io 负责 CI/CD。(说明:Drone.io 需要部署到自己的服务器上。在和 Gitlab 配置之后,Gitlab 会有 web hook 即时告知 Drone.io)
  • Docker swarm 负责部署。看了一些资料说 Kubenetes 学习曲线较为陡峭,实际试过了也发现的确是的,时间不够,不能折腾 Kubenetes 了,先 Swarm 也够了。

问题

大家都是用什么 CI/CD 流程?

从 git push 到代码 live,总共要多久?1/3/5 分钟?

发这个帖之前,在社区里搜了一下。 相关讨论不是很多,就几篇帖子

Gitlab CI + bash 脚本 + vm 虚拟机

Jenkins 现在也支持脚本配置和 docker

对 WoolenWang 回复

Gitlab CI 纯粹做测试。测完了发个 http 请求触发 bash 脚本进行部署? vm 虚拟机啥意思?就是云服务商提供的裸机是吧?没用 docker。 感谢回复

对 nouse 回复

嗯这样,谢谢

我们用的 CI 工具是 GitLab 和它的 CI, 部署用的是 Docker Swarm.

选用 GitLab CI 的想法是和 GitLab 紧密整合:把最终部署的步骤写成一个 CI job, 在项目的 Pipeline 界面手动触发这个 job 就可以部署。不用开发者学用一个新的软件界面。

部署耗时:目前我们放宽了 CI 的流程限制,合并进主干的代码不用等测试跑通,就会先构建 Docker Image. 构建好了之后就可以部署。

  • 构建 Docker Image 的过程是有 Docker 的分层缓存的。最近一次构建的时间是 16 秒.
    • 一个可以更好地利用 Docker 分层缓存的技巧是:在社区里搜了一下发现已经有人写好帖子了:https://ruby-china.org/topics/30078
    • 初次构建没有缓存,还是会慢一些。这可以通过从国内镜像安装依赖来解决。
  • 部署新版本:SSH 到一个 Docker Swarm Manager 节点,在上面运行 docker service update. 因为要滚动更新,还要下载镜像,这个时间稍微长一点。最近一次要 66 秒。未来应该还有提升空间。
对 5long 回复

赞,我也是打算这样做。Gitlab + Swarm。

Drone.io 我在发帖之后又继续试了。觉得构建镜像和推送镜像到 Docker hub 的部分挺简单的。

但是复制 docker-compose.yml 到服务器以及 ssh 进行 Swarm 的更新非常麻烦。 Drone.io 的官方文档又非常精简,没啥有用的内容。

appleboy/scp 和 applyboy/ssh 的文档试了又不行。Drone 插件不算多。 基本每一个插件点进去的顶部都是一个红框说这是 0.8 版本的语法。blahblah。

简言之就是因为文档劝退我了。 说这一堆希望对以后查阅到这篇帖子的人有用。

对 5long 回复

所以更新一次最快速度是:16 秒构建 + push image20 秒 -40 秒 + docker service update 1 分钟左右。
大概 2 分钟就可以全自动更新一版了。
话说有 rollback 的应急方案吗?还是说干脆代码回滚再 push。而不是用什么回滚机制。
感谢详尽的回复

对 1c7 回复

push image 没有那么慢。因为我们用的私有 Docker Registry 和 CI / 生产环境服务器都在同一个内网网络 (某公有云平台), 再加上合适的 Docker 分层缓存,如果没有依赖更新,每次 push 的量也就只有仓库里的几 MB 的代码量。16 秒的时间已经包含 push 在内了。

不过如果你真的要计量精确的部署时间,还得把 GitLab CI Job 的运行前的延迟加上。Job 在触发运行之后,会有几秒钟的时间停在"job 正在等待被某个 runner 认领执行"的状态。

rollback 我们没有专门的方案。如果需要部署到旧版本,可以 SSH 到 Docker Swarm Manager 上手动执行 docker service rollback. 也可以直接在 GitLab 的界面上找一个旧版本,再点一次部署。因为应用服务器上的旧版本镜像还在,不需要重新下载,这样部署的时间会更短一些。而且这样做,不需要担心引入了回滚操作而制造更多的语义。比如:不用担心"回滚的回滚"应该是什么意义。就不会造成误解 / 记错。

对 5long 回复

嗯原来这样。感谢。 过阵子等我学习(发音:踩坑)完 Docker, Docker Swarm, 实践用在项目里了, 写几篇博客分享一下~ 等 Swarm 稳了说不定再弄 k8s

Gitlab -> Gitlab-runner -> Swarm

不过我觉得 Rails 项目少量更新代码没必要 redeploy,于是直接找了个小工具 docker_swarm_helpers 去做热重启,我只能说——灰快。需要重新打镜像的时候,通过打 tag 去触发重新部署的流程

另外关于 Swarm 的管理,推荐 Portainer,至少不用再纠结 docker-compose.yml 文件放哪儿了 😂

对 IChou 回复

学习了~

我现在用 GitHub Actions 来构建 docker 镜像😂

对 chunlea 回复

没听过这种操作…… 我得去查查

rancher, rancher , rancher

对 ForrestDouble 回复

听过但是还没接触。谢重要的事情说 3 遍。

对 lidashuang 回复

求 example .gitlab-ci.yml

贴一下我的 GitHub Actions workflow。

workflow "Build Docker for master branch" {
  on = "push"
  resolves = [
    "Push Frontend Image to Tencent Cloud",
    "Push Backend Image to Tencent Cloud",
  ]
}

action "Filters for GitHub Actions" {
  uses = "actions/bin/filter@b2bea0749eed6beb495a8fa194c071847af60ea1"
  args = "branch master"
}

action "Docker Registry" {
  uses = "actions/docker/login@c08a5fc9e0286844156fefff2c141072048141f6"
  needs = ["Filters for GitHub Actions"]
  secrets = [
    "DOCKER_USERNAME",
    "DOCKER_PASSWORD",
  ]
  env = {
    DOCKER_REGISTRY_URL = "ccr.ccs.tencentyun.com"
  }
}

action "Build Frontend Image" {
  uses = "actions/docker/cli@c08a5fc9e0286844156fefff2c141072048141f6"
  needs = ["Docker Registry"]
  args = "build -t frontend frontend"
}

action "Build Backend Image" {
  uses = "actions/docker/cli@c08a5fc9e0286844156fefff2c141072048141f6"
  needs = ["Docker Registry"]
  args = "build -t backend backend"
}

action "Tag Frontend Image" {
  uses = "actions/docker/tag@c08a5fc9e0286844156fefff2c141072048141f6"
  args = "frontend ccr.ccs.tencentyun.com/xxx/xxx-frontend"
  needs = [
    "Build Frontend Image",
    "Build Backend Image",
  ]
}

action "Tag Backend Image" {
  uses = "actions/docker/tag@c08a5fc9e0286844156fefff2c141072048141f6"
  args = "backend ccr.ccs.tencentyun.com/xxx/xxx-backend"
  needs = ["Tag Frontend Image"]
}

action "Push Frontend Image to Tencent Cloud" {
  uses = "actions/docker/cli@c08a5fc9e0286844156fefff2c141072048141f6"
  args = "push ccr.ccs.tencentyun.com/xxx/xxx-frontend"
  needs = ["Tag Backend Image"]
}

action "Push Backend Image to Tencent Cloud" {
  uses = "actions/docker/cli@c08a5fc9e0286844156fefff2c141072048141f6"
  args = "push ccr.ccs.tencentyun.com/xxx/xxx-backend"
  needs = ["Tag Backend Image"]
}

可以参考我写的这篇文章:

https://mp.weixin.qq.com/s?__biz=Mzg4MzAzMDE5Nw==&mid=2247483692&idx=1&sn=73b776c3c7f41838ad6fa0d35c36b7ca&chksm=cf4ce0f6f83b69e012439ee61a0145ed6a8e890443daed51236dc9e7c3ea4942606041b28a40&token=1885576722&lang=zh_CN#rd

好赞的讨论帖 👍

需要 登录 后方可回复, 如果你还没有账号请 注册新账号