まーぽんって誰がつけたの?

iOS→Scala→インフラなおじさん技術メモ

Terraform入門 #1 Terraformはいいぞ

前書き

人が書いたterraformのメンテぐらいは見よう見まねでやってるけど、一からやれと言われたらよく分からない。そう思ってた1年前ぐらいの自分を思い出しながら気軽に入門してもらうにはどうすればいいか考えてみました。 Terraformはこわくないしほんとに便利なので、その辺を感じ取ってもらえればと思います。

f:id:masato47744:20170707194146p:plain

Terraformは何であって何でないのか、そしてなぜ必要なのか

そもそも、学習するにあたってTerraformって最高便利というところが分かってないと、なんでやらなあかんねんとなりそうだなと思ったので、まずはなぜ必要かを説明していきます。

Terraformってインフラのコードで書くやつでしょ?

terraformはインフラのリソースをコードで書けて実際に作成まで行ってくれます。この辺はだいたい知ってると思います。 ただ、Terraformはchefとかansibleといったプロビジョニングツールとはちょっとレイヤーが違います

terraformはインフラの土台を作るもの、chefとかはそれに味付けをしていくという役割になります。雑に示すとこんな感じです。

f:id:masato47744:20170707194326p:plain

Terraformは何をしてるのか

terraformは内部的には単にユーザーが書いたインフラの設定を見てAPIを呼んでるだけです。AWSならAWSのインフラの設定を書いて、単に裏側でAWSのAPIを呼んでるだけです。

f:id:masato47744:20170707194355p:plain

じゃあなんでわざわざterraformなるものをかませないといけないのか。AWSのAPIを呼べばいいじゃんとなりますよね。次からは、実際にインフラを管理していくときに起きる問題点をあげながら、terraformのいいところを見ていきます。

Terraformのいいところ

terraformのいいところは、API呼び出しをしてくれるだけでなく、その状態を保持してくれます。また、リソース同士の依存関係も表現してくれます。それぞれみていきましょう。

インフラの状態を保持する

AWSのGUIだと現在の状態が想定しているものなのか、誰かが手動で変更したかなど分かる術はありません。操作ログを見れば分かることは分かりますが現実的じゃありません。

この問題をterraformがどう解決しているかというと、tfstateというjsonファイルに、テキストでインフラのリソースの情報を保存することで状態を記憶するというアプローチをとっています。結構単純です。

リソースを新しく追加したり、削除したり、パラメータを少し変更したい場合は、このtfstateファイルと実際の状況をAPIを呼び出して確認し、必要最低限の差分のみ反映(API呼び出し)をしてくれます。もちろん差分がなければ何もしません。

f:id:masato47744:20170707194424p:plain

依存関係

依存関係については、この辺はAWSとかでいざAPIをたたいてみないと分からないとは思うんですが、何かリソースを作るときには必ず他のリソースの情報が必要になると言えます。

例えば、EC2のインスタンスのIPアドレスを使ってDNSレコードを作りたいという場合があったとき、これをAPIでやるとこんな感じで呼び出しが必要です。

f:id:masato47744:20170707194447p:plain

  1. EC2作成APIたたく
  2. 作り終わるのをしばし待つ
  3. 2のIDとかを指定して、EC2の詳細情報取得APIを呼ぶ
  4. IPアドレスをjsonから見つけてくる
  5. 4のIPアドレスをRoute53のレコード作成APIたたく

これが複数台ともなるとやってられなくなるでしょう、また、実際はもっと複雑な依存関係を持っています。

terraformなら、こんな感じで書いて1回実行するだけで、terraformが賢くAPI呼び出しをしてくれます。

resource "aws_instance" "web" {
  ami_id        = "ami-123456"
  instance_type = "t2.micro"
}

resource "aws_route53_record" "www" {
  zone_id = "Z12345678"
  name    = "abc.example.com"
  type    = "A"
  ttl     = "300"
  records = ["${aws_instance.web.public_ip}"]
}

上の例で、recordsのところに、aws_instance.web.public_ipという自分で書いたまだ実際に作成されていないリソースのIPアドレスを設定することができています!ここがすごいところで依存関係が記載できていることになります。 ソースの詳細はあまり気にせずここでは雰囲気を感じ取ってください。

複数プロバイダにまたがれる

さっきの例で、例えばだけど、AWSで色々作ってるんだけど、なんかDNSだけは会社の制度で、別のサービスで管理しないといけない。そんなことがあった場合は、依存関係はもっと複雑になります。AWSのAPIの知識に加え、その別のサービスのAPIの知識も必要です。 また、呼び出し方も独特の違いがあるでしょう。

こんなときもTerraformは便利で、Terraformにはプロバイダと呼ばれる概念があり、これはAWSやGCPなどクラウドプラットフォームなどが主なもので色々用意されています。AWSは用意されているプロバイダの一つに過ぎないのです。 プロバイダは自作することもできますが、公式にあるもので基本的には困らないと思います。

先ほどの例で、DNSだけは、DNSimpleというサービスを使うことになったとしましょう。そんなときは、先ほどのaws_route53_recordの部分の設定をdnsimple_recordに変えて、providerの情報を追加してあげるだけでいいのです。 DNSimpleのAPI呼び出しってどうやるんだろうって調べる必要がないのがすごいところです。

resource "aws_instance" "web" {
  ami_id        = "ami-123456"
  instance_type = "t2.micro"
}

provider "dnsimple" {
  token = "hogehogetoken"
  account = "piyopiyo"
}

resource "dnsimple_record" "www" {
  domain = "example.com"
  name   = "abc"
  value  = "${aws_instance.web.public_ip}"
  type   = "A"
  ttl    = 300
}

まとめ

どうでしょうか、Terraformのありがたみが分かったでしょうか?他のツールじゃなぜダメなんだとか、あれじゃダメなのとか疑問が湧いたら調べたり、質問してみたりしてください。きっと理解が深まると思います。 次回は、Terraformをもっと身近に感じるために気軽にできる環境で説明していこうと思います。

mpon.hatenablog.com