BOSHとリリースエンジニアリング
この記事は、Cloud Foundry Advent Calendar 2018の9日目の記事です。
このAdvent Calendarの2日目の記事において、 BOSHの設計理念である「モダンな release engineering の実装」について
やっぱりまだ語り足りないなあ
などと漏らしてしまいました。
BOSH 101のアップデートで燃え尽きてしまった感があったのに、なぜそういうことを勢い余って言ってしまったのか・・・
いや、しかし、この際がんばって語ろうと思います。
リリースエンジニアリングとは
言葉の定義としては、英語版Wikipediaに以下のように書いてあります。
Release engineering, frequently abbreviated as RE or as the clipped compound Releng, is a sub-discipline in software engineering concerned with the compilation, assembly, and delivery of source code into finished products or other software components.
すなわち、ソースコードからプロダクトを生み出す過程にある、コンパイル、結合、デリバリに関するソフトウェアエンジニアリングの取り組みの一種である、と。古臭い言い方をすれば、要件定義→設計→プログラミング→テストを経てリリース可能と判定されたソースコードを対象に、出荷可能な形に整えて実際に出荷するまでの作業を、いかに正確かつ効率的にやるかという課題を工学的に解決することである、ということですね。あまり噛み砕いてないですか。どうもすみません。
よくあるリリースエンジニアリング
例えばサービスのリリース作業を正確かつ効率的にやろうと思うと、今どき普通は次のようなことに取り組むだろうと思います。
- Gitリポジトリのmasterブランチもしくはリリース用ブランチに release ready なソースコードをcommit/pushする
- JenkinsなどのCI/CDツールがリリース対象ブランチの更新を自動的に検知すると、そのブランチをcheckoutし、ビルドし、デプロイ対象サーバに配布するジョブを自動実行する
- 更に必要に応じてサーバ上のファイルを入れ替えたりプロセスを再起動したりするようなジョブも自動でリモート実行する
簡単なシステム構成のサービスであれば、リリースエンジニアリング的にはこれでほぼ目標達成だと思われます。
リリースを正確かつ効率的にできてないとはどんな状態か
この動画であるあるネタとして紹介されていますので、書き起こします。
- ○○さんしかリリース作業ができないんだよなあ
- リリース作業自体がとても面倒なので、いっそのことリリースの頻度を減らしてしまおう
- 自分の環境では動いたんだけどなあ
- リリース前テストは通ったのに商用環境だとなぜか動かないんだよなあ
- ○○パッケージの○○バージョンがインストールされてないとちゃんと動かないということが、不具合解析の結果やっとわかったんだよなあ
いずれもとてもあるあるですねえ。
上で紹介した「よくあるリリースエンジニアリング」では、1. ○○さんしかリリース作業ができないんだよなあ
と 2. いっそのことリリースの頻度を減らしてしまおう
は解決しそうですが、3. 4. 5. の解決策は含まれていません。
さらに、リリース対象のサービスがマイクロサービスアーキテクチャが採用された分散システムとして構成されるような場合は、リリース失敗による切り戻しも考えないといけないとすると、リリースエンジニアリング的に相当な工夫をこらさないといけなさそうです。
モダンなRelease Engineeringとは
ところで、アップデートされたBOSH 101のこのスライドをご覧ください。
はい、そのとおりです。ここの文章を意訳したものですね。
ここで紹介されている4つの要素について、BOSHだと具体的にどういうことなのかを例示しつつ解説してみたいと思います。
Identifiability
この単語は日本語に訳すと「同定可能性」になるそうですが、何のことかよくわかりませんので、上のスライドの文章をコピペしますと以下のとおりです。
デプロイ対象となるソフトウェアの各構成要素と、デプロイ結果としての実システムとの対応関係を、一貫して管理できる
何をデプロイするのか
BOSHがデプロイを行う材料とするものは、BOSH101のスライドの14枚目にある通り、ざっくり言えば
- stemcell
- release
- deployment manifest
の3点です。
BOSHは本当に対応関係を一貫して管理しているのか。
私の手元にどの誤家庭にもあるOpenStackクラスタがございまして、BOSHが稼働しております。先ほどBOSHを使ってConcourse CIをデプロイしてみました。BOSH CLIを使って、concourseのデプロイに使った材料について問い合わせてみます。
$ bosh deployments
Using environment '192.168.13.70' as user 'admin'
Name Release(s) Stemcell(s) Team(s)
concourse concourse/4.2.2 bosh-openstack-kvm-ubuntu-xenial-go_agent/170.9 -
garden-runc/1.16.3
postgres/30
1 deployments
Succeeded
なるほど、以下の材料を使ったのですね。
- stemcell
- bosh-openstack-kvm-ubuntu-xenial-go_agent のバージョン170.9
- release
- concourse のバージョン4.2.2
- garden-runc のバージョン1.16.3
- postgres のバージョン30
なぜこれらが使われたかというと、 concourse-bosh-deployment GitHubリポジトリに置いてあるdeployment manifestを使ったからです。
releaseのバージョンはconcourse-bosh-deployment リポジトリ内のversions.ymlによって決まります。
stemcellはここにあるとおり、ubuntu-xenial
というOSでつくられたstemcellのうち、BOSHが保持している最新バージョン(すなわちlatest
)を使用する、ということになります。
ちなみに、このconcourseをデプロイした時点で私のBOSHには以下のようなstemcellが保持されていました。
$ bosh stemcells
Using environment '192.168.13.70' as user 'admin'
Name Version OS CPI CID
bosh-openstack-kvm-ubuntu-xenial-go_agent 170.9* ubuntu-xenial - 534ee6f2-b985-4ced-9ea5-cbfec8cc3018 light
(*) Currently deployed
1 stemcells
Succeeded
stemcellはubuntu-xenial
の170.9
たった1個しかBOSHが保持していなかったため、これを使った、ということになります。
なお余談ですが、concourseをデプロイした時点で最新のコミュニティ版のstemcellのバージョンは170.13でした。また、light
という表示が気になるところですが、実はこれはBOSH自体をデプロイするために使ったstemcell(=OpenStack Glance上のVMイメージ)をそのまま流用することで無駄なディスク容量を食わないようにするためにlight stemcellを使って登録したものである、という意味になります。
stemcellや各releaseがどういう構成になっているかについて調べる必要がある場合があるかもしれませんが、以下のようにすれば追うことができます。
- stemcell
- UbuntuやCentOSのstemcellについては、bosh-linux-stemcell-builderを使って作られます。stemcellのバージョンは、bosh-linux-stemcell-builderのGitHub releaseのバージョンに対応しています。
- また余談ですが、Ubuntu XenialのstemcellのOSベースイメージはこのrakeタスクを実行することにより作成されます。昔から今まで使われ続けてきたCloud Foundry関連のコンポーネントはRubyを使って書かれているものが多いですね。
- さらに、このへんを見るに、2週間ごとにOSベースイメージの作成が自動実行され、いずれかのdebパッケージにはだいたい更新が入っているので、2週間ごとにはだいたい新しいバージョンstemcellが作成されリリースされているようですね。そういった定期更新以外にも、ベースイメージに関わるCVEへの対応などに応じて都度新しいバージョンのstemcellが出ているようです。
- concourse release
- concourse-bosh-releaseを使って作られます。releaseのバージョンは、concourse-bosh-releaseのGitHub releaseのバージョンに対応しています。
- BOSHによってビルド・デプロイされるconcourseの実体はconcourse GitHubリポジトリのこのバージョンを用いて
bosh create-release
コマンドにより作成されAmazon S3にアップロードされたtarballです。このへんを読み解くとわかる感じですね。 - Amazon S3に置いてあるreleaseのtarballには、基本的に各パッケージのソースコードが含まれており、concourse-bosh-releaseもそうなっています。
(人気があったり、開発元の気前がよかったりするreleaseは、コンパイル済みのバイナリを含めてS3などのオブジェクトストレージに置いてあったりしますが。)
BOSHはデプロイにあたってreleaseに含まれるソースコード形式のパッケージを、デプロイ対象となるバージョンのstemcellから作成したVMを使ってビルドします。
これにより、VMのカーネルやビルドツールのバージョンによってコンパイル&ビルドで生成されるバイナリが変わる可能性が心配される点も解消されることになります。
BOSH 101のスライドで言えば、以下の4枚くらいで説明したものですね。
ちなみに、concourseのデプロイに使用したdeployment manifestはBOSHが保持していますが、以下のように参照することもできます。
$ bosh -d concourse manifest
Using environment '192.168.13.70' as user 'admin'
Using deployment 'concourse'
instance_groups:
- azs:
- z1
instances: 1
jobs:
- name: atc
【中略】
name: concourse
releases:
- name: concourse
sha1: 4107747823b7056c58620c34457746dcedb98cc5
url: https://bosh.io/d/github.com/concourse/concourse-bosh-release?v=4.2.2
version: 4.2.2
- name: garden-runc
sha1: 2a7c813e7e4d862e19334addf022916fb6b91eb0
url: https://bosh.io/d/github.com/cloudfoundry/garden-runc-release?v=1.16.3
version: 1.16.3
- name: postgres
sha1: a798999d29b9f5aa12035cff907b26674b491200
url: https://bosh.io/d/github.com/cloudfoundry/postgres-release?v=30
version: "30"
【中略】
variables:
- name: postgres_password
type: password
- name: token_signing_key
type: rsa
- name: tsa_host_key
type: ssh
- name: worker_key
type: ssh
Succeeded
デプロイの結果何が動いているのか
BOSHを使ってOpenStack上に3つのVMを作成し、concourseをデプロイしました。
bosh instances
コマンドによって参照できます。
$ bosh -d concourse instances
Using environment '192.168.13.70' as user 'admin'
Task 86. Done
Deployment 'concourse'
Instance Process State AZ IPs
db/a9a0b7ca-c89f-4335-88da-00be76c4e8a6 running z1 10.0.0.201
web/8352ef31-3891-4c80-8706-ae56325c4d33 running z1 10.0.0.10
192.168.13.80
worker/9b93be47-15f6-454f-a20c-9793e762252d running z1 10.0.0.202
3 instances
Succeeded
bosh instances --ps
コマンドにより、各VM上で動作しているプロセスの状態まで参照することもできます。これは、BOSHによって作成された各VMに常駐しているBOSH agentからmonitにより監視されているプロセスの状態が定期的にBOSH directorに送信され保持されているためです。
$ bosh -d concourse instances --ps
Using environment '192.168.13.70' as user 'admin'
Task 87. Done
Deployment 'concourse'
Instance Process Process State AZ IPs
db/a9a0b7ca-c89f-4335-88da-00be76c4e8a6 - running z1 10.0.0.201
~ pg_janitor running - -
~ postgres running - -
web/8352ef31-3891-4c80-8706-ae56325c4d33 - running z1 10.0.0.10
192.168.13.80
~ atc running - -
~ tsa running - -
worker/9b93be47-15f6-454f-a20c-9793e762252d - running z1 10.0.0.202
~ baggageclaim running - -
~ garden running - -
~ worker running - -
3 instances
Succeeded
各VMのIaaSとしてのIDやVMのタイプ(通常はフレーバと対応付けられる)まで参照したい場合は、bosh vms
コマンドを使用します。
$ bosh -d concourse vms
Using environment '192.168.13.70' as user 'admin'
Task 81. Done
Deployment 'concourse'
Instance Process State AZ IPs VM CID VM Type Active
db/a9a0b7ca-c89f-4335-88da-00be76c4e8a6 running z1 10.0.0.201 8bd0dd50-091b-43e7-a857-4e3fcaa6509b small true
web/8352ef31-3891-4c80-8706-ae56325c4d33 running z1 10.0.0.10 2988ff97-c609-4071-b70c-756f57eeb0e4 small true
192.168.13.80
worker/9b93be47-15f6-454f-a20c-9793e762252d running z1 10.0.0.202 1038fb16-6e98-4ae3-8dd3-64a17f007c58 large true
3 vms
Succeeded
さらに、各VMの基本的なメトリクス(Load Average、CPU使用率、メモリ使用率、ディスク使用率)まで参照したい場合は、bosh vms --vitals
コマンドを使用します。これは、BOSHによって作成された各VMに常駐しているBOSH agentにおいて、当該VMの基本メトリクスを収集し、定期的にBOSH directorに送信され保持されているためです。
$ bosh -d concourse vms --vitals
Using environment '192.168.13.70' as user 'admin'
Task 89. Done
Deployment 'concourse'
Instance Process State AZ IPs VM CID VM Type Active VM Created At Uptime Load CPU CPU CPU CPU Memory Swa System Ephemeral Persistent
(1m, 5m, 15m) Total User Sys Wait Usage Usage Disk Usage Disk Usage Disk Usage
db/a9a0b7ca-c89f-4335-88da-00be76c4e8a6 running z1 10.0.0.201 8bd0dd50-091b-43e7-a857-4e3fcaa6509b small true Wed Dec 12 02:05:49 UTC 2018 5d 9h 45m 58s 0.01, 0.01, 0.00 - 0.0% 0.1% 0.8% 15% (302 MB) 0% (0 B) 52% (35i%) 1% (0i%) 0% (0i%)
web/8352ef31-3891-4c80-8706-ae56325c4d33 running z1 10.0.0.10 2988ff97-c609-4071-b70c-756f57eeb0e4 small true Wed Dec 12 02:05:49 UTC 2018 5d 9h 46m 4s 0.00, 0.00, 0.00 - 0.0% 0.1% 0.4% 14% (283 MB) 0% (0 B) 52% (35i%) 3% (1i%) -
192.168.13.80
worker/9b93be47-15f6-454f-a20c-9793e762252d running z1 10.0.0.202 1038fb16-6e98-4ae3-8dd3-64a17f007c58 large true Wed Dec 12 02:05:49 UTC 2018 5d 9h 45m 57s 0.00, 0.00, 0.00 - 0.0% 0.0% 0.1% 7% (536 MB) 0% (0 B) 52% (35i%) 2% (1i%) -
3 vms
Succeeded
BOSHにおける Identifiability とは
以上のように、「何を」「どこに」デプロイしたのかを、BOSHにおいて厳密に一貫して管理しているので、仮に不具合が発生しても、どのコンポーネントのソースコードのどのバージョンの何行目に原因があるのか、あるいはいつの時点のOSベースイメージに原因があるのか、あるいはdeployment manifestによって注入した設定のどこを変えたことに原因があるのか、などを必ず見つけ出すことができます。この点において、BOSHにおいては Identifiability がとても高いレベルで達成されていると言えるでしょう。
なお、VMホストやネットワークなど、IaaS側の原因を見つけ出すことまではさすがに困難ですが、これはIaaSを直接使用する場合でも同様だと思います。
Reproducibility
この単語は日本語に訳すと「再現可能性」ですね。
ソースコードをはじめ、動作環境となるOSイメージ、永続的データ、外部環境との連携条件を含む構成情報まで、再現可能な形で統合管理できる
前節「Identifiability」で説明したとおり、BOSHを使用すると、何をどのようにデプロイしたのかが明確になっているため、カーネルから各種設定値に至るまでバージョンも含めて全く同一構成のシステムのクローンを再度デプロイすることが可能です。
Puppet、Chef、Ansibleなどを用いたビルドやデプロイ時に、aptやyumを使ってリモートのパッケージリポジトリからインストールを行ってしまうことがよくあると思います。このとき、manifest/cookbook/playbookで適切なバージョン固定を考慮しておかないと、全く同じ構成でのデプロイが行えず、再現性を実現できないことになります。さらに、デプロイ後に期間が空いてしまったあとに再デプロイしようとすると、前使っていたパッケージのバージョンがリモートリポジトリから消えてなくなっているということもありえるようです。
過去にデプロイしたことがあるstemcell/release/deployment manifestを残しておけば必ずシステムを再現できるというのは、特に分散システムの場合は極めてメリットが大きいと言えると思います。この点において、BOSHにおいては Reproducibility についても高いレベルで達成されていると言えるでしょう。
Consistency
この単語は日本語に訳すと「一貫性」ですが、特にシステム運用の手順のことを指して言っています。
ソフトウェアコンポーネントの開発から、デプロイ、更新、構成変更に至るまでの、日常的なワークフローの枠組みを提供する
bosh deploy
という、BOSH CLIにおいて最も重要なコマンドがありますが、よくデプロイツールに求められる要件として言われる「冪等性」をもっています。
すなわち、deployment manifestによって「あるべきシステム」を定義すれば、現時点でシステムが未デプロイであっても、修正デプロイ前であっても、デプロイ失敗状態であっても、全く同じbosh deploy
コマンドを実行することにより、デプロイ成功の暁には「あるべきシステム」が稼働している状態にすることができる、ということです。
Agility
これはおなじみの単語で、日本語では「俊敏さ」「軽快さ」という意味ですが、ザックリ言ってしまえば、アジャイル開発のプラクティスへの適合性を指しているということですね。
ソフトウェアリリースの作成自動化やシンプルなコマンドによる複雑なシステムの更新の実現により、CI/CDなど日々進化するベストプラクティスとの統合を可能にする
bosh deploy
というシンプルなコマンド一発で複雑なシステムの構築や更新が行えるというのはこれまでも説明してきた通りです。concourseやJenkinsなどのCI/CDツールと組み合わせ、stemcell/release/deployment manifestの更新を契機としたアップデートなどの自動化を図ることもできます。実際に、Concourseを使ってPivotal CFのアップデートの自動化を図る例も存在します。
さらに「ソフトウェアリリース」、すなわちBOSHによるデプロイの材料であるreleaseに対する「作成自動化」についても、BOSH CLIを使い、concourseやJenkinsなどのCI/CDツールと組み合わせて自動化を図ることができます。
BOSH CLIがサポートするrelease周りの操作についてはこのへんやこのへんを熟読して理解を進めることになります。
さいごに
冒頭で紹介した5つの「あるある」は、BOSHを使うことで以下のように解消されます。
-
○○さんしかリリース作業ができないんだよなあ
- どのstemcell/release/deployment manifestを使ってリリースするのかが分かれば、あとは
bosh deploy
コマンドを叩くだけだから。大丈夫だから。
- どのstemcell/release/deployment manifestを使ってリリースするのかが分かれば、あとは
-
リリース作業自体がとても面倒なので、いっそのことリリースの頻度を減らしてしまおう
-
bosh deploy
コマンドを叩くだけだから。もうめんどくさくないから。
-
-
自分の環境では動いたんだけどなあ
- 同じstemcell/release/deployment manifestを使って同じIaaSにデプロイしたら、IaaSに不具合がない限りは必ず同じように動くから。いいからやってみなよ。
-
リリース前テストは通ったのに商用環境だとなぜか動かないんだよなあ
- テスト環境と商用環境で同じIaaSを使ってる限り、必ず同じように動くから。もう心配すんなよ!
-
○○パッケージの○○バージョンがインストールされてないとちゃんと動かないということが、不具合解析の結果やっとわかったんだよなあ
- いいから、BOSH使えよ!