Azure Devops

去年写过一篇文章,Jenkins + Docker 构建自己的自动化部署。自动化部署虽好,但是Jenkins的服务器资源占用不低,甚至一度超过了我所有项目的总和,为了节省服务器开支,我便开始搜寻市面上的CI/DI服务提供商,最终选择了微软的Azure Devops

价格

这里主要介绍白嫖的价格,每个月1800分钟的构建时间,和1个并发构建任务。也就是同时只能执行一个任务(构建/发布),其他任务会排队等待,1800分钟的构建时长对于个人用户几乎也很难用光。

Azure Devops 价格.png

项目

不限制项目数量,不限制任务数量,像是Team City这类本地自建的CI/DI服务都有项目数限制,微软可谓是非常良心了。

可视化

轻量级的CI/DI服务有很多,但是大多数都是一个yaml文件完成所有配置,没有友好的用户操作界面。Azure Devops的UI使用起来还是非常舒服的,比Jenkins那上世纪审美的UI强了不止一丁半点。

Start

组织 Organization

创建完账号有默认就会有一个以账号名命名的组织。
顾名思义,一个组织可以有多个成员,多个项目,可以管理各种各样的权限,并且付费也是以组织为单位的。组织里有很多设置,这里先不做讨论。

项目 Project

这里的项目和Jenkins的项目是两个概念,Jenkins的项目就是一次构建发布操作,这里的项目是一个抽象的概念。一个项目也可以有多个成员,可以有多个构建流水线和多个发布流水线。因为没有项目数量的限制,你可以为你的所有项目都创建一份。
但不同项目间很多配置是不能共通的,包括服务器的SSH连接Github认证Docker仓库等等。这些配置作用域如果能扩大到组织就更好了,个人项目的话,多个项目可能都是用的同一台服务器,同一个Git账号,推送在同一个Docker仓库里,每个项目都配置一遍有些繁琐,尤其是配置发生变更的时候。
所以我的所有个人项目都放在同一个Project里,再用文件夹把不同项目的流水线区分开。

Azure Devops Project.png

连接 Service connection

Project Settings里可以找到Service connection。连接也是一个抽象的东西,任何需要建立连接的东西,如上文提到的SSH连接Github认证Docker仓库等,都在这里创建管理,用于后续构建发布使用。

Azure Devops Service connections.png

构建流水线 Pipelines

Azure Devops Pipelines.png

进入Pipelines页面后点击New pipeline按钮创建一个新的流水线。

选择仓库

前两步是连接代码仓库,根据自己情况选择,我这里选择GitHub。如果是第一次使用的话会跳转到GitHub官网进行认证。

Azure Devops Connect.png

值得一提的是就跟其他大多数CI工具一样,你需要用yaml文件描述构建过程,Azure Devops也会读取项目中的azure-pipelines.yml文件来进行构建。但是在Connect步骤时,你可以选择Use the classic editor从而不使用yaml文件,让构建过程全部保存在Azure Devops中。
这个我觉得看个人喜好,官方推荐是yaml的方式,我也采用的这种方式,可以在代码仓库中就看到大致的构建流程而不必上控制台查看。

配置

代码仓库选择之后就是配置构建过程了,到这一步时Azure Devops会先扫描一遍项目给出推荐的构建模板,同时也会给出两个选项Starter pipelineExisting Azure Pipelines YAML file。前者是新建一个空的yaml文件模板,后者则是选择项目中已有的azure-pipelines.yml文件。

Azure Devops Configure.png

我们这里选择Starter pipeline

Azure Devops YAML.png

左边是yaml文件编辑器,给出了简单的示范,注释里也给出了语法规则的连接https://aka.ms/yaml
右边是任务栏,手写任务可能会出错,可以使用右边的任务模板,通过填表单的形式生成yaml代码。

我的构建流程是直接用Docker做成镜像并push到我的私有仓库里。下面是我的博客构建yaml,可供参考。

trigger:
- master

resources:
- repo: self

stages:
- stage: Build
  displayName: Build image and push
  jobs:
  - job: Build
    displayName: Build
    pool:
      vmImage: ubuntu-latest
    steps:
    - task: Docker@2
      inputs:
        containerRegistry: 'registry.ap-northeast-1.aliyuncs.com(Tokyo)'
        repository: 'sakuradon/halo'
        command: 'buildAndPush'
        Dockerfile: './ci/Dockerfile'
        buildContext: '.'
        tags: '$(Build.BuildNumber)'

构建

yaml文件编写完成后会提交到仓库,这一步是必须的。因为trigger属性里包含了master分支,所以master分支每次有新的push时都会触发构建。当然也可以添加更多的分支,还可以在控制台手动触发构建。

发布流水线 Releases

点击Releases按钮进入流水线页面。

新建

新建一条流水线,这里同样提供了许多模板,我们选择Empty job创建一个空的流水线。

Azure Devops Release template.png

可以看到流水线大致分为两个部分。
一个是Artifacts,即要发布的内容,比如刚刚构建流水线的build产物。也可以是仓库代码,比如PHP这类无需构建的项目,就可以直接拉取代码然后发布到服务器上。
另一部分是Stages,每个Stage又可以执行多个Task。常见的场景就是一个Test Stage用来测试刚刚构建的产物,测试通过则进入Release Stage发布到线上。

Azure Devops Release.png

配置

这里以我的博客后台为例子。

Azure Devops Release example.png

我的Artifact设置为了构建流水线的产物,同时启用了自动发布,构建完成后会自动创建发布。

Azure Devops Release artifact.png

设置自动发布的话,点击Artifact旁的闪电按钮,Continuous deployment trigger设置为Enable即可。

Azure Devops Release artifact trigger.png

我的发布流程很简单,就一个Stage,一个Job
SSH连接到我的服务器后,cd到工作目录然后覆盖docker-compose.yml文件(主要是覆盖镜像的版本号),最后执行docker-compose up -d,从私有仓库拉取镜像并运行即可。

Azure Devops Release job.png

需要注意的是,SSH任务执行的命令有三个选项CommandsScript FileInline Script,后两者都是执行shell脚本的方式,第一种则是远程执行命令,需要使用绝对路径,因为cd命令是无效的。

发布

Release是可以自定义命名的,默认值是Release-$(Rev:rr),但我通常会在中间加上$(Build.BuildNumber)来直观的展示这次发布是哪一次构建的产物。
$(Rev:r)这个变量可以理解为一个递增的数字,用来保证发布名不会重名。
$(Build.BuildNumber)这个变量只有在Artifact为构建产物时才有效,Artifact为非构建产物时发布将会失败报错。

Azure Devops Release name.png

More

Azure Devops很强大,能做到的事情远不止这些,这里只是简单的介绍了一下基本的构建发布流程,诸如变量组,环境变量等功能都没有介绍。有兴趣的话自己折腾着玩玩还是挺有意思的。