はじめに
以下記事の続きです。
TerraformでVPC、サブネット、インターネットゲートウェイを作成する
今回はEC2とセキュリティグループを作成します。
以下ディレクトリ構造です。
.
├── README.md
├── main.tf
├── modules
│ ├── alb
│ │ ├── Create-alb.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── ec2 #本記事で作成
│ │ ├── Create-ec2.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── rds
│ │ ├── Create-rds.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── security_group #本記事で作成
│ │ ├── Create-securitygroup.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ └── vpc #前回作成
│ ├── Create-vpc.tf
│ ├── outputs.tf
│ └── variables.tf
├── outputs.tf
├── terraform.tfstate
├── terraform.tfstate.backup
└── variables.tf
セキュリティグループの作成
セキュリティグループもModule化するため、main.tf
に追記します。
sg_config
は環境に合わせてください。
VPCは、前回作成したVPCモジュールと紐づけています。
module ec2-sg {
source = "./modules/security_group"
sg_config = {
name = "ec2-sg"
vpc_id = module.vpc.vpc_id
protocol = "tcp"
port = [22, 80, 443]
cidr_blocks = ["0.0.0.0/0"]
}
次にmodule ec2-sg
で定義した変数をinputします。
object
で取り込むと変数1つずつvariable
でinputする必要が無いので便利です。
variable "sg_config" {
type = object({
name = string
vpc_id = string
protocol = string
port = list(number)
cidr_blocks = list(string)
})
}
セキュリティグループ全体の設定を書きます。for_each = var.sg_config.port
でport[22,80,443]でループを回しています。
resource "aws_security_group" "mysg" {
name = var.sg_config.name
vpc_id = var.sg_config.vpc_id
dynamic "ingress" {
for_each = var.sg_config.port
content {
from_port = ingress.value
to_port = ingress.value
protocol = var.sg_config.protocol
cidr_blocks = var.sg_config.cidr_blocks
}
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
後ほどEC2に紐付けるために、セキュリティグループIDをoutputしておきます。
output "sg_id" {
value = aws_security_group.mysg.id
}
EC2の作成
EC2もmodule化するためmain.tf
に追記します。ちょっとパラメータが多くなってしまいました。
module ec2 {
source = "./modules/ec2"
ec2_config = {
vpc_id = module.vpc.vpc_id
public_subnet_id = module.vpc.public_subnet_id
sg_id = module.ec2-sg.sg_id
NameTag = "Terraform"
instance_type = "t2.micro"
instance_count = 2
key_name = "test_key"
}
strage_config = {
volume_type = "gp2"
volume_size = 8
delete_on_termination = true
}
}
変数にinputします。
variable "ec2_config" {
type = object({
vpc_id = string
public_subnet_id = list(string)
sg_id = string
NameTag = string
instance_type = string
instance_count = number
key_name = string
})
}
variable "strage_config" {
type = object({
volume_type = string
volume_size = string
delete_on_termination = bool
})
}
EC2作成のコードを書きます。
いつかcount
ではなくインスタンス数でfor_each
に書き直します。。
# 最新のAmazon Linux AMI IDを取得
data aws_ssm_parameter amzn2_ami {
name = "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"
}
resource "aws_instance" "Myinstance" {
count = var.ec2_config.instance_count
ami = data.aws_ssm_parameter.amzn2_ami.value
instance_type = var.ec2_config.instance_type
key_name = var.ec2_config.key_name
vpc_security_group_ids = [
var.ec2_config.sg_id
]
subnet_id = element(var.ec2_config.public_subnet_id, count.index % length(var.ec2_config.public_subnet_id))
root_block_device {
volume_type = var.strage_config.volume_type
volume_size = var.strage_config.volume_size
delete_on_termination = var.strage_config.delete_on_termination
}
tags = {
Name = "${var.ec2_config.NameTag}-instance${count.index}"
}
}
作成したEC2インスタンスのpublic_ipをターミナル上に表示するためにoutputします。
DNS名を表示したい場合は、末尾をpublic_dns
にします。
インスタンスIDはALBとの接続で使います。
output "instance_ip" {
value = {
for instance in aws_instance.Myinstance[*] :
instance.tags.Name => instance.public_ip
}
}
output "instance_id" {
value = aws_instance.Myinstance[*].id
}
実は上記だけだとターミナル上で表示されないのでterraformルートディレクトリに設置したoutputs.tf
にも同じようなことを書きます。
output "instance_ip" {
value = module.ec2.instance_ip
}
以上でEC2作成コードが完成です。
実行後はこんな感じで表示されます。(2台作成時)
% terraform plan
% terraform apply
Outputs:
instance_ip = {
"Terraform-instance0" = "13.113.167.40"
"Terraform-instance1" = "13.115.52.183"
}
SSHも出来ました。
% ssh -i ~/.ssh/test-key.pem ec2-user@13.113.167.40
これでVPCとEC2が作成出来ました!次回はALBを作成します。
(再度セキュリティグループのモジュール使います)