🦔

あまり知られていないTerraform Cloud の機能

2024/01/29に公開

https://app.terraform.io/

Terraform Cloud には非常に多種多様の機能が用意されていますが、せいぜい Workspce や Variable Set、VCS 連携、Slack 連携くらいしか使用してない印象があります。

今回、いくつかの機能を網羅的に調べてみたので、その結果を貼ってみます。
エクスキューズとして、Terraform Cloud Plus 以上のプランじゃないと使用できない機能も多く、私の手元の環境では契約をしていないため、実際に機能をしようできてないものも含まれます。ご了承ください。

Workspace Explorer

各 Workspace の設定状況などを横断的に確認することができる機能

たとえば、Organization 内でどんな Provider が使われているかの一覧の表示が以下

使われている Terraform のバージョンと、対象となるプロジェクトの数の一覧は以下

Cost Estimation

作成するクラウド環境の費用がどの程度になるか、コストの概算を行ってくれる機能です。
以下のパブリッククラウドについて対応をしています。

  • AWS
  • GCP
  • Azure

すべてのリソースで計算をしてくれるわけではなく、一部のリソースに対象は限定されるようです。
AWS の Cost Estimation の対象リソースは以下
https://developer.hashicorp.com/terraform/cloud-docs/cost-estimation/aws

Drift Detection (plus以上)

Terraform の HCL の記述と実際のリソース状況の差分 (= Drift) を検知する機能です
Health 機能を有効にすることにより、24時間に一回、Teraform HCL の内容と実際のリソースとの比較を自動的に行ってくれるようです

ただし、Health 機能は Terraform cloud plus 以上のプラン限定の機能のようなため、現状確認することはできません
https://developer.hashicorp.com/terraform/cloud-docs/workspaces/health

Health assessments are available in Terraform Cloud Plus Edition. Refer to Terraform Cloud pricing for details.

Continuous validation (plus以上)

継続的検証、とでも訳すでしょうか。
こちらも Health 機能の一つで、 Terraform の check ブロックで記載されたテスト内容を定期的に実行する機能となります。

check "health_check" {
  data "http" "example" {
    url = "https://${aws_lb.example.dns_name}"
  }
 
  assert {
    condition     = data.http.example.status_code == 200
    error_message = "${data.http.example.url} returned an unhealthy status code"
  }
}

こちらも Terraform cloud plus 以上のプランが必要です。

Ephemeral workspaces (plus以上)

Ephemeral ( = 一時的 ) な workspace 、ということで、期間限定の workspace を設定することができます。
具体的には、Terraform cloud で作った環境について、一定期間たったら強制的に destroy することができる、という機能になります。

一時的な検証環境について作ったけど、削除をし忘れた。みたいなことを抑制するための機能になります。

こちらも Terraform cloud plus 以上のプランが必要です。
https://developer.hashicorp.com/terraform/cloud-docs/workspaces/settings/deletion

Ephemeral workspace (automatic destroy runs) functionality is available in Terraform Cloud Plus Edition. Refer to Terraform Cloud pricing for details.

Private Registry

Terrform で作成した module や provider は、 Registry に登録することによって再利用可能になります。

Registry については基本的には Public なものが公開されているため、こちらに登録することになります。
https://registry.terraform.io/

ただし、不特定多数に公開することが憚れるもの、組織内にだけ共有したいケースもあります。
その際の選択肢はいくつかありますが、Terraform cloud 環境で提供されている  private registry に登録する、ということも可能です。

公開手順は、 GitHub など VCS と連携する方法が取られており、多くの場合は GitHub と連携する形になります。
任意のリポジトリに module の関係ソース一式を登録しておき、そのリポジトリを連携することで、private registry への publish が行えるようです。

No Code Provisioning (plus以上)

登録済みの module を使って、HCL の設定ファイルを記述せずにリソースの作成を行うことができる機能です。
module 実行時に必要な variables の値を画面から渡し、terraform cloud 上で apply を行うと、結果的に No Code でリソースの provisioning が行えるから、このような名前になっているようです。

こちらの使用には Terraform cloud plus 以上のプランが必要です。
https://developer.hashicorp.com/terraform/cloud-docs/no-code-provisioning/module-design

No-code provisioning is available in Terraform Cloud Plus Edition. Refer to Terraform Cloud pricing for details.

Policy as code

OPA (Open Pollicy Agent)Sentinel などの機能を使って、Terraform の HCL で記述すべき内容/記述すべき内容のポリシーを定義することができます。
たとえば、以下のような内容をポリシーとして定義することができる仕組みになります。

  • 特定のリソースには必ず特定のタグを付与する
  • 検証環境では t3 系のインスタンスのみ立ち上げる / 本番環境では t3 系インスタンスを使用しない
  • ネットワークの CIDR に 0.0.0.0/0 を指定しない

以下は、「ネットワークの CIDR に 0.0.0.0/0 を指定しない」 を OPA の Policy ファイルとして定義した例です。

https://developer.hashicorp.com/terraform/cloud-docs/policy-enforcement/opa

package terraform.policies.public_ingress

import input.plan as plan

deny[msg] {
  r := plan.resource_changes[_]
  r.type == "aws_security_group"
  r.change.after.ingress[_].cidr_blocks[_] == "0.0.0.0/0"
  msg := sprintf("%v has 0.0.0.0/0 as allowed ingress", [r.address])
}

Policy ファイルの適用は、一般的にはたとえば conftest のようなコマンドラインツールを用いて行う必要があります。
Terraform cloud は、ツール自体で OPA のファイル (.rego) の実行と検証がサポートされているため、Terraform cloud に登録するだけでポリシーチェックを行うことが可能になっています

上記では OPA の記述例ですが、Hashicorp 的には Sentinel を推している (Sentinel は Hashicorp 製) ように見えるため、Sentinel で定義を書いたほうが Terraform cloud 上では便利かもしれません。
以下は、必ず成功する / 失敗する Policy Rule を Sentinel で書いてみて動作確認してみた例です

成功時

## Policy 1: test (hard-mandatory)

Result: true

./test.sentinel:2:1 - Rule "main"
  Value:
    true

失敗時

## Policy 1: test (hard-mandatory)

Result: false

./test.sentinel:2:1 - Rule "main"
  Value:
    false
╷
│ Error: Organization Policy Check hard failed.

Free Plan では設定画面から一つづつ policy の設定をしていく必要がありますが、Plus 以上になると GitHub などの VCS との連携が行えるようになるようです。

https://developer.hashicorp.com/terraform/cloud-docs/policy-enforcement/sentinel

Terraform Cloud Free Edition includes one policy set of up to five policies. In Terraform Cloud Plus Edition, you can connect a policy set to a version control repository or create policy set versions via the API. Refer to Terraform Cloud pricing for details.

Policy を用いた IaC の定義の管理は将来的に行いたいタスクですが、まずは Terraform で作成するリソースのルールをどのように設計するかを考える必要があります。

Usage Report

Terraform cloud の使用状況が表示されます。
Terraform cloud は 500 Resources までは無料で使用できるのですが、それ以降は課金対象になります
(500 resources を超過すると、 terraform plan , apply が動作しなくなる。はず)

そのため、Free Plan で使用している人は定期的に確認することをおすすめします。

API

https://developer.hashicorp.com/terraform/cloud-docs/api-docs
当然のことながら各種 API が用意されており、かなり多種多様な機能を API 経由でハンドリングできます
現状、あまり使い道が思いついていないですが、 Terraform cloud の Usage Report とかを Datadog 経由で連携しても良いかも?という気持ちには少しなっています。

 $ curl \
  --header "Authorization: Bearer $TOKEN" \
  --header "Content-Type: application/vnd.api+json" \
  --request GET \
  https://app.terraform.io/api/v2/organizations/xxxxxx | jq "."
  
{
  "data": {
    "id": "xxxxxx",
    "type": "organizations",
    "attributes": {
      "external-id": "org-RdmCbUAuvPve2ut3",
      "created-at": "2023-08-09T03:46:23.056Z",
      "email": "sada@xxxxxx.com",
      "session-timeout": null,
      "session-remember": null,
      "collaborator-auth-policy": "password",
      "plan-expired": false,
      "plan-expires-at": null,
      "plan-is-trial": false,
      "plan-is-enterprise": false,
      "plan-identifier": "free_standard",
      "cost-estimation-enabled": true,
      "managed-resource-count": 278,
      "send-passing-statuses-for-untriggered-speculative-plans": false,
      "allow-force-delete-workspaces": false,
      "assessments-enforced": false,
      "is-in-degraded-mode": false,
      "default-execution-mode": "remote",
      "remaining-testable-count": 5,
      "name": "xxxxxx",
(snip.)
}

Discussion