EC2インスタンス起動時に自動割り当てされるパブリックIPアドレスを解除する方法

Amazon Web Servicesは2023年7月30日にパブリックIPv4アドレスの新しい料金体系を発表しました。

 

今までEC2インスタンス起動時に自動で割り当てられるパブリックIPv4アドレスは無料でしたが、新しい料金体系では1時間当たり0.005ドルかかるそうです。

 

みなさんのクラウド環境にパブリックIPv4アドレスが必要ではないのに割り当てられているEC2インスタンスはありませんか?

 

今回の記事では、EC2インスタンスからパブリックIPv4アドレスを解除する方法を紹介します。

 

 

パブリックIPアドレスを解除する方法

AWSが発表した新しい料金体系では、パブリックIPv4アドレスは1時間当たり0.005ドルかかるそうです。一カ月でみると日本円で500円前後と微々たるものに感じるかもしれません。

 

しかし、数十、数百のインスタンス数となると数万円になり、かつそもそもパブリックIPv4アドレスが不要なのに割り当てられているのはセキュリティ上よくありませんよね。

 

今回の記事では、EC2インスタンスからパブリックIPv4アドレスを解除する方法を紹介するのですが、

 

結論から言うと、インスタンス起動時に自動で割り当てられたパブリックIPv4アドレスを手動で外すことはできません。

 

じゃあどうすればいいのかというと、

  • 対象EC2インスタンスのAMIを作成し、
  • AMIをもとにインスタンスを再作成
  • 再作成時に"Auto-assign public IP(パブリックIPの自動割り当て)"を"Disable(無効)"で設定し、
  • [インスタンスを起動]すればいいのです。

 

それでは、やってみましょう。

 

 

■条件・準備

ec2-ip-release構成図

今回の構築はTerraformを利用してEC2インスタンスを用意します。構築するリージョンはシンガポールリージョンです。

 

AMIの作成はマネージメントコンソールを利用し、作成したAMIをもとに再度TerraformでEC2インスタンスを起動していきます。

 

 

●Terraform記述

以下のTerraformのファイルを利用してください。※コード折りたためなくてすいません、details使って折りたたむことはできてもコードが崩れちゃって断念。。。

 

 

↓main.tf
# ---------------------------
# Terraform
# ---------------------------
terraform {
  required_version = ">=0.13"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~>3.0"
    }
  }
}

# ---------------------------
# Provider
# ---------------------------
provider "aws" {
  profile = "terraform"
  region  = "ap-southeast-1"
}

# ---------------------------
# Variables
# ---------------------------
variable "project" {
  type = string
}

variable "user" {
  type = string
}

variable "myip" {
  type = string
}

 

 

↓terraform.tfvars

※各項目は環境に合わせて設定してください。

 

project = "xxxx-test"
user    = "xxxxx"
myip    = "xx.xx.xx.xx/32"

 

 

↓ec2.tf

キーペアは任意で設定してください。

 

# ---------------------------
# EC2 Instance
# ---------------------------
resource "aws_instance" "master" {
  ami                         = data.aws_ami.ec2.id
  instance_type               = "t2.micro"
  subnet_id                   = aws_subnet.public_subnet_1a.id
  associate_public_ip_address = true
  iam_instance_profile        = aws_iam_instance_profile.ec2_profile.name
  vpc_security_group_ids = [
    aws_security_group.sg1.id
  ]

  key_name = "キーペア名"

  tags = {
    Name = "${var.project}-ec2"
    User = var.user
  }

  user_data = <<-EOF
  #!/bin/bash
  sudo amazon-linux-extras install -y nginx1
  sudo systemctl start nginx
  sudo systemctl enable nginx
  EOF
}

output "master_public_ip" {
  description = "Public IP address of master-ec2"
  value       = aws_instance.master.public_ip
}

 

 

↓data.tf

 

data "aws_ami" "ec2" {
  most_recent = true
  owners      = ["self", "amazon"]

  filter {
    name   = "name"
    values = ["amzn2-ami-kernel-5.10-hvm-2.0.*-x86_64-gp2"]
  }
  #   filter {
  #     name   = "supported_root-devise-type"
  #     values = ["ebs"]
  #   }
  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
}

 

 

↓iam.tf

 

# ---------------------------
# IAM Role
# ---------------------------
resource "aws_iam_instance_profile" "ec2_profile" {
  name = aws_iam_role.ec2_iam_role.name
  role = aws_iam_role.ec2_iam_role.name
}

resource "aws_iam_role" "ec2_iam_role" {
  name               = "${var.project}-ec2-iam-role"
  assume_role_policy = data.aws_iam_policy_document.ec2_assume_role.json
}

data "aws_iam_policy_document" "ec2_assume_role" {
  statement {
    actions = ["sts:AssumeRole"]

    principals {
      type        = "Service"
      identifiers = ["ec2.amazonaws.com"]
    }
  }
}

resource "aws_iam_role_policy_attachment" "ec2_iam_role_ssm" {
  role       = aws_iam_role.ec2_iam_role.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}

 

 

↓network.tf

 

# ---------------------------
# VPC
# ---------------------------
resource "aws_vpc" "vpc" {
  cidr_block                       = "10.0.0.0/16"
  instance_tenancy                 = "default"
  enable_dns_support               = true
  enable_dns_hostnames             = true
  assign_generated_ipv6_cidr_block = false

  tags = {
    Name = "${var.project}-vpc"
    User = var.user
  }
}

# ---------------------------
# Subnet
# ---------------------------
resource "aws_subnet" "public_subnet_1a" {
  vpc_id                  = aws_vpc.vpc.id
  availability_zone       = "ap-southeast-1a"
  cidr_block              = "10.0.1.0/24"
  map_public_ip_on_launch = true

  tags = {
    Name = "${var.project}-public-subnet-1a"
    User = var.user
  }
}

resource "aws_subnet" "public_subnet_1c" {
  vpc_id                  = aws_vpc.vpc.id
  availability_zone       = "ap-southeast-1c"
  cidr_block              = "10.0.2.0/24"
  map_public_ip_on_launch = true

  tags = {
    Name = "${var.project}-public-subnet-1c"
    User = var.user
  }
}

resource "aws_subnet" "private_subnet_1a" {
  vpc_id                  = aws_vpc.vpc.id
  availability_zone       = "ap-southeast-1a"
  cidr_block              = "10.0.3.0/24"
  map_public_ip_on_launch = false

  tags = {
    Name = "${var.project}-private-subnet-1a"
    User = var.user
  }
}

resource "aws_subnet" "private_subnet_1c" {
  vpc_id                  = aws_vpc.vpc.id
  availability_zone       = "ap-southeast-1c"
  cidr_block              = "10.0.4.0/24"
  map_public_ip_on_launch = false

  tags = {
    Name = "${var.project}-private-subnet-1c"
    User = var.user
  }
}

# ---------------------------
# Route Table
# ---------------------------
resource "aws_route_table" "public_rt" {
  vpc_id = aws_vpc.vpc.id

  tags = {
    Name = "${var.project}-public-rt"
    User = var.user
  }
}

resource "aws_route_table_association" "public_rt_1a" {
  route_table_id = aws_route_table.public_rt.id
  subnet_id      = aws_subnet.public_subnet_1a.id
}

resource "aws_route_table_association" "public_rt_1c" {
  route_table_id = aws_route_table.public_rt.id
  subnet_id      = aws_subnet.public_subnet_1c.id
}

resource "aws_route_table" "private_rt" {
  vpc_id = aws_vpc.vpc.id

  tags = {
    Name = "${var.project}-private-rt"
    User = var.user
  }
}

resource "aws_route_table_association" "private_rt_1a" {
  route_table_id = aws_route_table.private_rt.id
  subnet_id      = aws_subnet.private_subnet_1a.id
}

resource "aws_route_table_association" "private_rt_1c" {
  route_table_id = aws_route_table.private_rt.id
  subnet_id      = aws_subnet.private_subnet_1c.id
}

# ---------------------------
# IGW
# ---------------------------
resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.vpc.id

  tags = {
    Name = "${var.project}-igw"
    User = var.user
  }
}

resource "aws_route" "public_rt_igw_r" {
  route_table_id         = aws_route_table.public_rt.id
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = aws_internet_gateway.igw.id
}

 

 

↓security_group.tf

 

# ---------------------------
# Security Group
# ---------------------------
resource "aws_security_group" "sg1" {
  name        = "${var.project}-sg"
  description = "test sg"
  vpc_id      = aws_vpc.vpc.id

  ingress {
    description = "All traffic from myip"
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["${var.myip}"]
  }

  ingress {
    description = "All traffic from vpc"
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = [aws_vpc.vpc.cidr_block]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "${var.project}-sg"
    User = var.user
  }
}

 

 

以上のtfファイルを利用し、applyしてください。

 

ec2起動

 

起動できたでしょうか。

 

 

■AMI作成

起動したEC2インスタンスのAMIを作成していきます。

 

 

↓AWSマネージメントコンソールでEC2のダッシュボード画面に移動します。インスタンスを選択して、[Action]をクリックし、[Image & templates]→[Create image]を押します。

 

ami作成

 

以下の設定値で作成します。

 

項目 設定値
Image name 任意
Image description 任意
No reboot □ ※
Add new tag Key: Name, Value: 任意

 

 

ami作成画面

 

↓入力が完了しましたら、[Create image]をクリックします。

 

ami作成画面

 

↓左のナビゲーションペインから[AMI]をクリックします。作成が完了するまで、数分かかります。

 

amiのステータス

 

↓完了しますと、[Status]が[Available]となります。

 

amiのステータス

 

 

AMIの作成は以上です。

 

 

■AMIからEC2インスタンス起動

作成したAMIをもとに新たにEC2インスタンスを起動しましょう。

 

起動はTerraformで行います。マネージメントコンソールから起動しようとすると、VPCやサブネットなどのネットワーク設定・IAM インスタンスプロファイルを再度設定しなければいけません。

 

1台ならまだしも、数台以上の場合、確実に設定をミスります。ミスを減らすためにTerraformを利用して、EC2インスタンスを起動します。

 

Terraformの記述は、最初に利用したファイルに少し修正するだけで完了します。以下を利用してください。

 

二つ目のインスタンス(copy)の記述では、ami、キーペアの項目に自身のものを設定してください。そして、associate_public_ip_addressfalseであることを確認ください。’true’だとパブリックIPv4アドレスが割り当てられます。

 

# ---------------------------
# EC2 Instance
# ---------------------------
resource "aws_instance" "master" {
  ami                         = data.aws_ami.ec2.id
  instance_type               = "t2.micro"
  subnet_id                   = aws_subnet.public_subnet_1a.id
  associate_public_ip_address = true
  iam_instance_profile        = aws_iam_instance_profile.ec2_profile.name
  vpc_security_group_ids = [
    aws_security_group.sg1.id
  ]

  key_name = "saitou-keypairs"

  tags = {
    Name = "${var.project}-ec2"
    User = var.user
  }

  user_data = <<-EOF
  #!/bin/bash
  sudo amazon-linux-extras install -y nginx1
  sudo systemctl start nginx
  sudo systemctl enable nginx
  EOF
}

# ↓追記
resource "aws_instance" "copy" {
  ami                         = "AMI ID"
  instance_type               = "t2.micro"
  subnet_id                   = aws_subnet.private_subnet_1a.id
  associate_public_ip_address = false
  iam_instance_profile        = aws_iam_instance_profile.ec2_profile.name
  vpc_security_group_ids = [
    aws_security_group.sg1.id
  ]

  key_name = "キーペア名"

  tags = {
    Name = "${var.project}-ec2-copy"
    User = var.user
  }
}

# ここまで追記

output "master_public_ip" {
  description = "Public IP address of master-ec2"
  value       = aws_instance.master.public_ip
}

 

 

↓AMI IDはマネージメントコンソールから確認できます。

 

amiID

 

修正が完了しましたら、applyしてください。

 

 

■確認

AMIから新たに起動したEC2インスタンスにパブリックIPv4アドレスが自動割り当てされていないか確認しましょう。

 

AMIから作成のEC2確認

 

付いてないですね。

 

 

今回の構築は以上です。

 

 

まとめ:EC2インスタンス起動時に自動割り当てされるパブリックIPアドレスを解除する方法

EC2インスタンス起動時に自動で割り当てられるパブリックIPv4アドレスは今まで無料でしたが、2024年2月1日より有料となります。プロジェクトや環境によっては小さくないコスト増になるかと思いますので、パブリックIPv4アドレスが不要なインスタンスは解除してしまいましょう。

 

 

参考リンク:Amazon Web Services ブログ
 

 

↓ほかの協栄情報メンバーも自動化に関する記事を公開しています。ぜひ参考にしてみてください。

 

■Terraformの概要と使用方法(higa)
https://cloud5.jp/terraform_summary/

 

■AWS CodePipeline を利用してS3の静的ウェブサイトの更新を自動化する(tatsuoka)
https://cloud5.jp/tatsuoka-handson-beginner-codepipeline/

 

■AWS上にopenstackを構築(liuwanying)
https://cloud5.jp/openstack-install/

 

■Ansibleを利用してwindowsOSのインスタンスを操作する方法(umemoto)
https://cloud5.jp/control-windows-fromansible/

 

 

Last modified: 2023-08-05

Author