本文へジャンプ

インフラをコード化!
CloudFormationとTerraformを使ってEC2をデプロイしてみた

Posted by MONSTER DIVE

皆様こんにちは!
MDのバックエンドとインフラを担当しておりますMSMと申します。

最近はSAAを取得するためにAWSの学習に勤しんでおります。
何としても1回で合格したいですね。

そこで今回選んだテーマは、自身の知識整理も兼ねてAWSにも深く関わりのある
「Infrastructure as Code(IaC)」です。

Infrastructure as Code(IaC)

IaCとは、簡単に言うとAWSやGCP, Azureなどのクラウドサービスのリソースを、コード化し、管理できるようにすることです。

従来の方法では、サーバやネットワークの設定を全てコンソールから手動で行うことが多かったと思います。

しかし、インフラ構成が複雑化した場合や長く放置されていた場合に、稼働中のリソースをコンソールから1つずつ把握・管理するのは大変な作業になります。

そこで、そのインフラ構成図をコードとして作成・管理することで、インフラの構成に変更があった場合や、インフラ構成そのものを把握したいときに、簡単に管理・把握することができます。

そして最大の特徴は、テンプレートのコードを元に複数のクラウドリソースをまとめて自動デプロイすることができるという点です。

今回は、以下に説明する2つの代表的なIaCサービスで、同じインフラ構成のテンプレートを作成し、デプロイしたEC2からHello Worldしてみたいと思います。

AWS CloudFormation

AWS CloudFormation

  • AWSの公式IaCサービス。jsonまたはyaml形式のファイルで記述する。
  • テンプレートを作成し、コンソール画面またはAWS CLIからリソースのデプロイが可能。
  • GCPやAzureといった他社のクラウドサービスのリソースには対応していない。

HashiCorp Terraform

HashiCorp Terraform

  • HashiCorp社が提供するIaCサービス。
  • tfファイルという独自の拡張子を使用している。
  • Go言語によって開発されている
  • マルチベンダー対応

準備

以下のツールをそれぞれお使いのPCにインストールしてください。
インストール手順の解説は本記事では省略します。

コードからのデプロイ

それでは、実際に二つのツールを使ってそれぞれデプロイしてみましょう。

Cloudformationによるデプロイ

まずはCloudFormationのテンプレートを作成して、デプロイしてみましょう。

CloudFormationのテンプレートファイルは yaml または json が選択できますが、僕個人としては読みやすいyamlファイルの方で作成します。

  • cloudformation.yaml
---
Parameters:
Ec2ImageId:
Type: AWS::SSM::Parameter::Value
Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
Resources:
CFEC2:
Type: AWS::EC2::Instance
Properties:
AvailabilityZone: ap-northeast-1a
ImageId: !Ref Ec2ImageId
InstanceType: t2.micro
Tags:
- Key: Name
Value: instance_from_cf
SecurityGroups:
- !Ref CFSecurityGroup
UserData:
Fn::Base64: |
#!/bin/bash
yum update -y
yum install -y httpd.x86_64
systemctl start httpd.service
systemctl enable httpd.service
echo "Hello World from CF" > /var/www/html/index.html
# our EC2 security group
CFSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: security group for CluodFormation
Tags:
- Key: Name
Value: "sg_for_cf"
SecurityGroupIngress:
- CidrIp: 0.0.0.0/0
FromPort: 22
IpProtocol: tcp
ToPort: 22
- CidrIp: 0.0.0.0/0
FromPort: '80'
IpProtocol: tcp
ToPort: '80'

作成したCFテンプレートはAWS CLIを使用して、以下のコマンドでデプロイすることができます。

コマンドの実行はCFのテンプレートファイルがあるディレクトリを指定して実行します。
引数profileに指定するユーザは適宜変更してください。

aws --profile terraform cloudformation deploy --template cf.yaml --stack-name ec2-from-cf

CFでデプロイした場合はコンソールにスタックとして登録され、作成されたリソースが一覧として確認することができます。

cf-stack.png

デプロイに成功すると、指定した内容のEC2とSGが作成されます。

cf-ec2.png cf-sg.png

EC2のパブリックIPを開くとhtmlファイルを確認することができます。

cf-hello.png

作成したリソースは以下のコマンドで削除しましょう。

aws --profile terraform cloudformation delete-stack  --stack-name ec2-from-cf

Terraformによるデプロイ

Terraformは以下のディレクトリ構成で構築します。

root_dir
├── main.tf
├── terraform.tfvars
└── versions.tf

Terraformはバージョンによって仕様が異なる部分があるので、インストールしているterraformのバージョンに合わせて要求バージョンを指定します。

  • versions.tf
terraform {
required_version = ">= 0.14"
}

AWSのアカウントにアクセスするためのユーザの鍵情報は terraform.tfvars に記述しましょう。

  • terraform.tfvars
ACCESS_KEY = "XXXXXXXXXXXXXXX"
SECRET_KEY = "YYYYYYYYYYYYYYY"
  • main.tf
provider "aws" {
access_key = var.ACCESS_KEY
secret_key = var.SECRET_KEY
region     = "ap-northeast-1"
}
variable "ACCESS_KEY" { 
type = string
}
variable "SECRET_KEY" { 
type = string
}
data aws_ssm_parameter amzn2_ami {
name = "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"
}
resource "aws_instance" "myinstance" {
ami = data.aws_ssm_parameter.amzn2_ami.value
instance_type = "t2.micro"
vpc_security_group_ids = [aws_security_group.tf-sg.id]
user_data = <<-EOF
#!/bin/bash
yum update -y
yum install -y httpd.x86_64
systemctl start httpd.service
systemctl enable httpd.service
echo "Hello World from TF" > /var/www/html/index.html
EOF
tags = {
Name = "instance_from_terraforms"
}
}
resource "aws_security_group" "tf-sg" {
name = "sg_for_tf"
description = "security group for Terraform"
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}

ファイルの準備ができたら以下のコマンドを実行していきます。

terraform init
terraform apply

applyを実行すると、以下の質問が出るので yes を回答します。

Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes

CFと同様に指定したEC2インスタンス・SGの確認ができました。

tf-ec2.png tf-sg.png

こちらも同様にIPへアクセスすると、htmlページの確認ができました。

tf-hello.png

作成したリソースの後始末は、以下のコマンドを実行します。
テンプレートから作成した全てのリソースを削除します.

terraform destroy

削除確認の質問が出るので、yesを回答します。

Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yes

それぞれの長所・短所(個人的な感想)

CloudFormation

長所

  • AWS のコンソールからもデプロイが可能
  • AWS CLIが使えればそのままCLIからの実行が可能
  • デプロイ中のプロセスがコンソールで確認できる
  • テンプレートで作成したリソースは単体で削除できないので、誤った削除を防ぐことができる

短所

  • 使用できるクラウドベンダーがAWSのみ
  • yamlでも少しファイルの見通しが悪く感じる

Terraform

長所

  • コードの見通しが良い
  • 実行環境の構築が簡単
  • 様々なベンダーに対応(AWS, GCP, Azure, etc...)

短所

  • Terraformで作成したリソースの進捗状況がコンソールで確認できない
  • バージョンごとの仕様変更が大きい
  • コンソールからリソースを消せてしまうので、ローカルのtfファイルの内容と矛盾する可能性がある

終わりに

いかがだったでしょうか?
インフラをコード化することで、リソースの設定やリソース同士の繋がりが明確になりますね。

実務でのインフラ管理だけでなく、

  • SAAなどの資格をとるときにハンズオン形式に学習したものをコード化する
  • 実験的に色々なインフラ構成を試したい

といったような使い方もできるのではないでしょうか。

それでは今回はこの辺で!

Happy Coding!

参考記事:

Recent Entries
MD EVENT REPORT
What's Hot?