Welcome!
ここではOSS版のTerraformを利用してAWS上に一つインスタンスを作り、それぞれのコンポーネントや用語について説明をします。
このガイドのコンテンツは、完全な DevOps CI /CDパイプラインを活用しており、以下のGitHubリポジトリから取得可能です。
https://github.com/tkam8/terraform-workshop
バグまたは新規機能のリクエストは、以下の2つ方法で実施可能です。
GitHubのリポジトリをフォーク(Fork)して、 プルリクエスト(Pull Request )で修正を送信 GitHubのリポジトリ上で Issue を開く
初めてのTerraform
Goal:
ここではOSS版のTerraformを利用してAWS上に一つインスタンスを作り、それぞれのコンポーネントや用語について説明をします。
Prerequisites:
- インターネットに接続可能なPC
- 管理者権限(Terraformをインストールするため)
Terraform Installation:
Terraformがインストールされていない場合は[こちら](https://www.terraform.io/downloads.html)よりダウンロードをしてください。
ダウンロードしたらunzipして実行権限を付与し、パスを通します。下記はmacOSの手順です。
$ unzip terraform*.zip $ chmod + x terraform $ mv terraform /usr/local/bin $ terraform -version Terraform v0.12.21
注釈
Windowsの場合はこちらのリンクをご参照ください。 https://dev.classmethod.jp/tool/try-terraform-on-windows/
次に任意の作業用ディレクトリを作ります。
$ mkdir -p tf-workspace/hello-tf $ cd tf-workspace/hello-tf
Terraform Configuration Files:
早速このフォルダにTerraformのコンフィグファイルを作ってみます。コンフィグファイルは`HashiCorp Configuration Language`というフレームワークを使って記述していきます。
`main.tf`と`vaiables.tf`という二つのファイルを作ってみます。`main.tf`はその名の通りTerraformのメインのファイルで、このファイルに記述されている内容がTerraformで実行されます。`variables.tf`は変数を定義するファイルです。各変数にはデフォルト値や型などを指定できます。
$ cat <<EOF > main.tf terraform { required_version = "~> 0.12" } provider "aws" { access_key = var.access_key secret_key = var.secret_key token = var.session_token region = var.region } resource "aws_instance" "hello-tf-instance" { ami = var.ami count = var.hello_tf_instance_count instance_type = var.hello_tf_instance_type tags = { Name = var.instance_name } } EOF
次に`variables.tf`ファイルを作ります。
$ cat << EOF > variables.tf variable "access_key" {} variable "secret_key" {} variable "session_token" {} variable "region" {} variable "ami" {} variable "instance_name" {} variable "hello_tf_instance_count" { default = 1 } variable "hello_tf_instance_type" { default = "t2.micro" } EOF
Terraform Commands:
二つのファイルができたらそのディレクトリ上でTerraformの初期化処理を行います。`init`処理ではステートファイルの保存先などのバックエンドの設定や必要ばプラグインのインストールを実施します。
$ terraform init
ここではAWSのプラグインがインストールされるはずです。
$ ls -R .terraform/plugins .terraform/plugins: linux_amd64 .terraform/plugins/linux_amd64: lock.json terraform-provider-aws_v2.51.0_x4
次に`plan`と`apply`を実施してインスタンスを作ってみましょう。AWSのコンソールまたはaws cliでインスタンスの状況確認しておいてください。
$ aws ec2 describe-instances --query "Reservations[*].Instances[*].{InstanceId:InstanceId,State:State,Name:Tags[?Key=='Name']|[0].Value}" []
`plan`はTerraformによるプロビジョニングの実行プランを計画します。実際の環境やステートファイルとの差分を検出し、どのリソースにどのような変更を行うかを確認することができます。`apply`はプランに基づいたプロビジョニングの実施をするためのコマンドです。
また、実行前に変数に値をセットする必要があります。方法としては
- `tfvars`というファイルの中で定義する
- `terraform apply -vars=***`という形でCLIの引数で定義する
- `TF_VAR_***`という環境変数で定義する
- Plan中に対話式で入力して定義する
がありますが、今回は環境変数でセットします。
$ export TF_VAR_access_key=************ $ export TF_VAR_secret_key=************ $ export TF_VAR_session_token=********* $ export TF_VAR_instance_name=<enteryourname> $ export TF_VAR_region=ap-southeast-1 $ export TF_VAR_ami=ami-07ce5f60a39f1790e $ terraform plan $ terraform apply
Applyが終了するとAWSのインスタンスが一つ作られていることがわかるでしょう。AWSのコンソールまたはaws cliでインスタンスの状況確認してください。
$ aws ec2 describe-instances --query "Reservations[*].Instances[*].{InstanceId:InstanceId,State:State,Name:Tags[?Key=='Name']|[0].Value}" [ { "InstanceId": "i-00918d5c9466da418", "State": { "Code": 48, "Name": "running" }, "Name": "xxx" } ]
Terraform Modification:
次にインスタンスの数を増やしてみます。`hello_tf_instance_count`の値を上書きして再度実行します。
$ export TF_VAR_hello_tf_instance_count=2 $ terraform plan $ terraform apply -auto-approve
注釈
ちなみに今回は`-auto-approve`というパラメータを使って途中の実行確認を省略しています。AWSのインスタンスが二つに増えています。Terraformは環境に差分が生じた際はPlanで差分を検出し、差分のみ実施するため既存のリソースには何の影響も及ぼしません。
$ aws ec2 describe-instances --query "Reservations[*].Instances[*].{InstanceId:InstanceId,State:State,Name:Tags[?Key=='Name']|[0].Value}" [ { "InstanceId": "i-00918d5c9466da418", "State": { "Code": 48, "Name": "running" }, "Name": "xxx" }, { "InstanceId": "i-0b0aea4b4ab27ef4b", "State": { "Code": 16, "Name": "running" }, "Name": "xxx" } ]
Destroy Environment:
次に`destroy`で環境をリセットします。
$ terraform destroy
実行ししばらくするとEC2インスタンスが`terminated`の状態になってることがわかるはずです。
$ aws ec2 describe-instances --query "Reservations[*].Instances[*].{InstanceId:InstanceId,State:State,Name:Tags[?Key=='Name']|[0].Value}" [ { "InstanceId": "i-00918d5c9466da418", "State": { "Code": 48, "Name": "terminated" }, "Name": "xxx" }, { "InstanceId": "i-0b0aea4b4ab27ef4b", "State": { "Code": 16, "Name": "terminated" }, "Name": "xxx" } ]
Enterprise版の価値:
Applyが実行されると`terraform.tfstate`というファイルが生成されます。このファイルは現在のインフラの状態をJson形式で保持しているものですが、次のPlanのタイミングの差分の検出などで扱われ非常に重要です。例えばチームで作業をする際などはこのステートの共有方法をどうやって運用するかなどの考慮が必要になります。
また、このファイルには各リソースのIDのみならずデータベースやAWS環境のシークレットなど様々な機密性の高いデータが含まれておりステートファイルをセキュアに保つことも運用上重要です。
以降の章ではステートファイルのみならず、OSS版ではTerraformを安全に利用するために考慮する必要がある様々な運用上の課題に対してEnterprise版がどのような機能を提供しているかを一つずつ試してみます。
参考リンク
Terraform CloudによるRemote state管理
さて、最初のWorkshopではLocal環境でTerraformを実行し、StateファイルもLocal環境に作成されました。
Stateファイルは非常に重要なファイルで様々な情報がつまっています。
- ProvisioningされたResourceの識別情報
- APIキーやパスワードなどのSecret
- など
Terraformで継続的にProvisioningを行なうためにはStateファイルの管理が必至です。Terraformはデフォルトの挙動として、実行されて得たStateファイルをLocal環境に保存します。ただ、Local環境でStateファイルを管理するにはいくつかの問題があります。
- 個人のLocal環境だけに存在すると、チームでの作業が出来ない - 例えばAさんのローカルマシン上にだけStateファイルがある場合、Aさん以外の人はその環境にたいして、それ以上のProvisioningが出来ない。
- 誤って削除してしまうと元に戻せない(よって全てのインフラ情報が損失してしまう) - 既存の環境をStateファイルに取り込むimportというコマンドもありますが、非常に手間と時間がかかります。
- Stateファイルは常に最後のTerraform実行の情報だけが記載されるので、過去のインフラ状態のトラッキングが出来ない - トラッキングのために、Terraformの実行毎にStateファイルを共有スペース(ファイルサーバーやS3など)やVCSなどに保存するやり方もありますが、手間がかかります。
そこで、Terraform OSSのユーザーはこれらの問題を回避するために様々な仕組みをカスタムしてきました。ただ、これらのカスタマイズは各ユーザー側の開発・メンテナンスなどを必要とし、その管理のために本来の仕事とは別の時間を費やしてしまいます。
Terraform Cloud及びTerraform Enterpriseにはこれらの問題を解決すべく、様々なTeam collaboration及びGovernanceの機能を予め用意してあります。これからのWorkshopでは、これら機能を紹介していきます。
事前準備
- このWorkshopを行なうにはTerraform Cloudのアカウントが必要です。こちらからサインアップをしてください。(すでにアカウントをお持ちの方はスキップしてください。)
Remote State管理機能
Terraform cloudにはRemote State管理機能があります。ちなみに、この機能は誰でも無料で利用できます。
ここでは、Remote State管理機能を使うエクササイズを行います。
Workspaceの設定
Terraform Cloudにログインし、新規Workspaceを作成します。 ワークスペース名は任意で構いません。
注釈
1つのOrganization内では全てのWorkspace名が一意である必要がありますので、複数のユーザーで作業する場合、Workspace名がユニークになるようにしてください。
Workspaceは以下のボタンより作成できます。
以下の画面で、No VCS Connection を選択してください。
Workspace名にには重複しない任意の名前をつけてください。以下、このページでは、ここで指定した名前を YOURWORKSPACE という置き換え表示で表します。
つぎに、Workspaceの Setting > General > にナビゲートし、Execution modeを Local に設定して保存してください。
Execution modeを Local に設定すると、Terraformの実行はLocal環境で行いますが、作成されるStateファイルはTerraform Cloudに保存されます。
User Tokenの作成
さて、次にLocalのTerraform環境からTerraform Cloudにアクセスするために、User tokenを作成します。このUser tokenはローカル環境や別のシステム(CI/CDパイプラインや外部ツールなど)からTerraform Cloud APIを叩く際に必要となります。
右上の自分のアイコンをクリックして User Settings を選択します。
そこから、Tokens メニューから Create an API Token ボタンでUser Tokenを作成します。DescriptionにはこのTokenについての說明を追加できます。
作成されたTokenはこの画面でしか表示されないので、必ずコピーもしくはDownloadしておいてください。
次に、ここで作成されたTokenをLocal環境の
~/.terraformrc
に書き込みます。注釈
Windowsの場合、%APPDATA%terraform.rcとなります。
root@workstation:~# cat ~/.terraformrc credentials "app.terraform.io" { token = "TdobpJ0do60AZw.atlasv1.LK7nXDhzqJNy7zqIkwm0WaMPPuz4vEL5RU7aDTZ1vQQf16vjfEwyOrzDdw4KQejeGnM" }
これでLocal環境からTerraform CloudのAPIにアクセスする準備が整いました。
Remote Backendの設定
つぎにTerraformにRemote Backendを使用するコードを追加します。以下のコードを
remote_backend.tf
という名前で作成してください。 YOURORGANIZATION は使用しているOrganizationの値に、 YOURWORKSPACE は使用しているWorkspaceに置き換えてください。terraform { backend "remote" { hostname = "app.terraform.io" organization = "YOURORGANIZATION" workspaces { name = "YOURWORKSPACE" } } }
ここまでの準備が出来ましたら、Terraformを実行します。以下のコマンドを実行してください。
terraform init
ここで、もし直前のWorkshopで作成されたStateファイルが存在していると以下のように、「既存StateファイルをRemote Backendにコピーするか?」と尋ねられます。 Yes と入力して下さい。
root@workstation:~/hashicat-aws# terraform init Initializing the backend... Do you want to copy existing state to the new backend? Pre-existing state was found while migrating the previous "local" backend to the newly configured "remote" backend. No existing state was found in the newly configured "remote" backend. Do you want to copy this state to the new "remote" backend? Enter "yes" to copy and "no" to start with an empty state. Enter a value: yes Successfully configured the backend "remote"! Terraform will automatically use this backend unless the backend configuration changes.
それでは
apply
してみましょう。terraform apply
この
apply
ではLocalのStateファイルではなく、Terraform cloud上のStateファイルを使用します。よって、もうLocalのStateファイルは必要ないので削除しても構いません。この段階で、Terraform cloudのWorkspaceを確認すると、Stateファイルが作成されているはずです。
まとめ
これでRemote Backendの設定は完了です。ここでのエクササイズでは、個人個人でWorkspaceを作りましたが、これをチームで共有することでStateファイルの共有が実現できます。
ただ、Stateファイルの共有が実現できたとしてもまだまだチーム利用としては足りない機能が多々あります。それらを次からのWorkshopで見ていきたいと思います。
<https://github.com/hashicorp-japan/terraform-workshop/tree/master/contents>