(local-execつかったほうがいいよ) aws_spot_instance_request でインスタンスに terraform 管理下のタグをつける
はじめに
おとなしく local-exec
使ったほうが時間が節約されます。
背景
terraform の aws provider でスポットインスタンスを利用するには、 aws_spot_instance_request
を使う。
ただ、この resource には作成されたインスタンスに対するタグ付与機能が ない 。タグをつけるには事後処理が必要となる。
resource aws_spot_instance_request
の tag
の仕様について
aws_spot_instance_request
は、言ってしまえば aws_instance
にスポットインスタンス起動に必要な設定項目を追加したものである。
そのため、 tags
の適用対象は スポットリクエスト であり、インスタンスではない。
では、インスタンス側にそれを適用する方法があるのかというと、ない。
issue はあった
皆おなじことを思うためか、issue がある。 issue issue2
AWS が API として用意していない方法を aws provider 独自に実装することは無い (っぽい) ため、多分今後もない。
回避方法
local-exec
を使う
issue にて紹介されていた方法。
リソース作成後、 local-exec
を使って AWS CLI を実行する方法である。
シンプルで十分な方法なのだが、タグが terraform の管理対象から外れてしまう。
local-exec
を使う以上仕方ないのだが、terraform を使う意義が (所詮タグだが) 薄れてしまうのでできれば避けたい。
aws_ec2_tag
を使う (この記事で説明)
タグも terraform で管理したいならば、 aws_ec2_tag
を使えばよい。
しかし、単に aws_spot_instance_request
と aws_ec2_tag
を抱き合わせて使うと問題が起きる。
aws_ec2_tag
では resource_id
にインスタンス ID を与える必要があるが、 aws_spot_instance_request
の出力から spot_instance_id
が取得できるようになるにはタイムラグがある。
そして、そのタイムラグを terraform は考慮してくれない。 このような挙動が起きうることはドキュメントにも記載されている。
These attributes are exported, but they are expected to change over time and so should only be used for informational purposes, not for resource dependencies:
spot_bid_status
- The current bid status of the Spot Instance Request.spot_request_state
The current request state of the Spot Instance Request.spot_instance_id
- The Instance ID (if any) that is currently fulfilling the Spot Instance request.public_dns
- The public DNS name assigned to the instance. For EC2-VPC, this is only available if you've enabled DNS hostnames for your VPCpublic_ip
- The public IP address assigned to the instance, if applicable.private_dns
- The private DNS name assigned to the instance. Can only be used inside the Amazon EC2, and only available if you've enabled DNS hostnames for your VPCprivate_ip
- The private IP address assigned to the instancetags_all
- A map of tags assigned to the resource, including those inherited from the provider default_tags configuration block.
そのため、タグ付与は別 tfstate に分けることとする。 1
スポットリクエストを作成した tfstate に aws_spot_instance_request
を output
し、別 terraform から参照する。
出力されているスポットリクエスト情報にある spot_instance_id
をもとにインスタンスを取得し、 aws_ec2_tag
でタグを付与する。
local-exec
に頼らない方法としてこちらをやってみたので内容を説明する。
スポットリクエスト作成側
resource "aws_spot_instance_request" "instance" { for_each = local.mariadb_instances # インスタンスに関する 各種設定 } output "spot_request" { value = aws_spot_instance_request.instance }
タグ付与側
data "terraform_remote_state" "state" { # 利用している tfstate 保存方法にあわせてよしなに設定する } resource "aws_ec2_tag" "tag" { resource_id = data.terraform_remote_state.state.outputs.spot_request.spot_instance_id key = "Name" value = "spot-instance" }
終わりに
脚注でも書いたが、正直 local-exec
でいい。 aws_spot_instance_request
を使うようなシチュエーションは検証がほとんどなので。
それか AutoScaling つかって起動テンプレートに書けばいいと思う。でも固定 Private IP とかしたい場合は無理なのでやっぱり local-exec
でいいとおもう。
追記
output するタイミングで spot_instance_id
が確定していないので、「スポットリクエスト作成側」の terraform は 2 回実行する必要があるので、やっぱ local-exec
でいいと思います。
-
この時点でめんどい。そもそも
aws_spot_instance_request
を使うような状況は検証時なので、それならタグが terraform 管理から漏れてもどうでもいいため、local-exec
でいいと思う。↩