この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので十分ご注意ください。
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(無効)"で設定し、
- [インスタンスを起動]すればいいのです。
それでは、やってみましょう。
■条件・準備
今回の構築は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してください。
起動できたでしょうか。
■AMI作成
起動したEC2インスタンスのAMIを作成していきます。
↓AWSマネージメントコンソールでEC2のダッシュボード画面に移動します。インスタンスを選択して、[Action]をクリックし、[Image & templates]→[Create image]を押します。
以下の設定値で作成します。
項目 | 設定値 |
---|---|
Image name | 任意 |
Image description | 任意 |
No reboot | □ ※ |
Add new tag | Key: Name, Value: 任意 |
↓入力が完了しましたら、[Create image]をクリックします。
↓左のナビゲーションペインから[AMI]をクリックします。作成が完了するまで、数分かかります。
↓完了しますと、[Status]が[Available]となります。
AMIの作成は以上です。
■AMIからEC2インスタンス起動
作成したAMIをもとに新たにEC2インスタンスを起動しましょう。
起動はTerraformで行います。マネージメントコンソールから起動しようとすると、VPCやサブネットなどのネットワーク設定・IAM インスタンスプロファイルを再度設定しなければいけません。
1台ならまだしも、数台以上の場合、確実に設定をミスります。ミスを減らすためにTerraformを利用して、EC2インスタンスを起動します。
Terraformの記述は、最初に利用したファイルに少し修正するだけで完了します。以下を利用してください。
二つ目のインスタンス(copy)の記述では、ami、キーペアの項目に自身のものを設定してください。そして、associate_public_ip_addressがfalseであることを確認ください。’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はマネージメントコンソールから確認できます。
修正が完了しましたら、applyしてください。
■確認
AMIから新たに起動したEC2インスタンスにパブリックIPv4アドレスが自動割り当てされていないか確認しましょう。
付いてないですね。
今回の構築は以上です。
まとめ: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/