zaki work log

作業ログやら生活ログやらなんやら

[Terraform] EC2プライベートIPアドレスの固定とパブリックIPの割り振り

AWSのEC2のプライベートIPは、使用するサブネットアドレスから自動で割り当てられるが、複数のEC2間で通信したい場合などであらかじめ固定したIPアドレスを使いたいという場合にTerraformでどう設定するかについて。

固定プライベートIPの設定

通常はaws_instanceリソースでパラメタ内にサブネットを指定してEC2を作るだけのところを、

  • aws_network_interfaceでアドレス指定のENIを作る
  • aws_instanceで↑のENIを使ってEC2を作る

という手順で構築すれば良い。
Terraformコードで実装すると以下で、10.1.3.1を固定で割り当てる場合(サブネットは10.1.3.0/24)。

private_ipsに指定しているアドレスはsample_subnetの範囲で使用可能なアドレス。

# IPアドレス固定化のためのENI作成
resource "aws_network_interface" "eni_fixed_ipaddr" {
  subnet_id         = aws_subnet.sample_subnet.id
  private_ips       = ["10.1.3.1"]
  security_groups   = [aws_security_group.sample_sg.id]
}

# network_interfaceで定義したENIを指定
resource "aws_instance" "sample_server" {
  ami               = var.server_ami_id
  instance_type     = var.server_instance_type
  key_name          = aws_key_pair.sample_ssh_keypair.id

  network_interface {
    device_index = 0
    network_interface_id = aws_network_interface.eni_fixed_ipaddr.id
  }
}

もともとaws_instanceのパラメタで指定していたサブネットとセキュリティグループ設定をENI側に移動する。

パブリックIP使用との併用

上記の定義でプライベートIPは固定できるが、同時にパブリックIPを割り当てるためのassociate_public_ip_addressを使うと、network_interfaceの設定と競合してエラーになる。

resource "aws_instance" "sample_server" {
  ami                         = var.server_ami_id
  instance_type               = var.server_instance_type
  key_name                    = aws_key_pair.sample_ssh_keypair.id
  associate_public_ip_address = true  # これがNG

  network_interface {
    device_index = 0
    network_interface_id = aws_network_interface.eni_fixed_ipaddr.id
  }
}

エラーは以下。

╷
│ Error: Conflicting configuration arguments
│ 
│   with module.dev.aws_instance.sample_server,
│   on dev/main.tf line 119, in resource "aws_instance" "sample_server":
│  119: resource "aws_instance" "sample_server" {
│ 
│ "network_interface": conflicts with associate_public_ip_address
╵

これを回避するには、EC2のパラメタではなく、使用するサブネットのパラメタで指定する。
aws_subnetのパラメタにmap_public_ip_on_launchがあり、これをtrueにすることでサブネット内のEC2は自動でパブリックIPが割り当てられる。

resource "aws_subnet" "sample_subnet" {
  vpc_id                  = aws_vpc.sample_vpc.id
  cidr_block              = "10.1.3.0/24"
  availability_zone       = data.aws_availability_zones.available.names[0]
  map_public_ip_on_launch = true
}

このサブネット使用したENIをEC2で使うように構成すれば「プライベートIPを固定しつつパブリックIPを使用」できるようになる。

環境

$ terraform --version
Terraform v1.9.1
on linux_amd64
+ provider registry.terraform.io/hashicorp/aws v5.43.0

Your version of Terraform is out of date! The latest version
is 1.9.2. You can update by downloading from https://www.terraform.io/downloads.html