コードを複製せずにTerraformプロジェクトに複数の環境をデプロイする方法
序章
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キーリソース。
注:このチュートリアルはTerraformで特別にテストされています 1.0.2
.
ワークスペースを使用した複数のインフラストラクチャインスタンスの展開
複数のワークスペースは、個別のプロジェクトを作成したり認証キーを再設定したりせずに、メインインフラストラクチャの変更バージョンを展開またはテストする場合に役立ちます。 別の状態を使用して機能を開発およびテストしたら、新しいコードをメインワークスペースに組み込み、場合によっては追加の状態を削除できます。 あなたが init
Terraformプロジェクトは、バックエンドに関係なく、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"
}
この定義により、1つのCPUコアと1GBのRAMを搭載したUbuntu18.04を実行するドロップレットが作成されます。 fra1
領域。 その名前には、デプロイ元の現在のワークスペースの名前が含まれます。 完了したら、ファイルを保存して閉じます。
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.
...
入る yes
ドロップレットを展開するように求められたら default
ワークスペース。
ドロップレットの名前は web-default
、最初のワークスペースが呼び出されるため default
. ワークスペースを一覧表示して、それが使用可能な唯一のワークスペースであることを確認できます。
- terraform workspace list
出力は次のようになります。
Output* default
アスタリスク(*
)は、現在そのワークスペースが選択されていることを意味します。
と呼ばれる新しいワークスペースを作成して切り替えます testing
、を実行して、別のドロップレットをデプロイするために使用します workspace new
:
- 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-testing
、とは異なる名前が付けられています web-default
. これは、 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キーを追加する必要があります ~/.ssh/id_rsa.pub
.
完了したら、ファイルを保存して閉じます。
あなたの前に 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 ... demo@clouddrove"
}
Plan: 4 to add, 0 to change, 0 to destroy.
...
出力は、SSHキーリソースを作成することを示しています。これは、コードからモジュールをダウンロードして呼び出したことを意味します。
結論
より大きなプロジェクトでは、Terraformが提供するいくつかの高度な機能を利用して、複雑さを軽減し、メンテナンスを容易にすることができます。 ワークスペースを使用すると、安定したメインデプロイメントに触れることなく、コードへの新しい追加をテストできます。 ワークスペースをバージョン管理システムと組み合わせて、コードの変更を追跡することもできます。 既製のモジュールを使用することで開発時間を短縮することもできますが、モジュールが廃止された場合、将来的に追加の費用や時間が発生する可能性があります。
このチュートリアルは、Terraformシリーズでインフラストラクチャを管理する方法の一部です。 このシリーズでは、Terraformの初めてのインストールから複雑なプロジェクトの管理まで、Terraformの多くのトピックを取り上げています。