すべてのプロダクト
Search
ドキュメントセンター

Terraform:既存のクラウドリソースの管理に関する問題の解決策

最終更新日:Jan 17, 2025

このトピックでは、Terraform を使用して既存のクラウドリソースの管理に関する問題を解決する方法について説明します。

背景情報

このトピックは、以下の O&M シナリオに適用されます。

  • シナリオ 1:Terraform を初めて使用しますが、Web コンソール、Alibaba Cloud CLI、ROS、または API を使用してリソースを作成および管理しています。

  • シナリオ 2:Terraform を使用してリソースを管理しています。リソースのプロパティが変更された場合、リソースの状態は変更されないままにする必要があります。

  • シナリオ 3:すべてのリソースがテンプレートで定義されています。既存のテンプレートを再構築または分割する場合、リソースの増加はテンプレートまたはリソースの状態の管理に支障をきたしません。

  • シナリオ 4:最新のプロバイダーからの新しいパラメーターを元のドキュメントと同期する必要があります。

Terraform は、リソーステンプレート定義を使用して新しいリソースを作成、変更、および削除できるだけでなく、単純なコマンドを使用して Terraform 管理システム外のリソースをインポートおよび管理し、一元管理を行うこともできます。

既存のリソースのインポート

Terraform で既存のリソースをインポートするには、次の操作を実行できます。

  1. リソース ID を取得します。

    ID に基づいてリソースをクエリし、そのプロパティを取得します。

  2. テンプレートでインポートするリソースを宣言します。

    Terraform はテンプレート駆動型方式を使用します。インポートするリソースをテンプレートで宣言する必要があります。

  3. リソーステンプレート定義を完了します。

    リソースをインポートした後、リソースのプロパティに基づいて、テンプレートで宣言されたリソース定義を完了します。

  1. リソース ID を取得します。

    Web コンソール、Alibaba Cloud CLI、API などの方法を使用してリソース ID を取得できます。最も簡単な方法は、Terraform データソースを介して単純なクエリ条件を入力することです。次の例は、SLB インスタンスの ID を取得する方法を示しています。

    data "alicloud_slbs" "default" {
      name_regex  = "for-demo*"
    }
    output "slb_ids" {
      value = data.alicloud_slbs.default.ids
    }

    terraform apply コマンドを実行して、すべての対象 SLB インスタンスの ID を表示します。

    $ terraform apply
    data.alicloud_slbs.default: Refreshing state...
    
    Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
    
    Outputs:
    
    slb_ids = [
      "lb-gw8vinrqxxxxxxxxxxx",
      "lb-gw8axostxxxxxxxxxxx",
    ]
  2. テンプレートでインポートするリソースを宣言します。

    リソースの作成と同様に、リソースをインポートする前に、テンプレートでリソースを宣言して、状態のリソースの格納パスを指定する必要があります。次の例は、SLB インスタンスを宣言しています。

    resource "alicloud_slb" "this" {}

    単純な宣言の後、特定のパラメーターを定義せずにリソースをインポートできます。Terraform では、import コマンドを実行してリソースをインポートできます。完全なコマンド形式は Terraform import <リソースタイプ>.<リソース名> <リソース ID> です。

    $ terraform import alicloud_slb.this lb-gw8vinrqxxxxxxxxxxx
    alicloud_slb.this: Importing from ID "lb-gw8vinrqxxxxxxxxxxx"...
    alicloud_slb.this: Import prepared!
      Prepared alicloud_slb for import
    alicloud_slb.this: Refreshing state... [id=lb-gw8vinrqxxxxxxxxxxx]
    
    Import successful!
    
    The resources that were imported are shown above. These resources are now in
    your Terraform state and will henceforth be managed by Terraform.
  3. リソーステンプレート定義を完了します。

    テンプレートには、インポートされたリソースの完全な定義が含まれていないため、テンプレートの内容は、リソースのインポート後に状態に格納されている内容とは異なります。 plan コマンドを実行すると、更新が表示されます。

    $ terraform plan
    Refreshing Terraform state in-memory prior to plan...
    The refreshed state will be used to calculate this plan, but will not be
    persisted to local or remote state storage.
    
    data.alicloud_slbs.default: Refreshing state...
    alicloud_slb.this: Refreshing state... [id=lb-gw8vinrqxxxxxxxxxxx]
    
    ------------------------------------------------------------------------
    
    An execution plan has been generated and is shown below.
    Resource actions are indicated with the following symbols:
      ~ update in-place
    
    Terraform will perform the following actions:
    
      # alicloud_slb.this will be updated in-place
      ~ resource "alicloud_slb" "this" {
            address              = "47.254.181.122"
            ...
          ~ delete_protection    = "on" -> "off"
            id                   = "id=lb-gw8vinrqxxxxxxxxxxx"
            ...
          ~ name                 = "for_demo-test" -> "tf-lb-20191108144235105700000001"
            ...
        }
    
    Plan: 0 to add, 1 to change, 0 to destroy.
    
    ------------------------------------------------------------------------
    
    Note: You didn't specify an "-out" parameter to save this plan, so Terraform
    can't guarantee that exactly these actions will be performed if
    "terraform apply" is subsequently run.

    テンプレートをリソースの状態と一致させるには、plan コマンドを実行したときに更新が表示されなくなるまで、テンプレートに不足しているパラメーター定義を手動で追加する必要があります。

    resource "alicloud_slb" "this" {
      delete_protection = "on"
      name              = "for_demo-test"
    }

    更新の原因となっているフィールドを追加する必要があります。パラメーター定義を完了した後、plan コマンドを実行して結果を確認します。

    $ terraform plan
    Refreshing Terraform state in-memory prior to plan...
    The refreshed state will be used to calculate this plan, but will not be
    persisted to local or remote state storage.
    
    data.alicloud_slbs.default: Refreshing state...
    alicloud_slb.this: Refreshing state... [id=lb-gw8vinrqtqx1ro1r94c96]
    
    ------------------------------------------------------------------------
    
    No changes. Infrastructure is up-to-date.
    
    This means that Terraform did not detect any differences between your
    configuration and real physical resources that exist. As a result, no
    actions need to be performed.

    上記の情報は、それ以上の変更は必要なく、リソースのインポートプロセスが完了したことを示しています。

既存のリソースの削除

実際には、誤ったリソースがインポートされる、リソースが誤ったパスにインポートされる、リソースパスを変更する必要がある、または一部のリソースを永続的に保持する必要があるなどの問題が発生する可能性があります。これらの問題に対する簡単な解決策は、インポートされたリソースを状態から削除してから再度インポートすることです。

state rm コマンドを実行してリソースを削除できます。完全なコマンド形式は terraform state rm <リソースタイプ>.<リソース名> です。

$ terraform state rm alicloud_slb.this
Removed alicloud_slb.this
Successfully removed 1 resource instance(s).

state rm コマンドは、指定されたリソースを状態ファイルから削除するだけで、削除しません。したがって、リソースを再度インポートできます。

まとめ

上記の 4 つのシナリオに対処するには、次の解決策を使用できます。

  • シナリオ 1 の解決策:

    terraform import コマンドを実行して、Terraform で一元管理するために既存のリソースをインポートします。

  • シナリオ 2 の解決策:

    パラメータープロパティの値を決定する必要があります。テンプレートの値を使用する場合は、apply コマンドを実行してから値を変更する必要があります。Web コンソールの値を使用する場合は、テンプレートに値を追加または変更する必要があります。

  • シナリオ 3 の解決策:

    terraform state rm コマンドを実行して、状態から再構築されるすべてのリソースを削除します。次に、terraform import コマンドを実行してリソースをインポートします。

  • シナリオ 4 の解決策:

    シナリオ 3 の解決策と同様に、リソースを削除してからインポートします。

Terraform は単純なコマンドを提供します。 terraform import コマンドは、テンプレートと状態の内容が一致している必要があるという原則に基づいて、既存のリソースを一元管理するために使用できます。リソースが Terraform 管理システム外にあるかどうか、またはリソースが状態から削除されているかどうかを心配する必要はありません。