KAKEHASHI Tech Blog

カケハシのEngineer Teamによるブログです。

CDK for Terraformは実用可能か? DatadogのMonitorを構成管理してみる

概要

未だ0系でありながら、22年8月に一般提供が開始された CDK for Terraform の実用性を検討し、DatadogのMonitor(およびDowntime)の構成管理をコード化しました。

背景

弊社では主要な監視ツールの一つとしてDatadogを活用しており、弊チームでもDatadogMonitorという機能を利用して、インフラリソースの各種メトリクスが異常値を示した時のSlack通知やオンコール設定などを行っています。 しかしながら、多くの監視設定を漸進的に構築していくにはUIからの追加・変更作業が負担に感じる様になってきており、構成管理ツールの導入を検討しました。

一般的にDatadogの構成を管理する場合はTerraformの利用を検討できますが、弊チームではAWS上に構築したインフラの構成管理にAWS CDKを利用しています。そこで、CDK for Terraformを利用して、AWS CDKと同様の開発プロセスでDatadogの構成管理を実現できないか検討しました。

CDK for Terraformとは

Terraformの構成をTypeScript(など)の様な一般的手続き型言語で記述することができるフレームワークです。 私自身、AWSの構成管理に AWS CDK を利用していると「いつ使うツールなのか?」という疑問がありましたが、「AWS CDKを主なインフラ構成管理ツールとして利用している前提で、Datadog,Github,DatabricksなどAWS以外のSaaSの構成管理を行いたい」という場合には適したツールです。 HCL(Terraform) or 一般的な手続き型言語(CDK) のどちらで書く方が良いか?という議論はここではしませんが、両者の体験や効果は大きく違った物になる事は確かですので、環境に合わせて選択できるのは嬉しいですね!

構成管理に対応するSaaSの一覧はこちらで確認できます。 Terraform Registry

CDK for Terraformの仕組み

まずTerraform本家の仕組みについて確認します。

image

出典: https://spacelift.io/blog/terraform-architecture

TerraformProviderというプラグインに依存していますが、このProviderが各SaaSのリソースを定義したり、変更の適用方法を実装したりしています。 HCL(or JSON)で書かれた設定ファイルは、最終的にはこのProviderによって反映処理を行っていくことになります。

では CDK for Terraform の場合ですが、

image

出典: https://developer.hashicorp.com/terraform/cdktf/concepts/cdktf-architecture

この通り、本家のTerraformを利用する場合との相違点は、CDK(TS) => Terraform Template(JSON)の変換部分のみで、Terraform Template(JSON)から先のProviderを利用して適応していく部分は共通になっています。

つまり、synthを挟むことによる変換のオーバーヘッドはありますが、根本的には書き口が違う程度の差異になっているので、思ったより気軽に利用できると思います。

cdktf/cdktf-provider-datadogを利用して大丈夫?

cdktf/cdktf-provider-datadogTerraform Registoryで公開されたスキーマ定義から自動的にビルドされたCDKTFのDatadog用のコンストラクト集です。名前にProviderとありますが、内容としてはDatadogリソース(L1コンストラクト)が格納されているだけで、TerraformのProviderとは異なる様です。npmパッケージ(@cdktf/provider-datadog")として公開されているので簡単にInstallすることができます。 (Providercdktfコマンドによってローカルでビルドすることもできますが省略します。)

スター数は7と少ないですが、結論から言えば、最大でも1日以内にRegistryの変更が自動反映されている様なので、安心して利用できます。

仕組みとしては、provider-upgrade.ymlが毎日3時(UTC)に実行された時に、こちらからバージョンの差分をチェックして、変更があればPRを作成し、PRは自動マージされて、Providerのビルド・リリースタスクが起動します。 CDKTF自体のバージョンが上がった場合も、cdktf/cdktf-repository-managerupgrade-repositories.ymlからPRが作成されて、ビルド・リリースタスクが起動します。

他の各種SaaSのCDKTF Providerも同様に自動生成されており、本家のTerraformで開発する場合と全く同じ機能が利用することができる点は、CDK for Terraformを利用する際の安心材料になると思います。

AWS CDKとの対応

AWS CDK CDK for Terraform
実行コマンド cdk cdktf-cli
App aws-cdk-lib/core cdktf
Synth結果 Cloud Formation Template(JSON) Terraform Template(JSON)
実行 CloudFormation Terraformの各種Provider

実装

DatadogのMonitorの実装例を示します。 Lambdaの同時実行数を監視するMonitorと、未明にDowntimeを設定する例を示しています。

import { monitor, downtime } from '@cdktf/provider-datadog';
import { ValueOf } from '@common/utils/type';
import { Construct } from 'constructs';
import dayjs from 'dayjs';
import { DatadogDefs } from '@cdktf-src/utils/datadogDefs';
const { Monitor } = monitor;
const { Downtime } = downtime;

export class DdMonitorsStack extends TerraformStack {
  constructor(scope: Construct, id: string) {
    super(scope, id);
    
    // 1. Datadogのプロバイダーを設定する
    new DatadogProvider(this, 'datadog-provider', { 
      apiKey: process.env.API_KEY, 
      appKey: process.env.APP_KEY,
    });
    
    // 2. .tfstateをS3にUploadするための設定
    new S3Backend(this, {
      bucket: 'バケット名',
      key: '.tfstateファイルのKey',
      region: 'ap-northeast-1',
    });

    // 3. Monitorを作成
    const lambdaConcurrencyMonitor = new Monitor(this, 'lambda-concurrency-monitor', {
      name: 'Lambdaの同時実行数が増加',
      tags: ['lambda', 'critical'],
      message: '{{^is_recovery}} Lambdaの同時実行数が増加しています。 {{/is_recovery}}',
      query: `max(last_5m):max:aws.lambda.concurrent_executions{service:(サービス名)} > 10`,
      type: 'metric alert',
      monitorThresholds: {
        critical: '10', 
        warning: '7', 
      },
    });

    // 明日の午前0時
    const tomorrow = dayjs().startOf('day').add(1, 'days');
    // 4. Downtimeを設定
    new Downtime(app, 'monitor-downtime', {
      monitorId: lambdaConcurrencyMonitor.id as number,
      scope: ['*'],
      // 毎日 午前3時 ~ 4時 までアラートを停止する
      start: tommorrow.add(3, 'hours').unix(),
      end: tommorrow.add(4, 'hours').unix(),
      recurrence: { type: 'days', period: 1 },
      timezone: 'Asia/Tokyo',
      message: '一時的にOFF',
    });
  }
}

// 5. 上で定義したStackを生成する
const app = new App();  
new DdMonitorsStack(app, 'monitors');
app.synth();

Monitor, DowntimeなどのクラスはTypeScriptで記述されているので、もちろん型補完が効きます。また、先述の通りこれらのクラスはProviderのSchemaから自動生成されたいわばL1コンストラクトです。プロパティはTerraformのスキーマと完全に一致しており、定義には対応するドキュメントのリンクが記載されています。

image

デプロイは、cdktf-cli deploy monitorsで実行することができます。

注意する点としては、2のS3バックエンドを指定しておくことです。AWS CDKと同様に考えていると忘れがちですが、Terraformでは.tfstateファイルを共有しないと複数人でのデプロイ作業ができなくなります。

ドキュメント

まとめ

CDK for Terraformの名称的キメラ感に警戒していた方も少なくないのではないかと思うのですが、実際は比較的に薄いWrapperの様な構成になっており、AWS CDKユーザとしては取り入れやすく小回りの効くツールであることがわかりました。

一方で実践例はまだまだ少なく感じるのも事実ので、この記事がみなさんのご活用に貢献できれたら幸いです。