これは terraform Advent Calendar 2020 の12/7の記事です。
- 昨日(12/6)は entertvl さんの terraform-provider-esxi を使って自宅 ESXi サーバに VM を立てよう でした。ESXiへもTerraform使えるのか、、と初めて知りました!
- 明日(12/8)は transnano さん です。
書くこと
この記事では以下を書きます。できたサンプルコードはこちら。
- Linux OSの /etc/hosts ファイルから
- Terraform の aws_route53_record のための
- for_each を使ったパラメタを生成する
これまでの /etc/hosts 運用はつらひ..
日頃運用している環境はAWSとオンプレミスのハイブリッド構成です。管理するリソースにはVMサーバやNW機器などが数多くあり、踏み台サーバの /etc/hosts にそれぞれのIPとホスト名を記載していました。*1
#/etc/hosts 192.168.1.21 l2sw01 192.168.1.22 l2sw02 192.168.1.31 l3sw01 192.168.1.32 l3sw02 192.168.2.11 web01 192.168.2.12 web02 192.168.10.11 db01 192.168.10.12 db02
この運用の問題点は/etc/hostsが踏み台サーバ上にしかないため、それ以外の場所でホスト名を利用できないことです。 hostsファイルを必要な全ての場所にデプロイしようにも、展開したい場所はサーバや個人のPCなど幅広くあるため現実的ではありません。
DNS(Route53 Private hosted zones)を使って問題解決する
hostsファイルのデプロイが問題であれば、それを解決するのがDNSです。AWSのRoute53には インバウンド エンドポイント 機能があり、他VPCやダイレクトコネクト経由のオンプレミスからも Private hosted zone で管理された名前解決を行うことができます。
Terraformを書く
Route53 が使えるなら、それはTerraformの出番です。既存のhostsファイルは数百行に育っていたので楽に変換する方法を検討しました。
[morihaya@jump ~]$ wc -l /etc/hosts 408 /etc/hosts
検討した方法は以下で、シンプルにかけるfor_eachを選択しました。
- 普通に書く -> 行数も増えるしメンテもしづらいのでやりたくない
- ipとホスト名を渡すだけでOKなmoduleを作る -> moduleはterraform registryのものしかできれば使いたくない
- for_each -> シンプルでシュッとかけて読みやすい
以下がテンプレートで、生成したパラメタを挿入するだけです。
resource "aws_route53_record" "private" { zone_id = aws_route53_zone.private.zone_id for_each = { <ここへ生成したパラメタを入れる> } name = each.key type = "A" ttl = "300" records = [each.value] }
for_each では key = value
のように記述するため、hostsファイルからのパラメタ生成は以下のような簡単なシェル芸で行いました。 *2
$ cat hosts.sample | awk '{printf("\"%s.morihaya.tech\" = \"%s\"\n",$2,$1)}' "l2sw01.morihaya.tech" = "192.168.1.21" "l2sw02.morihaya.tech" = "192.168.1.22" "l3sw01.morihaya.tech" = "192.168.1.31" "l3sw02.morihaya.tech" = "192.168.1.32" "web01.morihaya.tech" = "192.168.2.11" "web02.morihaya.tech" = "192.168.2.12" "db01.morihaya.tech" = "192.168.10.11" "db02.morihaya.tech" = "192.168.10.12"
出来上がったもの
こうして出来上がったものがこちらです。 ホスト名とIPが並びますのでメンテナンスもしやすいと感じています。
data "aws_vpc" "default" { default = true } resource "aws_route53_zone" "private" { name = "morihaya.tech" vpc { vpc_id = data.aws_vpc.default.id } tags = { "Make" = "Terraform" } } resource "aws_route53_record" "private" { zone_id = aws_route53_zone.private.zone_id for_each = { "l2sw01.morihaya.tech" = "192.168.1.21" "l2sw02.morihaya.tech" = "192.168.1.22" "l3sw01.morihaya.tech" = "192.168.1.31" "l3sw02.morihaya.tech" = "192.168.1.32" "web01.morihaya.tech" = "192.168.2.11" "web02.morihaya.tech" = "192.168.2.12" "db01.morihaya.tech" = "192.168.10.11" "db02.morihaya.tech" = "192.168.10.12" } name = each.key type = "A" ttl = "300" records = [each.value] }
まとめ
以上、/etc/hosts での運用を Terraform の aws_route53_record + for_each を使って Private zone 運用に切り替えた話でした。
for_each 関数は バージョン 0.12.6
から追加されましたが、先日(2020-12-02)には 0.14がGAとなり "Concise Diff
" など良い機能が追加されましたし、今後も Terraform の進化が楽しみですね。