コードを複製せずにTerraformプロジェクトに複数の環境をデプロイする方法
著者は、 Write for DOnations プログラムの一環として、 Free and Open SourceFundを選択して寄付を受け取りました。
序章
Terraformは、プロジェクトのサイズと複雑さが増すにつれてますます役立つ高度な機能を提供します。 コードを構造化して繰り返しを最小限に抑え、ツールを利用したワークフローを導入してテストとデプロイを容易にすることで、複数の環境の複雑なインフラストラクチャ定義を維持するコストを軽減できます。
Terraformは、 state をバックエンドに関連付けます。バックエンドは、状態が保存および取得される場所と方法を決定します。 すべての状態にはバックエンドが1つだけあり、インフラストラクチャ構成に関連付けられています。 local
やs3
などの特定のバックエンドには、複数の状態が含まれる場合があります。 その場合、バックエンドへの状態とインフラストラクチャのペアリングは、ワークスペースを記述しています。 ワークスペースを使用すると、同じインフラストラクチャ構成の複数の異なるインスタンスを、別々のバックエンドに保存せずにデプロイできます。
このチュートリアルでは、最初に、異なるワークスペースを使用して複数のインフラストラクチャインスタンスをデプロイします。 次に、ステートフルリソースをデプロイします。このチュートリアルでは、これがDigitalOceanボリュームになります。 最後に、 Terraform Registry から作成済みのモジュールを参照します。これを使用して、独自のモジュールを補足できます。
前提条件
このチュートリアルを完了するには、次のものが必要です。
- DigitalOceanパーソナルアクセストークン。DigitalOceanコントロールパネルから作成できます。 手順については、DigitalOcean製品ドキュメントパーソナルアクセストークンの作成方法を参照してください。
- ローカルマシンにインストールされたTerraformと、DOプロバイダーでセットアップされたプロジェクト。 DigitalOcean チュートリアルでTerraformを使用する方法のステップ1およびステップ2を完了し、代わりにプロジェクトフォルダーに
terraform-advanced
という名前を付けてください。loadbalance
の。 ステップ2の間、pvt_key
変数とSSHキーリソースを含めないでください。
注:このチュートリアルは、Terraform1.0.2
で特別にテストされています。
ワークスペースを使用した複数のインフラストラクチャインスタンスの展開
複数のワークスペースは、個別のプロジェクトを作成したり認証キーを再設定したりせずに、メインインフラストラクチャの変更バージョンを展開またはテストする場合に役立ちます。 別の状態を使用して機能を開発およびテストしたら、新しいコードをメインワークスペースに組み込み、場合によっては追加の状態を削除できます。 Terraformプロジェクトをinit
すると、バックエンドに関係なく、Terraformはdefault
というワークスペースを作成します。 常に存在し、削除することはできません。
ただし、複数のワークスペースは、ステージングや本番環境など、複数の環境を作成するための適切なソリューションではありません。 したがって、状態を追跡するだけのワークスペースは、コードまたはその変更を保存しません。
ワークスペースは実際のコードを追跡しないため、複数のワークスペース間のコード分離をバージョン管理(VCS)レベルで管理し、それらをインフラストラクチャのバリアントと照合する必要があります。 これをどのように実現できるかは、VCSツール自体に依存します。 たとえば、Gitブランチでは適切な抽象化になります。 複数の環境のコードを管理しやすくするために、それらを再利用可能なモジュールに分割して、環境ごとに同様のコードを繰り返さないようにすることができます。
ワークスペースへのリソースのデプロイ
次に、複数のワークスペースから適用するDropletをデプロイするプロジェクトを作成します。
ドロップレット定義をdroplets.tf
というファイルに保存します。
terraform-advanced
ディレクトリにいると仮定して、次のコマンドを実行して編集用に作成して開きます。
- nano droplets.tf
次の行を追加します。
resource "digitalocean_droplet" "web" {
image = "ubuntu-18-04-x64"
name = "web-${terraform.workspace}"
region = "fra1"
size = "s-1vcpu-1gb"
}
この定義により、fra1
リージョンに1つのCPUコアと1GBのRAMを備えたUbuntu18.04を実行するドロップレットが作成されます。 その名前には、デプロイ元の現在のワークスペースの名前が含まれます。 完了したら、ファイルを保存して閉じます。
Terraformのプロジェクトを適用して、次のアクションを実行します。
- terraform apply -var "do_token=${DO_PAT}"
出力は次のようになります。
OutputTerraform 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:
# digitalocean_droplet.web will be created
+ resource "digitalocean_droplet" "web" {
+ backups = false
+ created_at = (known after apply)
+ disk = (known after apply)
+ id = (known after apply)
+ image = "ubuntu-18-04-x64"
+ ipv4_address = (known after apply)
+ ipv4_address_private = (known after apply)
+ ipv6 = false
+ ipv6_address = (known after apply)
+ ipv6_address_private = (known after apply)
+ locked = (known after apply)
+ memory = (known after apply)
+ monitoring = false
+ name = "web-default"
+ price_hourly = (known after apply)
+ price_monthly = (known after apply)
+ private_networking = (known after apply)
+ region = "fra1"
+ resize_disk = true
+ size = "s-1vcpu-1gb"
+ status = (known after apply)
+ urn = (known after apply)
+ vcpus = (known after apply)
+ volume_ids = (known after apply)
+ vpc_uuid = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
...
default
ワークスペースにドロップレットを展開するように求められたら、yes
と入力します。
ドロップレットの名前はweb-default
になります。これは、最初に使用するワークスペースがdefault
と呼ばれるためです。 ワークスペースを一覧表示して、それが使用可能な唯一のワークスペースであることを確認できます。
- terraform workspace list
出力は次のようになります。
Output* default
アスタリスク(*
)は、現在そのワークスペースが選択されていることを意味します。
workspace new
を実行して、別のドロップレットを展開するために使用するtesting
という新しいワークスペースを作成して切り替えます。
- terraform workspace new testing
出力は次のようになります。
OutputCreated and switched to workspace "testing"!
You're now on a new, empty workspace. Workspaces isolate their state,
so if you run "terraform plan" Terraform will not see any existing state
for this configuration.
以下を実行して、ドロップレットの展開を再度計画します。
- terraform plan -var "do_token=${DO_PAT}"
出力は前の実行と同様になります。
OutputTerraform 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:
# digitalocean_droplet.web will be created
+ resource "digitalocean_droplet" "web" {
+ backups = false
+ created_at = (known after apply)
+ disk = (known after apply)
+ id = (known after apply)
+ image = "ubuntu-18-04-x64"
+ ipv4_address = (known after apply)
+ ipv4_address_private = (known after apply)
+ ipv6 = false
+ ipv6_address = (known after apply)
+ ipv6_address_private = (known after apply)
+ locked = (known after apply)
+ memory = (known after apply)
+ monitoring = false
+ name = "web-testing"
+ price_hourly = (known after apply)
+ price_monthly = (known after apply)
+ private_networking = (known after apply)
+ region = "fra1"
+ resize_disk = true
+ size = "s-1vcpu-1gb"
+ status = (known after apply)
+ urn = (known after apply)
+ vcpus = (known after apply)
+ volume_ids = (known after apply)
+ vpc_uuid = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
...
Terraformは、web-default
とは異なる名前のweb-testing
というドロップレットを展開することを計画していることに注意してください。 これは、default
ワークスペースとtesting
ワークスペースは別々の状態を持ち、同じコードに由来していても、互いのリソースを認識していないためです。
testing
ワークスペースにいることを確認するには、現在のワークスペースをworkspace show
で出力します。
- terraform workspace show
出力は、現在のワークスペースの名前になります。
Outputtesting
ワークスペースを削除するには、最初に、デプロイされているすべてのリソースを破棄する必要があります。 次に、アクティブな場合は、workspace select
を使用して別のものに切り替える必要があります。 ここのtesting
ワークスペースは空なので、すぐにdefault
に切り替えることができます。
- terraform workspace select default
スイッチを確認するTerraformの出力を受け取ります。
OutputSwitched to workspace "default".
次に、workspace delete
を実行して削除できます。
- terraform workspace delete testing
その後、Terraformは削除を実行します。
OutputDeleted workspace "testing"!
default
ワークスペースにデプロイしたドロップレットは、次のコマンドを実行して破棄できます。
- terraform destroy -var "do_token=${DO_PAT}"
プロセスを終了するように求められたら、yes
と入力します。
このセクションでは、複数のTerraformワークスペースで作業しました。 次のセクションでは、ステートフルリソースをデプロイします。
ステートフルリソースの導入
ステートレスリソースはデータを保存しないため、一意ではないため、データをすばやく作成して置き換えることができます。 一方、ステートフルリソースには、一意であるか、単に再作成できないデータが含まれています。 したがって、永続的なデータストレージが必要です。
そのようなリソースを破壊してしまう可能性があるため、または複数のリソースがそれらのデータを必要とするため、 DigitalOceanVolumesなどの別のエンティティに保存することをお勧めします。
ボリュームは追加のストレージスペースを提供します。 ドロップレット(サーバー)に接続できますが、それらとは別のものです。 このステップでは、ボリュームを定義し、droplets.tf
のドロップレットに接続します。
編集のために開きます:
- nano droplets.tf
次の行を追加します。
resource "digitalocean_droplet" "web" {
image = "ubuntu-18-04-x64"
name = "web-${terraform.workspace}"
region = "fra1"
size = "s-1vcpu-1gb"
}
resource "digitalocean_volume" "volume" {
region = "fra1"
name = "new-volume"
size = 10
initial_filesystem_type = "ext4"
description = "New Volume for Droplet"
}
resource "digitalocean_volume_attachment" "volume_attachment" {
droplet_id = digitalocean_droplet.web.id
volume_id = digitalocean_volume.volume.id
}
ここでは、ボリューム自体とボリュームアタッチメントの2つの新しいリソースを定義します。 ボリュームは10GBで、ext4
としてフォーマットされ、new-volume
と呼ばれ、ドロップレットと同じ領域に配置されます。 ボリュームとドロップレットは別個のエンティティであるため、それらを接続するにはボリュームアタッチメントオブジェクトを定義する必要があります。 volume_attachment
は、ドロップレットとボリュームIDを取得し、ボリュームをディスクデバイスとしてドロップレットで使用できるようにするようにDigitalOceanクラウドに指示します。
完了したら、ファイルを保存して閉じます。
次のコマンドを実行して、この構成を計画します。
- terraform plan -var "do_token=${DO_PAT}"
Terraformが計画するアクションは次のとおりです。
OutputTerraform 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:
# digitalocean_droplet.web will be created
+ resource "digitalocean_droplet" "web" {
+ backups = false
+ created_at = (known after apply)
+ disk = (known after apply)
+ id = (known after apply)
+ image = "ubuntu-18-04-x64"
+ ipv4_address = (known after apply)
+ ipv4_address_private = (known after apply)
+ ipv6 = false
+ ipv6_address = (known after apply)
+ ipv6_address_private = (known after apply)
+ locked = (known after apply)
+ memory = (known after apply)
+ monitoring = false
+ name = "web-default"
+ price_hourly = (known after apply)
+ price_monthly = (known after apply)
+ private_networking = (known after apply)
+ region = "fra1"
+ resize_disk = true
+ size = "s-1vcpu-1gb"
+ status = (known after apply)
+ urn = (known after apply)
+ vcpus = (known after apply)
+ volume_ids = (known after apply)
+ vpc_uuid = (known after apply)
}
# digitalocean_volume.volume will be created
+ resource "digitalocean_volume" "volume" {
+ description = "New Volume for Droplet"
+ droplet_ids = (known after apply)
+ filesystem_label = (known after apply)
+ filesystem_type = (known after apply)
+ id = (known after apply)
+ initial_filesystem_type = "ext4"
+ name = "new-volume"
+ region = "fra1"
+ size = 10
+ urn = (known after apply)
}
# digitalocean_volume_attachment.volume_attachment will be created
+ resource "digitalocean_volume_attachment" "volume_attachment" {
+ droplet_id = (known after apply)
+ id = (known after apply)
+ volume_id = (known after apply)
}
Plan: 3 to add, 0 to change, 0 to destroy.
...
Terraformがドロップレット、ボリューム、およびボリュームをドロップレットに接続するボリュームアタッチメントを作成するという出力の詳細。
これで、ボリューム(ステートフルリソース)を定義してドロップレットに接続しました。 次のセクションでは、プロジェクトに組み込むことができる、公開済みの既成のTerraformモジュールを確認します。
既製のモジュールを参照する
プロジェクト用に独自のカスタムモジュールを作成する以外に、 TerraformRegistryで公開されている他の開発者の既成のモジュールやプロバイダーを使用することもできます。
モジュールセクションでは、使用可能なモジュールのデータベースを検索し、プロバイダーで並べ替えて、必要な機能を備えたモジュールを見つけることができます。 見つけたら、その説明を読むことができます。この説明には、モジュールが提供する入力と出力、および外部モジュールとプロバイダーの依存関係がリストされています。
次に、DigitalOceanSSHキーモジュールをプロジェクトに追加します。 既存の定義とは別にコードをssh-key.tf
というファイルに保存します。 次のコマンドを実行して、編集用に作成して開きます。
- nano ssh-key.tf
次の行を追加します。
module "ssh-key" {
source = "clouddrove/ssh-key/digitalocean"
key_path = "~/.ssh/id_rsa.pub"
key_name = "new-ssh-key"
enable_ssh_key = true
}
このコードは、レジストリからclouddrove/droplet/digitalocean
モジュールのインスタンスを定義し、それが提供するパラメーターの一部を設定します。 ~/.ssh/id_rsa.pub
から読み取ることにより、アカウントに公開SSHキーを追加する必要があります。
完了したら、ファイルを保存して閉じます。
このコードをplan
する前に、以下を実行して参照モジュールをダウンロードする必要があります。
- terraform init
次のような出力が表示されます。
OutputInitializing modules...
Downloading clouddrove/ssh-key/digitalocean 0.13.0 for ssh-key...
- ssh-key in .terraform/modules/ssh-key
Initializing the backend...
Initializing provider plugins...
- Reusing previous version of digitalocean/digitalocean from the dependency lock file
- Using previously-installed digitalocean/digitalocean v2.10.1
Terraform has been successfully initialized!
...
これで、変更のコードを計画できます。
- terraform plan -var "do_token=${DO_PAT}"
次のような出力が表示されます。
OutputTerraform 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:
...
# module.ssh-key.digitalocean_ssh_key.default[0] will be created
+ resource "digitalocean_ssh_key" "default" {
+ fingerprint = (known after apply)
+ id = (known after apply)
+ name = "devops"
+ public_key = "ssh-rsa ... [email protected]"
}
Plan: 4 to add, 0 to change, 0 to destroy.
...
出力は、SSHキーリソースを作成することを示しています。これは、コードからモジュールをダウンロードして呼び出したことを意味します。
結論
より大きなプロジェクトでは、Terraformが提供するいくつかの高度な機能を利用して、複雑さを軽減し、メンテナンスを容易にすることができます。 ワークスペースを使用すると、安定したメインデプロイメントに触れることなく、コードへの新しい追加をテストできます。 ワークスペースをバージョン管理システムと組み合わせて、コードの変更を追跡することもできます。 既製のモジュールを使用することで開発時間を短縮することもできますが、モジュールが廃止された場合、将来的に追加の費用や時間が発生する可能性があります。
このチュートリアルは、Terraformシリーズでインフラストラクチャを管理する方法の一部です。 このシリーズでは、Terraformの初めてのインストールから複雑なプロジェクトの管理まで、Terraformの多くのトピックを取り上げています。