このブログ記事では、Terraformにおける変数と出力について紹介します。
前回の記事では、シンプルな例を使用してTerraformでクラウドインフラストラクチャを簡単にセットアップする方法について説明しました。 その例からTerraformのIaCツールとしての有用性を既に観察できましたが、例のコードは多くのパラメータがハードコードされており、 コードが再利用不可能で柔軟性と安全性に欠けていた為、これはIaCツールとしてのTerraformを十分に活用的ていませんでした。 そこで、この記事では、HCLにおける変数と出力を活用してTerraformをより有効活用する方法について説明します。
変数
HCLでは、variableブロックを使用して変数を定義できます。このブロックは説明、型、
そしてデフォルト値と変数が機密情報かどうか(環境変数用)を含み、定義された変数はvar.<var_name>で使用できます。
変数はリソースが定義されている同じmain.tfファイルで定義することもできますが、
変数定義用に別のvars.tfファイルを設定することが多いです。以下はvars.tfでの変数定義の例です。
variable "ami" {
description = "Amazon Machine Image for EC2 instance"
type = string
}
variable "instance_type" {
description = "EC2 instance type (default: t4.micro)"
type = string
default = "t4.micro"
}
variable "db_password" {
description = "SENSITIVE DB password"
type = string
sensitive = true
}ハードコードされた文字列の代わりに、適切な場所でvar.amiやvar.instance_typeのような変数を使用できます。
Terraformでは、変数に値を提供する多くの方法があります。例えばplanとapplyを実行する際、
Terraformはまず-varと-var-file引数をチェックし、必要なすべての変数に値が提供されていることを確認します。
引数が提供されていない場合、または値が不十分な場合、*.auto.tfvarsとterraform.tfvarsファイルを探します
(tfvarsファイルには各行に<var_name> = <value>を含みます)。
次に、TF_VAR_<name>環境変数をチェックし、その後デフォルト値をチェックします。
それでも値が不十分な場合、CLIで手動で値を入力するよう求められます。
通常、非機密変数(amiやinstance_typeなど)の値は.tfvarsファイルで定義し、
機密変数(db_passwordなど、sensitiveパラメータをtrueに設定してCLIに表示されないようにする)は.envファイルまたは-var引数で定義します。
このセットアップを使用することで、インフラストラクチャの要件とフェーズ(開発、ステージング、本番)に応じて異なる.tfvarsファイルを編集または使用でき、
リポジトリで共有される可能性のあるファイルにハードコードされた秘密情報を避けることができるため、
コードを再利用可能で柔軟性と安全性のあるものにすることができます。
ローカル変数と出力
コードの再利用性のためではなく、より良いコード構成と繰り返しを避けるために変数を使用したい場合があります。
例えば、ローカル変数ec2_portを作成してEC2インスタンスのポート番号8080をハードコードすることを避けたい場合があります。
このような場合、定義されたファイル内でのみ適用されるローカル変数を使用でき、以下のようにlocalsブロックを使用して定義できます。
locals {
ec2_port = 8080
lb_port_in = 80
lb_port_out = 0
}上記のように、特定のファイルのすべてのローカル変数は同じlocalsブロック内で定義されます。
その後、local.ec2_port、local.lb_port_inなどのようにこれらの変数を使用できます。
また、applyコマンド後に属性の出力値を取得したい場合もあります。
例えば、ネットワーキングの設定(Kubernetesクラスターなど)でEC2インスタンスのIPアドレスを使用する場合などです。
このような場合、outputブロックで定義される出力を使用できます。
このブロックには、取得したいリソースの属性を指定する値(オプションで説明、型、sensitiveパラメータ)が含まれます。
出力は通常、変数がvars.tfで定義されるのと同様に、outputs.tfファイルで定義されます。
output "instance_1_ip_addr" {
type = string
values = aws_instance.instance_1.public_ip
}applyコマンドを使用してリソースが準備完了後、非機密出力がCLIに表示されます。
また、terraform output -jsonを使用してすべての出力パラメータを確認したり、terraform output <output_name>を使用して特定の出力の値をチェックしたりできます。
これらは、後続の手動または自動のインフラストラクチャ設定のためにログ記録やパイプ処理が可能です。
言語機能とメタ引数
変数と出力以外にも、HCLにはより良いコードを書くことを可能にする多くの言語機能があります。
例えば、リソース定義でテンプレート文字列("AMI used: ${var.ami}")、
演算子(!、==など)、条件文(<cond> ? true : false)、forループ([for i in var.list: i])などを使用できます。
また、ハッシュ化、型変換、日付と時刻などに関する便利な定義済み関数もあるため、
詳細については記事の最後に引用されている公式ドキュメントをチェックすることを強く推奨します。
リソースブロックでメタ引数を使用することもでき、これによりインフラストラクチャプロビジョニングをより細かく制御できます。
例えば、depends_on引数を用いて、この引数を持つリソースが構築される前に作成される必要があるリソースをリストで定義できます。
また、同じリソースの複数のレプリカを作成し、count.indexを使用して個別に参照できるcountメタ引数、
リスト(またはセット)を反復処理して各要素に対してリソースを作成し、each.keyで参照できるfor_each引数、
ライフサイクルでの動作を設定できるlifecycle引数(可用性のためのcreate_before_destroyや変更を避けるためのignore_changesなど)も使用できます。
Terraformには他にも多くの有用なメタ引数があるため、詳細については公式ドキュメントをチェックすることを推奨します。
結論
この記事では、IaCツールとしてTerraformをより活用するための変数、ローカル変数、出力、その他の有用な言語機能とメタ引数を紹介しました。 練習としてこれらの機能を使用して前回の記事のTerraformコードを書き直してみたり、他のプロジェクトでも活用してみることをお勧めします。 また、これらの機能の詳細と説明については、以下に引用されているリソースをチェックすることをお勧めします。
リソース
- DevOps Directive. 2022. Complete Terraform Course - From BEGINNER to PRO! (Learn Infrastructure as Code). YouTube.
- HashiCorp. n.d. Terraform Language Documentation. Terraform.