1. 概述

Concourse 是一个使用Go语言开发,开源的CICD系统。

本文我们将学习如何部署安装 Concourse,并演示其基本功能。

2. Concourse 介绍

Concourse 是一个基于流水线 (pipeline) 的自动化持续性集成和部署工具。“Pipeline” 一词在CICD系统中很流行,但Concourse的Pipeline有些不同。Concourse的Pipeline围绕资源(Resource)和作业(Job)构建。Pipeline表达了依赖关系流,类似于分布式的 Makefile 文件,

Resource:如git资源和s3资源用于表达源代码、依赖项、部署以及其他外部状态,还可用于更抽象的内容,比如通过时间资源进行的计划或间隔触发。

资源类型在Pipeline中定义,保持了Concourse的小巧通用性,无需复杂的插件系统。作业由get、put和task步骤组成,决定了作业的输入和输出。作业是幂等的、松散耦合的,可以根据项目需求扩展,而不会增加开发人员的心智负担。

Concourse中的所有操作都在容器中运行。

3. 手动安装 Concourse

Concourse 使用Golang开发,被编译为单个可执行二进制文件,可以轻松地在任何系统上运行。

3.1. 下载 Concourse

使用 wget 从GitHub下载Concourse,请替换 $VERSION 为实际版本号:

$ wget https://github.com/concourse/concourse/releases/download/v$VERSION/concourse-$VERSION-linux-amd64.tgz

然后解压

$ tar -xzf concourse-*-linux-amd64.tgz

解压后的目录结构:

$ tree concourse/
concourse/
├── bin
│   ├── bandwidth
│   ├── bridge
│   ├── concourse
│   ├── containerd
│   ├── containerd-shim
│   ├── containerd-shim-runc-v1
│   ├── containerd-shim-runc-v2
│   ├── containerd-stress
│   ├── ctr
│   ├── dhcp
│   ├── dummy
│   ├── firewall
│   ├── gdn
│   ├── host-device
│   ├── host-local
│   ├── init
│   ├── ipvlan
│   ├── loopback
│   ├── macvlan
│   ├── portmap
│   ├── ptp
│   ├── runc
│   ├── sbr
│   ├── static
│   ├── tap
│   ├── tuning
│   ├── vlan
│   └── vrf
├── fly-assets
│   ├── fly-darwin-amd64.tgz
│   ├── fly-linux-amd64.tgz
│   └── fly-windows-amd64.zip
└── resource-types
[...]
17 directories, 70 files

concourse/bin/ 目录中除了 concourse 可执行文件外,还包含了其他辅助工具。concourse/fly-assets/ 包含了适用于不同平台的 fly 包resource-types 目录包含了用于不同外部集成(如 gits3)的相关资源类型。

3.2. 部署 concoursefly

现在,我们有了 concourse 可执行文件。

然而,作为主要的配置驱动程序,**fly 也是 Concourse 包的一部分**。所以,我们也部署它:

$ tar -xzf concourse/fly-assets/fly-linux-amd64.tgz
$ chmod +x fly

在这里,我们解压fly

为了方便使用,建议将 将 concourse/bin/fly 加到环境变量中去。

3.3. 密钥生成

Concourse 使用密钥进行通信和签名请求。要生成这些密钥,我们可以使用 concoursegenerate-key 子命令:

$ concourse generate-key --type rsa --filename session_signing_key
wrote private key to ./session_signing.key
$ concourse generate-key --type ssh --filename tsa_host_key
wrote private key to ./tsa_host.key
$ concourse generate-key --type ssh --filename worker_key
wrote private key to ./worker.key

因此,我们现在有三个主要的密钥。

3.4. PostgreSQL 节点

Concourse 使用 PostgreSQL 数据库存储数据:

$ apt-get install postgresql

为了为 Concourse 配置安装,我们应该创建一个特定的 PostgreSQL 用户和数据库

$ su postgres --command "createuser -P dbaeldung"
Enter password for new role:
Enter it again:
$ su postgres --command "createdb --owner=dbaeldung concoursedb"

在这种情况下,我们使用 supostgres 用户身份运行两个 [–command]s。特别是,我们使用 createuser 与名称 dbaeldung 进行数据库访问。之后,我们 createdb 具有相应所有者的 concoursedb 数据库。

3.5. 配置

由于 Concourse 至少有一个 web 节点和一个连接到它的 worker 节点,我们可以选择是否在同一系统或不同系统上运行两者。然而,每种节点类型都需要自己的参数,我们可以将它们设置为全局 shell 变量或命令行参数

尽管我们在设置中使用相对路径,但通常最好使用绝对路径。

我们可能需要的绝大多数选项也可以从 https://concourse-ci.org/docker-compose.yml 的 Docker Compose 配置文件中获得。此外,我们可以检查 concouse web –helpconcourse worker –help 以获取完整列表。

3.6. 配置和启动 web 节点

让我们从 web 节点配置开始:

$ export CONCOURSE_POSTGRES_HOST=127.0.0.1
$ export CONCOURSE_POSTGRES_USER=dbaeldung
$ export CONCOURSE_POSTGRES_PASSWORD=PASSWORD
$ export CONCOURSE_POSTGRES_DATABASE=concoursedb
$ export CONCOURSE_EXTERNAL_URL=http://192.168.6.66:8080
$ export CONCOURSE_ADD_LOCAL_USER=ccbaeldung:PASSWORD
$ export CONCOURSE_MAIN_TEAM_LOCAL_USER=ccbaeldung
$ export CONCOURSE_SESSION_SIGNING_KEY=session_signing_key
$ export CONCOURSE_TSA_HOST_KEY=tsa_host_key
$ export CONCOURSE_TSA_AUTHORIZED_KEYS=authorized_worker_keys

在这里,我们设置预配置的 PostgreSQL 凭证和数据库名称,以及预期的连接 URL。此外,**我们添加一个本地管理用户 ccbaeldung,并将其设置为默认团队 main 的主要用户**。

最后,我们设置会话和 TSA 主机密钥,以及授权密钥文件。这样,web 节点就可以识别自己并设置会话。此外,它可以根据授权密钥决定哪个 worker 可以连接。

所以,让我们运行 web 节点:

$ concourse web

我们应该看到一些没有错误的 JSON 输出,这表明节点已准备好为工人提供服务。当然,大脑需要肌肉。

3.7. 配置和启动 worker 节点

现在,我们转向 worker 节点配置:

$ export CONCOURSE_TSA_HOST=192.168.6.66:8080
$ export CONCOURSE_EXTERNAL_URL=http://192.168.6.66:8080
$ export CONCOURSE_TSA_PUBLIC_KEY=tsa_host_key.pub
$ export CONCOURSE_TSA_WORKER_PRIVATE_KEY=worker_key
$ export CONCOURSE_WORK_DIR=<WORKER_PATH>

当然,每个 worker 只需要知道 web 节点套接字和 URL、其公共 TSA 主机密钥以及要使用的 worker 标识密钥。此外,worker 需要一个本地暂存路径来工作。它为每个步骤存储新的容器,并且必须具有正确的权限。

因此,我们应该能够运行 worker:

$ concourse worker

在这种情况下,我们分别运行 webworker 节点。当守护进程在不同节点上时,这尤其重要。然而,还有另一种选择,主要用于测试。

3.8. 使用 quickstart

为了方便起见,concourse 的 quickstart 选项同时运行 webworker 节点

$ export CONCOURSE_POSTGRES_HOST=127.0.0.1
$ export CONCOURSE_POSTGRES_USER=dbaeldung
$ export CONCOURSE_POSTGRES_PASSWORD=PASSWORD
$ export CONCOURSE_POSTGRES_DATABASE=concoursedb
$ export CONCOURSE_TSA_HOST=192.168.6.66:8080
$ export CONCOURSE_EXTERNAL_URL=http://192.168.6.66:8080
$ export CONCOURSE_ADD_LOCAL_USER=ccbaeldung:PASSWORD
$ export CONCOURSE_MAIN_TEAM_LOCAL_USER=ccbaeldung
$ export CONCOURSE_WORKER_WORK_DIR=<WORKER_PATH>
$ concourse quickstart

值得注意的是,我们需要设置 CONCOURSE_WORKER_WORK_DIR 作为 quickstart 的 worker 路径,因为 quickstart 的参数名与 concourse 不同 (–worker-work-dir). 然而,由于自动设置,在这种情况下关键配置不是必要的。

然而,不建议在生产环境中使用 quickstart

无论哪种方式,我们都应该有一个活动的 Web 界面和 worker。

4. 通过 Docker 部署 Concourse

或者,我们可以通过其 Docker 镜像部署 Concourse:

$ curl --remote-name https://concourse-ci.org/docker-compose.yml
$ docker compose up --detach

在这里,我们首先使用 curl 从官方 Concourse 网站获取容器 Docker Compose 文件,并将其与相同名称的 docker-compose.yaml 文件一起本地化。之后,**我们使用 compose 子命令和 docker-compose.yaml 文件来初始化和启动新的 [–detach]ed 容器实例**。

如果我们想通过网络访问而不是仅通过 localhost,我们可以将 CONCOURSE_EXTERNAL_URL 变量更改为指向我们选择的配置 IP 地址或主机名。

此时,应该有两个容器在运行:

  • concourse/concourse at 0.0.0.0:8080->8080/tcp
  • postgres at 5432/tcp

进一步,我们应该能够从 Web 浏览器访问新的容器部署 http://<HOSTNAME_OR_IP_ADDRESS>:8080。事实上,我们使用这种访问来获取与我们 [arch]itecture 和 platform 相关的相关 Fly 包:

$ curl 'http://xost:8080/api/v1/cli?arch=amd64&platform=linux' --output fly

一旦我们有了 fly 可执行文件,我们可以像以前一样部署它。

无论我们的设置机制如何,我们都应该能够访问 192.168.6.66:8080xost:8080 分别,以我们的 CONCOURSE_MAIN_TEAM_LOCAL_USER 登录,并检查 Concourse 的状态。

5. 演示

为了了解 Concourse 如何帮助我们,让我们通过一个简短的示例。自然,所有步骤都涉及 fly 或 Concourse Web UI。

5.1. 登录

有几种方法可以通过 fly 客户端登录并注册一个目标 web 节点

例如,我们可以向 –concourse-url 发出 login 子命令,并选择一个目标名称:

$ fly --target=baeltarget login --concourse-url=http://192.168.6.66:8080
logging in to team 'main'

在浏览器中导航到以下 URL:

  http://192.168.6.66:8080/login?fly_port=10666

or enter token manually (input hidden):
target saved

访问 URL 并登录后,我们会得到一个令牌,我们可以将其复制回来,以便在给定名称下保存目标。

或者,我们可以通过命令行提供凭据:

$ fly --target=baeltarget login --concourse-url=http://192.168.6.66:8080 --username=ccbaeldung --password=PASSWORD
logging in to team 'main'


target saved

其他选项涉及发送客户端证书。

无论如何,我们应该有一个准备好的目标,其中有一个 worker

$ fly --target=baeltarget workers
name  containers  platform  tags  team  state    version  age
xost  0           linux     none  none  running  2.5      16m56s

一旦我们保存了目标,请求应该很简单。

5.2. 创建Pipeline

与 Docker Compose 类似,Concourse 中的Pipeline只是具有自定义模式的 YAML 文本文件

$ fly --target=baeltarget set-pipeline --pipeline=baelpipe --config=baelpipe.yaml
jobs:
  job job1 has been added:
+ name: job1
+ plan:
+ - config:
+     image_resource:
+       name: ""
+       source:
+         repository: perl
+       type: registry-image
+     platform: linux
+     run:
+       args:
+       - -e
+       - printf "Perl script running...";
+       path: /usr/local/bin/perl
+   task: task1

pipeline name: baelpipe

apply configuration? [yN]: y
pipeline created!
you can view your pipeline here: http://192.168.6.66:8080/teams/main/pipelines/baelpipe

the pipeline is currently paused. to unpause, either:
  - run the unpause-pipeline command:
    fly -t baeltarget unpause-pipeline -p baelpipe
  - click play next to the pipeline in the web ui

在这里,*我们通过其 [–config]uration 文件 baelpipe.yaml 使用 set-pipeline 创建一个新的 –pipeline 名称 baelpipe*。

Pipeline本身只有一个作业 job1 和一个任务 task1。后者设置了一个 perl Docker 镜像并运行一个特定的 Perl 命令。

我们可以看到,一个新的Pipeline默认是暂停的。所以,让我们暂停 baelpipe

$ fly --target=baeltarget unpause-pipeline --pipeline=baelpipe
unpause 'baelpipe'

准备好Pipeline后,我们可以运行它。

5.3. 运行Pipeline作业

要运行Pipeline,我们可以使用 fly CLI 或 Web UI。

由于 UI 通常更容易并且两者都显示相同的输出,让我们通过命令行完成:

$ fly --target=baeltarget trigger-job --job baelpipe/job1 --watch
started baelpipe/job1 #1

initializing
initializing check: image
selected worker: xost
selected worker: xost
fetching perl@sha256:2fee8a8abdceb3666f59249fd10674ddeadbeefd1b70c04e519bc089d7c21447
1b13d4e1a46e [========================================] 47.3MiB/47.3MiB
1c74667957fc [========================================] 22.9MiB/22.9MiB
30d855666954 [========================================] 61.2MiB/61.2MiB
ad6669181616 [======================================] 201.3MiB/201.3MiB
0ee2b666f83c [==============================================] 136b/136b
69d0a6652e22 [========================================] 15.1MiB/15.1MiB
1d9deafd59b5 [==============================================] 132b/132b
selected worker: xost
running /usr/local/bin/perl -e printf "Perl script running...";
Perl script running...succeeded

因此,我们触发一个 build。每个 build 都是作业的单独运行。

或者,我们可以访问 http://192.168.6.66:8080/teams/main/pipelines/baelpipe/jobs/job1 在 Web UI 中并检查作业及其状态。

5.4. fly 管理

自然,fly 可以协助管理许多其他对象:

  • targets
  • workers
  • teams
  • volumes
  • pipelines
  • jobs
  • builds
  • cache
  • containers

由于其全面的文档,尽管它的多功能性,工具是相当容易使用的。

6. 总结

在这篇文章中,我们深入研究了 Concourse,一个Pipeline管理系统。

总之,在许多用于连续过程自动化的工具中,Concourse 以其简单的部署选项和简约但完整的特性集脱颖而出。