スクエニ ITエンジニア ブログ

CI/CDツールConcourseのパイプラインのアーキテクチャ

概要

継続的インテグレーション、継続的デリバリー(CI/CD : Continuous Integration /Continuous Derivery)を実現するためのツールの1つであるConcourseについて、筆者が特にパイプラインを構成するアーキテクチャが面白いと思ったのでまとめてみました。

Concourseとは

Concourseとは、継続的インテグレーション、継続的デリバリー(CI/CD : Continuous Integration /Continuous Derivery)を実現するためのツールの1つです。

公式ドキュメントでは、

  • 設定がソースコードのように扱える
    • YAMLファイル形式
  • パイプラインの処理の流れが可視化される
    • 処理の流れがグラフ構造としてWeb UI上に表れる
  • 再現性があり、デバッグも容易なビルド
    • あらゆる処理がコンテナ上で実行されていて、専用CLIツールを用いてコンテナ内に入って検証できる(例えば失敗したビルドの原因の調査など)

などが特徴としてあげられています。

今回はその中でもConcourseのパイプラインを構築する上で重要な、 「Resource」という概念が面白いと思ったのでまとめてみます。

Concourseにおけるパイプライン

Concourseにおいて、パイプラインは以下の要素で構成されます。

  • Job
    • 複数のTask、及びResrouceの入出力の組
  • Task
    • 実際の計算処理(例:ソースコードのビルドなど)
  • Resource
    • Concourse内外の入出力を表すオブジェクト

特に私が面白いと感じているのはこのResourceの存在です。

Concourseのドキュメントでも触れられているのですが、Concourseにはいわゆるプラグインのようなシステムではなく、代わりにそのパイプラインで注力したい さまざまな入出力をResourceとして抽象化 しています。

Concourse does not have a complex plugin system. Instead, it focuses on a single strong abstraction: resource, which are implemented by resource types.

The pipeline.resources field configures external artifacts that your pipeline will monitor for changes, fetch from, and push to.

例えば、GitのリポジトリやDockerのレジストリ、Amazon S3やGoogle Cloud Storageなどのストレージなど、多種多様なResourceが存在します。

例えば、Git をcloneして ls -la するのみ、というパイプラインが例として 公式に https://concourse-ci.org/git-trigger-example.html で紹介されています。ここでは、 git clone https://github.com/concourse/docsget: concourse-docs-git で表現されています。
ここでは新しいコミットがあるたびに git clonels -la が実行される設定になっています。

一方、出力操作は put として表現します。例えば、docker push がそれにあたります。

例えば、git clone した後、そのリポジトリ内のDockerfileを使って docker builddocker push を行うパイプラインは以下のようになります。

resources: 
- name: sample-git-repo # git repositoryを表すresource
  type: git
  icon: github # (オプション) https://materialdesignicons.com/ 上のicon名を指定すると後述の画面上に表示される
  source:
    uri: <git repository URL>
- name: sample-docker-repo # docker repositoryを表すresource
  type: docker-image
  icon: docker
  source:
    repository: <docker registry URL>

jobs:
- name: build
  plan:
  - get: sample-git-repo 
    trigger: true 
  - put: sample-docker-repo
    # docker-imageの場合はput時に docker build`, docker push が行われる。
    # docker build -f sample-git-repo/Dockerfile sample-git-repo/ 相当
    params:
        build: sample-git-repo/ 
        dockerfile: sample-git-repo/Dockerfile
        tag_file: sample-git-repo/tag_file # tag名をあらかじめファイルに書いておく必要がある

本稿で詳細を述べていませんが、公式CLIツール fly を使って既存のConcourseサーバ上に展開すると以下のような画面になります。
パイプライン設定のResourceとJobの関係を表したグラフになっています。

パイプライントップ画面

Jobが実行されると次のような画面になり、図中の黄色に強調されている部分がまさに実行中のjobを表しています。

パイプライントップ画面

さらにこのbuildをクリックすると、詳細のTask(get/put含む)の様子を知ることができます。
ここでも細かくどの処理が実行中なのか確認することができます。

(図中では tag_fileがないリポジトリを使ったため、tag_file を生成するtask、create-tag-file をput前に追加しています。また、実際はsample-git-repoのコミットハッシュが表示されるのですが省略しています。)

ジョブ詳細

正常終了したJobは緑色に変化します。失敗したJobは赤色になるため、複数Jobがある場合は成功したJobと失敗したJobの違いが可視化されます。

ジョブ詳細

さまざまなResource

私が特にこのResourceの仕組みの面白いと思っているところは、 定期的に実行する、という設定やSlackへの通知もこのResourceの仕組みに基づいている ことです!

Slack

Slackへの投稿もConcourseから見た入出力の方向は docker push と同様なため、putで表現できます。例えば、以下のような設定になります。

# resource設定は省略
put: sample-notification
  params:
    attachments: |
    [
      {
          "text": "sample notification",
      }
    ]    

time resource

定期実行の設定を実現するのは time resource です。

例えば、30秒ごとに echo "Hello world!" する例が公式に https://concourse-ci.org/time-trigger-example.html で紹介されています。

定期実行の処理がResourceで実現できるのは以下のような仕組みになっているからです。

実はResourceはversion情報を含んでいるのですが、Concourseは各Resourceに対して定期的に新しいversionがあるかどうか確認します。そして、新しいversion情報が検出されればジョブを実行するように設定できます。
例えばgitの場合は「コミット」がversion情報に該当するのですが、time の場合は設定に基づいた新しい「ジョブ開始時間」がそれにあたります。

※ 設定に基づいた:ここでは30秒おき、という設定。他には特定の時刻、といった設定も可能

ここで、Gitは開発者よってコミット(version情報)が更新されるResourceであるのに対し、 定期的に実行する = 定期的にジョブ開始時間(version情報)が更新される、と考えられるため、同じResourceという仕組みに抽象化できます。

つまり、Gitの場合は新しいコミットがあるたびにジョブを実行するような設定が実現できたように、time の場合も新しいジョブ開始時間が得られた場合にジョブを実行するような設定が実現できるため、定期実行も同じ仕組みのもとに実現できます。

まとめ

CI/CDツール Concourseのパイプラインでは、以下のようにさまざまな入出力がResourceとして抽象化されています。

Resource名\操作 get put
Git clone(checkout) push
Docker pull build & push
Google Cloud Storage download upload
Slack - 投稿
time (定期的な)時刻情報 -

Concourseが公式にサポートしているResourceはResource Typesにまとめられているのですが、このようにCI/CDを行う上で欠かせない入出力が他の処理(e.g. 上記の例では ls -laecho。他には make のようなビルドなど)と別の概念になっているところが面白いと思っています。

この記事を書いた人

記事一覧
SQUARE ENIXでは一緒に働く仲間を募集しています!
興味をお持ちいただけたら、ぜひ採用情報ページもご覧下さい!