AR ホームベーカリー

オイラのアウトプット用ホームベーカリー!

Terraform を書く時に気をつけること

忘れがちなので、気付いたタイミングで書いておく。

backend に変数 (Variables) は利用できない

こんな感じで怒られる。 起動時に引数に渡すか、backend 用に別ファイルを作れとのこと。

│ Error: Variables not allowed
│
│   on main.tf line 11, in terraform:
│   11:     profile = var.profile
│
│ Variables may not be used here.

qiita.com

github.com

上記記事でも言及されているけど、(インフラ構成するコードベースに対して) ハードコーディング強制するのはおまえ、という感じある。

変数を展開する際の ${} 有無について

ja.stackoverflow.com

上記記事で言及されているのがすべてなんだけど、 Terraform v0.11 までは律儀に書かないとダメだったけど、それ以降は書かなくても大丈夫になったらしい。

とはいえ、文字列内に含めたい場合は必要なはずなので、以下の理解でやっている。

variable "vpc_cidr" {}
variable "prefix" {}

vpc_cidr = "10.0.0.0/16"
prefix = "prod-example"

resource "aws_vpc" "vpc" {
  cidr_block = var.vpc_cidr
  instance_tenancy = "default"

  tags = {
    Name = "${var.prefix}-vpc"
  }
}
文字列に含めないで (単独で) 使う 文字列に含めて使う
var.vpc_cidr "${var.prefix}-vpc"

(LL 含む) 言語記述時はなるべく省略すべき、となるんだろうけど、 Terraform くらいなら全部 ${} で統一してしまっていいかもしれない。

MySQL の予約語

groups というテーブルがあるんだけど、SELECT を投げようとして syntax error になった。

mysql> SELECT * FROM groups;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'groups' at line 1

あーはん? と思ったんだけど、そういえばワンセンテンスだしもしかして予約語か? などと思い至る。 こういう時はテーブル名をシングルクォートかバッククォートで囲えば大体なんとかなるんや!

mysql> SELECT * FROM `groups`;

...

4545 rows in set (0.04 sec)

ハーイッタ。

MySQL予約語一覧

こう。 結構あるけど、ActiveRecord 側でブロックしないし、MySQL 側もシュッと作れてしまうので注意が必要。 せめて MySQL 側のエラーは syntax error で丸めるにしても、「予約語 (reserved words) じゃねえの?」ってサジェスト出してほしい。 内部的には一覧持ってると思うんだけどなー。

dev.mysql.com

Terraform の backend を S3 にする

ロケ地

  • Terraform 1.3.6
  • hashicorp/aws 4.45.0

Error loading state

state がローカルやんけ! と気づいて、 backend "s3" を書いて、リモートに手動でバケットを作成 (設定は名前以外、全部変更なしのアクセスきつきつでオッケー)。

後に terraform init -migrate-state したら Error loading state が無限に出るようになってしまった。

Initializing the backend...
Backend configuration changed!

Terraform has detected that the configuration specified for the backend
has changed. Terraform will now check for existing state in the backends.

╷
│ Error: Error loading state:
│     AccessDenied: Access Denied
│     status code: 403, request id: XXXXXXXXXXXXXXXX, host id: なんかなげーの
│
│ Terraform failed to load the default state from the "s3" backend.
│ State migration cannot occur unless the state can be loaded. Backend
│ modification and state migration has been aborted. The state in both the
│ source and the destination remain unmodified. Please resolve the
│ above error and try again.

結局何をやっても解決しないし、本番運用しているわけでもないので、 rm -rf .terraform* してローカルを綺麗にしてしまった。

これで再度 terraform init して、 S3 に state を設置できるようになった。

shared_credentials_file

これは単純な疑問なんだけど、 provider backendprofile~/.aws/credentials で指定したプロファイル名を書くだけだと動作しなくて、[default] を見ちゃうのはバグなんすかね……?

それぞれセットで shared_credentials_file = ~/.aws/credentials を書かないと、指定したプロファイル (とクレデンシャル) を参照してくれなくてハマってしまった。

で、shared_credentials_file を使うと以下の Warning が出る。

│ Warning: Attribute Deprecated
│
│   with provider["registry.terraform.io/hashicorp/aws"],
│   on providers.tf line 4, in provider "aws":
│    4:   shared_credentials_file = "~/.aws/credentials"
│
│ Use shared_credentials_files instead.
│
│ (and one more similar warning elsewhere)

動作はするので無視すればいいんだけど、v4 系は本来 shared_credentials_files らしい。 けど、そちらを指定するとエラーで死ぬ。

│ Error: Incorrect attribute value type
│
│   on providers.tf line 4, in provider "aws":
│    4:   shared_credentials_files = "~/.aws/credentials"
│
│ Inappropriate value for attribute "shared_credentials_files": list of string required.

期待した動作とちゃうやんけ! と言ってる外人兄貴もいるんだけど、その後クローズされてるしなん、なんだろうこれ。

github.com

terraform の provider バージョンの確認

一旦 terraform init してあれば terraform providers -version で確認できる。

terraform providers -version
Terraform v1.3.6
on darwin_arm64
+ provider registry.terraform.io/hashicorp/aws v4.45.0

事前に探したい場合は以下あたりから。

registry.terraform.io

Terraform リソース作成時にデフォルトで付与するタグを管理する

  • 作成したリソースが Terraform 由来であること
  • 複数の企業が単一アカウント ID に AdministratorAccess 持っている

という状態のインフラを管理しているので、それぞれ AWS のリソース作成時のタグに Build: Terrafrom Company: 会社名 を付与する運用にしている。

んだけど、 Terraform でリソース追加するたびに書いていて「うーん」と思っていたら、 provider に default_tags というのがあるらしい。

dev.classmethod.jp

# 東京リージョン
provider "aws" {
  profile = ""
  region = "ap-northeast-1"

  default_tags {
    tags = {
      Build = "Terraform"
      Company = "Example"
    }
  }
}

こんな感じとのことなので、すこし使ってみようと思う。

ちなみにタグ名が重複した時は、元記事にも書いてあるとおり、個別リソース側の値が優先されるとのこと。

registry.terraform.io

シェルスクリプトでの小数点を含む数値 (ロドーアベレージ) の比較

www.koikikukan.com

つまりこういうことだった。 $((hoge)) -gt $((fuga)) みたいにしたりしてもだめだし、じゃあ片側数字ならええんか? と思ってたけど、単純にダメなやつであった。

ATAI="0.40"
<200b>
LOAD_NOW=`uptime | grep "load average" | sed -e 's/^.*load\saverage:\s//g' | awk '{print $2}' | sed -e 's/,//g'`
MESSAGE="${INSTANCE} が重いかもしれん、ロードアベレージは ${LOAD_NOW} だ……"
<200b>
if [ `echo "${LOAD_NOW} > ${ATAI}" | bc` == 1 ]; then

シェルスクリプト初心者かー? みたいな感じになってしまった。

基本情報技術者試験落選

そういやそろそろ午前午後ともに受付終わりじゃん、来週末くらいに予約いれとこ、と思ったら都内はおろかほぼ日本全国予約できなくなってて草生える。 あーあ、めちゃくちゃだよ。

代わりに Ruby Silver でも受験すっか。