LoginSignup
4
1

More than 3 years have passed since last update.

TerraformでEC2、セキュリティグループを作成する

Last updated at Posted at 2020-06-11

はじめに

以下記事の続きです。
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モジュールと紐づけています。

./main.tf

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する必要が無いので便利です。

./modules/security_group/variables.tf
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]でループを回しています。

./modules/security_group/Create-securitygroup.tf
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しておきます。

./modules/security_group/outputs.tf
output "sg_id" {
  value = aws_security_group.mysg.id
}

EC2の作成

EC2もmodule化するためmain.tfに追記します。ちょっとパラメータが多くなってしまいました。

./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します。

./modules/ec2/variables.tf
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に書き直します。。

./modules/ec2/Create-ec2.tf
# 最新の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との接続で使います。

./modules/ec2/outputs.tf
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にも同じようなことを書きます。

./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を作成します。
(再度セキュリティグループのモジュール使います)

参考

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1