まえがき
東南アジア発のスタートアップスタジオ、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をインストールしてトップページを表示
前提
- OS: macOS 10.15.1
- AWS CLIはインストール済み(credentials設定済み)
- まだ入ってない人は以下の手順でインストールしてください
Terraformのインストール
Macの場合はHomebrewでTerraformがインストールできます。
$ brew update
$ brew install terraform
2019/12/03時点では、Ver0.12.16が入りました。
$ terraform -v
Terraform v0.12.16
EC2インスタンスの設定
初級編
さて、ではお待ちかねのEC2インスタンス作成です。
まずTerraformのコードを置くディレクトリを作成しましょう。
$ mkdir terraform
$ cd terraform/
Terraformコードを書くファイルの作成と初期設定
Terraformのコードは .tf
という拡張子のファイルに書きます。今回はEC2インスタンスに関する記述をするので、ファイル名は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 apply
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
のようになれば作成完了です。では、AWSのコンソールにいってEC2インスタンスのタブを見てみましょう。
おおっ!ちゃんとインスタンスが作成されていますね!このように、コード化した設定からEC2インスタンスを起動することができました!
中級編
作成できたのはいいものの、やっていることがよく分かりませんね。もうちょっと深堀りしてみましょう。
ちなみにTerraformのAWS関連公式ドキュメントはこちらです。公式をあたるのが一番早いです。
コマンド
まず、terraformのコマンドについて。今出てきた3種類は、それぞれ以下のようになっています。
コマンド | 内容 | 備考 |
---|---|---|
init | Terraformプロジェクトの初期設定を行う | AWS CLIのcredentialsが設定済みである事が前提 |
plan | Terraformコードの実行計画を見る | いわゆるdry run |
apply | Terraformコードの実行 |
したがって、コードを書いたらplanで環境がどうなるかを確認し、OKそうならapplyで実行、という流れになります。
コード
次に、 ec2.tf
の中を見てみましょう。1行1行にコメントを書いてみました。
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番ポートも開けなければいけません。これらを設定していきましょう。
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
を叩いてコンソールを見てみましょう。
ちゃんと複数ルールが設定されたセキュリティグループが作成されています!
EC2インスタンスにも作成されたセキュリティグループが正しく割り当てられていますね!
Nginxのインストール
さぁ、ここまできたならあとはもう少し。Nginxのインストールを行いましょう。
ここで、ssh接続するために鍵の設定が必要になりますので、先にキーペア作成を行っておきます。本筋とずれるので詳細は省きます。やり方はAWS公式ドキュメントをみてくださいね。
さて、鍵ファイルが出来ました。自分は作成したファイルを~/.ssh/test_terraform.pem
に置いていますので、それをコードに記述していきます。長くなるので、以下はEC2に関する記述の部分だけを記しています。
# 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にアクセスしてみましょう!
おおお!!無事にNginxのトップページが表示されました!このようにして、コードで環境の設定からプロビジョニングまで行うことができちゃうんですね!ビバTerraform!!😍🤗🙌
まとめ
Terraformを使うことによって、今までクラウドコンソール上でポチポチやってた環境をコード化して管理することが出来るようになりました!(というか、CLI経由で作ってた時代の手順をわかりやすくコード化した、という風にも言えますねw)
いずれにせよコード化が出来たことにより、環境の変更差分等は全てGitで管理できるようになります。いつ誰が何をどのように変更したか見える化できるので、今まで以上に安心して環境構築 & 保守ができるようになるのではないでしょうか!
また、一度よくあるインフラ形態をコード化しておけば、それを他のアプリケーションでも使い回すことが可能になります。まさに爆速インフラ構築!
ということで、インフラをコードに落として安心、安全な開発体制を整えていきましょう!
*なお今回のサンプルコードはGitHubにあげていますので、勉強用に是非お使いください!