DigitalOceanでPackerとTerraformを使用してHashicorpVaultサーバーを構築する方法
著者は、 Write for DOnations プログラムの一環として、 Free and Open SourceFundを選択して寄付を受け取りました。
序章
HashiCorpのVaultは、動的なクラウド環境にシークレットと機密データを安全に保存するためのオープンソースツールです。 強力なデータ暗号化、カスタムポリシーを使用したIDベースのアクセス、シークレットリースと失効、および常に記録される詳細な監査ログを提供します。 VaultはHTTPAPIも備えているため、Kubernetesなどの分散したサービス指向のデプロイでクレデンシャルを保存するための理想的な選択肢になります。
同じくHashiCorpによって開発されたPackerとTerraformを一緒に使用して、Vaultのイメージを作成およびデプロイできます。 このワークフロー内で、開発者はPackerを使用して、イメージに含める必要のあるものを指定する単一の構成ファイルから、さまざまなプラットフォーム用の不変のイメージを書き込むことができます。 その後、Terraformは、作成されたイメージのカスタマイズされたインスタンスを必要な数だけデプロイします。
このチュートリアルでは、Packerを使用して、Vaultがインストールされたシステムの不変のスナップショットを作成し、Terraformを使用してその展開を調整します。 最終的には、Vaultを適切に展開するための自動化されたシステムが得られ、基盤となるインストールおよびプロビジョニングプロセスではなく、Vault自体の操作に集中できます。
前提条件
- ローカルマシンにインストールされたPacker。 手順については、公式ドキュメントをご覧ください。
- ローカルマシンにインストールされたTerraform。 これを実現するには、DigitalOceanチュートリアルでTerraformを使用する方法のステップ1に従います。
- DigitalOceanアカウントの読み取りおよび書き込み権限を持つ個人用アクセストークン(APIキー)。 作成方法については、ドキュメントからパーソナルアクセストークンの作成方法にアクセスしてください。
- デプロイされたVaultドロップレットでの認証に使用するSSHキー。ローカルマシンで利用可能であり、DigitalOceanアカウントに追加されます。 また、指紋も必要です。指紋を追加すると、アカウントのセキュリティページからコピーできます。 詳細な手順については、DigitalOceanのドキュメントまたはSSHキーの設定方法チュートリアルを参照してください。
ステップ1—パッカーテンプレートの作成
このステップでは、 template と呼ばれるPacker構成ファイルを作成します。このファイルは、Vaultがプリインストールされたイメージを構築する方法をPackerに指示します。 構成は、一般的に使用される人間が読める形式の構成ファイル形式であるJSON形式で記述します。
このチュートリアルでは、すべてのファイルを~/vault-orchestration
の下に保存します。 次のコマンドを実行して、ディレクトリを作成します。
mkdir ~/vault-orchestration
そこに移動します:
cd ~/vault-orchestration
PackerとTerraformの構成ファイルを別々のサブディレクトリに別々に保存します。 次のコマンドを使用してそれらを作成します。
mkdir packer terraform
最初にPackerを使用するため、次のディレクトリに移動します。
cd packer
テンプレート変数の使用
プライベートデータとアプリケーションシークレットを別の変数ファイルに保存することは、それらをテンプレートから除外するための理想的な方法です。 イメージを構築するとき、Packerは参照される変数をそれらの値に置き換えます。 シークレット値をテンプレートにハードコーディングすることは、セキュリティ上のリスクです。特に、チームメンバーと共有したり、GitHubなどの公開サイトに公開したりする場合はそうです。
それらをpacker
サブディレクトリのvariables.json
というファイルに保存します。 お気に入りのテキストエディタを使用して作成します。
nano variables.json
次の行を追加します。
〜/ vault-orchestration / packer / variables.json
{ "do_token": "your_do_api_key", "base_system_image": "ubuntu-20-04-x64", "region": "fra1", "size": "s-1vcpu-1gb" }
変数ファイルは、変数名をそれらの値にマップするJSONディクショナリで構成されています。 作成しようとしているテンプレートでこれらの変数を使用します。 必要に応じて、開発者向けドキュメントに従って、ベースイメージ、リージョン、およびドロップレットサイズの値を編集できます。
your_do_api_key
を、前提条件の一部として作成したAPIキーに置き換えてから、ファイルを保存して閉じることを忘れないでください。
ビルダーとプロビジョナーの作成
変数ファイルの準備ができたら、Packerテンプレート自体を作成します。
VaultのPackerテンプレートをtemplate.json
という名前のファイルに保存します。 テキストエディタを使用して作成します。
nano template.json
次の行を追加します。
〜/ vault-orchestration / packer / template.json
{ "builders": [{ "type": "digitalocean", "api_token": "{{user `do_token`}}", "image": "{{user `base_system_image`}}", "region": "{{user `region`}}", "size": "{{user `size`}}", "ssh_username": "root" }], "provisioners": [{ "type": "shell", "inline": [ "sleep 30", "sudo apt-get update", "sudo apt-get install unzip -y", "curl -L https://releases.hashicorp.com/vault/1.8.4/vault_1.8.4_linux_amd64.zip -o vault.zip", "unzip vault.zip", "sudo chown root:root vault", "mv vault /usr/local/bin/", "rm -f vault.zip" ] }] }
テンプレートでは、BuildersおよびProvisionersの配列を定義します。 ビルダーは、システムイメージの構築方法(タイプに応じて)とその保存場所をPackerに指示します。一方、プロビジョナーには、ソフトウェアのインストールや構成など、システムを不変のイメージに変換する前にPackerがシステムに対して実行する必要のある一連のアクションが含まれます。 プロビジョナーがないと、基本システムイメージはそのままになります。 ビルダーとプロビジョナーの両方が、さらにワークフローをカスタマイズするためのパラメーターを公開します。
最初にタイプdigitalocean
の単一のビルダーを定義します。つまり、イメージのビルドを注文すると、Packerは提供されたパラメーターを使用して、指定されたAPIキーを使用して、指定されたサイズの一時的なドロップレットを作成します。基本システムイメージと指定された領域。 変数をフェッチするための形式はテンプレート:User 'variable name'
で、強調表示されている部分はその名前です。
一時的なドロップレットがプロビジョニングされると、プロビジョナーは指定されたユーザー名でSSHを使用してそれに接続し、ドロップレットからDigitalOceanスナップショットを作成して削除する前に、定義されたすべてのプロビジョナーを順番に実行します。
プロビジョナーのタイプはshell
で、ターゲットに対して特定のコマンドを実行します。 コマンドは、文字列の配列としてinline
で指定するか、サイズが原因でテンプレートに挿入するのが面倒になる場合は、個別のスクリプトファイルで定義できます。 テンプレート内のコマンドは、システムが起動するまで30秒間待機してから、Vault 1.8.4をダウンロードして解凍します。 公式Vaultダウンロードページを確認し、コマンド内のリンクをLinux用の新しいバージョン(利用可能な場合)に置き換えてください。
完了したら、ファイルを保存して閉じます。
テンプレートの有効性を確認するには、次のコマンドを実行します。
packer validate -var-file=variables.json template.json
Packerは、-var-file
引数を介して変数ファイルへのパスを受け入れます。
次の出力が表示されます。
OutputThe configuration is valid.
エラーが発生した場合、Packerはエラーが発生した場所を正確に指定するため、エラーを修正できます。
これで、Vaultがインストールされ、APIキーとその他のパラメーターが別のファイルで定義されたイメージを生成する作業テンプレートができました。 これで、Packerを呼び出してスナップショットを作成する準備が整いました。
ステップ2—スナップショットを作成する
このステップでは、Packer build
コマンドを使用して、テンプレートからDigitalOceanスナップショットを作成します。
スナップショットを作成するには、次のコマンドを実行します。
packer build -var-file=variables.json template.json
このコマンドは、完了するまでに少し時間がかかります。 これに似た多くの出力が表示されます。
Outputdigitalocean: output will be in this color. ==> digitalocean: Creating temporary RSA SSH key for instance... ==> digitalocean: Importing SSH public key... ==> digitalocean: Creating droplet... ==> digitalocean: Waiting for droplet to become active... ==> digitalocean: Using SSH communicator to connect: ... ==> digitalocean: Waiting for SSH to become available... ==> digitalocean: Connected to SSH! ==> digitalocean: Provisioning with shell script: /tmp/packer-shell464972932 digitalocean: Hit:1 http://mirrors.digitalocean.com/ubuntu focal InRelease ... ==> digitalocean: % Total % Received % Xferd Average Speed Time Time Time Current ==> digitalocean: Dload Upload Total Spent Left Speed ==> digitalocean: 100 63.5M 100 63.5M 0 0 110M 0 --:--:-- --:--:-- --:--:-- 110M digitalocean: Archive: vault.zip digitalocean: inflating: vault ==> digitalocean: Gracefully shutting down droplet... ==> digitalocean: Creating snapshot: packer-1635876039 ==> digitalocean: Waiting for snapshot to complete... ==> digitalocean: Destroying droplet... ==> digitalocean: Deleting temporary ssh key... Build 'digitalocean' finished after 5 minutes 6 seconds. ==> Wait completed after 5 minutes 6 seconds ==> Builds finished. The artifacts of successful builds are: --> digitalocean: A snapshot was created: 'packer-1635876039' (ID: 94912983) in regions 'fra1'
Packerは、テンプレートの作成中に行ったすべての手順をログに記録します。 最後の行には、スナップショットの名前(packer-1635876039
など)とそのIDが括弧で囲まれ、赤でマークされています。 次の手順で必要になるため、スナップショットのIDをメモします。
APIエラーが原因でビルドプロセスが失敗した場合は、数分待ってから再試行してください。
テンプレートに従ってDigitalOceanスナップショットを作成しました。 スナップショットにはVaultがプリインストールされており、システムイメージとしてDropletsを展開できるようになりました。 次のステップでは、このようなデプロイメントを自動化するためのTerraform構成を記述します。
ステップ3—Terraform構成の記述
このステップでは、Packerを使用して構築したVaultを含むスナップショットのDropletデプロイメントを自動化するためのTerraform構成を記述します。
以前に構築されたスナップショットからVaultをデプロイするための実際のTerraform構成を作成する前に、まずそのためにDigitalOceanプロバイダーを構成する必要があります。 次のコマンドを実行して、terraform
サブディレクトリに移動します。
cd ~/vault-orchestration/terraform
次に、do-provider.tf
という名前のファイルを作成します。このファイルには、プロバイダーを保存します。
nano do-provider.tf
次の行を追加します。
〜/ vault-orchestration / terraform / do-provider.tf
terraform { required_providers { digitalocean = { source = "digitalocean/digitalocean" version = "~> 2.0" } } } variable "do_token" { } variable "ssh_fingerprint" { } variable "instance_count" { default = "1" } variable "do_snapshot_id" { } variable "do_name" { default = "vault" } variable "do_region" { } variable "do_size" { } provider "digitalocean" { token = var.do_token }
このファイルはパラメーター変数を宣言し、digitalocean
プロバイダーにAPIキーを提供します。 後でこれらの変数をTerraformテンプレートで使用しますが、最初にそれらの値を指定する必要があります。 そのために、Terraformは、Packerと同様に、変数定義ファイルでの変数値の指定をサポートしています。 ファイル名は.tfvars
または.tfvars.json
で終わる必要があります。 後で-var-file
引数を使用してそのファイルをTerraformに渡します。
ファイルを保存して閉じます。
テキストエディタを使用して、definitions.tfvars
という変数定義ファイルを作成します。
nano definitions.tfvars
次の行を追加します。
〜/ vault-orchestration / terraform /definitions.tfvars
do_token = "your_do_api_key" ssh_fingerprint = "your_ssh_key_fingerprint" do_snapshot_id = your_do_snapshot_id do_name = "vault" do_region = "fra1" do_size = "s-1vcpu-1gb" instance_count = 1
your_do_api_key,
your_ssh_key_fingerprint
、およびyour_do_snapshot_id
を、それぞれアカウントAPIキー、SSHキーのフィンガープリント、および前の手順でメモしたスナップショットIDに置き換えることを忘れないでください。 do_region
およびdo_size
パラメーターは、Packer変数ファイルと同じ値である必要があります。 複数のインスタンスを一度にデプロイする場合は、instance_count
を目的の値に調整します。
終了したら、ファイルを保存して閉じます。
DigitalOcean Terraformプロバイダーの詳細については、公式ドキュメントにアクセスしてください。
Vaultスナップショットの展開構成は、terraform
ディレクトリの下のdeployment.tf
という名前のファイルに保存します。 テキストエディタを使用して作成します。
nano deployment.tf
次の行を追加します。
〜/ vault-orchestration / terraform / deployment.tf
resource "digitalocean_droplet" "vault" { count = var.instance_count image = var.do_snapshot_id name = var.do_name region = var.do_region size = var.do_size ssh_keys = [ var.ssh_fingerprint ] } output "instance_ip_addr" { value = { for instance in digitalocean_droplet.vault: instance.id => instance.ipv4_address } description = "The IP addresses of the deployed instances, paired with their IDs." }
ここでは、vault
という名前のタイプdigitalocean_droplet
の単一のリソースを定義します。 次に、変数値に従ってパラメーターを設定し、SSHキー(フィンガープリントを使用)をDigitalOceanアカウントからDropletリソースに追加します。 最後に、コンソールに新しくデプロイされたすべてのインスタンスのIPアドレスをoutput
します。
ファイルを保存して閉じます。
デプロイメント構成で他のことを行う前に、ディレクトリをTerraformプロジェクトとして初期化する必要があります。
terraform init
次の出力が表示されます。
OutputInitializing the backend... Initializing provider plugins... - Finding digitalocean/digitalocean versions matching "~> 2.0"... - Installing digitalocean/digitalocean v2.15.0... - Installed digitalocean/digitalocean v2.15.0 (signed by a HashiCorp partner, key ID F82037E524B9C0E8) Partner and community providers are signed by their developers. If you'd like to know more about provider signing, you can read about it here: https://www.terraform.io/docs/cli/plugins/signing.html Terraform has created a lock file .terraform.lock.hcl to record the provider selections it made above. Include this file in your version control repository so that Terraform can guarantee to make the same selections by default when you run "terraform init" in the future. Terraform has been successfully initialized! You may now begin working with Terraform. Try running "terraform plan" to see any changes that are required for your infrastructure. All Terraform commands should now work. If you ever set or change modules or backend configuration for Terraform, rerun this command to reinitialize your working directory. If you forget, other commands will detect it and remind you to do so if necessary.
ディレクトリをプロジェクトとして初期化するとき、Terraformは利用可能な構成ファイルを読み取り、出力に記録されているように、必要と思われるプラグインをダウンロードします。
これで、VaultスナップショットをデプロイするためのTerraform構成の準備が整いました。 これで、検証とドロップレットへの展開に進むことができます。
ステップ4—Terraformを使用したVaultのデプロイ
このセクションでは、validate
コマンドを使用してTerraformの構成を確認します。 正常に検証されたら、apply
して、結果としてドロップレットをデプロイします。
次のコマンドを実行して、構成の有効性をテストします。
terraform validate
次の出力が表示されます。
OutputSuccess! The configuration is valid.
次に、plan
コマンドを実行して、構成に従ってインフラストラクチャをプロビジョニングするときにTerraformが何を試行するかを確認します。
terraform plan -var-file="definitions.tfvars"
Terraformは、-var-file
パラメーターを介して変数定義ファイルを受け入れます。
出力は次のようになります。
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.vault[0] will be created + resource "digitalocean_droplet" "vault" { + backups = false + created_at = (known after apply) + disk = (known after apply) + graceful_shutdown = false + id = (known after apply) + image = "94912983" + 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 = "vault" + price_hourly = (known after apply) + price_monthly = (known after apply) + private_networking = (known after apply) + region = "fra1" + resize_disk = true + size = "s-1vcpu-1gb" + ssh_keys = [ + "...", ] + 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. Changes to Outputs: + instance_ip_addr = (known after apply) ...
resource "digitalocean_droplet" "vault"
行の先頭にある緑色の+
は、Terraformが次のパラメーターを使用してvault
という新しいドロップレットを作成することを意味します。 これは正しいので、terraform apply
を実行して計画を実行できるようになりました。
terraform apply -var-file="definitions.tfvars"
プロンプトが表示されたら、yes
と入力します。 数分後、Dropletはプロビジョニングを終了し、次のような出力が表示されます。
Output 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: # digitalocean_droplet.vault[0] will be created + resource "digitalocean_droplet" "vault" { ... } Plan: 1 to add, 0 to change, 0 to destroy. Changes to Outputs: + instance_ip_addr = (known after apply) ... digitalocean_droplet.vault[0]: Creating... digitalocean_droplet.vault[0]: Still creating... [10s elapsed] ... digitalocean_droplet.vault[0]: Creation complete after 44s [id=271950984] Apply complete! Resources: 1 added, 0 changed, 0 destroyed. Outputs: instance_ip_addr = { "271950984" = "your_new_server_ip" }
出力では、Terraformは実行したアクション(この場合はドロップレットを作成するため)をログに記録し、最後にパブリックIPアドレスを表示します。 次のステップで、これを使用して新しいドロップレットに接続します。
Vaultを含むスナップショットから新しいドロップレットを作成し、検証する準備が整いました。
ステップ5—デプロイされたドロップレットを確認する
このステップでは、SSHを使用して新しいドロップレットにアクセスし、Vaultが正しくインストールされていることを確認します。
Windowsを使用している場合は、KittyやPuttyなどのソフトウェアを使用して、SSHキーでドロップレットに接続できます。
LinuxおよびmacOSマシンでは、すでに使用可能なssh
コマンドを使用して以下に接続できます。
ssh root@your_server_ip
プロンプトが表示されたら、yes
と答えます。 ログインしたら、次のコマンドを実行してVaultを実行します。
vault
次のような「ヘルプ」出力が表示されます。
OutputUsage: vault <command> [args] Common commands: read Read data and retrieves secrets write Write data, configuration, and secrets delete Delete secrets and configuration list List data or secrets login Authenticate locally agent Start a Vault agent server Start a Vault server status Print seal and HA status unwrap Unwrap a wrapped secret Other commands: audit Interact with audit devices auth Interact with auth methods debug Runs the debug command kv Interact with Vault's Key-Value storage lease Interact with leases namespace Interact with namespaces operator Perform operator-specific tasks path-help Retrieve API help for paths plugin Interact with Vault plugins and catalog policy Interact with policies print Prints runtime configurations secrets Interact with secrets engines ssh Initiate an SSH session token Interact with tokens
exit
と入力すると、接続を終了できます。
これで、新しくデプロイしたDropletが作成したスナップショットから作成され、Vaultが正しくインストールされていることを確認できました。
プロビジョニングされたリソースを破棄するには、次のコマンドを実行し、プロンプトが表示されたらyes
と入力します。
terraform destroy -var-file="definitions.tfvars"
結論
これで、TerraformとPackerを使用してHashicorpVaultをDigitalOceanDropletsにデプロイするための自動システムができました。 これで、必要な数のVaultサーバーをデプロイできます。 Vaultの使用を開始するには、初期化して、さらに構成する必要があります。 その方法については、公式ドキュメントにアクセスしてください。
Terraformを使用したその他のチュートリアルについては、TerraformコンテンツページおよびTerraformでインフラストラクチャを管理する方法シリーズをご覧ください。複雑なプロジェクト。