terraformとapex infraの依存関係

背景

AWSの構成管理にterraformを使っているんだけど、Lambda関数とそれに関連するAWSリソースの管理はapexを使っている。apexの方がLambda関数のバージョニングができたり、コードの依存関係を簡単にzipにまとめてアップロードできたりして便利なのだ。

apexには、apex infraというコマンドがあり、Lambda関数にAWS関連するリソース(パーミッションとかCloudWatch Logsとか)を管理できる。実際には内部的にterraformを使っている。

課題

terraformで管理するリソースとapex infraで管理するリソースに明確なボーダーラインを引くことは難しい。apexで管理するLambda関数はterraformで管理するさまざまなリソースと依存関係になっていることがほとんどだからだ。どこで何が管理されているのかわからなってくる。

方針

こういうときの考え方として、依存関係の方向性を単方向にすると良かったりする。apex infraで管理するリソースはterraformで管理するリソースを参照することができるけど、逆にterraformで管理するリソースはapex infraで管理するリソースを参照できない、というルールを作る。

実装

apex infraからterraformのリソースを参照するためにterraform_remote_stateを使う。ここでは例として、apexで管理するLambda関数をterraformで管理するSNSトピックにsubscribeしたいとする。

data "terraform_remote_state" "global" {
  backend = "s3"

  config {
    region = "ap-northeast-1"
    bucket = "my-terraform"
    key    = "global"
  }
}
resource "aws_sns_topic_subscription" "lambda" {
  topic_arn = "${data.terraform_remote_state.global.my_topic}"
  protocol  = "lambda"
  endpoint  = "${var.apex_function_arns["my_function"]}"
}

SNSトピックのARNは事前にoutputでremote stateとして公開しておく必要がある。

こうすることで、terraform側からapexで管理するLambda関数を参照せずに済んでいる。Lambda関数を参照するリソースはapex infraで管理し、そうでないリソースはterraformで管理するという方針でうまく整理できそうだ。