①コマンドのインストール
homebrewでインストールできた。
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
②コマンドラインの設定
チュートリアルだとパスを通したり、コマンドの補完の設定をしているが自分の場合zshで履歴に基づいて予測候補を表示できるようにしているのでここはパス
③DockerをTerraformで動かす
ここから実践的な感じで、Dockerを実際にTerraformで動かして見る。まずはディレクトリの作成
open -a Docker
mkdir learn-terraform-docker-container
cd learn-terraform-docker-container
んで、 main.tf というファイルを作る。これがTerraformのメインの設定ファイルになるっぽい。
terraform {
required_providers {
docker = {
source = "kreuzwerker/docker"
version = "~> 2.13.0"
}
}
}
provider "docker" {}
resource "docker_image" "nginx" {
name = "nginx:latest"
keep_locally = false
}
resource "docker_container" "nginx" {
image = docker_image.nginx.latest
name = "tutorial"
ports {
internal = 80
external = 8000
}
}
んで、これを書いた状態で↓を実行するとプロジェクトが立ち上がる。(この状態ではまだリソースは動いていない)
terraform init
で、↓を実行するとリソースが実際に立ち上がる。
terraform apply
今回の場合はnginxのイメージを持っているDockerコンテナを立ち上げるような設定にしている。またポートを80:8000にしているので、localhost:8000でnginxのサーバーに接続できる。
立ち上げたリソースを停止するには↓を実行
terraform destroy
④AWSリソースをTerraformで立ち上げる
TerraformでAWSのリソースを立ち上げて見る。
Dockerの時と同様に main.tf に設定を書く。
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.16"
}
}
required_version = ">= 1.2.0"
}
provider "aws" {
region = "us-west-2"
}
resource "aws_instance" "app_server" {
ami = "ami-830c94e3"
instance_type = "t2.micro"
tags = {
Name = "ExampleAppServerInstance"
}
}
おそらく、チュートリアルドキュメントを見る限り各設定項目の意図は↓の通り
-
required_providers...Terraformを使う上で必須となるprovider。sourceでproviderの存在する場所、versionで利用するpvoviderのバージョンを指定している
-
provider...Terraformでリソースを管理するプラットフォーム的な何か。Docker、AWS、GCPみたいな粒度の値が入る。
-
resources...provider上で実際に立ち上げるリソース。これはシンプルだね
設定ファイルを書いたら先ほど同様に↓で立ち上げる。
terraform init
terraform apply
ちなみに。設定ファイルはフォーマットや記述ミスのチェックも可能で↓で行う。CIとかで使えそうだね。
terraform fmt
terraform validate
なんかエラーに遭遇したのでメモ
terraform apply
をすると↓のエラー
aws_instance.app_server: Creating...
╷
│ Error: creating EC2 Instance: InvalidAMIID.NotFound: The image id '[ami-830c94e3]' does not exist
│ status code: 400, request id: 24596a32-6f55-49d6-b205-94a0bf5078f1
│
│ with aws_instance.app_server,
│ on main.tf line 16, in resource "aws_instance" "app_server":
│ 16: resource "aws_instance" "app_server" {
│
╵
見た感じAMIがないよ!って言ってるのでいろいろ調べてたところ、リージョンによってamiのIDが異なるっぽい。
チュートリアルの main.tf で us-west-2 のリージョンが使われていたが、当然お金かけたくないので ap-northeast-1 に変更した。ただ、amiのIDはそのままにしていたのでエラーになったっぽい。
aws ec2 describe-images --owners self amazon --region ap-northeast-1
AWS CLIでこんな感じのコマンドを叩くと東京リージョンでawsm公式が持っているAMIが取得できる。と思ったんだけど取得結果が見づらいのでコンソールから調べて見る。
EC2インスタンスを立ち上げるときに↓みたいな画面になるが、ここで無料利用枠の対象となるイメージを選択。
AMIのIDがあるのでそれを main.tf にコピーして見る。
よし。無事 terraform apply に成功。やったぜ。
実際にコンソール見たら立ち上がってた。すごい。
ちなみに立ち上げたリソースの詳細をチェックするには↓を実行する。
terraform show
↓みたいな結果が表示されればOK
resource "aws_instance" "app_server" {
ami = "ami-078296f82eb463377"
arn = "..."
associate_public_ip_address = true
availability_zone = "ap-northeast-1c"
cpu_core_count = 1
cpu_threads_per_core = 1
disable_api_stop = false
disable_api_termination = false
ebs_optimized = false
get_password_data = false
hibernation = false
id = "i-0413a991b88bc950e"
instance_initiated_shutdown_behavior = "stop"
instance_state = "running"
instance_type = "t2.micro"
ipv6_address_count = 0
ipv6_addresses = []
monitoring = false
primary_network_interface_id = "eni-04ae1cf226d4d833d"
private_dns = "ip-172-31-3-118.ap-northeast-1.compute.internal"
private_ip = "172.31.3.118"
public_dns = "ec2-43-206-106-51.ap-northeast-1.compute.amazonaws.com"
public_ip = "43.206.106.51"
secondary_private_ips = []
security_groups = [
"default",
]
source_dest_check = true
subnet_id = "subnet-0a658c50"
tags = {
"Name" = "ExampleAppServerInstance"
}
tags_all = {
"Name" = "ExampleAppServerInstance"
}
tenancy = "default"
user_data_replace_on_change = false
vpc_security_group_ids = [
"sg-759f0a37",
]
capacity_reservation_specification {
capacity_reservation_preference = "open"
}
credit_specification {
cpu_credits = "standard"
}
enclave_options {
enabled = false
}
maintenance_options {
auto_recovery = "default"
}
metadata_options {
http_endpoint = "enabled"
http_put_response_hop_limit = 1
http_tokens = "optional"
instance_metadata_tags = "disabled"
}
private_dns_name_options {
enable_resource_name_dns_a_record = false
enable_resource_name_dns_aaaa_record = false
hostname_type = "ip-name"
}
root_block_device {
delete_on_termination = true
device_name = "/dev/xvda"
encrypted = false
iops = 100
tags = {}
throughput = 0
volume_id = "vol-026751c2ae22eb49d"
volume_size = 8
volume_type = "gp2"
}
}
一旦ここでコミットしておきましょか。
ちなみに設定の変更を反映するときも terraform apply でOK
インフラを止める
立ち上げたリソースを停止したい場合は↓を実行
terraform destroy
さっき起動中になっていたリソースが終了済みになった。
変数を渡す
terraformの設定ファイルに変数を渡して、コマンド実行ごとに違う値を渡すことができる。
variables.tf を作成して↓の通り記述
variable "instance_name" {
description = "Value of the Name tag for the EC2 instance"
type = string
default = "ExampleAppServerInstance"
}
変数を設定ファイルに渡すときは↓のように書く
resource "aws_instance" "app_server" {
ami = "ami-078296f82eb463377"
instance_type = "t2.micro"
tags = {
Name = var.instance_name
}
}
var.instance_name とすると、instance_name という変数の値をtagsのNameに渡すことができる。
変数に default = "ExampleAppServerInstance" としているので、特に値を渡さなければdefaultの値でリソースが立ち上がる。
ちなみにここで特にinstance IDを指定していないからなのか、先ほどとは違うインスタンスが立ち上がった。(一度destroyしていると違うリソースが立ち上がる?)
次にコマンド実行時に変数を渡す。
terraform apply -var "instance_name=YetAnotherName"
こうすると、以下のようなログが流れNameの値が変わったことがわかる。
Terraform will perform the following actions:
# aws_instance.app_server will be updated in-place
~ resource "aws_instance" "app_server" {
id = "i-07106c4743876f6cb"
~ tags = {
~ "Name" = "ExampleAppServerInstance" -> "YetAnotherName"
}
~ tags_all = {
~ "Name" = "ExampleAppServerInstance" -> "YetAnotherName"
}
# (29 unchanged attributes hidden)
# (7 unchanged blocks hidden)
}
Plan: 0 to add, 1 to change, 0 to destroy.
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
実際にコンソール上でも値が変わっていることがわかる。
リソース情報を出力できるようにする
Terraform上でどんなリソースが立ち上がっているのかをコマンドラインから確認できるようにする。
こうすると共同作業者が使いやすかったりAWSコンソールから探しやすかったりのメリットがありそう。
outputs.tf を作成し、↓のように記述
output "instance_id" {
description = "ID of the EC2 instance"
value = aws_instance.app_server.id
}
output "instance_public_ip" {
description = "Public IP address of the EC2 instance"
value = aws_instance.app_server.public_ip
}
設定内容は↓のコマンドで確認できる。
terraform output
実行結果
tomolico@mourifuyusatorunoMacBook-Air learn-terraform-aws-instance % terraform output
instance_id = "i-07106c4743876f6cb"
instance_public_ip = "54.65.225.171"
Terraform Cloudにリソース情報を保存
terraformのコードから作られるリソース情報をcloud上に管理しておくことができる。GUIから見れるっぽくて便利だね。
maim.tf に↓の記述を追加
cloud {
organization = "organization-name"
workspaces {
name = "learn-tfc-aws"
}
}
origanizationはサインインするときに設定する。nameは任意の名前でOK。
CLIとterraform cloudを連携する。↓のコマンドを実行。
terraform login
↓のようにAPIのtokenを入力するように求められるので、web上で発行したトークンを入力する。
Generate a token using your browser, and copy-paste it into this prompt.
Terraform will store the token in plain text in the following file
for use by subsequent commands:
/Users/tomolico/.terraform.d/credentials.tfrc.json
Token for app.terraform.io:
Enter a value:
ちなみにトークンはweb上で個別発行もできる。
そのまま立ち上げようとすると以下のようなエラーに遭遇。どうやら環境変数でAWSのクレデンシャルを渡さないといけないらしい。
Initializing plugins and modules...
╷
│ Error: error configuring Terraform AWS Provider: no valid credential sources for Terraform AWS Provider found.
│
│ Please see https://registry.terraform.io/providers/hashicorp/aws
│ for more information about providing credentials.
workspaceのvariablesってところで設定できるので設定しておく。ちなみにこの画面に辿り着くには先に空のワークスペースを立ち上げておく必要がありそう。おそらくcloudで接続していないときはデフォルトでコマンドラインで設定した環境変数を読み込む設定になっていたのだろうけど、cloud連携した結果読み込み先が変わったって話かなと思う。
ちなみに普通にインスタンスを立ち上げようとすると↓みたいな警告が出てくる。
Changes to Outputs:
+ instance_id = (known after apply)
+ instance_public_ip = (known after apply)
╷
│ Warning: Value for undeclared variable
│
│ The root module does not declare a variable named "AWS_SECRET_ACCESS_KEY"
│ but a value was found in file
│ "/home/tfc-agent/.tfc-agent/component/terraform/runs/run-ufJR9wYcwnidho6D/terraform.tfvars".
│ If you meant to use this value, add a "variable" block to the
│ configuration.
│
│ To silence these warnings, use TF_VAR_... environment variables to provide
│ certain "global" settings to all configurations in your organization. To
│ reduce the verbosity of these warnings, use the -compact-warnings option.
╵
╷
│ Warning: Value for undeclared variable
│
│ The root module does not declare a variable named "AWS_ACCESS_KEY_ID" but a
│ value was found in file
│ "/home/tfc-agent/.tfc-agent/component/terraform/runs/run-ufJR9wYcwnidho6D/terraform.tfvars".
│ If you meant to use this value, add a "variable" block to the
│ configuration.
│
│ To silence these warnings, use TF_VAR_... environment variables to provide
│ certain "global" settings to all configurations in your organization. To
│ reduce the verbosity of these warnings, use the -compact-warnings option.
╵
放置しておいても動くのだけど、環境変数ファイルとかから読み込ませるなりしておいた方がいいのかな。
cloud連携した状態でリソースを立ち上げると↓みたいな状態になる。こっちのがわかりやすいのはわかりやすいわね
ちなみにリソースを終了すると↓の表示になる。なんとコマンドライン実行時に非同期でプルしてくれました。すごい。







