CI
microservices
Concourse
FujitsuDay 21

Concourseでマイクロサービスを継続的インテグレーション

More than 1 year has passed since last update.

これはFujitsu Advent Calendar 2016の21日目の記事です。

※タイトルについて、申し訳ないですがハウツーではないです。


はじめに

先日、Cloud Foundry Days in Tokyoというコミュニティイベントに参加してきました。

資料はconnpassに公開されていますが、ConcourseというCI/CDツールが度々登場しました。

プロペラマークが目印です。

今回のイベントで頻出したのはConcourseがCloudFoundryのために作られたCI/CDツールだからという理由もあるでしょう。

ただCI/CDツールと言えばJenkinsというイメージだった私は焦りを覚えてConcourseを触って見ることにしました。


Concourseをとりあえず動かす

Concourseは、ビルド等のタスクの集まりをパイプラインで記述することでビルドパイプラインを実行、可視化してくれるCI/CDツールです。

また、各タスクはDockerコンテナ上で実行されるので再現性の高いビルドが可能となっています。

日本語の資料は少ないですが、以下のサイトがよくまとまっているので、とりあえず動かすのは難しくなかったです(今回はdocker-compose版を使用)。

これで今どきのマイクロサービスを継続的インテグレーションできる気がしてきました。


サービスのテスト

Cinema 3というgithubで見つけた超シンプルなマイクロサービスっぽいものを使わせていただきます。

これは映画予約を想定した4つのマイクロサービスから構成されます。(bookings, movies, showtimes, user)

今回は元のコードから以下の点を変更することにしました。

ということで作ったmoviesサービスがこちら(https://github.com/matsulib/cinema3-movies)です。

以下のコマンドを実行してみると…

$ fly -t lite set-pipeline -p movies -c cinema3-movies/ci/pipelines/pipeline-movies.yml

成功しました。

m1.PNG

標準出力、標準エラー出力からテスト結果を確認することができます。

m2.PNG

Jenkinsには、xUnit形式で出力したXMLファイルのテスト結果をレポートとして表示できる機能がありますが、Concourseにはないようです。

どうしてもレポートを見たい人はタスクの成果物としてレポートをコンテナの外にファイル出力する必要があります。


社内で使う場合

タスクはDockerコンテナ上で実行されますが、タスクが終了するとコンテナは消えてしまいます。

毎回タスクが走るたびに何も入っていないベースイメージからビルド環境を構築するのは無駄なので、必要なものが入ったイメージを予め作っておき、そのイメージキャッシュを利用した方が良いです。(これだけはやっておきたい〜マイクロサービスのデプロイメント - クラウドワークス エンジニアブログ

例えば上記のmovies-unittestというタスクを実行するコンテナは、今回私が作ったlibmatsu/mongo-python3というDockerイメージから作られています。


movies_unittest.yml

---

platform: linux

image_resource:
type: docker-image
source:
repository: libmatsu/mongo-python3

inputs:
- name: cinema3-movies

run:
path: cinema3-movies/ci/scripts/test_runner.sh


このDockerイメージはDockerHubに公開されていますが、そんなとこに公開できないよという環境の人は多いと思います。

そのような場合はPrivate Docker Registryが使えます。その他、社内環境でのConcourseの利用例は以下のリンク先に紹介されています。


リポジトリ管理再考

あとはmoviesサービス以外のサービスも作ってインテグレーションテストしてPaaSにデプロイするだけ、と思ってこんな感じのパイプラインを作ったら問題が発生しました。

i2.PNG

エラーが出ているのは無視してください。ところでこのpipeline.ymlはどのリポジトリに管理されているのでしょうか?

例えばmoviesリポジトリのciディレクトリにはmovies用のpipeline.ymlしか含まれていません。

全体用のpipeline.ymlを管理するリポジトリを新たに作るのか、もしくは元のCinema3のように1つのリポジトリにしてサブディレクトリごとにビルドするのか。。

後者の方がすっきりすると思うし、確かにサービスごとにリポジトリを分ける必要はないという意見もあります。


Aを更新したらBとの結合テストをしてからAを更新、Bを更新したらAとの結合テストをしてからBを更新、またはSlackからbotに依頼したらAかBを更新…やりたかったことはこれではないでしょうか。その観点からすると、複数GitレポジトリにそれぞれCIするとか、分散ロックなどはただの手段です。やりたいことをもっと直接的に表現できるツールはないでしょうか。

これだけはやっておきたい〜マイクロサービスのデプロイメント - クラウドワークス エンジニアブログ


ただリポジトリ1つの場合、githubの変更をトリガーにジョブが走る設定だと、あるサービスを変更すると全てのユニットテストが走ってしまってあんまり独立してないなあと若干感じます。

そもそも誰がインテグレーションテストを書くのかという問題もあります。

1つのチームが1つのサービスを作る分には問題ないが、複数のチームが関わると生じる問題と解決案は『マイクロサービスアーキテクチャ』でも繰り返し述べられています。

でも結局は組織論ってお話になりそうです。


おわりに

Concourseを使ってみました。導入は難しくないのでCI/CDツールの選択肢としてはありだと思います。

CI/CDの知識も含めて運用上のベストプラクティスがまとまっていれば良いなと思いました。