著者は、寄付の一環としてウィキメディア財団を選択しました。
はじめに
インフラストラクチャーのコード化(IaC)は、コードでリソースの状態とそれらの関係を定義することによって、インフラストラクチャーの展開と変更を自動化する実践です。そのコードを実行すると、クラウド内の実際のリソースが作成または変更されます。IaCを使用すると、エンジニアはTerraform(HashiCorpによる)などのIaCツールを使用してインフラストラクチャーをプロビジョニングできます。
IaCを使用すると、インフラストラクチャーの変更をアプリケーションコードと同じコードレビュープロセスを経ることができます。コードをバージョン管理(Gitなど)に格納して、インフラストラクチャーの状態の履歴を保持し、さらに高度なツール(自己サービス内部開発者プラットフォーム(IDP)など)を使用してデプロイメントプロセスを自動化できます。
Terraformは、その多くのプラットフォームに対する幅広いサポートにより、人気のあるプラットフォームに依存しないIaCツールです。これには、GitHub、Cloudflare、およびDigitalOceanなどの多くのプラットフォームが含まれます。ほとんどのTerraformの設定は、HashiCorp Configuration Language(HCL)と呼ばれる宣言型の言語を使用して書かれています。
TerraformのCloud Development Kit(CDKTF)は、Terraformの上に構築されたツールであり、HCLの代わりにTypeScript、Python、またはGoなどのなじみのあるプログラミング言語を使用してインフラストラクチャを定義することができます。このツールは、HCLに不慣れな開発者にとってより浅い学習曲線を提供しつつ、ループ、変数、および関数などのネイティブプログラミング機能を使用できるようにします。
このチュートリアルでは、まずcdktfコマンドラインインターフェース(CLI)ツールをインストールします。次に、TypeScriptでCDKTFプロジェクトを作成し、2つのNGINXサーバーを定義し、load balancerによって負荷分散されるプロジェクトを定義します。その後、cdktfを使用してインフラストラクチャをデプロイします。このチュートリアルの最後には、インフラストラクチャを拡張するためのCDKTFプロジェクトが得られます。
注意: このチュートリアルは CDKTF 0.11.2
および Terraform 1.2.2
でテストされています。
前提条件
このチュートリアルを完了するには、以下が必要です:
- A good understanding of Infrastructure-as-Code (IaC). You can learn about IaC in Infrastructure as Code Explained.
- A DigitalOcean account. If you do not have one, sign up for a new account.
- A DigitalOcean Personal Access Token, which you can create via the DigitalOcean console. Instructions on how to do that can be found at How to Generate a Personal Access Token.
- A password-less SSH key added to your DigitalOcean account. You can add that by following How To Use SSH Keys with DigitalOcean Droplets. When you add the key to your account, remember the name you give it, as you will need it in this tutorial. For CDKTF to accept the name of your key, it must start with a letter or underscore and may contain only letters, digits, underscores, and dashes.
- ローカルマシンにインストールされた Terraform。これは、「DigitalOcean で Terraform を使用する方法」の「ステップ 1 – Terraform のインストール」で設定できます。
- ローカルマシンにインストールされた Node.js。これに関する手順は、「Node.js のインストールとローカル開発環境の作成」シリーズで見つけることができます。
- JavaScript でのプログラミングに慣れていること。スキルを構築するには、「JavaScript でのコーディング方法」シリーズをチェックしてください。
- TypeScript の基本的な機能を使い慣れていること。TypeScript に慣れていない場合は、「TypeScript でのコーディング方法」チュートリアルシリーズがスピードアップするための良いリソースです。
- A code editor or integrated development environment (IDE) that supports TypeScript. If you are not currently using one, try Visual Studio Code. You can also read up on How To Work With TypeScript in Visual Studio Code.
ステップ1 — cdktf
CLIのインストール
まず、cdktf
コマンドラインツールをインストールします。
cdktf
CLIは、NPMパッケージとして利用できます。npmjs.comでcdktf
を検索すると、似た名前の2つのパッケージが見つかります:cdktf
とcdktf-cli
。
概念的には、CDKTFはTerraformの上にある抽象化レイヤーです。それは2つの部分から成り立っています。
-
言語固有の構成要素(関数やクラスなど)を含むライブラリは、インフラストラクチャを定義するために使用されます。この部分は、
cdktf
npm パッケージ内にカプセル化されています。たとえば、次のサンプル CDKTF プロジェクトで、cdktf
パッケージからのApp
とTerraformStack
クラスの使用を見ることができます: -
CDKTFプロジェクト内の構成要素を解析し、それらを一連のJSONドキュメントに変換し、それらをHCLと同じ方法でTerraformに取り込むアダプターです。このアダプターは
cdktf-cli
パッケージによって提供されるcdktf
というCLIツールにカプセル化されています。
cdktf
CLIツールをインストールするには、cdktf-cli
パッケージが必要です。このパッケージは、npm
、yarn
、または選択したパッケージマネージャーを使用してグローバルにインストールできます。
cdktf-cli
をnpm
でインストールするには、次のコマンドを実行します:
注意: この記事の公開後には、おそらくより新しいバージョンのcdktf-cli
パッケージがあります。最新バージョンでチュートリアルを試すには、代わりにnpm install --global cdktf-cli@latest
を実行することができますが、一部の出力が若干異なる可能性があることに注意してください。
また、macOSまたはLinuxでHomebrewを使用してcdktf
CLIをインストールすることもできます。その場合、cdktf
のフォーミュラを使用します:
インストールが成功したことを確認するには、引数なしでcdktf
コマンドを実行します:
次のような出力が表示されます:
OutputPlease pass a command to cdktf, here are all available ones:
cdktf
Commands:
cdktf init Create a new cdktf project from a template.
cdktf get Generate CDK Constructs for Terraform providers and modules.
cdktf convert Converts a single file of HCL configuration to CDK for Terraform.
cdktf deploy [stacks...] Deploy the given stacks
cdktf destroy [stacks..] Destroy the given stacks
cdktf diff [stack] Perform a diff (terraform plan) for the given stack
cdktf list List stacks in app.
cdktf login Retrieves an API token to connect to Terraform Cloud.
cdktf synth Synthesizes Terraform code for the given app in a directory.
cdktf watch [stacks..] [experimental] Watch for file changes and automatically trigger a deploy
cdktf output [stacks..] Prints the output of stacks
cdktf debug Get debug information about the current project and environment
cdktf completion generate completion script
Options:
--version バージョン番号を表示します
--disable-logging ログファイルを書き込みません。CDKTF_DISABLE_LOGGING環境を使用してサポートされています。
--disable-plugin-cache-env TF_PLUGIN_CACHE_DIRを自動的に設定しません。
--log-level 書き込まれるログレベル。
-h, --help Show help
Options can be specified via environment variables with the "CDKTF_" prefix (e.g. "CDKTF_OUTPUT")
出力には利用可能なコマンドが表示されます。このチュートリアルの残りでは、cdktf init
、cdktf get
、cdktf deploy
、およびcdktf destroy
を使用して経験を積むことになります。
今、cdktf
CLIをインストールしたので、いくつかのTypeScriptコードを書くことでインフラストラクチャを定義できます。
ステップ2 — 新しいCDKTFプロジェクトの作成
このステップでは、後続の手順で構築するCDKTFプロジェクトの土台となる、さっきインストールしたcdktf
CLIを使用します。
以下のコマンドを実行して、CDKTFプロジェクトを配置するディレクトリを作成します:
次に、新しく作成したディレクトリに移動します:
cdktf init
コマンドを使用して、構築するCDKTFプロジェクトの枠組みを作成します:
CDKTFは、TypeScript、Python、Java、C#、またはGoを使用してインフラストラクチャを定義することを開発者に許可します。 --template=typescript
オプションは、cdktf
に対してこのCDKTFプロジェクトをTypeScriptを使用してスキャフォールドするよう指示します。
Terraform(およびそれによってCDKTF)は、管理しているリソースを追跡するために、Terraformステートファイルと呼ばれるファイルにその定義と状態を記録します。 --local
オプションは、CDKTFにこれらのステートファイルをcdktf
を実行しているマシン上のローカルに保持するよう指示します(各ファイルはterraform.<stack>.tfstate
の命名構造に従います)。
コマンドを実行した後、CLIは製品を改善するためにCDKTFチームにクラッシュレポートを送信する許可を求める場合があります:
Output? Do you want to send crash reports to the CDKTF team? See https://www.terraform.io/cdktf/create-and-deploy/configuration-file for
more information (Y/n)
同意する場合はY
を入力し、同意しない場合はN
を入力し、次にENTER
キーを押します。
cdktf
は、プロジェクトのスキャフォールドを作成し、パッケージをインストールします。プロジェクトがスキャフォールドされると、次のような出力が表示されます:
Output Your cdktf typescript project is ready!
cat help Print this message
Compile:
npm run get Import/update Terraform providers and modules (you should check-in this directory)
npm run compile Compile typescript code to javascript (or "npm run watch")
npm run watch Watch for changes and compile typescript in the background
npm run build Compile typescript
Synthesize:
cdktf synth [stack] Synthesize Terraform resources from stacks to cdktf.out/ (ready for 'terraform apply')
Diff:
cdktf diff [stack] Perform a diff (terraform plan) for the given stack
Deploy:
cdktf deploy [stack] Deploy the given stack
Destroy:
cdktf destroy [stack] Destroy the stack
Test:
npm run test Runs unit tests (edit __tests__/main-test.ts to add your own tests)
npm run test:watch Watches the tests and reruns them on change
Upgrades:
npm run upgrade Upgrade cdktf modules to latest version
npm run upgrade:next Upgrade cdktf modules to latest "@next" version (last commit)
infra
ディレクトリにもいくつかの新しいファイルが追加されます。最も重要なファイルはcdktf.json
とmain.ts
です。
cdktf.json
は、CDKTFプロジェクトの構成ファイルです。ファイルを開くと、次のようなものが表示されます:
app
プロパティは、TypeScriptコードをTerraform互換のJSONに合成するために実行されるコマンドを定義します。このプロパティは、main.ts
がCDKTFプロジェクトのエントリポイントであることを示しています。
main.ts
ファイルを開くと、次のようなものが表示されます:
CDKTFの言語では、関連するインフラストラクチャリソースのコレクションをスタックにグループ化できます。たとえば、Droplets、ロードバランサー、およびDNSレコードからなるAPIアプリケーションのリソースは、APIStack
という単一のスタックにグループ化できます。各スタックは独自の状態を保持し、他のスタックとは独立して展開、変更、または破棄できます。スタックの一般的な使用法は、本番用のスタックと開発用のスタックを別々に持つことです。
アプリケーションは複数のスタックのコンテナです。たとえば、アプリケーションはさまざまなマイクロサービスのスタックをグループ化できます。
main.ts
で生成されたCDKTFプロジェクトのスキャフォールドには、現在リソースを定義していないMyStack
という単一のスタッククラスが含まれています。MyStack
のインスタンスはinfra
という名前で作成され、app
というアプリケーション内に含まれます。後続の手順では、MyStack
のコンストラクタ内でインフラストラクチャリソースを定義します。
プロジェクトを作成した後の次のステップは、CDKTFプロジェクトをプロバイダで構成することです。
ステップ3 — DigitalOceanプロバイダのインストール
このステップでは、CDKTF プロジェクトに DigitalOcean プロバイダーをインストールします。
プロバイダーは、Terraform(cdktf
の下で使用される)にクラウドプロバイダー、SaaS プロバイダー、およびその他のアプリケーションプログラミングインターフェイス(API)を公開するプラットフォーム上でリソースを作成、更新、削除する方法に関する指示を提供するライブラリです。プロバイダーは、これらの上流APIを呼び出すロジックを標準の関数にカプセル化し、Terraformが呼び出せるようにします。
たとえば、Terraformを使用せずに新しい DigitalOcean ドロップレットを作成する場合、/v2/droplets
エンドポイントの DigitalOcean API に POST
リクエストを送信する必要があります。 代わりに、Terraformでは、DigitalOcean プロバイダー をインストールし、次のサンプルスニペットに示すように digitalocean_droplet
リソースを定義します:
次に、この TypeScript コードを Terraform 互換の JSON に変換し、プロバイダーに渡して、そのプロバイダーがあなたの代わりにドロップレットを作成するための適切な API 呼び出しを行うために、cdktf
CLI ツールを使用できます。
これで、プロバイダーが何であるかが理解できたので、CDKTF プロジェクトに DigitalOcean プロバイダーを設定できます。
cdktf.json
ファイルを開いて、terraformProviders
配列に文字列 digitalocean/digitalocean
を追加してください。
digitalocean/digitalocean
は、Terraform Registry 上の DigitalOcean プロバイダーの識別子です。
ファイルを保存して閉じます。
次に、cdktf get
を実行してプロバイダーをダウンロードしてインストールします。
cdktf get
は、プロバイダーをダウンロードし、スキーマを抽出し、対応する TypeScript クラスを生成し、それを .gen/providers/
の下に TypeScript モジュールとして追加します。この自動コード生成により、CDKTF で任意の Terraform プロバイダーや HCL モジュールを使用し、それをサポートするエディターでコード補完を提供することができます。
cdktf get
の実行が完了すると、以下のような出力が表示されます:
OutputGenerated typescript constructs in the output directory: .gen
また、生成されたプロバイダーのコードが含まれる .gen
という新しいディレクトリも表示されます。
このステップでは、プロジェクトに digitalocean/digitalocean
プロバイダーをインストールしました。次のステップでは、DigitalOcean プロバイダーを DigitalOcean API で認証するために必要な資格情報で構成します。
ステップ 4 — DigitalOcean プロバイダーの構成
このステップでは、DigitalOceanプロバイダーを、あなたのDigitalOceanパーソナルアクセス トークンで構成します。これにより、プロバイダーはあなたの代わりにDigitalOcean APIを呼び出すことができます。
異なるプロバイダーは、上流のAPIと認証するために異なる資格情報を必要とし、サポートしています。DigitalOceanプロバイダーでは、DigitalOceanパーソナルアクセス トークンを提供する必要があります。このトークンをプロバイダーに指定するには、DIGITALOCEAN_TOKEN
またはDIGITALOCEAN_ACCESS_TOKEN
環境変数として設定します。
次のコマンドをターミナルで実行して、そのターミナルセッションの環境変数を設定します。
注意: export
を呼び出すことで、そのターミナルセッションの環境変数のみが設定されます。ターミナルを閉じて再度開いた場合や、別のターミナルでcdktf
コマンドを実行した場合は、環境変数が有効になるように再度export
コマンドを実行する必要があります。
次に、プロバイダーをMyStack
クラス内に指定します。これにより、スタック内でプロバイダーが提供するリソースを定義できます。次のようにmain.ts
ファイルを更新します。
プロバイダーのモジュールは、./.gen/providers/digitalocean
にあります。これは、cdktf get
を実行したときに自動生成されました。
このステップでは、認証情報を含むdigitalocean/digitalocean
プロバイダーを構成しました。次に、このチュートリアルの目標の一部を形成するインフラストラクチャの定義を開始します。
ステップ5 — ドロップレット上のウェブアプリケーションの定義
このステップでは、2つの異なるファイルを提供する2つのNGINXサーバーを、2つの同一のUbuntu 20.04ドロップレットに展開します。
まず、2つのドロップレットの定義から始めます。ハイライトされた変更を使用してmain.ts
を修正します。
コード内の重複を避けるために、JavaScriptネイティブのループ(Array.prototype.map()
)を使用します。
コンソールを介してドロップレットを作成するかのように、指定する必要があるいくつかのパラメータがあります:
image
– ドロップレットが実行されるLinuxディストリビューションとバージョン。region
– ドロップレットが実行されるデータセンター。size
– ドロップレットに予約するCPUとメモリリソースの量。name
– ドロップレットを参照するために使用される一意の名前。
image
、region
、およびsize
の値は、DigitalOceanがサポートしているものでなければなりません。すべてのサポートされているLinuxディストリビューションイメージ、Dropletサイズ、およびリージョンの有効な値(スラッグと呼ばれる)は、DigitalOcean APIスラッグページで見つけることができます。必須およびオプションの属性の完全なリストは、digitalocean_droplet
のドキュメントページで見つけることができます。
SSHキーの追加
前提条件の一環として、DigitalOceanアカウントにパスワードなしのSSH公開キーをアップロードし、その名前をメモしました。それを使用してSSHキーのIDを取得し、Dropletの定義に渡します。
SSHキーは手動でDigitalOceanアカウントに追加されたため、現在のTerraform構成で管理されているリソースではありません。新しいdigitalocean_ssh_key
リソースを定義しようとすると、既存のものを使用せずに新しいSSHキーが作成されます。
新しいdigitalocean_ssh_key
データソースを定義します。Terraformでは、データソースは、現在のTerraform構成で管理されていないインフラストラクチャに関する情報を取得するために使用されます。言い換えると、これらは既存の外部インフラストラクチャの状態への読み取り専用ビューを提供します。データソースが定義されると、データをTerraform構成の他の場所で使用できます。
main.ts
の中で、MyStack
のコンストラクタ内で新しいDataDigitaloceanSshKey
データソースを定義し、SSHキーに割り当てた名前(ここでは名前はdo_cdktf
です)を渡します。
次に、Dropletの定義を更新してSSHキーを含めます。
プロビジョニングされると、パスワードの代わりにプライベートSSHキーを使用してDropletにアクセスできます。
NGINXのインストール用のユーザーデータスクリプトの指定
これで、Ubuntuを実行し、SSHアクセスが構成された2つの同一のDropletが定義されました。次のタスクは、それぞれのDropletにNGINXをインストールすることです。
Dropletが作成される際に、CloudInitというツールがサーバーをブートストラップします。CloudInitはユーザーデータと呼ばれるファイルを受け入れることができ、これによりサーバーのブートストラップ方法を変更できます。ユーザーデータには、サーバーが解釈できるcloud-config
ファイルやBashスクリプトなどが含まれる可能性があります。
このステップの残りでは、Bashスクリプトを作成し、それをDropletのユーザーデータとして指定します。このスクリプトでは、ブートストラッププロセスの一部としてNGINXをインストールします。さらに、スクリプトは/var/www/html/index.html
ファイル(NGINXが提供するデフォルトのファイル)の内容を、Dropletのホスト名とIPアドレスで置き換えます。これにより、2つのNGINXサーバーが異なるファイルを提供することになります。次のステップでは、これらのNGINXサーバーの両方をロードバランサーの背後に配置します。異なるファイルを提供することで、ロードバランサーがリクエストを適切に配信しているかどうかが明らかになります。
main.ts
のまま、Dropletの構成オブジェクトにuserData
プロパティを追加します:
警告:シェバン(#!
)の前に新しい行がないことを確認してください。そうでないと、スクリプトが実行されない場合があります。
最初にDropletがプロビジョニングされると、スクリプトはroot
ユーザーとして実行されます。UbuntuのパッケージマネージャーであるAPTを使用してnginx
パッケージをインストールします。次に、DigitalOceanのMetadata Serviceを使用して自身に関する情報を取得し、ホスト名とIPアドレスをindex.html
に書き込みます。このindex.html
はNGINXによって提供されます。
このステップでは、Ubuntuを実行する2つのDropletを定義し、それぞれにSSHアクセスを構成し、ユーザーデータ機能を使用してNGINXをインストールしました。次のステップでは、これらのNGINXサーバーの前に配置されるロードバランサーを定義し、ラウンドロビン方式でロードバランスするように構成します。
ステップ6 — ロードバランサーの定義
このステップでは、DigitalOceanロードバランサーを定義し、digitalocean_loadbalancer
リソースのインスタンスを定義します。
main.ts
のMyStack
コンストラクターの最後に、以下のロードバランサーの定義を追加してください。
forwardingRule
引数は、ロードバランサーにポート80
でのHTTPリクエストを受け付け、それらを各Dropletのポート80
に転送するように指示します。
dropletIds
は、ロードバランサーがリクエストを渡すDropletを指定します。これは数字を取りますが、droplet.id
の値は文字列です。したがって、文字列のDroplet ID値を数字に変換するために、Fn.tonumber
Terraform関数を使用しました。
注意:droplet.id
の値はDropletがプロビジョニングされるまで不明です。そのため、ここではJavaScriptネイティブのparseInt
ではなく、Fn.tonumber
Terraform関数を使用しました。Terraform関数は、Terraformが構成を適用する前に不明なランタイム値で動作するように設計されています。
ファイルを保存して閉じます。
これで、2つのDropletとそれらの前に配置されたロードバランサーが定義されました。あなたのmain.ts
は、次のように見えるはずです:
次のステップでは、cdktf
CLIツールを使用してCDKTFプロジェクト全体を実現します。
ステップ7 — インフラストラクチャのプロビジョニング
このステップでは、前のステップで定義したDropletsとロードバランサーをプロビジョニングするために、cdktf
CLIツールを使用します。
infra/
ディレクトリにいて、ターミナルセッションのDIGITALOCEAN_ACCESS_TOKEN
環境変数を設定していることを確認し、cdktf deploy
コマンドを実行してください:
次のような出力が表示されるはずです:
Outputinfra Initializing the backend...
infra Initializing provider plugins...
infra - Reusing previous version of digitalocean/digitalocean from the dependency lock file
infra - Using previously-installed digitalocean/digitalocean v2.19.0
infra Terraform has been successfully initialized!
infra Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
infra # digitalocean_droplet.bar (bar) will be created
+ resource "digitalocean_droplet" "bar" {
+ backups = false
+ created_at = (known after apply)
+ disk = (known after apply)
+ graceful_shutdown = false
+ id = (known after apply)
+ image = "ubuntu-20-04-x64"
+ ipv4_address = (known after apply)
+ ipv4_address_private = (known after apply)
+ ipv6 = false
+ ipv6_address = (known after apply)
+ locked = (known after apply)
+ memory = (known after apply)
+ monitoring = false
+ name = "bar"
+ price_hourly = (known after apply)
+ price_monthly = (known after apply)
+ private_networking = (known after apply)
+ region = "lon1"
+ resize_disk = true
+ size = "s-1vcpu-1gb"
+ ssh_keys = [
+ "34377800",
]
+ status = (known after apply)
+ urn = (known after apply)
+ user_data = "f9b1d9796d069fe504ce0d89439b6b664b14b1a1"
+ vcpus = (known after apply)
+ volume_ids = (known after apply)
+ vpc_uuid = (known after apply)
}
# digitalocean_droplet.foo(foo)が作成されます
+ resource "digitalocean_droplet" "foo" {
+ backups = false
+ created_at = (known after apply)
+ disk = (known after apply)
+ graceful_shutdown = false
+ id = (known after apply)
+ image = "ubuntu-20-04-x64"
+ ipv4_address = (known after apply)
+ ipv4_address_private = (known after apply)
+ ipv6 = false
+ ipv6_address = (known after apply)
+ locked = (known after apply)
+ memory = (known after apply)
+ monitoring = false
+ name = "foo"
+ price_hourly = (known after apply)
+ price_monthly = (known after apply)
+ private_networking = (known after apply)
+ region = "lon1"
+ resize_disk = true
+ size = "s-1vcpu-1gb"
+ ssh_keys = [
+ "34377800",
]
+ status = (known after apply)
+ urn = (known after apply)
+ user_data = "f9b1d9796d069fe504ce0d89439b6b664b14b1a1"
+ vcpus = (known after apply)
+ volume_ids = (known after apply)
+ vpc_uuid = (known after apply)
}
# digitalocean_loadbalancer.lb(lb)が作成されます
+ resource "digitalocean_loadbalancer" "lb" {
+ algorithm = "round_robin"
+ disable_lets_encrypt_dns_records = false
+ droplet_ids = (known after apply)
+ enable_backend_keepalive = false
+ enable_proxy_protocol = false
+ id = (known after apply)
+ ip = (known after apply)
+ name = "default"
+ redirect_http_to_https = false
+ region = "lon1"
+ size_unit = (known after apply)
+ status = (known after apply)
+ urn = (known after apply)
+ vpc_uuid = (known after apply)
+ forwarding_rule {
+ certificate_id = (known after apply)
+ certificate_name = (known after apply)
+ entry_port = 80
+ entry_protocol = "http"
+ target_port = 80
+ target_protocol = "http"
+ tls_passthrough = false
}
+ healthcheck {
+ check_interval_seconds = (known after apply)
+ healthy_threshold = (known after apply)
+ path = (known after apply)
+ port = (known after apply)
+ protocol = (known after apply)
+ response_timeout_seconds = (known after apply)
+ unhealthy_threshold = (known after apply)
}
+ sticky_sessions {
+ cookie_name = (known after apply)
+ cookie_ttl_seconds = (known after apply)
+ type = (known after apply)
}
}
Plan: 3 to add, 0 to change, 0 to destroy.
─────────────────────────────────────────────────────────────────────────────
Saved the plan to: plan
To perform exactly these actions, run the following command to apply:
terraform apply "plan"
Please review the diff output above for infra
❯ Approve Applies the changes outlined in the plan.
Dismiss
Stop
注意: CDKTFはまだ開発中ですので、上記の表示と異なる場合があります。
この表示には、cdktf
が作成、更新、および破棄するすべてのリソースとプロパティがリストされています。ドロップレットのIDなど、一部の値はリソースがプロビジョニングされた後にのみわかります。その場合、出力のプロパティ値として(known after apply)
が表示されます。
リソースのリストを確認して、期待どおりのものかどうかを確認してください。その後、矢印キーを使用して承認オプションを選択し、ENTER
を押します。
次のような出力が表示されます:
Outputinfra digitalocean_droplet.foo (foo): Creating...
digitalocean_droplet.bar (bar): Creating...
infra digitalocean_droplet.bar (bar): Still creating... [10s elapsed]
infra digitalocean_droplet.foo (foo): Still creating... [10s elapsed]
1 Stack deploying 0 Stacks done 0 Stacks waiting
この出力は、cdktf
がDigitalOcean APIと通信してDropletを作成していることを示しています。 DropletのIDは、Dropletがプロビジョニングされるまでわからないため、cdktf
は最初にDropletsを作成します。
Dropletの作成には通常1分未満かかります。 Dropletsがプロビジョニングされると、cdktf
はロードバランサーの作成に移行します。
Outputinfra digitalocean_droplet.bar (bar): Creation complete after 54s [id=298041598]
infra digitalocean_droplet.foo (foo): Creation complete after 55s [id=298041600]
infra digitalocean_loadbalancer.lb (lb): Creating...
infra digitalocean_loadbalancer.lb (lb): Still creating... [10s elapsed]
ロードバランサーの作成には時間がかかる場合があります。ロードバランサーが作成された後、スタックが正常に展開されたことを示す要約が表示されます。
Outputinfra digitalocean_loadbalancer.lb (lb): Still creating... [1m30s elapsed]
infra digitalocean_loadbalancer.lb (lb): Creation complete after 1m32s [id=4f9ae2b7-b649-4fb4-beed-96b95bb72dd1]
infra
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
No outputs found.
今すぐ、DigitalOceanコンソールを訪れることができます。そこで、default
という名前の1つのロードバランサーと、それぞれがロードバランサーのターゲットとして機能する2つの健全なDroplet (foo
とbar
) を見ることができます。
NGINXが実行され、コンテンツが正しく提供されていることをテストするには、各DropletのIPアドレスにアクセスしてください。次のようなテキストが表示されるはずです:
Droplet: bar, IP Address: droplet_ip
その文字列のテキストが表示されない場合やサーバーが応答しない場合は、指定したユーザーデータが正しいかどうか、およびシェバン (#!
) の前に文字 (改行を含む) がないかどうかを確認してください。また、SSHプライベートキーを使用してDropletにSSHでき、CloudInitが生成した出力ログを/var/log/cloud-init-output.log
で確認できます:
ドロップレットが起動し、コンテンツを提供していることを確認したら、ロードバランサーのテストを開始できます。これを行うには、いくつかのリクエストを送信します。
次のコマンドをターミナルから実行して、ロードバランサーに10件のリクエストを送信します:
以下のような出力が表示されるはずですが、表示されるIPアドレスは異なります:
OutputDroplet: foo, IP Address: droplet_foo_ip
Droplet: bar, IP Address: droplet_bar_ip
Droplet: foo, IP Address: droplet_foo_ip
Droplet: bar, IP Address: droplet_bar_ip
Droplet: bar, IP Address: droplet_bar_ip
Droplet: foo, IP Address: droplet_foo_ip
Droplet: bar, IP Address: droplet_bar_ip
Droplet: foo, IP Address: droplet_foo_ip
Droplet: bar, IP Address: droplet_bar_ip
Droplet: foo, IP Address: droplet_foo_ip
これにより、ロードバランサーへのリクエストが各Dropletに5回転送されたことが示され、ロードバランサーが機能していることがわかります。
注意: ロードバランサーが常に2つのDroplet間で完璧にバランスをとるわけではないかもしれません。1つのDropletに4つのリクエストが送信され、もう1つに6つのリクエストが送信されたということがあります。この動作は正常です。
このステップでは、cdktf
を使用してリソースをプロビジョニングし、次にデジタルオーシャンコンソールを使用してDropletsとロードバランサーのIPアドレスを見つけました。その後、それぞれのDropletとロードバランサーにリクエストを送信して動作を確認しました。
次のステップでは、デジタルオーシャンコンソールにログインせずに、DropletsとロードバランサーのIPアドレスを取得します。
ステップ8 — 情報の出力
前のステップでは、DropletとロードバランサーのIPアドレスを取得するためにデジタルオーシャンコンソールにログインする必要がありました。このステップでは、この情報がcdktf deploy
コマンドの出力に表示されるようにコードをわずかに変更して、コンソールへの移動を省略します。
Terraformは、管理されているリソースの構成と状態をステートファイルに記録します。infra
スタックの場合、ステートファイルはinfra/terraform.infra.tfstate
にあります。このステートファイル内にDropletsとロードバランサーのIPアドレスを見つけることができます。
ただし、大きなファイルを整理するのは不便です。CDKTFはTerraformOutput
構造を提供しており、これを使用して変数を出力し、スタックの外部で使用できるようにします。出力は、cdktf deploy
の実行後にstdout
に表示されます。cdktf output
を実行すると、いつでも出力を表示できます。
注意: このチュートリアルでは、コンソールに情報を出力するだけですが、その真の力は他のスタックからの出力を入力として使用するスタックを使用することにあります。この機能はクロススタック参照として知られています。
main.ts
ファイルを更新して、ロードバランサーとDropletsのIPアドレスの出力を含めます。
ファイルを保存して閉じます。
cdktf deploy
を実行して変更を反映します。
出力には、次のような内容が表示されます:
Output─────────────────────────────────────────────────────────────────────────────
Changes to Outputs:
+ droplet0IP = "droplet_foo_ip"
+ droplet1IP = "droplet_bar_ip"
+ loadBalancerIP = "load_balancer_ip"
You can apply this plan to save these new output values to the Terraform
state, without changing any real infrastructure.
─────────────────────────────────────────────────────────────────────────────
この出力により、インフラストラクチャの変更は行われず、スタックからの出力のみが表示されます。
矢印キーを使用して承認を選択し、ENTER
キーを押します。端末出力の最後には、次のような内容が表示されます:
Outputinfra
droplet0IP = droplet_foo_ip
droplet1IP = droplet_bar_ip
loadBalancerIP = load_balancer_ip
これで、cdktf deploy
またはcdktf output
を実行するたびに、DropletsとロードバランサーのIPアドレスが端末出力に表示され、DigitalOceanコンソールからその情報にアクセスする必要がなくなります。
これで、2つのDropletsとロードバランサーをプロビジョニングし、それらが動作していることを確認しました。開発したCDKTFプロジェクトをベースにして、より洗練されたインフラストラクチャを定義することができます(参照実装はdo-community / digitalocean-cdktf-typescript
で見つけることができます)。
このチュートリアルでプロビジョニングされたリソースには料金が発生します。作成されたインフラストラクチャを使用する予定がない場合は、破棄してください。次の最終ステップでは、このチュートリアルで作成されたリソースを破棄してプロジェクトをクリーンアップします。
ステップ9 — インフラストラクチャの破棄
このステップでは、このチュートリアルで作成されたすべてのリソースを削除します。
infra/
ディレクトリ内にまだいる場合、cdktf destroy
を実行します:
以下のような出力が表示されるはずです:
Outputinfra Initializing the backend...
infra Initializing provider plugins...
infra - Reusing previous version of digitalocean/digitalocean from the dependency lock file
infra - Using previously-installed digitalocean/digitalocean v2.19.0
infra Terraform has been successfully initialized!
infra digitalocean_droplet.bar (bar): Refreshing state... [id=298041598]
digitalocean_droplet.foo (foo): Refreshing state... [id=298041600]
infra digitalocean_loadbalancer.lb (lb): Refreshing state... [id=4f9ae2b7-b649-4fb4-beed-96b95bb72dd1]
infra Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
- destroy
Terraform will perform the following actions:
infra # digitalocean_droplet.bar (bar) will be destroyed
- resource "digitalocean_droplet" "bar" {
- backups = false -> null
- created_at = "2022-05-02T10:04:16Z" -> null
- disk = 25 -> null
- graceful_shutdown = false -> null
- id = "298041598" -> null
- image = "ubuntu-20-04-x64" -> null
- ipv4_address = "droplet_bar_public_ip" -> null
- ipv4_address_private = "droplet_bar_private_ip" -> null
- ipv6 = false -> null
- locked = false -> null
- memory = 1024 -> null
- monitoring = false -> null
- name = "bar" -> null
- price_hourly = 0.00744 -> null
- price_monthly = 5 -> null
- private_networking = true -> null
- region = "lon1" -> null
- resize_disk = true -> null
- size = "s-1vcpu-1gb" -> null
- ssh_keys = [
- "34377800",
] -> null
- status = "active" -> null
- tags = [] -> null
- urn = "do:droplet:298041598" -> null
- user_data = "f9b1d9796d069fe504ce0d89439b6b664b14b1a1" -> null
- vcpus = 1 -> null
- volume_ids = [] -> null
- vpc_uuid = "bed80b32-dc82-11e8-83ec-3cfdfea9f3f0" -> null
}
# digitalocean_droplet.foo (foo) が破棄されます
- resource "digitalocean_droplet" "foo" {
- backups = false -> null
- created_at = "2022-05-02T10:04:16Z" -> null
- disk = 25 -> null
- graceful_shutdown = false -> null
- id = "298041600" -> null
- image = "ubuntu-20-04-x64" -> null
- ipv4_address = "droplet_foo_public_ip" -> null
- ipv4_address_private = "droplet_foo_private_ip" -> null
- ipv6 = false -> null
- locked = false -> null
- memory = 1024 -> null
- monitoring = false -> null
- name = "foo" -> null
- price_hourly = 0.00744 -> null
- price_monthly = 5 -> null
- private_networking = true -> null
- region = "lon1" -> null
- resize_disk = true -> null
- size = "s-1vcpu-1gb" -> null
- ssh_keys = [
- "34377800",
] -> null
- status = "active" -> null
- tags = [] -> null
- urn = "do:droplet:298041600" -> null
- user_data = "f9b1d9796d069fe504ce0d89439b6b664b14b1a1" -> null
- vcpus = 1 -> null
- volume_ids = [] -> null
- vpc_uuid = "bed80b32-dc82-11e8-83ec-3cfdfea9f3f0" -> null
}
# digitalocean_loadbalancer.lb (lb) が破棄されます
- resource "digitalocean_loadbalancer" "lb" {
- algorithm = "round_robin" -> null
- disable_lets_encrypt_dns_records = false -> null
- droplet_ids = [
- 298041598,
- 298041600,
] -> null
- enable_backend_keepalive = false -> null
- enable_proxy_protocol = false -> null
- id = "4f9ae2b7-b649-4fb4-beed-96b95bb72dd1" -> null
- ip = "load_balancer_ip" -> null
- name = "default" -> null
- redirect_http_to_https = false -> null
- region = "lon1" -> null
- size_unit = 1 -> null
- status = "active" -> null
- urn = "do:loadbalancer:4f9ae2b7-b649-4fb4-beed-96b95bb72dd1" -> null
- vpc_uuid = "bed80b32-dc82-11e8-83ec-3cfdfea9f3f0" -> null
- forwarding_rule {
- entry_port = 80 -> null
- entry_protocol = "http" -> nul
infra l
- target_port = 80 -> null
- target_protocol = "http" -> null
- tls_passthrough = false -> null
}
- healthcheck {
- check_interval_seconds = 10 -> null
- healthy_threshold = 5 -> null
- path = "/" -> null
- port = 80 -> null
- protocol = "http" -> null
- response_timeout_seconds = 5 -> null
- unhealthy_threshold = 3 -> null
}
- sticky_sessions {
- cookie_ttl_seconds = 0 -> null
- type = "none" -> null
}
}
Plan: 0 to add, 0 to change, 3 to destroy.
─────────────────────────────────────────────────────────────────────────────
Saved the plan to: plan
To perform exactly these actions, run the following command to apply:
terraform apply "plan"
Please review the diff output above for infra
❯ Approve Applies the changes outlined in the plan.
Dismiss
Stop
この時点では、各リソースの横に +
ではなく -
が表示され、CDKTFがリソースを破棄する予定であることを示します。提案された変更を確認し、矢印キーを使用して承認を選択し、ENTER
キーを押します。DigitalOcean プロバイダーは、リソースを破棄するために DigitalOcean API と通信します。
Outputinfra digitalocean_loadbalancer.lb (lb): Destroying... [id=4f9ae2b7-b649-4fb4-beed-96b95bb72dd1]
infra digitalocean_loadbalancer.lb (lb): Destruction complete after 1s
infra digitalocean_droplet.bar (bar): Destroying... [id=298041598]
digitalocean_droplet.foo (foo): Destroying... [id=298041600]
ロードバランサーは依存関係がないため(他のリソースがその入力でロードバランサーを参照していないため)、最初に削除されました。ロードバランサーがドロップレットを参照しているため、ドロップレットはロードバランサーが破棄された後にのみ破棄できます。
リソースが破棄されると、出力に次の行が表示されます:
OutputDestroy complete! Resources: 3 destroyed.
結論
このチュートリアルでは、CDKTFを使用して、NGINXサーバーを実行する2つのDigitalOceanドロップレットから成るロードバランスされたWebページをプロビジョニングおよび破棄しました。また、リソースに関する情報をターミナルに出力しました。
CDKTFはTerraformの抽象化レイヤーです。Terraformの理解があるとCDKTFの理解が助けになります。Terraformについてもっと学びたい場合は、Terraformを詳しくカバーしたTerraformでインフラストラクチャを管理する方法シリーズを読むことができます。
CDKTFについてさらに学ぶには、公式のCDK for Terraformドキュメントやチュートリアルをチェックしてください。