導入
Terraformプロジェクトを適切に構成することは、それらの维持性と拡張性を日々の操作中に保証するために重要です。コードファイルを適切に組織するシステム的な方法は、デプロイメント中にスケーラブルであり、あなたとあなたのチームが使用できるようにするために必要です。
このチュートリアルでは、一般的な目的と Complexityに応じてTerraformプロジェクトを構成する方法を学びます。その後、Terraformのより一般的な機能を使用して、簡単な構造のプロジェクトを作成します:変数、ローカル、データソース、プロビジョニングャー。最後に、プロジェクトはDigitalOceanにUbuntu 20.04サーバー(Droplet)をデプロイし、Apache Webサーバーをインストールし、ドメインをWebサーバーにポイントすることができます。
前提条件
-
DigitalOceanのコントロールパネルから作成できるDigitalOceanの個人的なアクセストークン。デジタルオーシャンの製品文書How to Create a Personal Access Tokenにある指示に従ってください。
- パスワードを使用せずにデジタルオーシャンアカウントに追加されたSSHキー。これはデジタルオーシャンドロップルにSSHキーを使用する方法に従って作成することができます。
- あなたのローカルマシンにTerraformをインストールしていること。Operating Systemに基づいた指示については、Step 1 of the How To Use Terraform with DigitalOcean tutorialを参照してください。
-
ローカルマシンにインストールされたPython 3です。OSに対応するPython 3用のローカルプログラミング環境のインストールと設定方法のステップ1を完了することができます。
-
DigitalOceanアカウントに追加された完全登録済みドメイン名です。その方法については、公式ドキュメントを参照してください。
注: このチュートリアルはTerraform 1.0.2
で特にテストされています。
Terraformプロジェクトの構造の理解
この節では、Terraformが何を考えているか、 infrastructural コードを構成する方法を見ていきます。あなたはどの方針を選択していくべきかも知ります。さらに、Terraformの作業空間を知っておくと、それが何であるか、Terraformは何を保存していますか?
本节中,您将了解Terraform如何定义项目,如何组织基础设施代码,以及何时选择特定的方法。您还将学习Terraform的工作空间,它们的作用以及Terraform如何存储状态。
A resource is an entity of a cloud service (such as a DigitalOcean Droplet) declared in Terraform code that is created according to specified and inferred properties. Multiple resources form infrastructure with their mutual connections.
Terraform使用一种特殊的编程语言来定义基础设施,称为Hashicorp Configuration Language(HCL)。HCL代码通常存储在以.tf
结尾的文件中。Terraform项目是指任何包含.tf
文件的目录,并且已经使用init
命令进行了初始化,该命令设置Terraform缓存和默认本地状态。
Terraform state is the mechanism via which it keeps track of resources that are actually deployed in the cloud. State is stored in backends (on disk locally or in a cloud file storage service or specialized state management software) for optimal redundancy and reliability. You can read more about different backends in the Terraform documentation.
プロジェクトワークスペースを使用すると、同じバックエンド内に複数の状態を持ち、同じ構成に紐付けることができます。これにより、同じインフラストラクチャの複数の独立したインスタンスをデプロイすることができます。各プロジェクトは、default
という名前のワークスペースで始まります。これは、明示的に他のワークスペースを作成または選択しない限り使用されます。
モジュールは、他のプログラミング言語のライブラリと似た Terraform の構成要素で、複数のリソース宣言を含むパラメータ化されたコードコンテナです。これにより、インフラストラクチャの一般的な部分を抽象化し、異なる入力で後で再利用することができます。
Terraform プロジェクトは、動的データ入力に使用する外部コードファイルを含むこともできます。これは、CLIコマンドのJSON出力を解析し、リソース宣言に使用することができるように提供します。この教程では、Pythonスクリプトを使用してこれを行います。
Terraform プロジェクトに含まれる内容を理解したら、Terraform プロジェクト構成の2つの一般的な手法を見ていきましょう。
簡単な構造
シンプルな構造は、小さいと試験的なプロジェクトに適しており、様々な種類の少しのリソースと変数があります。一般的に、各リソースタイプに1つの設定ファイルを持っており(主に1つの主要な設定に helper ファイルが添付される)、カスタムモジュールはほとんどないことになります。多くのリソースはユニークで、一般化して再利用することができる量は十分でないからです。これに沿って、ほとんどのコードは同じディレクトリに保存され、お互いに近くに並んでいます。これらのプロジェクトには、APIキーなどのクラウドにアクセスするための変数のいくつかがあり、動的データ入力や他のTerraform、HCLの機能を使用する可能性がありますが、主要な機能ではありません。
この方法のファイル構造の例として、このチュートリアルで作成するプロジェクトの最後の形は以下のようになります。
.
└── tf/
├── versions.tf
├── variables.tf
├── provider.tf
├── droplets.tf
├── dns.tf
├── data-sources.tf
└── external/
└── name-generator.py
このプロジェクトでは、Apache Web Server Dropletをデプロイし、DNS記録を設定するために、プロジェクト変数の定義、DigitalOcean Terraformプロバイダ、Droplet、DNS記録の各々のファイルに保存されます。最小限のTerraformとDigitalOceanプロバイダのバージョンをversions.tf
に指定し、Dropletの名前を生成するPythonスクリプトをexternal
フォルダに保存し、HCLコードから離れておくためです。
複雑な構造
単純な構成とは対立していますが、この方法は大規模プロジェクトに適当です。明らかに定義されたサブディレクター strukturen 内に複数のモdule を含むことができ、それら module は複雑さ에 よって異なります。これら module は彼此依存です。この方法は複数のアプリケーションを管理する大規模プロジェクトに适当です。同じコードを最大限に再利用します。この方法は複数のアプリケーションを管理する大規模プロジェクトに適当です。同じコードを最大限に再利用します。
開発、ステージング、品質保证、および実生产環境インスタンスも同じプロジェクト内で不同のディRECTORY に置くことができ、共通の module を使うことで重複コードを eliminat し、PROJECT が全てのtruth となります。次の例では、複雑な構成であるプロジェクトのファイル構成を見てみましょう:
.
└── tf/
├── modules/
│ ├── network/
│ │ ├── main.tf
│ │ ├── dns.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ └── spaces/
│ ├── main.tf
│ ├── outputs.tf
│ └── variables.tf
└── applications/
├── backend-app/
│ ├── env/
│ │ ├── dev.tfvars
│ │ ├── staging.tfvars
│ │ ├── qa.tfvars
│ │ └── production.tfvars
│ └── main.tf
└── frontend-app/
├── env/
│ ├── dev.tfvars
│ ├── staging.tfvars
│ ├── qa.tfvars
│ └── production.tfvars
└── main.tf
このapproach はさらに詳しくはseries How to Manage Infrastructure with Terraform で探します。
あなたは现在でも、Terraform プロジェクトの仕様、如何に構成するか、および Terraform 工作空间の役割を知っています。次のスteps で、Droplet を作成し、Apache ウェブサーバーをinstall し、DNS 记录を設定します。最初に、DigitalOcean Provider と変数を initialize し、Droplets を definetion し、Dynamic datasource を provide して Droplet 名を指定し、DNS record を deploy します。
手順 1 — プロジェクトの初期設定
この節で、デジタルオーシャンのTerraformプロバイダーをプロジェクトに追加し、プロジェクト変数を定義し、デジタルオーシャンのプロバイダーインスタンスを宣言します。これにより、Terraformがあなたのアカウントに接続できるようになります。
最初に、以下のコマンドでTerraformプロジェクト用のディレクトリを作成します。
それに移動します。
このプロジェクトは簡単な構成を追跡するために、プロバイダー、変数、Droplet、およびDNSレコードコードを前節のファイル構造に従って別のファイルに格納します。まず、デジタルオーシャンのTerraformプロバイダーをプロジェクトに必要なプロバイダーとして追加する必要があります。
次に、名前がversions.tf
のファイルを作成し、以下のコマンドを実行して編集することで開きます。
以下の行を追加します。
このterraform
ブロックで、必要なプロバイダー(デジタルオーシャン、バージョン2.x
)をリストに追加します。完了した後、ファイルを保存し閉じます。
次に、variables.tf
ファイルにプロジェクトが露出する変数を定義します。ここでは、異なるリソースタイプを別のコードファイルに格納する方法に従っています。
以下の変数を追加します。
ファイルを保存し閉じます。
do_token
変数は、DigitalOceanの個人アクセストークンを保持し、domain_name
変数は、希望するドメイン名を指定します。デプロイされるDropletには、SSH指紋によって识別されるSSHキーが自動的にインストールされます。
次に、このプロジェクト用のDigitalOceanプロバイダのインスタンスを定義します。それをprovider.tf
という名前のファイルに保存します。編集用に作成して開けるために、以下のコマンドを実行します。
プロバイダを追加します。
完了したら、保存して終了してください。これは、先程provider.tf
に指定した必要なプロバイダに対応するdigitalocean
プロバイダを定義し、そのトークンを変数の値に設定しました。これは実行時に提供されます。
この段階で、プロジェクト用のディレクトリを作成し、DigitalOceanプロバイダを利用可能にしました。プロジェクト変数を宣言し、後で提供される認証トークンを使用して、DigitalOceanプロバイダのインスタンスに接続しました。今後、プロジェクト定義に使用する動的データを生成するスクリプトを書いていきます。
手順2 — 動的なデータ用のPythonスクリプトを作成
UNIX epoch formatで表される、ローカルマシンの現在の時間とweb
との結合によりDropletの名前が動的に生成されます。命名スクリプトは、名前のスキーマに従って複数のDropletを生成する際に、それぞれを簡単に区別するために有用です。
スクリプトをname-generator.py
という名前のファイルに、external
という名前のディレクトリに保存します。まず、以下のコマンドを実行してディレクトリを作成します。
external
ディレクトリは、プロジェクトのルートにあり、PythonスクリプトのようなHCL以外のコードファイルを格納します。
name-generator.py
をexternal
以下に作成し、編集用に開きます。
以下のコードを追加します。
このPythonスクリプトはjson
とtime
モジュールをインポートし、辞書としてresult
を宣言し、fixed_name
と、それを実行しているマシンの現在のUNIX時間を結合したインタープロライズされた文字列になるname
の値を設定します。その後、result
をJSONに変換し、stdout
に出力します。スクリプトを実行するたびに、出力は異なります。
完成したら、ファイルを保存して閉じてください。
注意:大きく、複雑な構造化されたプロジェクトは、外部データ源の作成と使用についてより深く考える必要があります。特に、移植性とエラー処理について。Terraformは、実行されたプログラムがstderr
に人間が読むことができるエラーメッセージを書き込み、非ゼロのステータスで gracefully exit することを期待しています。これはこのステップで示されていないことがありますが、タスクのシンプリシティーのためです。また、プログラムに副作用がないことを期待しています。これにより、必要な回数だけ再実行できます。
Terraformが期待するデータ源についての詳細な情報は、公式ドキュメントを参照してください。
スクリプトが準備されたら、データ源を定義することができます。これにより、スクリプトからデータを引き出すことができます。データ源を、プロジェクトのルートにあるdata-sources.tf
という名前のファイルに保存します。
編集用に次のコマンドで作成します。
以下の定義を追加します。
ファイルを保存して閉じます。
このデータ源はdroplet_name
と呼ばれ、external
ディレクトリに配置されているPython 3を使用してname-generator.py
スクリプトを実行します。その出力を自動的に解析し、デシリアライズされたデータをresult
属性に配置し、他のリソース定義の中で使用することができます。
データ源を宣言したら、Apacheが実行するDropletを定義することができます。
ステップ3 — ドロプレットの定義
このステップで、あなたはDropletリソースの定義を書き、簡単な構造化アプローチに従ってDroplets用のコードファイルに保存します。その名前は、刚刚作成した動的データ源から来て、デプロイされるたびに異なるでしょう。
編集用のdroplets.tf
ファイルを作成して開きます。
以下のDropletリソース定義を追加します。
まず、DigitalOcean SSHキーリソースをssh_key
という名前で宣言します。これは、名前を持ったキーをアカウントから取得します。ハイライトされたコードを自分のSSHキーの名前に置き換えてください。
次に、名前がweb
のDropletリソースを宣言します。クラウド上の実際の名前は異なるですが、名前を持ったdroplet_name
外部データ源から要求されるからです。DropletリソースをSSHキーでブートストラップするたびに、ssh_key
のIDをssh_keys
パラメーターに渡します。これにより、DigitalOceanは適用する必要のあるキーを知ります。
これだけでdroplet.tf
に関連した設定を完了しました。ですので、終了したらファイルを保存し閉じてください。
次に、刚刚宣言したDropletに指向するDNSレコードの設定を書いてください。
ステップ 4 — DNSレコードの定義
プロセスの最後のステップは、ドロップレットにあるあなたのドメインを指すDNSレコードを設定することです。
DNS設定をdns.tf
という名前のファイルに保存します。これは、前のステップで作成した他のリソースタイプとは異なるものです。このファイルを作成して編集します:
以下の行を追加します:
このコードは、変数を使用してあなたのドメイン名に対するDigitalOcean DNSレコードを宣言します。レコードの種類はA
です。レコードの名前は@
です。これはドメイン自身に対するプレースホルダー routing とし、Droplet IPアドレスをそのvalue
として設定します。name
の値を他のものに変更することができます。これはサブドメインの作成になります。
これらの設定が完了したら、ファイルを保存して閉じます。
Dropletを設定し、名前生成データ源、DNSレコードを設定した後、雲上でプロジェクトをデプロイする準備が整いました。
ステップ 5 — 設定の計画と適用
この节では、Terraformプロジェクトを初期化し、云にデployし、すべてが正しく provisioned されたか確認します。
今度はプロジェクトの基础设施は完全に定義されていますが、部署する前にはTerraformプロジェクトを初期化します。以下のコマンドを実行します:
実行後、次のような出力が得られます:
OutputInitializing the backend...
Initializing provider plugins...
- Finding digitalocean/digitalocean versions matching "~> 2.0"...
- Finding latest version of hashicorp/external...
- Installing digitalocean/digitalocean v2.10.1...
- Installed digitalocean/digitalocean v2.10.1 (signed by a HashiCorp partner, key ID F82037E524B9C0E8)
- Installing hashicorp/external v2.1.0...
- Installed hashicorp/external v2.1.0 (signed by HashiCorp)
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.
今度は部署する前には、プロジェクトを初期化します。以下のコマンドを运行します:
実行後、次のような出力が得られます:
次に、Dropletを Dynamically generated name と accompaning domain でDigitalOceanアカウントに deploy します。
先にDefinining the domain name, SSH key fingerprint, and your personal access token as environment variables, so you don’t have to copy the values each time you run Terraform. Run the following commands, replacing the highlighted values:
あなたのAPI tokenはDigitalOcean Control Panel에서見つけられます。
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:
次のコマンドを実行し、変数値を渡してください:
+ resource "digitalocean_droplet" "web" {
+ backups = false
+ created_at = (known after apply)
+ disk = (known after apply)
+ 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 = "web-1625908814"
+ 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)
}
実行後、次のような出力が得られます:
+ resource "digitalocean_record" "www" {
+ domain = "your_domain'"
+ fqdn = (known after apply)
+ id = (known after apply)
+ name = "@"
+ ttl = (known after apply)
+ type = "A"
+ value = (known after apply)
}
Plan: 2 to add, 0 to change, 0 to destroy.
...
绿色で+
形を持つ行は、それぞれのresourceをcreationすることを示しています—それらは正しくできることです。因みに、configurationをdeployするには、次のコマンドを実行します:
出力は前回と同じですが、今回はconfirmationを求められます:
OutputPlan: 2 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: `yes`
入力してください(例えばyes
)し、TerraformはDropletとDNS recordをprovisioningします。
Outputdigitalocean_droplet.web: Creating...
...
digitalocean_droplet.web: Creation complete after 33s [id=204432105]
digitalocean_record.www: Creating...
digitalocean_record.www: Creation complete after 1s [id=110657456]
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
Terraformは現在、 deploy した resource を state に記録しました。DNS 记录と Droplet が成功にconnect できたかを確認するには、次のコommand を実行して Droplet 的 IP address を取得します:
Droplet 的 IP address を得る:
Outputipv4_address = "your_Droplet_IP"
...
public DNS record を確認するには、以下のコommand を実行します:
出力は A record が指す IP address を示す:
OutputAddress: your_Droplet_IP
同じであり、如くなっています, 意味 Droplet と DNS record が provisioning 成功しました。
次のスtep の変更を反映させるには、deployed resource を破棄する必要があります。これを行うには、下述のコommand を実行します:
prompt に対して yes
を入力して続行します:
In this step, you have created your infrastructure and applied it to your DigitalOcean account. You’ll now modify it to automatically install the Apache web server on the provisioned Droplet using Terraform provisioners.
Step 6 — Running Code Using Provisioners
Now you’ll set up the installation of the Apache web server on your deployed Droplet by using the remote-exec
provisioner to execute custom commands.
Terraformのプロビューション器は、作成した远程資源に特定のアctionsを実行することができます(remote-exec
プロビューショナル)からも本地主机に実行させることができます(local-exec
プロビューショナル)。プロビューショナルが失敗した場合、現在の状態でnodeはtaintedとマARKED wird, das heißt, es wird bei der nächsten Runde gelöscht und wieder erstellt werden.
Terraformに Droplet への接続を行うには、Droplet 上に設定されたSSHキーの私钥が必要です。私钥の位置を渡す最好の方法は変数を使用することです, 因みにくいvariables.tf
を編集します:
新しい変数を追加します:
保存して閉じます。
次に、Droplets の構成ファイルを編集します。droplets.tf
を編集するために以下のコmmandを运行します:
次の行を高亮显示して追加:
connection
ブロックは、Terraform が目标 Droplet に接続する方法を指定します。provisioner
ブロックは、 provisioning 後に実行するコmmands を含むinline
パラメーターを宣言します。つまり、更新パッケージ管理器缓存とApacheの安装。保存して終了します。
私钥のPATHを临时的環境変数にも設定します:
注意: プライベートキーおよびTerraform内で読み取りたい他のファイルは、プロジェクト内に配置する必要があります。Ubuntu 20.04または他のディストリビューション上でSSHキーベースの認証を設定する方法についてのLinuxサーバー上でSSHキーベースの認証を設定する方法チュートリアルを参照してください。
再度設定を適用してみてください:
質問にyes
を入力してください。以前と同様の出力が表示されますが、それにremote-exec
プロビジョニングャーの長い出力が続きます:
Outputdigitalocean_droplet.web: Creating...
digitalocean_droplet.web: Still creating... [10s elapsed]
digitalocean_droplet.web: Still creating... [20s elapsed]
digitalocean_droplet.web: Still creating... [30s elapsed]
digitalocean_droplet.web: Provisioning with 'remote-exec'...
digitalocean_droplet.web (remote-exec): Connecting to remote host via SSH...
digitalocean_droplet.web (remote-exec): Host: ...
digitalocean_droplet.web (remote-exec): User: root
digitalocean_droplet.web (remote-exec): Password: false
digitalocean_droplet.web (remote-exec): Private key: true
digitalocean_droplet.web (remote-exec): Certificate: false
digitalocean_droplet.web (remote-exec): SSH Agent: false
digitalocean_droplet.web (remote-exec): Checking Host Key: false
digitalocean_droplet.web (remote-exec): Connected!
...
digitalocean_droplet.web: Creation complete after 1m5s [id=204442200]
digitalocean_record.www: Creating...
digitalocean_record.www: Creation complete after 1s [id=110666268]
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
現在、Webブラウザーであなたのドメインにアクセスすることができます。デフォルトのApacheウェルカムページが表示されます。
これは、Apacheが正常にインストールされ、Terraformがすべてのものを正しくプロビジョニングしたことを意味します。
デプロイされたリソースを破棄するには、以下のコマンドを実行し、質問にyes
を入力してください:
これで、Droplet上にApacheウェブサーバーをデプロイし、必要なドメインのDNS記録を設定する簡単な構造のTerraformプロジェクトを完了しました。
結論
複雑さに応じてTerraformプロジェクトを構成する2つの一般的な方法を学びました。簡単な構成方法を遵循し、remote-exec
プロビジョニングャーを使用してコマンドの実行を行い、Apacheを実行するDropletをデプロイし、ドメイン用のDNSレコードを設定しました。
参照のために、このチュートリアルで作成したプロジェクトのファイル構造は以下の通りです。
.
└── tf/
├── versions.tf
├── variables.tf
├── provider.tf
├── droplets.tf
├── dns.tf
├── data-sources.tf
└── external/
└── name-generator.py
定義したリソース(Droplet、DNSレコードと動的データソース、DigitalOceanプロバイダと変数)は、このチュートリアルの第1節で説明された簡単なプロジェクト構造に基づいて、それぞれ独自のファイルに格納されています。
Terraformプロビジョニングャーとそのパラメーターについての詳細な情報は、公式ドキュメントを参照してください。
このチュートリアルは、Terraformを使用したインフラ管理シリーズの一部です。このシリーズは、Terraformの様々なトピックをカバーしています。内容は、Terraformの最初のインストールから複雑なプロジェクトの管理までにわたります。
Source:
https://www.digitalocean.com/community/tutorials/how-to-structure-a-terraform-project