Open20

Terraform学習記録

ふろんふろん

AWS・GCPみたいなクラウドプラットフォームから、他のSaas設定のIaC化にも使える。
背後ではそれぞれのサービスのAPIを叩いている。
Terraform provider: 各サービスをTfに対応させる設定(?)

ふろんふろん

Tfのworkflowは大体以下のような感じ。
Write: .tfファイルにresourceを定義する。
Plan: Tfがplan(実行計画)を作成する
Apply: planに基づいてAPIを叩く。

ふろんふろん

Tf languageの最終目標はresourceを宣言すること。
他の言語機能はすべてそれを補助するためのもの。

Tf languageは以下のような構文を基本ブロックとして構成される。

<BLOCK TYPE> "<BLOCK LABEL>" "<BLOCK LABEL>" {
    <IDENTIFIER> = <EXPRESSION>
}

# 例
resource "aws_vpc" "main" {
    cidr_block = var.base_cidr_block
}
ふろんふろん

blockは0個以上のlabelを持てる。
上の代入式をargument、expressionはリテラルや変数によるなにかしらの値を指す。

var.[var_name]var_nameの値を使える。

ドキュメントの例を見てもなにが予約語でなにが変数名かわからない。provider特有の予約語とかもあるのか?

ふろんふろん

同じディレクトリにある.tfファイルの集合をmoduleという(tf.jsonファイルもあるらしいけどそれは一旦おいておく)。
同じmoduleにある設定はすべて対等に扱われる。子ディレクトリは別のmoduleとして扱われる。
別のファイルに置いておくのは管理を容易にする以外の意味はない。

ふろんふろん

module callというものを用いることで他のmoduleの設定を取り込むことができる。
Tfは単一のroot moduleを持つ。1つのroot moduleと、root moduleが取りこむ他のmoduleという木構造でモデル化できる。
CLIではterraform *をするディレクトリがroot moduleに対応する。

ふろんふろん

_override.tfをsuffixに持つ.tfファイルを使うことで、設定をoverrideできるらしい。
いろいろ細かい挙動があるらしいけどとりあえず飛ばす。

ふろんふろん

Tfの設定にはproviderやexternal moduleといったdependencyがありうる。
そのversionを.terraform.lock.hclに記述する。
.terraform.lock.hclterraformコマンドを実行するディレクトリに置く。
terraform initの際に自動的にlockファイルが作成される。
詳細についてはまたあとで。

ふろんふろん

block文はtypeを持つ(resourceとかdataとか)。typeによってlabelの数が決まる。

ふろんふろん

resourceはTfの基本となる要素。各resourceブロックは1つのinfrastructure object(例: virtual network, compute instances, DNS record)に対応する。

ふろんふろん

resource文は2つのlabelを持つ。それぞれresource type (例: "aws_instance")とresourceのlocal nameに対応する。
各resourceは1つのresource typeを持つ。それぞれのresource typeが具体的になにを表すかはproviderによって定義されている。
argumentという名前の通り、resourceを表す関数(arguments |-> concrete resource)に引数を渡してると考えるとよさそう。
各resource typeに必要なargumentはproviderが定義している。例えばlambdaならこれ

ふろんふろん

precondition, postcondition blockでassert的なものができる。
.tfに書かれたlocalなconfigと、現状のインフラの状態を表すstateがある。apply時はこれらを比較して必要な操作をする。デフォルトではstateはlocalのterraform.tfstateに記述されるが、Terraform Cloudに置いたほうがバージョン管理・暗号化・共有がしやすい。

ふろんふろん

meta arguments
リソースの性質を表さない、メタ変数(引数)。

depends_on

Tfが推論できない依存関係を明示するのに使う。これ書かなかったらapplyでエラー出るって認識でいいのかな?

count

同じresourceを複数作りたい場合につかう。

for_each

for_eachしたいときに使う。

provider

providerの設定を変えたいときに使う。

lifecycle

applyの処理の順番を変えたいときに使う。
デフォルトでは以下

  1. create: configにはあるがstateにはないresourceをcreateする
  2. destroy: configにはないがstateにはあるresourceをdestroyする
  3. update in-place: (可能なら)現存するresourceの設定を変更する
  4. destroy and re-create: update in-placeができないresourceを削除&作成する
ふろんふろん

data sources
data blockを使って外部のデータを変数として使える。
すでにあるresourceの情報とかを使えるってことでいいのかな→あってそう
filterというargumentを使ってresourceを特定するっぽい?
filterとは限らないっぽい、S3だとbucketというargumentでバケットを特定している。

ふろんふろん

provider blockでproviderの設定ができる。例えば、AWSのregionとか

ふろんふろん

なんかterraform blockとかいうのが出てきた、なにこれ
Tfそのものの挙動をいじるために使うらしい、Tfのバージョンとか、experimentalなTfの機能を使うかとか。
terraform block内にrequired_providersというblockもあるな、なんだこれ。
すべてのTf moduleはどのproviderを使うかを指定するためにrequired_providersが必要らしい。その中でproviderやそのバージョンを指定する。

ふろんふろん

input variable

variable blockで、「moduleの引数」のようなものを宣言できる。
子moduleが定義したinput variableは、親moduleがその値を渡して使う。
variable内には変数名やその型、デフォルトの値を定義する、validationとかnullableの定義もできる。
親moduleはどうやって値を渡すんだ?→ module blockを使う。
output variableはoutput blockを使って子モジュール内の値を親モジュールにexposeできる。
local variableは同じmoduleの中で使える値。DRYにするため。

ふろんふろん

module block
超重要っぽい。

module "servers" {
  source = "./app-cluster"
  servers = 5
}

local name: 上の例ではserversの部分
source: 必須。moduleを定義する.tfファイルを含むlocal directoryかremote moduleへのパスを書く。
version: module registryから拾ってくる場合に使う。
上の例ではmodule.servers.*という形でmoduleのoutput variableにアクセスできる。