Terraformのworkspaceを使いこなしたい

Terraformのworkspace(旧environment)について、いまいち理解しきれていない部分があったので整理しておくことにした。まずは普通にworkspaceを使った時にどのような動きになるのかを確認した。そして、応用としてworkspace毎に別のテナントを使ったり、workspaceによってリソースの名前を変えるというテクニックについて検証した。なお、Terraformのバージョンは v0.10.5 を、プロバイダーはOpenStackを用いている。

単純にworkspaceを分けて使う

まずは何も工夫せず、純粋にworkspaceを分けて使う時に何が起こるのかを確認する。プロバイダーを定義して…

次に、リソースとしてセキュリティグループを1つ定義しておく。

この時点ではworkspaceは分けていない。標準のDefaultのままである。ここでapplyする。

当然だが、リソースが作成される。リソースの状態は./terraform.tfstateに保存される(以下のサンプルでserialが2になっているのは、sg.tfを追加する前に一度applyしたため)。

一度リソースをdestroyして、workspaceを用意していく。標準ではDefaultのみ。

stagingという名前のworkspaceを追加する。

一覧にstagingが追加され、terraform.tfstate.d/staging ディレクトリが作成される。

applyするとどうなるか。

作成時の画面はいつもと同じだが、terraform.tfstateの位置が変わる。標準だとCWDに作られるが、workspaceを指定している時は terraform.tfstate.d/${workspace}/terraform.tfstate になる。つまり、 terraform.tfstate.d/staging/terraform.tfstate だ。

次にworkspaceとしてproductionを作成して、そちらでapplyしてみる。workspaceが変わったので、tfstateも変わり、terraform.tfstate.d/production/terraform.tfstate になる。別々のtfstateで管理しているので、リソースも複数作成されていることになる。

セキュリティグループを確認すると、secgroup_1が2つあることが確認できる。このように、workspaceは状態の管理を分けていることがわかる。

workspace毎にテナントを変える

前節ではworkspaceの動きについて確認した。こうなると、少し実践的なことを試してみたくなる。本節では、workspace毎に別々のテナントを使う、ということをやってみる。前節では同じテナントに同じ名前のリソースを作っていたが、これは管理上わかりにくいと感じる。リソースの名前はテナント内ではユニークであることが望ましいだろう。となると、別々のテナントにするという手が思いつく。

workspace毎にどうやってテナントを変えたらよいか。Terraformではworkspace名をtfファイル内で参照することができるので、これを利用する。

provider.tfを以下のように変更する。これにより、staging workspaceを選択した場合は「repl-staging」テナントが使われ、production workspaceを選択した場合は「repl-production」が使われる。

後はそれぞれテナントを用意してやればよいので、作業ログなどは省略する。作業スペース毎にテナントを作っているので、OpenStack内では完全に分離されている。かなり安全といえるだろう。しかし、テナントの切り替えが必要であること、workspace毎にテナントを用意しておく必要があることなどから少し手間がかかるデメリットもある。

workspaceによってリソース名を変える

前節ではworkspace毎にテナントを分けるテクニックを検証した。本節では、同じテナントを使うがリソースがどのworkspaceに属しているのか認識できるようにするテクニックを検証する。同じテナントで複数のworkspaceを運用して不便なのは、同じ名前のリソースができるからである。つまり、workspaceによってリソース名が異なればよい。

modules/sg/sg.tfとして、以下のようなモジュールを用意する。ポイントはnameの部分で、workspaceがproductionであれば変数として渡したnameを使い、そうでなければ”${workspace}-${name}”という、workspace名をprefixにつけた名前となる。

モジュールを呼び出した側は以下のようになる。

stagingでapplyすると、staging-secgroup_1という名前でセキュリティグループが作成されている。

productionでapplyした場合はprefixがつかず、secgroup_1という名前で作成される。

このようにworkspaceとmoduleを組み合わせることで、同じ設定でもproductionとstagingで別々の名前のリソースを用意できることがわかった。workspace分のリソースが作られることになるが、テナントの管理に比べると楽だろう。

Terraformの追加構文にはかなり多くの関数が用意されている。モジュールでうまく隠蔽して、良い感じのInfrastructure as Codeを実現していきたい。