every Tech Blog

株式会社エブリーのTech Blogです。

ansibleとterraformって何が違うんですか?

ansibleとterraformって何が違うんですか?

f:id:kajidai:20201208174411j:plain

はじめに

弊社ではインフラは主にAWS(一部GCP)を利用しており、構成管理にansibleとterraformを使用しています。 新しく入社された方や、これまでインフラをあまり触ってこなかった方がこれらに触れる際、本件表題のような質問をされることが何度かありました。

私はこのたぐいの質問をされるたびにそれぞれの成り立ち、歴史的背景、ソフトウェアとしての実装と振る舞いの違い、そして弊社での使われ方について説明をしてきました。 大抵はそれで納得してその後は疑問なく使い分けができるようになっていく(ように見える)のですが、やはり中には腑に落ちないようであったり、使い分けに悩まれる様子がみられる方もいます。

説明している最中、自分でも「この説明で適切なのだろうか」「そもそもなぜこれらが混同されやすいのだろうか」と疑問に思うことがよくあり、良い機会ですので今回文章としてまとめました。

この文章が表題の疑問の回答になり、今後の学習のお役に立てれば幸いです。

作っただけでは動かない

ansibleやterraformの話をする前に、基礎の話から押さえておきましょう。 インフラエンジニアであったり、サービスの保守運用の経験がある方であれば「何を当たり前のことを」と思うかもしれませんが、アプリケーションは作っただけでは動きません

なぜでしょうか?「アプリケーションは完璧に仕様を満たしています!動かせばいいだけじゃないか!」そう思われますか?

そう、動かせばいいだけなのです!

しかしながら、アプリケーションを動かすためには、アプリケーションの他にもたくさんのものが必要になります。

それらは、普段手元のパソコンで開発していると当たり前のように存在しているために気づかないものであったり、インターネットを通してたくさんの人にサービスを届けるために必要なものであったり、様々です。 ひとまずこの文章内では、これらのことをひとまとめに「リソース」と呼ぶことにしましょう。インフラとはリソースの集合であると言えます。

リソースという言葉は色々な場面で色々な意味合いで用いられます。 ここでいう「リソース」はこの文章内ではこのように名前をつけて呼ぶ、という程度の意味で捉えてください。

リソースの例をあげていけばきりがないのですが、いくつか代表的なものを取り上げましょう。

コンピューター

あなたの手元にはコンピューターがありますか?いえ、答える必要はないですね。この文章を目にしているということは、そういうことですね。

当然のことですが、アプリケーションを動かすためにはコンピューターが必要です。

オンプレミスであれば機器を購入するかレンタルするかして、データセンターに配置しなければなりません。あるいはVPSを契約してもいいかもしれません。 もちろんAWSやGCPなどのクラウド環境で仮想コンピューターを用意しても良いでしょう。

ネットワーク

あなたのコンピューターは何かしらのネットワークに繋がっていますか?いえ、答える必要はないですね。この文章を目にしているということは、そういうことですね。

インターネットを通じてサービスを提供するのであれば、何かしらインターネットへの接続性が必要になります。 あるいは、既存のネットワーク内に配置するのであれば、多少のネットワーク構成の変更が必要になるかもしれません。 また、接続性を確保することと同様に、不必要な接続を遮断する設定も重要です。

このノリももう飽きてきませんか?私は飽きました。ですので、あとはまとめていくつか紹介しましょう。

ロードバランサー、DNS、TLS証明書……、etc

これらは必須というわけではありませんが、ほとんどの場合必要になるでしょう。

どれも購入・あるいは契約し、設定し、配置しなければなりません。

動かし続けるのはもっと大変

さてアプリケーションを動作させるために必要ないくつかのリソースを確保しました。アプリケーションは正しく動作し、目的を完全に達成しました。

素晴らしいことです!ではこれで全ては解決でしょうか?

そうならばどれほど良かったでしょう……。

f:id:hueless:20201208105626p:plain

ほとんどの場合、アプリケーションは変更され続けます。あなたは今アプリケーションを変更しました。ではそれをどのようにすれば反映できますか?

変更前のアプリケーションは動いていて、以前と変わりなく使われています。これをダウンタイムなく新しいものに置き換えるためにはどのような手順が必要でしょうか?

あるいは、あなたのアプリケーションは非常に人気が高く、多くのユーザーの要求を満たすために、100台のサーバで動いているかもしれません。 どのようにして100台のサーバに同時に、齟齬なく変更を反映させれば良いでしょうか?

このようなシナリオはたくさん考えられます。もちろんありうる全てのシナリオを想定するのは不可能ですし、コストに見合いません。 しかしながら、日常的に発生するようなシナリオに対してはどのように対処するかを想定しておくべきでしょう。

アプリケーションを作ることだけが仕事ではない

これまで紹介してきた通り、アプリケーションは作る場面だけでなく、実際に動作させる場面でもたくさんの考慮すべきこと、行うべきことがあります。 いうまでもなく、それは知識や経験、技術が必要な、専門的な作業です。

ansibleやterraformは、アプリケーションを動作させるために必要になるこれらの作業を錯誤なく、確実に、簡単に行えるようにするためのソフトウェアです。

ansibleとterraform

ansibleやterraformはどのようにこのような作業の役に立つのでしょうか?

それを説明するためにはまずInfrastructure as Code(以後IaCと省略)の概念を説明する必要があります。 なぜなら、ansibleとterraformはIaCを実現するためのツールだからです。

そもそも、Infrastructure(口語ではもっぱらインフラと省略されますので、この文章でも以降インフラと表記します)とは何でしょうか?

前項であげたリソースの例はどれもインフラを構成する要素ですが、他にもデータベースやミドルウェアなどを含む場合もあります。 あるいはCI環境などもインフラの一部だと捉える人もいるかもしれません。

はっきりとこういうものだ、という定義は難しいのですが、私は「アプリケーションを動作させるに足る環境」であると理解しています。

つまり

サービス=アプリケーション+インフラ

であると言えます。

IaC

サービスを提供するためのインフラを準備する時、IaCを用いず従来通りの手法で行う場合、一般的にはドキュメントやチェックシートによって管理することになります。 小規模かつ変更の少ないインフラであればこのような手法でも十分に運用可能です。

しかし、インフラの規模が大きくなるにつれ、それぞれのリソースの相互作用が増え、構造が複雑になっていきます。 それだけでなく、管理するリソースが増えるということは、それだけ変更が必要になる頻度も上がります。

このような場合、ドキュメントやチェックシートによる管理は実際のリソースとの差異が生まれやすくなり、その差異を確認することも困難になっていきます。

この課題を解決するための手法がIaCです。 アプリケーションは何らかの表現形式で記述したコードによって表現されています。 IaCは、この考え方をインフラに応用した手法と言えます。

考え方としては単純で 「インフラを構築するためのアプリケーションを作り、それによってリソースの変更を人間の手ではなく、コンピューターにやらせよう。 インフラが正しく構築できるかどうかはそのアプリケーションのコードの正しさによって管理しよう」 というものです。

この手法によって、インフラ構築の自動化・均質化・明文化・履歴管理が可能になります。また、これらが可能になることにより再現性が非常に高く保てます。

自動化

従来手法では人間が手で行なっていた変更作業を、コンピュータが行うことで自動化が可能になります。 また、原則的には記述されたことと実際の差異が生まれないため、リソースの管理が容易になります。

均質化

従来手法ではドキュメントや実際の変更作業のクオリティ、読みやすさ・漏れ・ミスが担当の人間の経験に左右されていたのが、ある程度均質化されます。 もちろんコードであっても担当の人間によってクオリティは多少揺らぎは生まれますが、自然言語による文章表記よりもその幅は大きく減少します。

明文化

自然言語文章ではどうしても人間の解釈次第になってしまい、曖昧になってしまったり、当たり前に行うことなのでわざわざドキュメントに書かないというようなことがあります。 IaCでは書かれたコードの解釈も実行もコンピューターが行うため、曖昧さが排除され、インフラを構成するリソースのあるべき状態を明文化することが可能になります。

履歴管理

これは厳密にはIaCの特性というわけではないのですが、実際には改善することがほとんどです。 現代ではアプリケーションのコードは何かしらのバージョン管理システム(多くの場合gitでしょう)によって履歴管理が行われ、版ごとの差分や変更の意図などを記録することが可能になっています。 IaCではインフラを構成するリソースはコードによって表現されるので、従前より利用しているこのようなバージョン管理システムを利用することで、アプリケーションと同様に履歴を管理することが容易になります。

IaCの2つのアプローチ

現在、IaCには主に手続き型と宣言型の2つのアプローチがあります。 これはアプリケーションコードを記述する手法に手続き型・オブジェクト指向型・関数型のようにいくつかのアプローチがあるのと同じような状況です。

手続き型

手続き型はその名の通り、インフラを構築していく手順を記述していくアプローチです。

メリットは、単に手順をそのままコードに書き下していくような形になるため、最初の障壁が低く、初学者でも詰まりにくいことです。 また、コードも従来アプリケーション開発で用いられてきた汎用のプログラミング言語であることも多く、自由度が高いことも挙げられます。

デメリットは、冪等性の担保に対してのサポートが弱いことです。また、手順の積み重ねになるので、全体としての意図の見えにくくなる点や、大きな変更に弱いという点も挙げられます。 そのほか、自由度が高いが故にバグが入りうることもデメリットと言えるでしょう。

宣言型

宣言型はインフラを構成するリソースの状態を記述していくアプローチです。現在の状態から宣言された状態への差分を自動的に埋めるように処理が行われます。

メリットは、最終的にリソースがあるべき状態を記述するため、バグが起こりにくく、冪等性も担保されやすい点や、全体としての意図が見えやすくなる点が挙げられます。

デメリットは、専用のDSLが用いられることが多いことや、手続き型より抽象的な記述になるため、最初の障壁が高いことが挙げられます。 また、手続き型よりも自由度が低いことが多く、アプリケーションコードを書きなれた人間からすると、フラストレーションを感じることが多いように思います。

ansibleとterraform

さてこの時点までざっと5000字ほどあるのですが、ようやく本題です。みなさんこの文章の本題を覚えていますか? 私は忘れかけていました。なので改めて記載しますが、この文章は「ansibleとterraformって何が違うんですか?」という疑問の答えになることを目標に書かれています。

では具体的に何が違うのでしょうか? ここまでの文章を読んだのであればある程度想像がつくでしょうが、それぞれIaCを実現するアプローチが手続き型と宣言型であるという点が一番大きな差異であると言えます。

ansible

ansibleは手続き型アプローチを採用しており、構成手順をplaybookと呼ばれるファイルにYAMLで記述するのが特徴です。 ansible自体はPythonで記述されており、プラグインもPythonで記述することができます。

類似の手続き型アプローチを採用したツールとして、chef、puppet、fabricなどがあります。これらの中でのansibleの特徴は、よりシンプルで扱いやすい点が挙げられます。 ただ、これらのツールでできることにはそれほど大きな違いはない印象です。各々の組織の要件にあったものを用いると良いでしょう

terraform

terraformは宣言型アプローチを採用しており、hclという独自言語でtfファイルにリソースを宣言するのが特徴です。 また、terraformはリソースの状態を管理するためにstateファイルというjson形式のファイルを用います。 このため、既存のリソースをterraformでの管理に切り替えるのには比較的手間がかかります。 リソースをterraformで管理したいのであれば、多少手間でも最初からterraformを使って定義することをお勧めします。

terraform自体はGoで記述されていますが、プラグイン(実際にはproviderやprovisionerと言います)はterraform本体のプロセスとgrpcで通信を行う別のプロセスとして実行されるため、各自好きな言語で記述することができます。

使い分け

これまで述べてきたように、ansibleとterraformではIaCに対するアプローチが異なります。ansibleは手順を自動化し、terraformは状態管理を自動化します。 弊社では主にterraformをインフラの構築全般に使い、ansibleはサーバ単体の構築に用いています。

サーバ単体の構築は大抵の場合、リソース間の相互作用がそのサーバ単体の中で閉じられているため、全体像がそれほど複雑になりません。 また、サーバの中に配置したいものは一般的なミドルウェアであったり、あるいは自前で開発したバッチスクリプトであったり、多岐に渡るため、シェルスクリプトと一対一のように記述できるansibleが扱いやすく、採用の動機になります。

対して、VPCやセキュリティグループ、RDBなどはリソースごとに相互作用があり、どこかで定義した値を別の場所で使う、ということが多くあります。このようなシーンではterraformはうまく相互関係を解決してくれます。 また、稀にではありますがごく一時的に手作業でパラメータを変更してしまう場合もある(実際はこのような作業はあまりよくないですが、軽微な変更の検証など)ので、冪等性をツール側で担ってくれる点も採用理由の一つです。

弊社ではこのように使い分けをしていますが、近年はほとんどのサービスをECSかEKSの上に構築しており、サービスの管理はECSであればecs-deploy、EKSであればkustomizehelmを使っており、個々のコンテナはDockerfileで管理されているため、相対的にansibleの利用頻度は下がっています。

おわりに

以上、ansibleとterraformの違いについて、それぞれの特徴の説明と、弊社での使い分けについて解説をしました。

今回はそれぞれのツールの具体的な使い方やプラクティス、tipsなどの説明には踏み込めませんでしたが、いずれ機会があればそのあたりにも触れてみたいと思います。