kbigwheelのプログラミング・ソフトウェア技術系ブログ

プログラミング・ソフトウェア技術系のことを書きます

クラウドインフラを構築するときの手順書とInfrasctucture as Codeの間のトレードオフ

tl;dr

インフラを構築するとき、構築方法を手順書で残すかInfrastructure as Codeで残すかの間にはトレードオフがある。

手順書 Infrastructure as Code
学習コスト
利便性

前置き

AWSなどのSaaS/IaaSでサービス基盤を構築するとき、手順書とInfrastructure as Codeのどちらを取るかが最近特に悩ましくなってきました。

手順書とはインフラ構築時の順序やコマンドなどを列挙した文書のことでpuppetやchefすらないときから用いられる由緒正しいインフラ屋の手法です。 一方Infrastructure as Code(IaC)はChef, Terraformなどに代表されるコードで定義されたインフラの定義であり言ってしまえば構築手順書を自動化したものです。 IaCを更に細分化するとMutable Infrastructureの視点によるもの(Chef, Ansible)とImmutable Infrastructureの視点によるもの(Terraform, Packer)に分けられると思います1

法名 手順書 MIaC(Mutable Infrastructure as Code) IIaC(Immutable Infrastructure as Code)
概要 書かれたコマンドを一つ一つTerminalで実行 継続して同じホストに対して自動化された処理を実行 毎回新しいホストに対して自動化された処理を実行 / ホストの元となるイメージを作成
代表的ツール txtファイル
Wiki
Confluence
Chef
Ansible
capistrano
Docker
Packer

上では代表的なツールを挙げましたが実際には各分野のツールもだいたいどれかの属性を帯びていることが多いです。例えばKubernetesの関連ツールであるhelmはそれ単体ですと手順書でしか形式知にできませんが、helmfileやArgo CDなどを使用することでIaCにすることができます。KubernetesやECSのようなコンテナクラスタは使い方によってどれにでもなると言えるでしょう。

Immutable Infrastructure as Codeの利点

時間が無限に使えるという仮定の元であればIIaCがほとんどの場合最良であることはある程度インフラ構築をやったことがある人であればほぼ合意できるかと思います。

手順書の場合、その手順の検証(テスト)のコストが大きくほとんどの場合テストがされません。また実行者の環境へ暗黙的に特定のコマンドがインストールされていることが前提となっているのに(jqなど)それが書かれていないこともよくあります。つまり再現性が低いのです。それに対してIaCでは文字通りコード化されているためテストのコストが圧倒的に低いです。例えばterraformであれば terraform init; terraform apply; terraform destroy で最低限のテストが実行できます。

MIaCについては既存のホストの状態によって実行結果が変わることがネックになります。例えばホスト内から特定のコマンドを削除したりディレクトリを移動することでchefやansibleの実行は失敗する可能性があります。それをカバーしようとして前提チェックや依存コマンド・環境などのレシピを積み上げていくと膨大な量となります。しかもそれでも本当に100%カバーできているかはわかりません。IIaCであれば実行したいアプリケーションの依存物はすべて同梱されており外部からそれを変更することは(それを明確に意図しない限り)できないので再現性が高くなります。

このように、基本的には手順書よりMIaC, MIaCよりIIaCのほうが特に再現性の点で優れていると言えます。 ではIIaCの欠点とはなんでしょうか。

Immutable Infrastructure as Codeの欠点

私が考えるIIaCの主な欠点は2つです。

  1. 計算資源の観点から見たコストの高さ
  2. 学習コストの高さ
1. 計算資源の観点から見たコストの高さ

ここで言う計算資源としては主にストレージ・デプロイ時間のことです。

PackerにしろDockerにしろ、作成したイメージはアプリケーションが依存するものをライブラリだけではなくOSのレイヤーまで含みます。結果的にビルドから実際の実行ホストまでのすべての経路においてMIaCと比べて多くのストレージや通信量がかかります。 実際Packerでビルドをやっていたときはアプリケーションはたかだか数十MBであるにもかかわらず作成したイメージは数GBになる話は珍しくありませんでした。 Dockerになってレイヤー化されたこと、OSのコア部分はホストOS側で担保されることなどによりPackerと比べては劇的に減りましたが結局最初のPull時点ではすべてのレイヤーをダウンロードする必要があるため減ったストレージはDocker Hubが担ってくれている部分のみと言えます。

またデプロイ時間も基本的には増えます。Packerの場合はVMインスタンスを新たに立ち上げる必要がありますし、Dockerの場合でも新たにイメージをpullする必要があります。MIaCによるデプロイはVMインスタンスをそのまま使い回せるため基本的にはIIaCよりも早いです。その仕組みの違い上、MIaCスタイルのデプロイとIIaCスタイルのデプロイそれぞれで最善を尽くすと絶対にIIaCは速度でMIaCスタイルを上回ることはできません。

2. 学習コストの高さ

IIaCという考え方はそれまでの試みや概念を土台としています。 また考え方自体が新しいため世の中に知見やノウハウ・それについて書かれた文書などがまだ多くありません。 IIaCのためのツールもまだ未熟で日本語でのドキュメントが少なかったり単純にバグがまだまだあったり機能が少なかったりします。

これらの欠点に対する私見

個人的に①の欠点はそれほど重大だとは思っていません。 というのは近年のストレージの価格は十分に低下しており、CPUが最も高価なIaaSでは相対的にそれほど気にならないからです2。 またデプロイ時間についてもMIaCスタイルのデプロイ(Capistrano, CodeDeploy)は工程が複雑になりがちで結果的にイメージをダウンロードしてきて実行するだけのIIaCスタイルの方が早くデプロイできるケースが多いです。

②については、確かにコストが高いことがあります。特にKubernetesの関連技術はまだ移り変わりが早く半年や一年で様相が一変しているようなことは少なくありません。

IIaCの覇権は明白

一方で、IIaCの覇権は2020/07現在かなり明白になっています。そもそもIIaCの成り立ちがMIaCなどの既存手法の問題・痛みを解決するものであり、すでに本番環境での採用・実践例も溢れています。 Dockerは本当にプロダクションユースなのか・Dockerのコンテナオーケストレーションツールのデファクトスタンダードはどれかといった業界全体による検証のフェイズはとっくに過ぎており Terraform / Docker / Kubernetes などといったデファクトスタンダードIIaCツールが揃った今、新しくIIaCを始める人にとってもツール選択に迷うことはかなり減りました。 このような背景のためにIIaCの導入は変化に適応する開発組織では確定路線であり、あとはいつ手順書やMIaCなどから移行するかを決めるのみです。


  1. この両方が選択できたりどちらかが曖昧なツールもたくさんあります。前者がAWS CodeDeploy、後者がTerraformなどです

  2. 実際のところはストレージが安くなりネットワークも十分に早くなったからIIaCのような手法が取れるようになった、発達したというのが本当のところだと思います