--- lang: ja-jp tags: Terraform --- # Terraform Import ## Overview [Terraform: Import](https://www.terraform.io/docs/import/index.html) Terraformは既存のインフラストラクチャをインポート可能です。この機能により、その他の方法で作成されたリソースを受け取り、Terraformによる管理へと移行することができます。 この機能は、Terraformによるインフラストラクチャの管理へとゆっくりと段階的に移行する優れた手段となります。現時点ではTerraformがサポートしていないリソースの管理を、将来的に(サポートされた後に)統合することが実現できます。 ### Currently State Only (2020年4月時点で)Terraform Importの機能では`tfstate`にリソースをインポートする機能のみが実装されています。設定ファイルを自動生成する機能は未実装です。しかし、将来的にはそのような機能がサポートされる予定です。 この制約により、`terraform import`コマンドを実行することに先立って、既に利用しているリソースについての`resource`のブロックの設定を宣言する必要が出てきます。宣言されたリソースについて、既存のリソースが紐づくことになります。 この対応は退屈で冗長な作業である一方で、既存のリソースをインポートする唯一の方法ともなっています。将来的なTerraformのバージョンではこの対応は自動化され、移管作業全体を大変シンプルなものにするでしょう。 ## Import Usage [Terraform: Import > Import Usage](https://www.terraform.io/docs/import/usage.html) 既存のインフラストラクチャをインポートするには、`terraform import`コマンドを使用します。 このコマンドは(現時点では)**一度に一つのリソースのみをインポートできます**。言い換えれば、Terraform Import機能で(AWS VPCといった)リソースの集合全体を一度にインポートすることができないということです。 リソースをインポートするには、まず`resource`ブロックをTerraform設定ファイルに記述し、Terraformがリソースを管理するための名称を与えなければなりません。 ```hcl= % resource "aws_instance" "example" { # ... instance configuration ... } ``` "example"という名称は設定ファイルの記述者がそのリソース設定を宣言したモジュールのスコープについてローカルなものです。これはリモートのシステムにより発行されたいかなる識別子に対しても区別されるものであり、リソースの名称は定数的である一方で時間の経過とともに更新されうるものことを想定するものです。 `resource`のブロックを記述せずに、インスタンスがインポートされたあとにそれらを記述することも可能です。 ```shell= % terraform import aws_instance.example i-abcd1234 ``` このコマンドはまず`i-abcd1234`という識別子のAWSインスタンスを見つけ出し、次に既に反映されている設定を(EC2 APIに記載されるとおりに)モジュールの`aws_instance.example`という名称のリソースに紐付けます。この具体例では、モジュールパスがルートであることを示唆しています。最後に、Terraformのステートファイル`tfstate`にその内容を反映させます。 子モジュールにリソースをインポートすることも可能です。その際にはモジュールへのパスを利用し、`count`または`for_each`の集合にリソースを紐付けます。[Terraform: Resource Addressing](https://www.terraform.io/docs/internals/resource-addressing.html)を参考に、対象リソースを指定する方法について学びます。 与えられる識別子のシンタックスはインポートされるリソースの種類に依存しません。例えば、AWSインスタンスはEC2 APIから発行される「不透明な」(訳注:秘匿されている)識別子を利用している一方で、AWS Route53 Zonesでは自身のドメイン名そのものが識別子となります。インポート可能なリソースの個々のドキュメントを参照して、`terraform import`コマンドを実行する際に利用するリソースの識別子の形式を調べてください。 このコマンドを実行した結果として、対象のリソースはステートファイルに記録されます。`terraform plan`コマンドを実行し、インポートされたリソースに対する設定とこれから記述する設定の差分を確認し、実現されるべき状態へとリソースの詳細を記述します。 ### Complex Imports これまでに紹介したTerraform Import機能は比較的"simple"なものです。一つのリソースがステートファイルにインポートされます。複数のリソースがインポートされるような"complex"なインポートが必要となる場合もあります。例えば、AWSセキュリティグループのインポートでは`aws_security_group`をインポートしますが、各ルールについて`aws_security_group_rule`のインポートも包含します。 このようなシナリオでは、副次的なリソースは設定ファイルには現れないため、インポート結果を精査し、それら副次的なものについてそれぞれ`resource`ブロックを作成する必要があります。この操作が行われなかった場合には、Terraformは次回の実行時にインポートされたリソースを破壊してしまいます。 インポートしたリソースの名称を変更したり、移動させたりしたい場合には、[Terraform: state management commands](https://www.terraform.io/docs/commands/state/index.html)が有用です。 ## Resource Importability [Terraform: Import > Resource Importability](https://www.terraform.io/docs/import/importability.html) Terraformにおける各リソースは、インポート可能にするためになんらかの基本的なロジックを実装する必要があります。そのため、現時点ではインポート可能なリソースには制限があります。インポート機能がサポートされるリソースについては、インポート方法の詳細が各リソースのドキュメントの最下部の"Import"セクションに記載されています。インポートしたいもののTerraformが未対応のリソースについては、関連するプロバイダのリポジトリにイシューを投げてください。 リソースをインポート可能にする方法は比較的シンプルなものです。もしこのインポート機能の発展に貢献することに意欲がある場合には、Terraformチームはあなたの手助けを歓迎します。 開発の詳細については、[Terraform: plugin documentation on writing a resource](https://www.terraform.io/docs/import/importability.html)を参考にしてください。