【Terraform de Azure】 Azure CosmosDB をプロビジョニングされたスループット構成で作成してみました

## 概要

「Infrastructure as Code」ということで、Terraform を用いて Azure CosmosDB をプロビジョニングされたスループット構成で作成し、Azure CLI から確認してみます。

### ローカル環境

- macOS Monterey 12.3.1
- python 3.8.12
- Azure CLI 2.34.1
- terraform v1.0.11

### 前提条件

1. Azure環境がすでに用意されていること（テナント/サブスクリプション）
2. ローカル環境に「azure cli」がインストールされていること
3. ローカル環境に「terraform」環境が構成されていること
4. TerraformでAzure上に環境構築するための[サービスプリンシパルが作成](https://qiita.com/turupon/items/5d024d43a60cd101be94)されており、Terraform のためのローカル環境変数が定義されていること

---

## Azure CosmosDB 作成してみる

### terraform 定義ファイルの作成

プロバイダの定義

```main.tf
# プロバイダーの定義
terraform {
  required_providers {
    azurerm =  "~> 2.33"
  }
}

provider "azurerm" {
  features {}
  tenant_id       = var.ARM_TENANT_ID
  subscription_id = var.ARM_SUBSCRIPTION_ID
  client_id       = var.ARM_CLIENT_ID
  client_secret   = var.ARM_CLIENT_SECRET
}


# リソースグループ
resource "azurerm_resource_group" "this" {
  name     = var.resource_group_name
  location = var.region
  tags     = var.tags_def
}
```

パラメータ定義ファイル

```variables.tf
# 環境変数（Azureサービスプリンシパル）
variable ARM_TENANT_ID {}
variable ARM_SUBSCRIPTION_ID {}
variable ARM_CLIENT_ID {}
variable ARM_CLIENT_SECRET {}

# タグ情報
variable tags_def {
  default = {
    owner      = "ituru"
    period     = "2022-06-30"
    CostCenter = "PSG2"
    Environment = "CPDemo"
  }
}

# 各種パラメータ
variable region {}                  // 利用リージョン
variable resource_group_name {}     // リソースグループ名

variable cosmosdb_account_name {}   // CosmosDBアカウント名
variable database_name {}           // CosmosDB Database名
variable container_name {}          // CosmosDB Container(Table)名
```

パラメータ値定義ファイル

```terraform.tfvars
# 環境変数の定義（Azureサービスプリンシパル）
ARM_TENANT_ID       = "zzzzzzzz-cccc-4645-5757-zzzzzzzzzzzz"
ARM_SUBSCRIPTION_ID = "yyyyyyyy-1717-4343-9779-yyyyyyyyyyyy"
ARM_CLIENT_ID       = "xxxxxxxx-xxxx-4444-9922-xxxxxxxxxxxx"
ARM_CLIENT_SECRET   = "hogehogehogehogehogehogehogehogege"

# パラメータ値の定義
region                  = "japaneast"           // 利用リージョン
resource_group_name     = "rg_ituru_cosmosdb01" // リソースグループ名
cosmosdb_account_name   = "iturucosmosdb01"     // CosmosDBアカウント名
database_name           = "CPDemoDB01"          // CosmosDB Database名
container_name          = "container01"         // CosmosDB Container(Table)名
```

CosmosDB定義ファイル

```cosmosdb.tf
# CosmosDB Account
resource "azurerm_cosmosdb_account" "this" {
  name                = var.cosmosdb_account_name
  location            = azurerm_resource_group.this.location
  resource_group_name = azurerm_resource_group.this.name
  tags                = var.tags_def
  offer_type          = "Standard"
  kind                = "GlobalDocumentDB"

  consistency_policy {
    consistency_level       = "Session"
    max_interval_in_seconds = 5
    max_staleness_prefix    = 100
  }

  geo_location {
    location          = azurerm_resource_group.this.location
    failover_priority = 0
  }
}

# CosmosDB Database
resource "azurerm_cosmosdb_sql_database" "this" {
  name                = var.database_name
  resource_group_name = azurerm_cosmosdb_account.this.resource_group_name
  account_name        = azurerm_cosmosdb_account.this.name
  throughput          = 400
}

# CosmosDB Container
resource "azurerm_cosmosdb_sql_container" "this" {
  name                  = var.container_name
  resource_group_name   = azurerm_cosmosdb_account.this.resource_group_name
  account_name          = azurerm_cosmosdb_account.this.name
  database_name         = azurerm_cosmosdb_sql_database.this.name
  partition_key_path    = "/section"
  partition_key_version = 1
  throughput            = 400
}
```

Output定義ファイル

```outputs.tf
# CosmosDBのアカウントエンドポイントURIを出力
output "cosmosdb_account_endpoint" {
  value = azurerm_cosmosdb_account.this.endpoint
}

# CosmosDBのアカウントKey情報を出力
output "cosmosdb_account_key" {
  value = azurerm_cosmosdb_account.this.primary_key
  sensitive = true
}

# CosmosDBのアカウント接続文字列を出力
output "cosmosdb_account_connect" {
  value = azurerm_cosmosdb_account.this.connection_strings
  sensitive = true
}
```

### terraform の実行

```
## init
$ terraform init
    :
Terraform has been successfully initialized!

## plan
$ terraform plan
    :
Plan: 4 to add, 0 to change, 0 to destroy.

## apply
$ terraform apply
    :
Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
```

### ローカルの作業ディレクトの状況

```
$ tree -a
.
├── .terraform
│   └── providers
│       └── registry.terraform.io
│           └── hashicorp
│               └── azurerm
│                   └── 2.99.0
│                       └── darwin_amd64
│                           └── terraform-provider-azurerm_v2.99.0_x5
├── .terraform.lock.hcl
├── cosmosdb.tf
├── main.tf
├── outputs.tf
├── terraform.tfstate
├── terraform.tfstate.backup
├── terraform.tfvars
└── variables.tf
```

---

## terraform 実行後の確認

### Azure CLI からの確認

```
## 作成先サブスクリプションへの接続
$ az account set --subscription '<Subscription_Name>'


## Azure Cosmos DB データベース アカウントの一覧表示
$ az cosmosdb list -g rg_ituru_cosmosdb01 -o table                       
DatabaseAccountOfferType    DefaultIdentity     DisableKeyBasedMetadataWriteAccess    DisableLocalAuth    DocumentEndpoint                                  EnableAnalyticalStorage    EnableAutomaticFailover    EnableFreeTier    EnableMultipleWriteLocations    InstanceId                            IsVirtualNetworkFilterEnabled    Kind              Location    Name             NetworkAclBypass    ProvisioningState    PublicNetworkAccess    ResourceGroup
--------------------------  ------------------  ------------------------------------  ------------------  ------------------------------------------------  -------------------------  -------------------------  ----------------  ------------------------------  ------------------------------------  -------------------------------  ----------------  ----------  ---------------  ------------------  -------------------  ---------------------  -------------------
Standard                    FirstPartyIdentity  False                                 False               https://iturucosmosdb01.documents.azure.com:443/  False                      False                      False             False                           37383738-aeae-4224-a66a-555a633360ed  False                            GlobalDocumentDB  Japan East  iturucosmosdb01  None                Succeeded            Enabled                rg_ituru_cosmosdb01


## Azure Cosmos DB アカウントの下にSQL データベースの一覧表示
$ az cosmosdb sql database list -g rg_ituru_cosmosdb01 -a iturucosmosdb01         
[
  {
    "id": "/subscriptions/yyyyyyyy-1717-4343-9779-yyyyyyyyyyyy/resourceGroups/rg_ituru_cosmosdb01/providers/Microsoft.DocumentDB/databaseAccounts/iturucosmosdb01/sqlDatabases/CPDemoDB01",
    "location": null,
    "name": "CPDemoDB01",
    "options": null,
    "resource": {
      "_self": "dbs/qyhAAA==/",
      "colls": "colls/",
      "etag": "\"0000b611-0000-2300-0000-627be1770000\"",
      "id": "CPDemoDB01",
      "rid": "qyhAAA==",
      "ts": 1652285815.0,
      "users": "users/"
    },
    "resourceGroup": "rg_ituru_cosmosdb01",
    "tags": null,
    "type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases"
  }
]


## Azure Cosmos DB SQL データベースの下にあるSQL コンテナーの一覧表示
$ az cosmosdb sql container list -g rg_ituru_cosmosdb01 -a iturucosmosdb01 -d CPDemoDB01
[
  {
    "id": "/subscriptions/yyyyyyyy-1717-4343-9779-yyyyyyyyyyyy/resourceGroups/rg_ituru_cosmosdb01/providers/Microsoft.DocumentDB/databaseAccounts/iturucosmosdb01/sqlDatabases/CPDemoDB01/containers/tbl01",
    "location": null,
    "name": "container01",
    "options": null,
    "resource": {
      "_conflicts": "conflicts/",
      "_docs": "docs/",
      "_self": "dbs/qyhAAA==/colls/qyhAAO0mfuc=/",
      "_sprocs": "sprocs/",
      "_triggers": "triggers/",
      "_udfs": "udfs/",
      "analyticalStorageTtl": null,
      "conflictResolutionPolicy": {
        "conflictResolutionPath": "/_ts",
        "conflictResolutionProcedure": "",
        "mode": "LastWriterWins"
      },
      "defaultTtl": null,
      "etag": "\"0000ba11-0000-2300-0000-627be1970000\"",
      "geospatialConfig": {
        "type": "Geography"
      },
      "id": "tbl01",
      "indexingPolicy": {
        "automatic": true,
        "compositeIndexes": null,
        "excludedPaths": [
          {
            "path": "/\"_etag\"/?"
          }
        ],
        "includedPaths": [
          {
            "indexes": null,
            "path": "/*"
          }
        ],
        "indexingMode": "consistent",
        "spatialIndexes": null
      },
      "partitionKey": {
        "kind": "Hash",
        "paths": [
          "/section"
        ],
        "systemKey": null,
        "version": 1
      },
      "rid": "qyhAAO0mfuc=",
      "ts": 1652285847.0,
      "uniqueKeyPolicy": {
        "uniqueKeys": []
      }
    },
    "resourceGroup": "rg_ituru_cosmosdb01",
    "tags": null,
    "type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers"
  }
]
```

### 作成したリソースの削除

```
## destroy
$ terraform destroy
```

---

### まとめ

これで、Terraform でサクッと Azure環境上に Azure CosmosDB をプロビジョニングされたスループット構成で作成できました。 Azure Portal や Azure CLI で構築するのもいいですが、IaC化もいいですね。