Terraform CloudのPrivate Registryを使ってmoduleを組織内に公開してみる

2023.02.20

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

「組織内でmoduleを使い回したい」

Terraformを運用しているとリポジトリを跨いでmoduleを使い回したくなることがあると思います。

そんな時には、Terraform CloudのPrivate Registryが便利です。

Private RegistryはTerraform CloudのFreeプランでも使えます。

HashiCorp Terraform Cloud Pricing

Terraform moduleの公開

Terraformは、moduleを公開することで別のリポジトリでも公開したmoduleを使うことができます。

moduleを公開する方法はいくつかありますが、今回は以下の2つを紹介します。

  • Terraform Registry
    • 全世界に公開
  • Terraform Cloud Private Registry
    • 組織内に公開

Module Sources | Terraform | HashiCorp Developer

Terraform Registry

Publicに公開する場合は、Terraform Registryを使うことができます。 Terraform Registryに公開したmoduleは、全世界の誰でも使用することができます。

Terraform Registryに公開する条件は以下です。

  • リポジトリはGithubで、公開設定がPublicに設定されている
  • リポジトリの命名が、terraform-[PROVIDER]-[NAME]
    • 例) terraform-aws-ec2-instance
  • リポジトリのdescriptionが設定されていること
  • 標準モジュール構造に準拠していること
  • リリースタグ名がセマンティックバージョンであること
    • 例) v1.0.5 v0.9.2

Terraform Registry - Publishing Modules | Terraform | HashiCorp Developer

Terraform Cloud Private Registry

Private Registryでできることは、主に2つあります。

  • 組織内にmodule/providerを公開
  • Public module/providerを登録

1つ目は、先ほど紹介したリポジトリの公開設定をPrivateのまま、組織内にmoduleを公開できることです。

2つ目は、Public module/providerを登録できることです。 事前にチーム内で承認されたPublic module/providerを登録しておくことで、「このmoduleは使っていいんだっけ」という確認の手間を減らせます。

ガバナンスを効かせることにもつながると思います。

Private Registry - Terraform Cloud | Terraform | HashiCorp Developer

Private RegistryとTerraform Registryの異なる点

異なる点としては以下です。

  • Private Registryでは、リポジトリの公開設定がPrivateでもOK
  • Private RegistryではGithub以外のVCSも使用可能
    • Terraform Cloudが対応しているVCS(Gitlab、Bitbucketなど) を使用できる

moduleを公開する条件(モジュール構造、命名規則)は、Terraform RegistoryとPrivate Registryはほぼ同様です。

他にはNo-Code provisioningという機能が使えることも、Private Registryの特徴かと思います。

No-Code provisioningはTerraform CloudのGUI上からパラメータを渡すだけで、リソースを作成できる機能です。

やってみた

実際にTerraform CloudのPrivate Registryを使って、moduleを公開してみます。

以下のチュートリアルをやってみます。 Githubを使った手順はこちらのチュートリアルにあるので、今回はGitlabを使ってみます。

このチュートリアルでは、S3静的Webサイトホスティングのリソースを構築できるmoduleをPrivate Registryに登録します。 その後、実際に他のリポジトリで登録したmoduleを使用できるか確認します。

サンプルリポジトリの用意

Gitlab上で、terraform-aws-s3-webappという名前でリポジトリを作成しておきます。 この際、リポジトリの公開範囲はPrivateとしておきます。

サンプルリポジトリをローカルにCloneして、Gitlab上にPushします。

hashicorp/learn-private-module-aws-s3-webapp

$ git clone git@github.com:hashicorp/learn-private-module-aws-s3-webapp.git
$ git remote add gitlab git@gitlab.com:[Organization名]/terraform-aws-s3-webapp.git
$ git push gitlab HEAD

以下の状態になっていればOKです。

その後、Gitlab上でタグを切ってリリースします。

これでGitlab上の準備完了です。

Private Registryの設定

ここからはTerraform Cloudの設定です。

Registry->Publish -> Moduleの順に選択します。

前の手順で作成したリポジトリを選択します。 ちなみに、terraform-[PROVIDER]-[NAME] の命名規則に沿っていないものは表示されず選択できません。

今回は通常のmoduleのため、No-code provisioningのチェックは外したままにPublish moduleを選択します。

moduleを登録できました!簡単ですね。

moduleのページでは、InputsやOutputの情報が確認できます。

この情報はterraform-docsのように、moduleのtfファイルから自動的に生成してくれます。

別リポジトリから登録したmoduleを使用する

登録したmoduleを使ってみましょう。

moduleを呼び出す用のサンプルリポジトリをForkして、ローカルにcloneします。

hashicorp/learn-private-module-aws-s3-webapp

s3-webappのmoduleを呼び出すだけのシンプルな構成です。 Organization名のところを置き換えて、Pushしておきます。

main.tf

provider "aws" {
  region = var.region
}

module "s3-webapp" {
  source  = "app.terraform.io/[Oragnization名]/s3-webapp/aws"
  name    = var.name
  region  = var.region
  prefix  = var.prefix
  version = "1.0.0"
}

実行の確認のために、変数を設定してWorkspaceを作成します。

認証情報をWorkspaceに設定したらRunを実行します。

Planの結果から、moduleを呼び出せていることが確認できたので成功です。

Tips: CLIでやってみる

まずは何も変更せず、前回のコードのままterraform initしてみます。

Tokenがない場合、Terraform Cloud内のPrivate Registryからmoduleを取得できないため失敗します。 (terraform loginでTokenをすでに作成している場合は成功します。)

$ terraform init
Initializing modules...
╷
│ Error: Error accessing remote module registry
│ 
│ Failed to retrieve available versions for module "s3-webapp" (main.tf:14) from app.terraform.io: error looking up module versions: 401
│ Unauthorized.
╵
╷
│ Error: Error accessing remote module registry
│ 
│ Failed to retrieve available versions for module "s3-webapp" (main.tf:14) from app.terraform.io: error looking up module versions: 401
│ Unauthorized.

失敗する場合は以下コマンドを実行して、Terraform CloudのTokenを作成します。

$ terraform login
# プロンプトに従って情報を入力

再度コマンドを実行すると、コマンドが成功してmoduleがインストールされることを確認できます。

$ terraform init
$ ls -1 .terraform/modules
modules.json
s3-webapp

一応上記の設定で、CLIから実行できます。

しかし、stateファイルがTerraform Cloudに保存されません。 そのため、cloudブロックを追加して利用するWorkspaceを指定することをお勧めします。

main.tf

terraform {
  cloud {
    organization = "[Organization名]"
    workspaces {
      name = "learn-private-module-root"
    }
  }
}

provider "aws" {
  region = var.region
}

module "s3-webapp" {
  source  = "app.terraform.io/[Oragnization名]/s3-webapp/aws"
  name    = var.name
  region  = var.region
  prefix  = var.prefix
  version = "1.0.0"
}

変更後、terraform initを実行するとTerraform Cloudにファイルが保存されます。

おわりに

Terraform CloudのPrivate Registryを使用した組織内へのmodule公開でした。

マルチレポのケースであったり、インフラの中央チームがあってmoduleを提供・各チームはそのmoduleを使用したい場合かなり便利な機能かと思います。

今は小規模でも将来的にmoduleを使い回して効率を上げたい場合は、ぜひ利用してもらいたい機能です。

以上、AWS事業本部の佐藤(@chari7311)でした。

あわせて読みたい記事