web-dev-qa-db-ja.com

手動変更をTerraformリモート状態にインポートする方法

私はterraformを初めて使用します-s3でリモートtfstateを作成しましたが、AWSインフラストラクチャで行われる手動の変更もいくつかあります。これらの手動変更をtfstateにインポートする必要があります。

一部のリソースにimportコマンドを使用しましたが、IAMポリシーなどの一部のリソースには、そのようなimportコマンドがありません。

また、DBなどの一部のリソースは、新しいパラメーターが追加されて変更されているため、それらもインポートする必要があります。これらの変更をインポートしようとすると、次のように表示されます。

Error importing: 1 error(s) occurred:

* Can't import aws_security_group.Q8SgProdAdminSshInt, would collide
  with an existing resource.

Please remove or rename this resource before continuing.

どんな助けでもいただければ幸いです。ありがとう。

この質問に直接答える前に、いくつかのコンテキストが役立つと思います。

舞台裏では、Terraformは、構成内のリソースから基盤となるプロバイダーAPI内のオブジェクトへのマッピングを含む状態ファイルを維持します。 Terraformを使用して新しいオブジェクトを作成すると、作成されたオブジェクトのIDが自動的に状態に保存されるため、今後のコマンドで参照されたオブジェクトを検索して、読み取り、更新、および削除操作を行うことができます。

したがって、terraform importは、状態ファイルにエントリを作成する別の方法です。新しいオブジェクトを作成してそのIDを記録するのではなく、ユーザーはコマンドラインでIDを指定します。 Terraformは、そのIDを持つオブジェクトを読み取り、結果を状態ファイルに追加します。その後、Terraformが自分で作成したリソースと状態を区別できなくなります。

以上のことを踏まえて、質問を1つずつ解決していきましょう。


terraform importをサポートしていないリソースのインポート

各リソースはインポートを実行するために少量の検証とデータフェッチコードを必要とするため、現時点ではすべてのリソースがインポートでサポートされているわけではありません。

上記からterraform importが何をするかについて私たちが知っていることを考えると、理論的には提供されたIDのTerraformの検証をスキップし、代わりに手動でリソースを状態に追加することができます。 これは高度な操作であり、状態が破損しないように注意して実行する必要があります

まず、ローカル作業に使用するローカルファイルに状態を取得します。

terraform state pull >manual-import.tfstate

これにより、テキストエディタで開くことができるファイルmanual-import.tfstateが作成されます。 JSON構文を使用しているため、内部構造は安定した形式として文書化されていませんが、期待される構造との一貫性が保たれている限り、慎重に編集できます。

インポート、複製、編集する場所と同じモジュール内にある既存のリソースを見つけるのが最も簡単です。次のようなresourcesオブジェクトがあると仮定しましょう。

"resources": {
    "null_resource.foo": {
        "type": "null_resource",
        "depends_on": [],
        "primary": {
            "id": "5897853859325638329",
            "attributes": {
                "id": "5897853859325638329"
            },
            "meta": {},
            "tainted": false
        },
        "deposed": [],
        "provider": ""
    }
},

このresourcesオブジェクト内の各属性は、構成内のリソースに対応します。属性名は、リソースのタイプと名前です。この場合、リソースタイプはnull_resourceであり、属性名はfooです。あなたの場合、ここにaws_instance.serverのようなものが表示されるかもしれません。

id属性は、多くのリソース(すべてではありません!)にとって、入力する必要がある主なものです。したがって、架空のIAMポリシーに対してこの構造を複製できます。

"resources": {
    "null_resource.foo": {
        "type": "null_resource",
        "depends_on": [],
        "primary": {
            "id": "5897853859325638329",
            "attributes": {
                "id": "5897853859325638329"
            },
            "meta": {},
            "tainted": false
        },
        "deposed": [],
        "provider": ""
    },
    "aws_iam_policy.example": {
        "type": "aws_iam_policy",
        "depends_on": [],
        "primary": {
            "id": "?????",
            "attributes": {
                "id": "?????"
            },
            "meta": {},
            "tainted": false
        },
        "deposed": [],
        "provider": ""
    }
},

このステップでの課題は、このリソースに必要なIDの種類を把握することです。これを知る唯一の確実な方法は コードを読む です。これは、このリソースがIDがポリシーの完全なARNであることを期待していることを示しています。

その知識を使用して、上記の例の2つの?????シーケンスを、インポートするポリシーのARNに置き換えます。

状態を手動で変更した後、ファイルの最上位にあるserial番号を更新する必要があります。 Terraformは、新しい変更にはシリアル番号が大きくなることを想定しているため、この番号を増やすことができます。

更新が完了したら、更新された状態ファイルをTerraformにアップロードし直す必要があります。

terraform state Push manual-import.tfstate

最後に、Terraformに状態を更新して、動作することを確認するように依頼できます。

terraform refresh

繰り返しになりますが、状態ファイルは基盤となるシステムとの関係のTerraformの記録であり、このファイルの内容が失われた場合に回復するのが難しいため、これはかなり危険なプロセスです。多くの場合、リソースがインフラストラクチャですでに重要な役割を果たしており、適切な移行戦略が利用できない場合を除いて、このすべての作業に進むよりも、リソースを単純に置き換える方が簡単です。

既存のリソースと衝突するインポート

あなたの質問で与えられたエラーメッセージは、既存のリソースとのインポートの「衝突」について話している:

Error importing: 1 error(s) occurred:

* Can't import aws_security_group.Q8SgProdAdminSshInt, would collide with an existing resource.

Please remove or rename this resource before continuing.

このメッセージの意味は、Terraformが新しいリソースを状態ファイルに書き込もうとしたときに、aws_security_group.Q8SgProdAdminSshIntという名前のリソースエントリがすでに存在していることを検出したことです。これは、それがすでにインポートされているか、Terraform自体によって新しいセキュリティグループがすでに作成されていることを示しています。

次の状態の既存のリソースの属性を調べることができます。

terraform state show aws_security_group.Q8SgProdAdminSshInt

返されたデータを、インポートしようとしたセキュリティグループと比較します。 IDが一致する場合、リソースはすでにインポートされているため、何もする必要はありません。

IDが一致しない場合は、2つのオブジェクトのどちらを保持するかを判断する必要があります。 Terraformにすでにあるものを保持したい場合は、インポートしようとしていたものを手動で削除できます。

代わりにインポートしようとしていたものを保持したい場合は、不要なものをTerraform状態から削除して、インポートが成功するようにすることができます。

terraform state rm aws_security_group.Q8SgProdAdminSshInt

これにより、Terraformがリソースを「忘れる」ことに注意してください。 EC2には引き続き存在するため、コンソール、コマンドラインツール、またはAPIを使用して手動で削除する必要があります。削除する前に必ずidを書き留めて、クリーンアップするために見つけられるようにしてください。

32
Martin Atkins

リソースについては、インポート機能を使用するか、ブロックのようなテラフォーム状態を手動で追加する必要があります。

または、dB構成について述べたように構成に変更があった場合、dBリソースがterraformリモート状態によって管理されている場合。terraform refresh が手伝う..

0
Shubham Bansal