TerraformでNAT Gatewayを作る。EKS Fargateの検証する時に、EKSリソースと一緒に自動生成したいからだ。

 

ちなみに手動作成の手順は以下。
AWS NATゲートウェイの作成と設定

 

NATゲートウェイを作るだけなら、以下コードだけでよい。

nat.tf

###########################################
# EIP
###########################################

resource "aws_eip" "poc_eip" {
  vpc              = true
}

###########################################
# NAT Gateway
###########################################

resource "aws_nat_gateway" "nat_gw" {
  allocation_id = aws_eip.poc_eip.id
  subnet_id     = var.public-a

  tags = {
    Name = "NAT-for-PoC"
  }

  # To ensure proper ordering, it is recommended to add an explicit dependency
  # on the Internet Gateway for the VPC.
  # depends_on = [aws_internet_gateway.example]
}

 

先にEIPを作ってNATゲートウェイに割り当てている。このEIPはリソースに関連付けている限りは課金対象外だが、関連付けリソースから外れると課金対象になる。このためNATゲートウェイ削除時にはEIPもリリースしないといけないが、忘れがちなので要注意である。Terraformで作成するならTerraform destroy時に一緒にリリースされるはずだから安心だ。(しかし未検証)

 

で、上記をapplyするとEIPとNATゲートウェイが作成される。しかし実際に使用できるようにするにはルートテーブルの設定が必要なのである。これが、よくわからなくてハマった。当初はaws_route_table_associationで設定可能か?と思って試してみた。しかしドキュメントを見ると設定可能なのはインターネットゲートウェイかサブネットIDのみで、NATゲートウェイは含まれていない。それでも無理矢理コードを書いてapplyしてみたら、無効なパラメータなんだよボケ!と怒られた。

Error: error creating Route Table (rtb-1234567890123445) Association: InvalidParameterValue: invalid value for
  parameter gateway-id: nat-02d182b4d52eb6aa7
    status code: 400, request id: ae4cb491-23d6-41e8-b7ef-e01983cabef8
    (snip)

 

しばし思いを馳せて、NATゲートウェイの関連付けはaws_route_table_associationではなくroute_tableでやればいいらしいのはなんとなく分かった。しかしドキュメントを読んでも設定項目がわからん…
Terraform - route_table

 

そこで、ルートテーブルの設定をマネコンから手動で実施して、その状態をimportして探ってみた。importするため以下のような最低限のtfコードを用意してimportコマンドを実行する。

rt-prv.tf

resource "aws_route_table" "rt_prv" {
}

 

$ terraform import aws_route_table.rt_prv rtb-1234567890123445

 

実行後のtfstateを確認する。以下は対象ルートテーブルの辺りだけ抜粋。

{
      "mode": "managed",
      "type": "aws_route_table",
      "name": "rt_prv",
      "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
      "instances": [
        {
          "schema_version": 0,
          "attributes": {
            "arn": "arn:aws:ec2:ap-northeast-1:0123456789010:route-table/rtb-1234567890123445",
            "id": "rtb-1234567890123445",
            "owner_id": "0123456789010",
            "propagating_vgws": [],
            "route": [
              {
                "carrier_gateway_id": "",
                "cidr_block": "0.0.0.0/0",
                "destination_prefix_list_id": "",
                "egress_only_gateway_id": "",
                "gateway_id": "",
                "instance_id": "",
                "ipv6_cidr_block": "",
                "local_gateway_id": "",
                "nat_gateway_id": "nat-02d182b4d52eb6aa7",
                "network_interface_id": "",
                "transit_gateway_id": "",
                "vpc_endpoint_id": "",
                "vpc_peering_connection_id": ""
              }
            ],
            "tags": {
              "Name": "dev-private-rt"
            },
            "tags_all": {
              "Name": "dev-private-rt"
            },
            "timeouts": {
              "create": null,
              "delete": null,
              "update": null
            },
            "vpc_id": "vpc-1234567890123445"
          },
          "sensitive_attributes": [],
          "private": 
          (snip)
          

 

上記の値を参考にroute_tableでNATゲートウェイの関連付けができそうではある。しかしここで、今更ではあるがふと気がついた。

もともと今回使っているサブネットやルートテーブルはTerraform外で作成したものである。既存の管理外ルートテーブルを下手にTerraformで操作して干渉させるのはNGじゃないかと。そして、importを実行した時点でTerraform管理下になってしまっているが、確認したかっただけなので管理下に置くつもりはないのである。(なので、今後のTerraform作業はこのtfstateから干渉されないパスで実行する)

 

ネットワーク周りもすべてTerraformで作成したものであれば使い終わったらすべてdestroyで問題ないが、そうでないとなかなか厄介だ。かといってそのために今からコード追加したり書き換えるのも面倒だ。

で、考えた挙句、ルートテーブル関連付けだけは手動でやることにした。本来は全自動でやりたいが、現状はNATゲートウェイ作成とEKSクラスタ作成を2段階で分割する必要がある。なかなか、思い通りにはいかない。まぁこういうジレンマは、TerraformだろうがCFnだろうがついて回る。試行錯誤でやっていくしかない。

 

ところで自分はこれまでTerraformインポートは構成の確認のために使っていたが、こういう目的で使うこともあるのか。備忘録。
Terraform import機能を使って既存のVPCとサブネットをTerraformで管理できるようにする

 

追記
Terraform import後の結果を見やすく出力するコマンドがあったのを思い出した。

$ terraform state show [AWSリソース名].[Terraformリソース名]

 

$ terraform state show aws_route_table.rt_prv
# aws_route_table.rt_prv:
resource "aws_route_table" "rt_prv" {
    arn              = "arn:aws:ec2:ap-northeast-1:0123456789010:route-table/rtb-01234567890123456"
    id               = "rtb-01234567890123456"
    owner_id         = "0123456789010"
    propagating_vgws = []
    route            = [
        {
            carrier_gateway_id         = ""
            cidr_block                 = "0.0.0.0/0"
            destination_prefix_list_id = ""
            egress_only_gateway_id     = ""
            gateway_id                 = ""
            instance_id                = ""
            ipv6_cidr_block            = ""
            local_gateway_id           = ""
            nat_gateway_id             = "nat-02d182b4d52eb6aa7"
            network_interface_id       = ""
            transit_gateway_id         = ""
            vpc_endpoint_id            = ""
            vpc_peering_connection_id  = ""
        },
    ]
    tags             = {
        "Name" = "dev-private-rt"
    }
    tags_all         = {
        "Name" = "dev-private-rt"
    }
    vpc_id           = "vpc-01234567890123456"

    timeouts {}
}

 

 

Travel Travel


関連がありそうな記事