はじめに
先日、Azureの各種リソースをTerraformで構築する方法を記しました。
miyohide.hatenablog.com
今回は、このお話の続きです。
以下のエントリーでAzure KeyVaultをSpring Bootで書いたアプリケーションで使う方法を記しました。
miyohide.hatenablog.com
この記事ではデータベースを手で作成し、ユーザやパスワードはAzure Key Vaultに別途登録したのですが、何かと手間です。
そこで、あらかじめAzure Key Vaultに登録しておいたユーザやパスワードを使ってデータベースをTerraformで作成する方法を記します。
TerraformでAzure Key Vaultのシークレットデータを読み込む
Terraformで既存のAzure Key Vaultのシークレットデータを読み込むには、Data Sourceのazurerm_key_vaultとazurerm_key_vault_secretを使うと良さそうです。
対象のKey Vaultをazurerm_key_vaultで指定します。
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/key_vault
azurerm_key_vaultで得られたidを使ってazurerm_key_vault_secretから対象のデータを取得します。
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/key_vault_secret
具体的な実装は以下の通り。
data "azurerm_key_vault" "keyvault" {
name = var.keyvault_name
resource_group_name = var.keyvault_resource_group
}
data "azurerm_key_vault_secret" "database-user" {
name = "app-database-user"
key_vault_id = data.azurerm_key_vault.keyvault.id
}
data "azurerm_key_vault_secret" "database-password" {
name = "app-database-password"
key_vault_id = data.azurerm_key_vault.keyvault.id
}
ここでは、Azure Key Vaultのシークレットに登録しているapp-database-user
とapp-database-password
を使ってAzure Database for PostgreSQLを作成します。
なお、Azure Key Vaultにはバージョンという概念があります。
docs.microsoft.com
同時に複数のバージョンを有効化することができるのですが、複数のバージョンを有効化したままでは今回の処理はうまく動きませんでした。どれか一つだけを有効化した方が良いかなとおもます。
Azure Database for PostgreSQLの作成
TerraformでAzure Database for PostgreSQLを作成する方法は、以下のドキュメントを参考にしました。
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/postgresql_database
ユーザやパスワードはAzure Key Vaultのデータを使います。ユーザはdata.azurerm_key_vault_secret.database-user.value
、パスワードはdata.azurerm_key_vault_secret.database-password.value
と指定してあげればOKです。
具体的な実装は以下の通りです。
resource "azurerm_postgresql_server" "pg-server" {
name = var.postgresql_server_name
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
administrator_login = data.azurerm_key_vault_secret.database-user.value
administrator_login_password = data.azurerm_key_vault_secret.database-password.value
sku_name = var.postgresql_sku_name
version = var.postgresql_version
storage_mb = var.postgresql_storage
public_network_access_enabled = true
ssl_enforcement_enabled = true
ssl_minimal_tls_version_enforced = "TLS1_2"
}
resource "azurerm_postgresql_database" "pg-db" {
name = "app_production"
resource_group_name = azurerm_resource_group.rg.name
server_name = azurerm_postgresql_server.pg-server.name
charset = "utf8"
collation = "Japanese_Japan.932"
}
変数の利用
上記の例でvar.
からはじまるものはTerraformの変数の機能を使っています。
www.terraform.io
今回は以下のような記述をvariables.tf
として記述しました。
variable "keyvault_name" {
type = string
}
variable "keyvault_resource_group" {
type = string
}
variable "postgresql_server_name" {
type = string
}
variable "postgresql_version" {
type = string
default = "11"
}
variable "postgresql_sku_name" {
type = string
default = "B_Gen5_1"
}
variable "postgresql_storage" {
type = number
default = 5120
}
実装の全体と実行
最終的な実装は以下の通りになりました。
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 2.65"
}
}
required_version = ">= 0.14.9"
}
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "rg" {
name = "rg-railsapp"
location = "japaneast"
}
data "azurerm_key_vault" "keyvault" {
name = var.keyvault_name
resource_group_name = var.keyvault_resource_group
}
data "azurerm_key_vault_secret" "database-user" {
name = "app-database-user"
key_vault_id = data.azurerm_key_vault.keyvault.id
}
data "azurerm_key_vault_secret" "database-password" {
name = "app-database-password"
key_vault_id = data.azurerm_key_vault.keyvault.id
}
resource "azurerm_postgresql_server" "pg-server" {
name = var.postgresql_server_name
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
administrator_login = data.azurerm_key_vault_secret.database-user.value
administrator_login_password = data.azurerm_key_vault_secret.database-password.value
sku_name = var.postgresql_sku_name
version = var.postgresql_version
storage_mb = var.postgresql_storage
public_network_access_enabled = true
ssl_enforcement_enabled = true
ssl_minimal_tls_version_enforced = "TLS1_2"
}
resource "azurerm_postgresql_database" "pg-db" {
name = "app_production"
resource_group_name = azurerm_resource_group.rg.name
server_name = azurerm_postgresql_server.pg-server.name
charset = "utf8"
collation = "Japanese_Japan.932"
}
あとはこれを実行します。
variables.tf
でdefault
を指定していない項目に対して値を入力すると...
無事作成されました。
接続
接続してみます。Cloud Shellから接続するときはAzure Database for PostgreSQLの設定で「Azureサービスへのアクセスを許可」を「はい」に変更する必要があります。
ユーザやパスワード、データベースを指定すると無事接続できました。
注意点
最初、データベースの作成時にcollation
をja_JP.utf8
に指定したら以下のエラーメッセージが出ました。
azurerm_postgresql_database.pg-db: Creating...
azurerm_postgresql_database.pg-db: Still creating... [10s elapsed]
╷
│ Error: Code="InvalidDatabaseCollation" Message="The provided database collation is invalid."
│
│ with azurerm_postgresql_database.pg-db,
│ on main.tf line 50, in resource "azurerm_postgresql_database" "pg-db":
│ 50: resource "azurerm_postgresql_database" "pg-db" {
いろいろと調べてみると、Azure Database for PostgreSQLはWindows上で動いているようで、そのためにja_JP.utf8
は使えないそうです。
asazure.hatenablog.jp
lets.postgresql.jp
上で接続結果の画像を載せましたが、compiled by Visual C++ build 1800, 64-bit
とあることからもWindowsベースで動いているような気がします。