前書き

Terraformは、組織的な方法でインフラストラクチャを構築および管理するためのツールです。 他のプロバイダーが提供する多種多様なサービスに加えて、DigitalOceanドロップレットとDNSエントリを管理するために使用できます。 使いやすいコマンドラインインターフェイスを介して制御され、デスクトップまたはリモートサーバーから実行できます。

Terraformは、アプリケーション環境またはデータセンターを構成するコンポーネントを記述する構成ファイルを読み取ることで機能します。 構成に基づいて、実行計画を生成します。実行計画には、目的の状態に到達するために行うことを記述します。 その後、インフラストラクチャを構築するための計画が実行されます。 構成の変更が発生すると、Terraformは増分計画を生成および実行して、既存のインフラストラクチャを新しく記述された状態に更新できます。

このチュートリアルでは、Terraformを使用して、HAProxyサーバーによって負荷分散される2つのNginxサーバーで構成される単純なインフラストラクチャを作成する方法を示します(下の画像を参照)。 これは、Terraformの使用を開始するのに役立ち、独自のニーズを満たすDigitalOceanベースのインフラストラクチャを管理および展開するためにどのように使用できるかについてのアイデアを提供します。

image:https://assets.digitalocean.com/articles/terraform/terraform_example.png [インフラストラクチャの例]

このチュートリアルに従うために必要なものを見てみましょう。

前提条件

DigitalOceanアカウント

このチュートリアルはTerraformのDigitalOceanプロバイダーの使用に焦点を当てているため、有効なDigitalOceanアカウントが必要です。 お持ちでない場合は、https://cloud.digitalocean.com/registrations/new [こちらから登録してください]。

DigitalOcean APIトークン

DigitalOceanコントロールパネルを使用して、パーソナルアクセストークンを生成します。 これを行う手順については、https://www.digitalocean.com/community/tutorials/how-to-use-the-digitalocean-api-v2#HowToGenerateaPersonalAccessToken [個人アクセストークンを生成する方法]のリンクを参照してください。

Terraformを実行するすべての端末で、DigitalOcean Personal Access Tokenをエクスポートします。

export DO_PAT=

Terraformはこのトークンを使用してDigitalOcean APIに対する認証を行い、アカウントを制御します。 これを非公開にしてください!

パスワードなしのSSHキーをDigitalOcean Cloudに追加する

DigitalOceanアカウントにパスワードなしのSSHキーをまだ追加していない場合は、https://www.digitalocean.com/community/tutorials/how-to-use-ssh-keys-with-digitalocean-dropletsに従って追加してください[このチュートリアル]。

秘密鍵が `+〜/ .ssh / id_rsa +`にあると仮定して、次のコマンドを使用して公開鍵のMD5フィンガープリントを取得します。

ssh-keygen -E md5 -lf ~/.ssh/id_rsa.pub | awk '{print $2}'

これにより、次のようなものが出力されます。

md5:

Terraformを実行する場合、次のように、このフィンガープリントから `+ md5:+`プレフィックスを除いたものを提供する必要があります(強調表示されたすべての単語を適切な値に置き換えます)。

terraform plan \
 -var "do_token=${DO_PAT}" \
 -var "pub_key=/.ssh/id_rsa.pub" \
 -var "pvt_key=/.ssh/id_rsa" \
 -var "ssh_fingerprint="

これで前提条件が整いましたので、Terraformをインストールしましょう!

Terraformをインストールする

*注意:*このチュートリアルはTerraform 0.1.1を使用して書かれています。

Terraformはインストールが非常に簡単で、デスクトップまたはリモートサーバーで実行できます。 手順は次のとおりです。

[[1-download-terraform]]
===== 1. ダウンロードTerraform

ご使用のOSおよびアーキテクチャに適したパッケージをダウンロードします。http://www.terraform.io/downloads.html [Terraformのダウンロード]

[[2-extract-terraform]]
===== 2. 地形の抽出

ダウンロードしたパッケージを選択したディレクトリに解凍します。

`+〜/ Downloads +`にダウンロードした場合は、次のコマンドを実行して抽出できます。

mkdir -p
unzip ~/Downloads/terraform_0.1.1_darwin_amd64.zip -d

これにより、パッケージがホームディレクトリ内の `+ opt / terraform / +`ディレクトリにアーカイブ解除されます。

[[3-add-path-to-profile]]
===== 3. プロファイルにパスを追加

最後のステップは、Terraformのbinディレクトリである `+〜/ opt / terraform / bin +`をPATH環境変数に追加して、簡単にアクセスできるようにすることです。

たとえば、_bash_をシェルとして使用する場合、パスを `+ .bash_profile +`に追加できます。 編集用にプロファイルを開きます。

vi ~/.bash_profile

TerraformのパスをPATHに追加するには、ファイルの最後に次の行を追加します。

export PATH=$PATH:

保存して終了。

これで、すべての新しいbashセッションで `+ terraform +`コマンドを見つけることができます。 現在のセッションに新しいPATHをロードする場合は、次を入力します。

. .bash_profile

Terraformのインストールを確認する

Terraformが正しくインストールされていることを確認するために、実行してみましょう。 ターミナルで、Terraformを実行します。

terraform

パスが適切に設定されている場合、次のような出力が表示されます。

Available commands are:
   apply      Builds or changes infrastructure
   graph      Create a visual graph of Terraform resources
   output     Read an output from a state file
   plan       Generate and show an execution plan
   refresh    Update local state file against real resources
   show       Inspect Terraform state or plan
   version    Prints the Terraform version

これらは、Terraformが受け入れるコマンドです。 ここでは簡単に説明しましたが、後でそれらの使用方法について説明します。

Terraformがインストールされたので、インフラストラクチャを説明する構成の記述を始めましょう!

構成ディレクトリを作成する

Terraformでインフラストラクチャを構築する最初のステップは、特定のプロジェクトの構成ファイルを保存するディレクトリを作成することです。 ディレクトリの名前は重要ではありませんが、例では「loadbalance」を使用します(名前は自由に変更できます)。

mkdir

Terraform設定は、ファイル拡張子が「+ .tf +」で終わるテキストファイルです。 それらは人間が読める形式であり、コメントをサポートしています。 TerraformはJSON形式の構成ファイルもサポートしていますが、ここではそれらについて説明しません。 Terraformは、作業ディレクトリ内のすべての構成ファイルを宣言的な方法で読み取るため、リソースと変数の定義の順序は重要ではありません。 インフラストラクチャ全体が単一の構成ファイルに存在することもありますが、このチュートリアルではリソースごとに構成ファイルを分離します。

現在のディレクトリを新しく作成したディレクトリに変更します。

cd

これからは、作業ディレクトリが先ほど変更したディレクトリであると想定します。 新しいターミナルセッションを開始する場合は、Terraform構成を含むディレクトリに必ず変更してください。

立ち往生した場合

行き詰まっていて、Terraformが期待どおりに動作しない場合は、 `+ terraform.tfstate +`ファイルを削除し、作成されたリソースを手動で破棄することからやり直すことができます(例: コントロールパネルまたはhttps://github.com/pearkes/tugboat[Tugboat]などの別のAPIツールを使用してください)。

また、Terraformが何をしようとしているかを確認できるように、stdoutへのロギングを有効にすることもできます。 それには、次のコマンドを実行します。

export TF_LOG=1

また、有効な構成を構築できない場合は、GitHub Gistで完全な構成ファイルを入手できます:https://gist.github.com/thisismitch/91815a582c27bd8aa44d[Configuration Files]。

それでは、Terraform構成の作成に進みましょう。

プロバイダー構成の作成

Terraformは、同梱の「プロバイダー」を通じてさまざまなサービスプロバイダーをサポートします。 TerraformがDigitalOcean APIと対話してインフラストラクチャを構築するために使用するDigitalOceanプロバイダーに興味があります。 DigitalOceanプロバイダーを使用するための最初のステップは、適切な資格情報変数を使用してプロバイダーを構成することです。 それでは今やろう。

`+ provider.tf +`というファイルを作成します。

vi provider.tf

ファイルに次の行を追加します。

variable "do_token" {}
variable "pub_key" {}
variable "pvt_key" {}
variable "ssh_fingerprint" {}

provider "digitalocean" {
 token = "${var.do_token}"
}

保存して終了。 最初の4行の内訳は次のとおりです。

  • 変数「do_token」:DigitalOcean Personal Access Token

  • 変数「pub_key」:公開キーの場所。したがって、新しいドロップレットにインストールできます。

  • 変数「pvt_key」:秘密鍵の場所。Terraformは新しいドロップレットに接続できます

  • 変数「ssh_fingerprint」:SSHキーのフィンガープリント

次の行は、_do_token_変数に「トークン」を割り当てることにより、DigitalOceanアカウントの資格情報を指定します。 実行時に、これらの変数の値をTerraformに渡します。

DigitalOceanプロバイダーの公式Terraformドキュメントは、http://www.terraform.io/docs/providers/do/index.html [DigitalOcean Provider]にあります。

DigitalOceanリソース

各プロバイダーには独自の仕様があり、通常はそれぞれのサービスプロバイダーのAPIにマップされます。 DigitalOceanプロバイダーの場合、3種類のリソースを定義できます。

  • * digitalocean_domain *:DNSドメインエントリ

  • * digitalocean_droplet *:ドロップレット(つまり、 VPSまたはサーバー)

  • * digitalocean_record *:DNSレコード

Nginxサーバーを実行するドロップレットを作成することから始めましょう。

最初のNginxサーバーの説明

`+ www-1.tf +`という新しいTerraform構成ファイルを作成します。

vi www-1.tf

以下の行を挿入して、ドロップレットリソースを定義します。

resource "digitalocean_droplet" "www-1" {
   image = "ubuntu-14-04-x64"
   name = "www-1"
   region = "nyc2"
   size = "512mb"
   private_networking = true
   ssh_keys = [
     "${var.ssh_fingerprint}"
   ]

上記の構成では、最初の行は「www-1」という名前の_digitalocean_droplet_リソースを定義しています。 残りの行では、液滴の属性を指定します。この属性には、DigitalOcean APIからアクセスできます。 その他はすべて自明であるため、各行については説明しません。 また、Terraformは、パブリックIPアドレスやプライベートIPアドレスなど、ドロップレットに関するさまざまな情報を収集します。これらの情報は、構成内の他のリソースで使用できます。

Dropletリソースに必要な引数またはオプションの引数がわからない場合は、公式のTerraformドキュメントを参照してください:http://www.terraform.io/docs/providers/do/r/droplet.html[DigitalOcean Droplet Specification]。

ここで、TerraformがSSH経由でサーバーに接続するために使用できる「+ connection +」を設定します。 ファイルの最後に次の行を挿入します。

 connection {
     user = "root"
     type = "ssh"
     private_key = "${file(var.pvt_key)}"
     timeout = "2m"
 }

これらの行は、SSH経由で何かをプロビジョニングしたい場合にTerraformがサーバーに接続する方法を説明しています(秘密鍵変数の使用に注意してください)。

接続が設定されたので、「remote-exec」プロビジョニングツールを設定できます。 remote-execプロビジョニングツールを使用して、Nginxをインストールします。 それを行うには、構成に次の行を追加します。

 provisioner "remote-exec" {
   inline = [
     "export PATH=$PATH:/usr/bin",
     # install nginx
     "sudo apt-get update",
     "sudo apt-get -y install nginx"
   ]
 }
}

保存して終了。

_inline_配列の文字列は、_gin_をインストールするために_root_が実行するコマンドであることに注意してください。

Terraformを実行してNginxサーバーを作成する

現在、Terraform構成は単一のNginxサーバーを記述しています。 テストしてみましょう。

まず、プロジェクトのTerraformを初期化します。 これにより、構成ファイルが読み取られ、プロバイダーのプラグインがインストールされます。

terraform init

次の出力が表示されます。

OutputInitializing provider plugins...
- Checking for available provider plugins on https://releases.hashicorp.com...                                                           - Downloading plugin for provider "digitalocean" (0.1.2)...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.digitalocean: version = "~> 0.1"

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 plan +`コマンドを実行して、Terraformがあなたが説明したインフラストラクチャの構築を試みます(つまり、 実行計画を参照してください)。 以下にリストされているすべての変数の値を指定する必要があります。

terraform plan \
 -var "do_token=${DO_PAT}" \
 -var "pub_key=/.ssh/id_rsa.pub" \
 -var "pvt_key=/.ssh/id_rsa" \
 -var "ssh_fingerprint="

すべての変数が正しく設定されている場合、次の行を含む複数行の出力が表示されます。

Refreshing Terraform state prior to plan...
...
+ digitalocean_droplet.www-1
...

緑の `+ digitalocean_droplet.www-1 +`の行は、Terraformが「www-1」と呼ばれる新しいドロップレットリソースを作成し、その詳細がそれに続くことを意味します。 それがまさに私たちが望んでいることなので、計画を実行しましょう。 次の ` terraform apply +`コマンドを実行して、最新計画を実行します。 繰り返しますが、以下の変数のすべての値を指定します。

terraform apply \
 -var "do_token=${DO_PAT}" \
 -var "pub_key=/.ssh/id_rsa.pub" \
 -var "pvt_key=/.ssh/id_rsa" \
 -var "ssh_fingerprint="

次の行を含む出力が表示されるはずです(簡潔にするために省略されています)。

digitalocean_droplet.www-1: Creating...
...

digitalocean_droplet.www-1: Provisioning with 'remote-exec'...
digitalocean_droplet.www-1: Creation complete

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
...

この時点で、Terraformは「+ www-1 +」という新しいドロップレットを作成し、その上にNginxをインストールしました。 新しいDropletのパブリックIPアドレスにアクセスすると、Nginxのようこそ画面が表示されます。

2番目のNginxサーバーの説明

Nginxサーバーについて説明したので、2つ目のサーバーを追加するのは非常に簡単です。 元の設定ファイルをコピーして、dropletリソースの名前(およびホスト名)を置き換えてみましょう。

これを手動で行うか、「+ sed 」を使用して「 www-1 」のすべてのインスタンスを「 www-2 」に置き換えて(2つあり)、新しいファイルを作成します。 これを行うための ` sed +`コマンドは次のとおりです。

sed 's/www-1/www-2/g' www-1.tf > www-2.tf

これで、 `+ terraform plan `または ` terraform apply +`を再度実行すると、それぞれ新しい計画が表示または実行されます。 TerraformがNginxのドロップレットをもう1つ作成することは既にわかっているので、後で使用するために保存します。

ここでHAProxyドロップレットを設定しましょう。

HAProxyサーバーの説明

`+ haproxy-www.tf +`という新しいTerraform構成ファイルを作成します。

vi haproxy-www.tf

次の行を挿入して、新しい液滴を説明します。 最初の部分は、「haproxy-www」という名前が異なることを除いて、Nginxドロップレットの説明と同じです。

resource "digitalocean_droplet" "haproxy-www" {
   image = "ubuntu-16-04-x64"
   name = "haproxy-www"
   region = "nyc2"
   size = "512mb"
   private_networking = true
   ssh_keys = [
     "${var.ssh_fingerprint}"
   ]

次の接続情報を挿入します(Nginxドロップレットと同じ)。

 connection {
     user = "root"
     type = "ssh"
     private_key = "${file(var.pvt_key)}"
     timeout = "2m"
 }

接続が設定されたので、「remote-exec」プロビジョニングツールを設定できます。 remote-execプロビジョニングツールを使用して、HAProxyをインストールおよび構成します。 それを行うには、構成に次の行を追加します。

 provisioner "remote-exec" {
   inline = [
     "export PATH=$PATH:/usr/bin",
     # install haproxy 1.5
     "sudo add-apt-repository -y ppa:vbernat/haproxy-1.5",
     "sudo apt-get update",
     "sudo apt-get -y install haproxy",

     # download haproxy conf
     "sudo wget https://gist.githubusercontent.com/thisismitch/91815a582c27bd8aa44d/raw/8fc59b7cb88a2be9b802cd76288ca1c2ea957dd9/haproxy.cfg -O /etc/haproxy/haproxy.cfg",

     # replace ip address variables in haproxy conf to use droplet ip addresses
     "sudo sed -i 's/HAPROXY_PUBLIC_IP//g' /etc/haproxy/haproxy.cfg",
     "sudo sed -i 's/WWW_1_PRIVATE_IP//g' /etc/haproxy/haproxy.cfg",
     "sudo sed -i 's/WWW_2_PRIVATE_IP//g' /etc/haproxy/haproxy.cfg",

     # restart haproxy to load changes
     "sudo service haproxy restart"
   ]
 }
}

保存して終了。

繰り返しますが、_inline_配列の文字列は、HAProxyをインストールおよび構成するためにrootが実行するコマンドです。 HAProxyのインストール後、https://gist.githubusercontent.com/thisismitch/91815a582c27bd8aa44d/raw/8fc59b7cb88a2be9b802cd76288ca1c2ea957dd9/haproxy.cfg [sample haproxy.cfg file]がダウンロードされます。 この時点で、 `+ sed +`コマンドは、Terraform変数(上記の赤で強調表示)を使用して、HAProxy構成ファイル内の特定の文字列を各ドロップレットの適切なIPアドレスに置き換えます。プロビジョニングされます。 最後に、構成変更をロードするためにHAProxyが再起動されます。

より実用的なケースでは、Terraformシステムに独自の_haproxy.cfg_ファイルがあり、「file」プロビジョニング機能を使用してサーバーにコピーできます。

これでHAProxyサーバーについて説明しましたが、Terraformを実行してビルドする必要があります。

Terraformを実行してHAProxyサーバーを作成する

現在、Terraform構成には、2つのNginxサーバーとHAProxyサーバーが記述されています。 しましょう

新しい実行プランを表示するには、 `+ terraform plan +`コマンドを再度実行します。

terraform plan \
 -var "do_token=${DO_PAT}" \
 -var "pub_key=/.ssh/id_rsa.pub" \
 -var "pvt_key=/.ssh/id_rsa" \
 -var "ssh_fingerprint="

次の行を含む複数行の出力が表示されます。

...
digitalocean_droplet.www-1: Refreshing state... (ID: 2236747)
...
+ digitalocean_droplet.haproxy-www
...
+ digitalocean_droplet.www-2
...

これは、_www-1_ドロップレットがすでに存在し、Terraformが_haproxy-www_および_www-2_ドロップレットを作成することを意味します。 `+ terraform apply +`を実行して、残りのコンポーネントをビルドしましょう。

terraform apply \
 -var "do_token=${DO_PAT}" \
 -var "pub_key=/.ssh/id_rsa.pub" \
 -var "pvt_key=/.ssh/id_rsa" \
 -var "ssh_fingerprint="

次の行を含む出力が表示されるはずです(簡潔にするために省略されています)。

digitalocean_droplet.www-2: Creating...
...
digitalocean_droplet.www-2: Provisioning with 'remote-exec'...
digitalocean_droplet.www-2: Creation complete
...
digitalocean_droplet.haproxy-www: Creating...
...
digitalocean_droplet.haproxy-www: Provisioning with 'remote-exec'...
digitalocean_droplet.haproxy-www: Creation complete
...
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
...

この時点で、Terraformは新しいNginxサーバーとHAProxyサーバーを作成しました。 haproxy-wwwのパブリックIPアドレスにアクセスすると、Nginxのようこそ画面が表示されます(HAProxyは2つのNginxサーバーの負荷を分散しているため)。

*セットアップは完了です!*チュートリアルの残りの部分には、DNSドメインの構成に関する情報とTerraformでのリソースの記録、および他のTerraformコマンドの使用方法に関する情報が含まれています。

DNSドメインとレコードの作成

前述のように、TerraformはDNSドメインを作成し、ドメインを記録することもできます。 たとえば、ドメイン `+ example.com +`を新しく作成したHAProxyサーバーに向けたい場合、そのためのTerraform構成を作成できます。 *注:*独自の一意のドメイン名を使用しないと、この手順は失敗します(つまり、 「example.com」またはDigitalOcean DNSに既に存在する他のレコードを使用しないでください)

DNSを記述する新しいファイルを作成します。

vi

次のドメインリソースを挿入します。

# Create a new domain record
resource "digitalocean_domain" "default" {
  name = ""
  ip_address = "${digitalocean_droplet.haproxy-www.ipv4_address}"
}

それから、「。example.com」を「example.com」にポイントするCNAMEレコードを追加しましょう。

resource "digitalocean_record" "CNAME-www" {
 domain = "${digitalocean_domain.default.name}"
 type = "CNAME"
 name = "www"
 value = "@"
}

保存して終了。

DNSエントリを追加するには、他のリソースと同様に、「+ terraform plan 」に続いて「 terraform apply +」を実行します。

その他のTerraformコマンド

Terraformには、これまで説明しなかった他のコマンドがいくつかあるため、ここではそれらのほとんどについて説明します。

状態を表示

Terraformは、プランを実行するたびに状態ファイルを更新するか、状態を「更新」します。 Terraformの外部でインフラストラクチャを変更すると、状態ファイルが古くなることに注意してください。

環境の現在の状態を表示するには、次のコマンドを使用します。

terraform show terraform.tfstate

状態を更新

リソースがTerraformの外部で変更された場合、状態ファイルを更新して最新の状態にすることができます。 このコマンドは、プロバイダーから更新されたリソース情報を取得します。

terraform refresh \
 -var "do_token=${DO_PAT}" \
 -var "pub_key=/.ssh/id_rsa.pub" \
 -var "pvt_key=/.ssh/id_rsa" \
 -var "ssh_fingerprint="

インフラストラクチャを破壊する

生産環境では一般的に使用されませんが、Terraformは作成したインフラストラクチャを破壊することもあります。 これは主に、複数回構築および破棄される開発環境で役立ちます。 これは2段階のプロセスであり、以下で説明します。

[[1-create-an-execution-plan-to-destroy-the-infrastructure]]
===== 1. インフラストラクチャを破壊する実行計画を作成します。

terraform plan -destroy -out=terraform.tfplan \
 -var "do_token=${DO_PAT}" \
 -var "pub_key=/.ssh/id_rsa.pub" \
 -var "pvt_key=/.ssh/id_rsa" \
 -var "ssh_fingerprint="

Terraformは、インフラストラクチャ内のリソースを削除することを示す、赤でマークされ、マイナス記号が前に付いたリソースを含むプランを出力します。

[[2-apply-destroy]]
===== 2. 破棄を適用します。

terraform apply terraform.tfplan

破壊計画に示されているように、Terraformはリソースを破壊します。

結論

Terraformがどのように機能するかを理解したので、便利なサーバーインフラストラクチャを記述する構成ファイルを作成してください。 サンプルのセットアップは単純ですが、サーバーの展開を自動化することがいかに簡単かを示しています。 PuppetやChefなどの構成管理ツールを既に使用している場合は、Terraformのプロビジョナーでそれらを呼び出して、作成プロセスの一部としてサーバーを構成できます。

Terraformにはさらに多くの機能があり、他のプロバイダーと連携できます。 公式のhttp://www.terraform.io/docs/index.html[Terraform Documentation]をチェックして、Terraformを使用して独自のインフラストラクチャを改善する方法の詳細を確認してください。