Help us understand the problem. What is going on with this article?

【爆速Terraform入門】AWS環境をコードで管理してみよう

まえがき

東南アジア発のスタートアップスタジオ、GAOGAOでエンジニアをしているMass-minと申します。
先日は、GAOGAOにて開発をサポートさせていただいている株式会社Ancar様のアドベントカレンダーで、記事を書かせていただきました!まだ読んでない方は是非!

【ザンギョーウはヤメロ】スクラム開発で、チームが絶対に残業してはいけない理由

そんなこんなで、今日はAncar様にてサービス開発を行った際に得た技術的知見をアウトプットしていこうかと思います。

インフラ構築どうしてる?

みなさま、インフラ構築ってどうしてますか?
よほど大きな規模のプロダクトやレスポンスにシビアな要求があるプロダクトでない限りは、お手軽さという面でオンプレよりクラウドに軍配が上がるかと思います。
AWSやGCP、Azureなどを使っているサービスは、今や世の中の大半を占めると言っても過言ではないかと思われます。

そんな今の世の中ですが、一度クラウドサービスのコンソール上でポチポチボタンを押して環境を構築した後、その環境をドキュメントなり何なりで適切に管理、保守出来ているチームは意外に少ないのでは、と思いました。
ドキュメントに落とし込んでいれば、同じような環境をもう一度作成する場合のスピードは段違いになりますよね。特にスタートアップにおいて、仮説検証の段階で環境を作っては壊しを繰り返す場合は顕著です。
また変更した箇所をちゃんとドキュメントにも反映していれば、わざわざコンソール画面の中で設定の項目を見なくてよくなります。
したがって、何かしらのカタチで環境をまるごと管理したいという欲求が出てきます。

ここで登場するのがTerraformです。Terraformはクラウド環境を独自の言語でコード化して管理し、コマンド1発で環境のセットアップ、及び削除を行えるツールです。
TerraformはHashiCorp社が運営するサービスで、AWSが提供しているわけではありません。AWSに縛られず、GCPやAzureなどの環境もTerraformでコード管理することが出来ます。つまり一度Terraformの書き方を覚えてしまえば、どんな環境でもおおよそコード化して管理できてしまう、というわけです。ステキじゃないですか!

というわけで今回は、Terraformの入門編。EC2インスタンスの設定をコード化して、環境構築を行ってみましょう。

おしながき

  • 前提
  • Terraformのインストール
  • EC2インスタンスの設定
    • 初級編 - TerraformでEC2インスタンスを作成してみる
    • 中級編 - コードの内容を追ってみる
    • 実践編 - Nginxをインストールしてトップページを表示

前提

Terraformのインストール

Macの場合はHomebrewでTerraformがインストールできます。

HomebrewでTerraformをインストール
$ brew update
$ brew install terraform

2019/12/03時点では、Ver0.12.16が入りました。

Terraformのバージョン確認
$ terraform -v
Terraform v0.12.16

EC2インスタンスの設定

初級編

さて、ではお待ちかねのEC2インスタンス作成です。
まずTerraformのコードを置くディレクトリを作成しましょう。

ディレクトリを作成し移動
$ mkdir terraform
$ cd terraform/

Terraformコードを書くファイルの作成と初期設定

Terraformのコードは .tfという拡張子のファイルに書きます。今回はEC2インスタンスに関する記述をするので、ファイル名はec2.tfとしましょう。

ec2.tf
provider "aws" {
  profile = "default"
  region = "ap-northeast-1"
}

resource "aws_instance" "terraform-web" {
  ami = "ami-0ab3e16f9c414dee7"
  instance_type = "t2.micro"
  tags = {
    Name = "ec2-terraform"
  }
}

とりあえずこれだけ。この状態で、terraformプロジェクトの初期設定を行います。

初期化
$ terraform init

Terraform has been successfully initialized! と出れば完了です。何かしらエラーが出た人は、 前提の欄に書いたAWS CLIのcredentials設定が終わっていないかもしれませんね。AWS CLIの設定を見てキーの設定を行ってください。

作成計画を確認し、実際にコードを実行する

さて、では次に作成される予定のEC2について、作成計画を見てみましょう。

作成計画を見る
$ terraform plan

なんかワーって出てきたかと思います。とりあえず次のステップ、実際にインスタンスを作成するところまでいってみましょう。

Terraformコードの実行
$ terraform apply

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.のようになれば作成完了です。では、AWSのコンソールにいってEC2インスタンスのタブを見てみましょう。
image.png

おおっ!ちゃんとインスタンスが作成されていますね!このように、コード化した設定からEC2インスタンスを起動することができました!:tada:

中級編

作成できたのはいいものの、やっていることがよく分かりませんね。もうちょっと深堀りしてみましょう。
ちなみにTerraformのAWS関連公式ドキュメントはこちらです。公式をあたるのが一番早いです。

コマンド

まず、terraformのコマンドについて。今出てきた3種類は、それぞれ以下のようになっています。

コマンド 内容 備考
init Terraformプロジェクトの初期設定を行う AWS CLIのcredentialsが設定済みである事が前提
plan Terraformコードの実行計画を見る いわゆるdry run
apply Terraformコードの実行

したがって、コードを書いたらplanで環境がどうなるかを確認し、OKそうならapplyで実行、という流れになります。

コード

次に、 ec2.tfの中を見てみましょう。1行1行にコメントを書いてみました。

ec2.tf
provider "aws" {            # AWS以外にも、GCPやAzure、Herokuなどがここに入る
  profile = "default"       # キーを指定せず、AWS CLIに設定したdefaultのcredentials情報を用いる
  region = "ap-northeast-1" # Terraformのコードで環境を作成する対象のリージョン
}

resource "aws_instance" "terraform-web" { # EC2インスタンスに関する記述。コード内ではterraform-webという名前でアクセスできる
  ami = "ami-0ab3e16f9c414dee7"           # どのAMIをベースにインスタンスを作成するか、ID指定
  instance_type = "t2.micro"              # インスタンスタイプ指定
  tags = {
    Name = "ec2-terraform"                # タグに Name: ec2-terraform をセット
  }
}

もうお分かりですね。
providerで対象とするサービスを指定し、認証情報やリージョンを設定する。
そして、構築したい個々の内容をresourceに書いていく、という感じです。
今はEC2のみ設定していますが、RDSやS3、VPCだって同じように書けます。書いていくとだんだん分かるのですが、コード管理できるのはめちゃめちゃ楽ですよ!

実践編

それではみなさんよいクリスマスを!...とはならず。EC2がポッと1つたっただけでは面白くないですよね。最後に、EC2インスタンスにNginxをインストールしトップページを表示するところまでやって終わりにしましょう。

セキュリティグループの設定

プラウザからアクセスしてNginxのトップページを表示するには、80番ポートへのアクセスを受け付ける必要があります。
また、そもそもNginxをインストールするためにssh接続してインスタンスにアクセスしなければなりませんね。したがって、22番ポートも開けなければいけません。これらを設定していきましょう。

ec2.tf
provider "aws" {
  profile = "default"
  region = "ap-northeast-1"
}

# セキュリティグループ
resource "aws_security_group" "terraform-web-sg" {
  egress {
    from_port = 80
    to_port = 80
    protocol = "tcp"
    cidr_blocks = [
      "0.0.0.0/0"
    ]
  }
  tags = {
    Name = "sg-terraform"
  }
}

# インバウンドのルール
resource "aws_security_group_rule" "inbound_http" {
  security_group_id = aws_security_group.terraform-web-sg.id
  type = "ingress"
  from_port = 80
  to_port = 80
  protocol = "tcp"
  cidr_blocks = [
    "0.0.0.0/0"
  ]
}
resource "aws_security_group_rule" "inbound_ssh" {
  security_group_id = aws_security_group.terraform-web-sg.id
  type = "ingress"
  from_port = 22
  to_port = 22
  protocol = "tcp"
  cidr_blocks = [
    "0.0.0.0/0"
  ]
}

# EC2
resource "aws_instance" "terraform-web" {
  ami = "ami-0ab3e16f9c414dee7"
  instance_type = "t2.micro"
  vpc_security_group_ids = [aws_security_group.terraform-web-sg.id] # <= 追加
  tags = {
    Name = "ec2-terraform"
  }
}

まず、セキュリティグループのegressはアウトバウンド、igressはインバウンドのルールに関する記述です。セキュリティグループにルールを複数追加したい場合は、aws_security_group_ruleで記述します。そしてEC2の記述には、セキュリティグループのidについての記述を追加します。

ではterraform applyを叩いてコンソールを見てみましょう。

image.png

ちゃんと複数ルールが設定されたセキュリティグループが作成されています!:tada:

image.png

EC2インスタンスにも作成されたセキュリティグループが正しく割り当てられていますね!

Nginxのインストール

さぁ、ここまできたならあとはもう少し。Nginxのインストールを行いましょう。
ここで、ssh接続するために鍵の設定が必要になりますので、先にキーペア作成を行っておきます。本筋とずれるので詳細は省きます。やり方はAWS公式ドキュメントをみてくださいね。

さて、鍵ファイルが出来ました。自分は作成したファイルを~/.ssh/test_terraform.pemに置いていますので、それをコードに記述していきます。長くなるので、以下はEC2に関する記述の部分だけを記しています。

ec2.tf
# EC2
resource "aws_instance" "terraform-web" {
  ami = "ami-0ab3e16f9c414dee7"
  instance_type = "t2.micro"
  vpc_security_group_ids = [aws_security_group.terraform-web-sg.id]
  key_name = "test_terraform" # <= 追加
  tags = {
    Name = "ec2-terraform"
  }
  provisioner "remote-exec" { # <= 追加
    connection {
      host = self.public_dns
      type = "ssh"
      user = "ec2-user"
      private_key = file("~/.ssh/test_terraform.pem")
    }
    inline = [
      "sudo yum -y update && sudo yum install -y nginx && sudo service nginx start"
    ]
  }
}

例のごとく、Apply complete! Resources: 1 added, 0 changed, 1 destroyed.と出たら完了です。

ではちゃんとNginxが動いているか確認しましょう!
まずはTerraformで作成した環境の内容を表示するコマンドを打ってみます。

内容表示
$ terraform show

ズラズラと出てきたかと思いますが、これが構築された環境の内容です。
EC2の記述の中に、public_ipというのがあると思います。これが、作成したEC2インスタンスに振られたパブリックIPです!
では、ブラウザでこのIPにアクセスしてみましょう!

image.png

おおお!!無事にNginxのトップページが表示されました!このようにして、コードで環境の設定からプロビジョニングまで行うことができちゃうんですね!ビバTerraform!!:tada:😍🤗🙌

まとめ

Terraformを使うことによって、今までクラウドコンソール上でポチポチやってた環境をコード化して管理することが出来るようになりました!:tada:(というか、CLI経由で作ってた時代の手順をわかりやすくコード化した、という風にも言えますねw)
いずれにせよコード化が出来たことにより、環境の変更差分等は全てGitで管理できるようになります。いつ誰が何をどのように変更したか見える化できるので、今まで以上に安心して環境構築 & 保守ができるようになるのではないでしょうか!
また、一度よくあるインフラ形態をコード化しておけば、それを他のアプリケーションでも使い回すことが可能になります。まさに爆速インフラ構築!
ということで、インフラをコードに落として安心、安全な開発体制を整えていきましょう!

*なお今回のサンプルコードはGitHubにあげていますので、勉強用に是非お使いください!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした