Terraform のドキュメントを読む
気まぐれに Terraform のドキュメントを読む。
Intro
クラウドやオンプレのインフラに関わる「リソース」を人間が読める形式の構成ファイルに定義し、一貫したプロビジョニングや管理を実現出来るようになる云々。
Terraform はクラウドサービスの API をプロバイダーを介して叩くっぽい。
Terraform が実施するワークフローには3ステップあるよう。
- Write:リソースの定義。configuration と state file の2つのファイルがあるっぽい。
- Plan:実行計画(?)を作成するよう。
- Apply:依存関係に従い、正しい順序でリソースの操作を行うよう。
インフラストラクチャをイミュータブルに。
state file を使って現実のインフラを追跡する(?)。インフラ環境の source of truth として機能する。
state file を使うことである変更が実際のインフラに与える影響を特定する。
Terraform の構成ファイルは宣言的。つまり、構成ファイルの内容はインフラ構成の最終的な状態をそのまま表している。
宣言的であるため、リソースを作成するために逐次的な動作手順を記述する必要はない。(e.g. まず A を作って、そしたら次に B を作って、といったようにステップバイステップでの作業手順は不要)
Terraform はリソース間の依存関係を明らかにするためにリソースグラフを作成する。
依存関係を持たないリソースは並行的に作成・修正を行う。
modules と呼ばれる形である構成を再利用可能にすることができるらしい。
Get Started をクリックすると主要なプロバイダー毎にセクションが分けられている。
GCP が一番馴染みがあるので、とりあえず GCP のところを読む。
Get Started - Google Cloud
さらにセクションが分けられている。
What is Infrastructure as Code with Terraform?
IaC ツールによって GUI でなく構成ファイルを使ってインフラの管理が出来る。
IaC はバージョニング出来て、再利用可能で、共有も出来る構成ファイルを使うことで、リソースを作ったり変更したり管理したりを、安全で、一貫していて、繰り返し使えるやり方で提供する。
Terraform は HashiCorp の IaC ツール。
人間にとって読みやすく、宣言的な構成ファイルにより、インフラのライフサイクル(作ったり、変更したり、削除したり)を管理する。
手作業であれこれやるよりもたくさん利点があるよと。
プロバイダーと呼ばれるプラグイン機能があり、これにより Terraform は GCP や AWS などのクラウドプラットフォームと API を介して相互間のやり取りができるようになる。
プロバイダーはたくさんある。
これらのプロバイダーでは、インフラのリソース(VM のインスタンスとか VPC とかかな)を個別に定義している。
プロバイダー毎に個別に定義されたリソースを組み合わせて「modules」と呼ばれる単位で「一貫した言語」で再利用や管理が出来るようになると。
Terraform の構成言語は宣言的。ステップバイステップで、つまり命令的にリソースの操作を行わないよと。
Terraform のプロバイダーはリソース間の依存関係を自動的に算出し、正しい順番で作成や削除を行う。
(A というリソースがある前提で B というリソースがある場合に、B を作る前に A を作るぞ、という話)
Terraform を使ってインフラ構成を「デプロイ」するために必要になるもの
- Scope: プロジェクトが利用するインフラを特定する(e.g. GCP にデプロイしよう)
- Author: 構成内容を書き出そう
- Initialize: インフラを管理するために必要なプラグインをインストールしよう。(ここでのプラグインってのはプロバイダーとは別なのかな?)
- Plan: Terraform がインフラ構成に与える変更内容をプレビューしよう
- Apply: 計画された変更を作成しよう。
実際にデプロイされたインフラリソースの内容を state file で追跡する。
この state file が、インフラ環境を表す source of truth となる。
Terraform はこの state file を使うことで何がどう変更されるのかを明らかにすることが出来るようになる。
state file を共有することで複数の開発者とコラボレーション出来るようになる。
(state backend って用語?)
Terraform Cloud というものが使えるみたいだけど、別に GitHub で管理するでも良さそうに見えた。
Quick Start をやってみる
Terraform のサイト上で直接体験出来るみたいだったので試してみる。
terraform {
required_providers {
docker = {
source = "kreuzwerker/docker"
version = "~> 2.15.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
}
}
こんなコード(?)を書く。tf
で markdown のハイライトが効く。
書き終わったら terraform init
を実行する。
> terraform init
Initializing the backend...
Initializing provider plugins...
- Finding kreuzwerker/docker versions matching "~> 2.15.0"...
- Installing kreuzwerker/docker v2.15.0...
- Installed kreuzwerker/docker v2.15.0 (self-signed, key ID BD080C4571C6104C)
Partner and community providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:
https://www.terraform.io/docs/cli/plugins/signing.html
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
provider "docker" {}
という記述を見てプラグインのダウンロードが開始されるよう。
.terraform.lock.hcl
というロックファイルが作成された。
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/kreuzwerker/docker" {
version = "2.15.0"
constraints = "~> 2.15.0"
hashes = [
"h1:NEBNtKNukqr6qk5vWu8Xx/nHBVNNdlty0hrFG76K7AE=",
"zh:0241e5c7b66c14aa54e367dfe380fbde8388d3254cbe8a70717c12f71897e82b",
"zh:0f162f0a01ffe9eec32e78dfc2a5b05a373230c41f041439efa3f4b68903fdcb",
"zh:1c222c1425fbb0367154bcb8e4d87b19d6eae133fbb341f73102fa3b300f34bf",
"zh:679206433e31d8fa69d95167af6d2cd762218e89811b735ee20bd8da19f97854",
"zh:a16baab045bc7a709a9767816304cc5548aa2ee0b72c0eee49e3826e6a46a3fd",
"zh:a29c4e304a6a7faf5b651a61a91a1aa2e837591cff049fbe1c747b6319e43956",
"zh:bed7a69dbb9a024aecfac840ca2ac2f1527062f3d9c8c718e4e81d464b5ad329",
"zh:c22aa10806de216b6aa0b36a2c1114a9fdaa5b47925aaad3333de3ce24cc52c9",
"zh:d034295663d8a39035fd6fdf0488b72544b13f48acaee797af967343248676f8",
"zh:d9001dfeac0db1799d8ab9d04be090522529baae0dba7f7e82b71f2168f05582",
"zh:d9f3eb7ef8f256eb9148d72bd4a00e34f3be5570484598e26b603cbdc5eed923",
"zh:ef573f1e0f000127fa9f569c8ee320f03ba1d302a6fbf9aac8300efa6fc6f4b2",
"zh:ef7e246b4205202161b4119c10a1282f74243e029508184132731f9f6f6d9f4c",
]
}
次に terraform apply
コマンドを実行する。
> terraform apply
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
+ create
Terraform will perform the following actions:
# docker_container.nginx will be created
+ resource "docker_container" "nginx" {
+ attach = false
+ bridge = (known after apply)
+ command = (known after apply)
+ container_logs = (known after apply)
+ entrypoint = (known after apply)
+ env = (known after apply)
+ exit_code = (known after apply)
+ gateway = (known after apply)
+ hostname = (known after apply)
+ id = (known after apply)
+ image = (known after apply)
+ init = (known after apply)
+ ip_address = (known after apply)
+ ip_prefix_length = (known after apply)
+ ipc_mode = (known after apply)
+ log_driver = "json-file"
+ logs = false
+ must_run = true
+ name = "tutorial"
+ network_data = (known after apply)
+ read_only = false
+ remove_volumes = true
+ restart = "no"
+ rm = false
+ security_opts = (known after apply)
+ shm_size = (known after apply)
+ start = true
+ stdin_open = false
+ tty = false
+ healthcheck {
+ interval = (known after apply)
+ retries = (known after apply)
+ start_period = (known after apply)
+ test = (known after apply)
+ timeout = (known after apply)
}
+ labels {
+ label = (known after apply)
+ value = (known after apply)
}
+ ports {
+ external = 8000
+ internal = 80
+ ip = "0.0.0.0"
+ protocol = "tcp"
}
}
# docker_image.nginx will be created
+ resource "docker_image" "nginx" {
+ id = (known after apply)
+ keep_locally = false
+ latest = (known after apply)
+ name = "nginx:latest"
+ output = (known after apply)
+ repo_digest = (known after apply)
}
Plan: 2 to add, 0 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.
Docker イメージと Docker コンテナがそれぞれリソースとして扱われているよう。
yes
とタイプすると nginx イメージ(docker_image.nginx
)がビルドされてから、docker コンテナ(docker_container.nginx
)が作成された。
docker ps
を実行すると nginx のコンテナが起動していることが分かる。
適当に curl localhost:8000
を実行するとちゃんと疎通した。
コンテナを停止させリソースを吐きするために terraform destroy
を実行する。
> terraform destroy
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
+ create
Terraform will perform the following actions:
# docker_container.nginx will be created
+ resource "docker_container" "nginx" {
+ attach = false
+ bridge = (known after apply)
+ command = (known after apply)
+ container_logs = (known after apply)
+ entrypoint = (known after apply)
+ env = (known after apply)
+ exit_code = (known after apply)
+ gateway = (known after apply)
+ hostname = (known after apply)
+ id = (known after apply)
+ image = (known after apply)
+ init = (known after apply)
+ ip_address = (known after apply)
+ ip_prefix_length = (known after apply)
+ ipc_mode = (known after apply)
+ log_driver = "json-file"
+ logs = false
+ must_run = true
+ name = "tutorial"
+ network_data = (known after apply)
+ read_only = false
+ remove_volumes = true
+ restart = "no"
+ rm = false
+ security_opts = (known after apply)
+ shm_size = (known after apply)
+ start = true
+ stdin_open = false
+ tty = false
+ healthcheck {
+ interval = (known after apply)
+ retries = (known after apply)
+ start_period = (known after apply)
+ test = (known after apply)
+ timeout = (known after apply)
}
+ labels {
+ label = (known after apply)
+ value = (known after apply)
}
+ ports {
+ external = 8000
+ internal = 80
+ ip = "0.0.0.0"
+ protocol = "tcp"
}
}
# docker_image.nginx will be created
+ resource "docker_image" "nginx" {
+ id = (known after apply)
+ keep_locally = false
+ latest = (known after apply)
+ name = "nginx:latest"
+ output = (known after apply)
+ repo_digest = (known after apply)
}
Plan: 2 to add, 0 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.
yes
とタイプすると、コンテナが削除され、次にイメージが削除された。
docker images
も docker ps
も空になっていた。