一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用

前言

现代软件工程越来越复杂,而开发效率随着软件复杂度增加呈指数型下降。为在提高开发效率的同时也能保证质量,越来越多团队开始践行敏捷开发方法。

持续集成是敏捷开发的重要实践之一。它倡导团队通过自动化构建工具频繁地验证软件可用性,从而尽早发现集成错误并集中精力改善软件质量。

本文将使用 CODING DevOps 工具链和腾讯云容器服务(下称 TKE)为 Ruby + Sinatra 应用项目配置持续集成过程:运行单元测试、构建 Docker 镜像、推送到制品库、部署到 K8s 集群,以实现自动化构建、测试、发布、部署。

项目仓库地址:https://coding-public.coding.net/p/ruby-sinatra/d/ruby-sinatra.git

可以看到这个 Web 应用项目的结构非常简单。然而随着项目规模的逐步增大、参与人员的不断增加,构建、测试、发布过程变得越来越复杂。单靠开发人员在本地机器上人工手动进行集成变得愈发困难,既消耗时间也分散精力,团队的协作效率越来越低。而借助持续集成,则可以自动化构建、测试、发布的过程,将开发人员从重复的人力劳动中解放出来,更专注于开发且更快地发现和解决问题。

在继续下面的步骤前,请确保在 CODING 项目中开启了“持续集成”和“制品库”功能。
一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用
一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用

创建制品库

如今容器化部署已经是大势所趋,无论是伸缩性还稳定性都相较于传统的裸机部署提升不少。本文的应用也选择了容器化部署。容器化部署最后的发布产物则是容器镜像,故需要创建用于存放发布产物的 Docker 制品库。
一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用

设置制品库凭证

K8s 集群从制品库拖取镜像需要访问凭证,这里使用 CODING 制品库自动生成的访问令牌。这里要注意的是,访问令牌生成后需要立即复制下来,否则关闭访问令牌的窗口后将无法再次查看。
一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用
一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用
生成访问令牌后会得到一条 Docker 仓库的登录命令,例如:

docker login -u release-1587202817568 -p 2f4f129287b3319c52f760635fxxxxxxxxxxxxxx coding-public-docker.pkg.coding.net

其中提供了 3 部分信息:

  • 仓库域名:coding-public-docker.pkg.coding.net
  • 用户名:release-1587202817568
  • 密码:2f4f129287b3319c52f760635fxxxxxxxxxxxxxx

在 TKE 的集群中创建 Secret,输入上面获得的仓库访问凭证。
一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用
一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用

设置集群凭据

要通过 CODING 持续集成触发 K8s 集群部署过程需要在 CODING 中录入集群凭据,以便在 CODING 持续集成中使用 kubectl 命令实现 K8s 集群控制。

在 TKE 控制台中找到“集群APIServer信息”,复制其中的“Kubeconfig”。
一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用

在 CODING 的凭据管理中录入 Kubeconfig。
一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用
一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用
一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用

创建部署

为方便将应用部署 K8s 集群中,需要先创建 Deployment 工作负载,之后就可以通过 CODING 持续集成反复运行 kubectl deployment patch ... 命令来将新构建出来的应用镜像部署到 K8s 集群上。

由于现在还没有构建本文中 Ruby + Sinatra 应用的 Docker 镜像,这里选用 nginx r 镜像来代替,确保 Deployment 能正常跑起来。
一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用
一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用

创建构建计划

这里选择预置内容较少的“自定义构建过程”模板,之后在这个模板的基础做详细的配置。
一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用
一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用

回到“凭据管理”中编辑刚录入的 K8s 凭据,在“凭据授权”列表里勾选刚创建的构建计划并保存。
一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用
一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用

配置构建流程

这里把 Ruby + Sinatra 应用持续集成过程分成 6 个阶段:

  1. 开始
  2. 检出
  3. 运行单元测试
  4. 构建 Docker 镜像
  5. 推送到制品库
  6. 部署到 K8s 集群

从模板创建的构建计划已经包含了“开始”和“检出” 2 个阶段。其中“检出”阶段可以不用修改直接使用。

一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用

下面对其他阶段进行完善。

“开始”阶段

此阶段是默认生成的,所有模板都会包含这个阶段。在这个阶段中可以设置一些全局使用的参数,如“构建基础环境”、“环境变量”等。在这里需要添加 3 个环境变量,它们会被后面阶段引用。

一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用

  • CODING_DOCKER_REG_HOST:制品库主机,用于登录制品库。
  • DOCKER_IMAGE_NAME:Docker 镜像名称,用于构建和推送镜像。
  • TKE_CLUSTER_CREDENTIAL_ID:TKE 集群凭据 ID。

上述环境变量的值是根据上面创建的 Docker 制品库来设置的,可以在制品库指引中查看相关信息。注意,页面上的 Docker 镜像名称不完整,需要把 <PACKAGE> 替换成实际的值,如果值为 ruby-sinatra,则镜像名称就是 coding-public-docker.pkg.coding.net/ruby-sinatra/release/ruby-sinatra
一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用
而 TKE 的集群凭据 ID 则可以在凭据管理中查看。

一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用

“运行单元测试”阶段

在这个阶段里,将运行代码中已经写好的单元测试代码。整个过程会在 Docker 容器中进行,这样可以节省准备运行环境的时间,也可以与后面构建 Docker 镜像时使用的基础环境保持一致。

首先给对模板创建出来的“3-1 自定义构建过程”删除掉,然后添加名为“运行单元测试”的阶段,之后在这个阶段里添加“执行 Pipeline 脚本”的步骤,并在右边的输入框中输入运行单元测试的脚本。这里使用 Jenkins Pipeline 来调用 docker run 命令来运行单元测试。

docker.image('ruby:2.6').withRun('-v $(pwd):/app -w /app') { c ->
    sh 'bundle install'
    sh 'rake test'
}

一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用

“构建 Docker 镜像”阶段

接下来是配置 Docker 镜像的构建过程,同上一步类似,添加名为“构建 Docker 镜像”的阶段,在阶段里添加“执行 Pipeline 脚本”的步骤,在脚本输入框中输入脚本。这里使用了 Jenkins Pipeline 来构建 Docker 镜像。

docker.build("${env.DOCKER_IMAGE_NAME}:${env.GIT_BUILD_REF}")

一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用

其中的镜像名称使用了 1-1 阶段设置的环境变量。而标签则使用内置的环境变量 GIT_BUILD_REF,其值对应“构建对应的 Git 修订版本号”。内置环境变量的具体说明请见 https://help.coding.net/docs/devops/ci/env.html

“推送到制品库”阶段

这是构建过程的最后一个阶段,和上一个阶段类似,添加名为“推送到制品库”的阶段,在阶段里添加“执行 Pipeline 脚本”的步骤,在脚本输入框中输入脚本。这里使用了 Jenkins Pipeline 来推送镜像到制品库。

docker.withRegistry("https://${env.CODING_DOCKER_REG_HOST}", "${env.CODING_ARTIFACTS_CREDENTIALS_ID}") {
    docker.image("${env.DOCKER_IMAGE_NAME}:${env.GIT_BUILD_REF}").push()
}

一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用

脚本中用到了在 1-1 阶段定义的环境变量:CODING_DOCKER_REG_HOSTDOCKER_IMAGE_NAME。还有两个内置环境变量:CODING_ARTIFACTS_CREDENTIALS_IDGIT_BUILD_REF。其中 CODING_ARTIFACTS_CREDENTIALS_ID 为制品库私钥凭据,用于登录制品库。

“部署到 K8s 集群”

这是构建过程的最后一个阶段,和上一个阶段类似,添加名为“部署到 K8s 集群”的阶段,在阶段里添加“执行 Pipeline 脚本”的步骤,在脚本输入框中输入脚本。这里同样使用了 Jenkins Pipeline 来调用 docker push 命令来运行单元测试。

withKubeConfig([credentialsId: "${env.TKE_CLUSTER_CREDENTIAL_ID}"]) {
    sh "kubectl patch deployment ruby-sinatra --patch '{\"spec\": {\"template\": {\"spec\": {\"containers\": [{\"name\": \"ruby-sinatra\", \"image\": \"${env.DOCKER_IMAGE_NAME}:${env.GIT_BUILD_REF}\"}], \"imagePullSecrets\": [{\"name\": \"ruby-sinatra-reg\"}]}}}}'"
}

一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用

脚本中用到了在 1-1 阶段定义的环境变量:TKE_CLUSTER_CREDENTIAL_ID

配置完成后别忘了保存!
一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用
这是完成后的完整流程。
一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用
此时,已经可以通过“立即构建”来手动触发持续集成过程了。

一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用
一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用
整个流程运行完成后,可以查看每一步的运行日志。

一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用
一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用

配置触发规则

CODING 持续集成提供了多种触发规则,如果默认配置无法满足需求,还可自行配置所需的规则。
一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用

查看构建产物

构建计划运行成功后,可以到 CODING 制品库查看持续集成的构建产物。
一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用

查看部署结果

构建计划运行成功后,可以到 TKE 控制台查看 Deployment 的部署状态。
一分钟开始持续集成之旅系列之:Ruby + Sinatra 应用
简单的、自动化的部署可以用本文的方法来配置一个自动化的部署阶段。对于体系化、需要考虑回退、负载流量控制、发布时间窗口、更新策略等则可以使用 CODING 持续部署。

上一篇:[计算机视觉论文速递] 2018-03-18


下一篇:对不同文件类型应用fencs来绕过utf8编码问题