Terraform の萜ずし穎

Terraform の萜ずし穎
ルヌプ、if ステヌトメント、デプロむメント手法に関連する萜ずし穎や、Terraform 党般に圱響を䞎えるより䞀般的な問題など、いく぀かの萜ずし穎に焊点を圓おおみたしょう。

  • count パラメヌタず for_each パラメヌタには制限がありたす。
  • ダりンタむムれロの導入を制限する。
  • たずえ良い蚈画であっおも倱敗する可胜性はありたす。
  • リファクタリングには萜ずし穎がある可胜性がありたす。
  • 遅延された䞀貫性は、遅延ず䞀臎したす。

count および for_each パラメヌタには制限がありたす

この章の䟋では、ルヌプず条件ロゞックで count パラメヌタヌず for_each 匏を広範囲に䜿甚しおいたす。 パフォヌマンスは良奜ですが、泚意しなければならない重芁な制限が XNUMX ぀ありたす。

  • Count ず for_each はリ゜ヌス出力倉数を参照できたせん。
  • count ず for_each はモゞュヌル構成では䜿甚できたせん。

count ず for_each はリ゜ヌス出力倉数を参照できたせん

耇数の EC2 サヌバヌをデプロむする必芁があるが、䜕らかの理由で ASG を䜿甚したくないず想像しおください。 コヌドは次のようになりたす。

resource "aws_instance" "example_1" {
   count             = 3
   ami                = "ami-0c55b159cbfafe1f0"
   instance_type = "t2.micro"
}

䞀぀ず぀芋おいきたしょう。

count パラメヌタは静的な倀に蚭定されおいるため、このコヌドは問題なく動䜜したす。apply コマンドを実行するず、2 ぀の EC2 サヌバヌが䜜成されたす。 しかし、珟圚の AWS リヌゞョン内の各アベむラビリティヌゟヌン (AZ) に XNUMX ぀のサヌバヌをデプロむしたい堎合はどうすればよいでしょうか? コヌドで aws_availability_zones デヌタ ゜ヌスからゟヌンのリストをロヌドし、各ゟヌンをルヌプし、count パラメヌタヌず配列むンデックス アクセスを䜿甚しおその䞭に ECXNUMX サヌバヌを䜜成できたす。

resource "aws_instance" "example_2" {
   count                   = length(data.aws_availability_zones.all.names)
   availability_zone   = data.aws_availability_zones.all.names[count.index]
   ami                     = "ami-0c55b159cbfafe1f0"
   instance_type       = "t2.micro"
}

data "aws_availability_zones" "all" {}

count パラメヌタヌは問題なくデヌタ ゜ヌスを参照できるため、このコヌドも正垞に機胜したす。 しかし、䜜成する必芁があるサヌバヌの数がリ゜ヌスの出力に䟝存する堎合はどうなるでしょうか? これを瀺す最も簡単な方法は、random_integer リ゜ヌスを䜿甚するこずです。これは、名前が瀺すように、ランダムな敎数を返したす。

resource "random_integer" "num_instances" {
  min = 1
  max = 3
}

このコヌドは 1 から 3 たでの乱数を生成したす。このリ゜ヌスの出力を aws_instance リ゜ヌスの count パラメヌタヌで䜿甚しようずするずどうなるかを芋おみたしょう。

resource "aws_instance" "example_3" {
   count             = random_integer.num_instances.result
   ami                = "ami-0c55b159cbfafe1f0"
   instance_type = "t2.micro"
}

このコヌドで terraform plan を実行するず、次の゚ラヌが発生したす。

Error: Invalid count argument

   on main.tf line 30, in resource "aws_instance" "example_3":
   30: count = random_integer.num_instances.result

The "count" value depends on resource attributes that cannot be determined until apply, so Terraform cannot predict how many instances will be created. To work around this, use the -target argument to first apply only the resources that the count depends on.

Terraform では、リ゜ヌスが䜜成たたは倉曎される前の蚈画段階で count ず for_each を蚈算する必芁がありたす。 これは、count ず for_each はリテラル、倉数、デヌタ ゜ヌス、さらにはリ゜ヌス リスト (スケゞュヌル時に長さを決定できる限り) を参照できるが、蚈算されたリ゜ヌス出力倉数は参照できないこずを意味したす。

count ず for_each はモゞュヌル構成では䜿甚できたせん

い぀か、モゞュヌル構成に count パラメヌタヌを远加したくなるかもしれたせん。

module "count_example" {
     source = "../../../../modules/services/webserver-cluster"

     count = 3

     cluster_name = "terraform-up-and-running-example"
     server_port = 8080
     instance_type = "t2.micro"
}

このコヌドは、モゞュヌル内で count を䜿甚しお、webserver-cluster リ゜ヌスのコピヌを 0 ぀䜜成しようずしたす。 たたは、count パラメヌタヌを XNUMX に蚭定しお、ブヌル条件に基づいおモゞュヌルの接続をオプションにするこずもできたす。これは合理的なコヌドのように芋えるかもしれたせんが、terraform plan を実行するず次の゚ラヌが発生したす。

Error: Reserved argument name in module block

   on main.tf line 13, in module "count_example":
   13: count = 3

The name "count" is reserved for use in a future version of Terraform.

残念ながら、Terraform 0.12.6 の時点では、モゞュヌル リ゜ヌスでの count たたは for_each の䜿甚はサポヌトされおいたせん。 Terraform 0.12 リリヌス ノヌト (http://bit.ly/3257bv4) によるず、HashiCorp は将来この機胜を远加する予定であるため、この本を読んだ時期によっおは、すでに利甚可胜になっおいる可胜性がありたす。 確実に調べるには、 ここでTerraformの倉曎ログを読んでください.

れロダりンタむム展開の制限事項

create_before_destroy ブロックを ASG ず組み合わせお䜿甚​​するこずは、ダりンタむムをれロにデプロむするための優れた゜リュヌションです。ただし、自動スケヌリング ルヌルはサポヌトされおいないずいう XNUMX ぀の泚意点がありたす。 より正確に蚀えば、これにより、デプロむごずに ASG サむズが min_size にリセットされたす。これは、自動スケヌリング ルヌルを䜿甚しお実行䞭のサヌバヌの数を増やしおいる堎合に問題になる可胜性がありたす。

たずえば、webserver-cluster モゞュヌルには aws_autoscaling_schedule リ゜ヌスのペアが含たれおおり、午前 9 時にクラスタヌ内のサヌバヌの数が 11 台から 9 台に増加したす。 たずえば午前 XNUMX 時にデプロむするず、新しい ASG は XNUMX 台ではなく XNUMX 台のサヌバヌで起動し、翌日の午前 XNUMX 時たでそのたたの状態になりたす。

この制限はいく぀かの方法で回避できたす。

  • aws_autoscaling_schedule の繰り返しパラメヌタを 0 9 * * * (「午前 9 時に実行」) から 0-59 9-17 * * * (「午前 9 時から午埌 5 時たで毎分実行」) のような倀に倉曎したす。 ASG にすでに XNUMX 台のサヌバヌがある堎合、この自動スケヌリング ルヌルを再床実行しおも䜕も倉曎されたせん。これが望たしいこずです。 ただし、ASG が最近デプロむされたばかりの堎合、このルヌルにより、最倧 XNUMX 分以内にサヌバヌの数が XNUMX に達するこずが保蚌されたす。 これは完党に゚レガントなアプロヌチではなく、XNUMX 台のサヌバヌから XNUMX 台のサヌバヌぞの倧幅な倉曎やその逆もナヌザヌに問題を匕き起こす可胜性がありたす。
  • AWS API を䜿甚しお ASG 内のアクティブなサヌバヌの数を決定するカスタム スクリプトを䜜成し、倖郚デヌタ ゜ヌスを䜿甚しおそれを呌び出し (249 ペヌゞの「倖郚デヌタ ゜ヌス」を参照)、ASG のdesired_capacity パラメヌタを、によっお返される倀に蚭定したす。スクリプト。 こうするこずで、新しい ASG むンスタンスは垞に既存の Terraform コヌドず同じ容量で実行されるため、保守がより困難になりたす。

もちろん、Terraform にはダりンタむムなしのデプロむメントのサポヌトが組み蟌たれおいるこずが理想的ですが、2019 幎 XNUMX 月の時点で、HashiCorp チヌムにはこの機胜を远加する蚈画はありたせんでした (詳现 - ここ).

正しい蚈画が実行されない可胜性がある

plan コマンドは完党に正しいデプロむメント プランを生成しおも、apply コマンドが゚ラヌを返す堎合がありたす。 たずえば、第 2 章で䜜成した IAM ナヌザヌに䜿甚したのず同じ名前で aws_iam_user リ゜ヌスを远加しおみたす。

resource "aws_iam_user" "existing_user" {
   # ППЎставьте сюЎа ОЌя уже существующегП пПльзПвателя IAM,
   # чтПбы пПпрактОкПваться в ОспПльзПваМОО кПЌаМЎы terraform import
   name = "yevgeniy.brikman"
}

ここで plan コマンドを実行するず、Terraform は䞀芋劥圓なデプロむメント プランを出力したす。

Terraform will perform the following actions:

   # aws_iam_user.existing_user will be created
   + resource "aws_iam_user" "existing_user" {
         + arn                  = (known after apply)
         + force_destroy   = false
         + id                    = (known after apply)
         + name               = "yevgeniy.brikman"
         + path                 = "/"
         + unique_id         = (known after apply)
      }

Plan: 1 to add, 0 to change, 0 to destroy.

apply コマンドを実行するず、次の゚ラヌが衚瀺されたす。

Error: Error creating IAM User yevgeniy.brikman: EntityAlreadyExists:
User with name yevgeniy.brikman already exists.

   on main.tf line 10, in resource "aws_iam_user" "existing_user":
   10: resource "aws_iam_user" "existing_user" {

もちろん、問題は、その名前の IAM ナヌザヌがすでに存圚しおいるこずです。 そしお、これは IAM ナヌザヌだけでなく、ほがすべおのリ゜ヌスで発生する可胜性がありたす。 誰かがこのリ゜ヌスを手動たたはコマンド ラむンを䜿甚しお䜜成した可胜性がありたすが、いずれにせよ、ID が䞀臎するず競合が発生したす。 この゚ラヌにはさたざたなバリ゚ヌションがあり、Terraform を初めお䜿甚する人を驚かせるこずがよくありたす。

重芁な点は、terraform plan コマンドは、Terraform 状態ファむルで指定されおいるリ゜ヌスのみを考慮するずいうこずです。 リ゜ヌスが他の方法 (たずえば、AWS コン゜ヌル内で手動でクリックするなど) で䜜成された堎合、リ゜ヌスは状態ファむルに保存されないため、Terraform は plan コマンドを実行するずきにそれらを考慮したせん。 その結果、䞀芋正しいように芋える蚈画が倱敗に終わるこずもありたす。

このこずから孊べるこずが XNUMX ぀ありたす。

  • すでに Terraform の䜿甚を開始しおいる堎合は、他のものを䜿甚しないでください。 むンフラストラクチャの䞀郚が Terraform を䜿甚しお管理されおいる堎合、手動で倉曎するこずはできなくなりたす。 そうしないず、Terraform で奇劙な゚ラヌが発生する危険があるだけでなく、コヌドがむンフラストラクチャを正確に衚珟できなくなるため、IaC の利点の倚くが無効になりたす。
  • すでにむンフラストラクチャがある堎合は、import コマンドを䜿甚したす。 既存のむンフラストラクチャで Terraform の䜿甚を開始する堎合は、terraform import コマンドを䜿甚しお状態ファむルに远加できたす。 このようにしお、Terraform はどのむンフラストラクチャを管理する必芁があるかを認識したす。 import コマンドは 2 ぀の匕数を取りたす。 190 ぀目は、構成ファむル内のリ゜ヌス アドレスです。 ここでの構文はリ゜ヌス リンクの堎合ず同じです: _。 (aws_iam_user.existing_user など)。 22 番目の匕数は、むンポヌトするリ゜ヌスの ID です。 リ゜ヌス ID aws_iam_user がナヌザヌ名 (yevgeniy.brikman など)、リ゜ヌス ID aws_instance が EC5 サヌバヌ ID (i-XNUMXeXNUMXeXNUMX など) であるずしたす。 リ゜ヌスのむンポヌト方法は通垞、ペヌゞの䞋郚にあるドキュメントに瀺されおいたす。

    以䞋は、第 2 章で Terraform 構成に远加した aws_iam_user リ゜ヌスず IAM ナヌザヌを同期するむンポヌト コマンドです (もちろん、yevgeniy.brikman は自分の名前に眮き換えおください)。

    $ terraform import aws_iam_user.existing_user yevgeniy.brikman

    Terraform は AWS API を呌び出しお IAM ナヌザヌを怜玢し、そのナヌザヌず Terraform 蚭定内の aws_iam_user.existing_user リ゜ヌスずの間に状態ファむルの関連付けを䜜成したす。 今埌、plan コマンドを実行するず、Terraform は IAM ナヌザヌがすでに存圚するこずを認識し、再床䜜成しようずしなくなりたす。

    Terraform にむンポヌトしたいリ゜ヌスがすでにたくさんある堎合、コヌドを手動で蚘述しお䞀床に 4 ぀ず぀むンポヌトするのは面倒な堎合があるこずに泚意しおください。 したがっお、AWS アカりントからコヌドず状態を自動的にむンポヌトできる Terraforming (http://terraforming.dtanXNUMX.net/) のようなツヌルを怜蚎する䟡倀がありたす。

    リファクタリングには萜ずし穎がある可胜性がある

    リファクタリング これは、倖郚の動䜜を倉曎せずに、コヌドの内郚構造を倉曎するプログラミングの䞀般的な手法です。 これは、コヌドをより明確、敎然ずし、保守しやすくするためです。 リファクタリングは定期的に䜿甚する必芁のある䞍可欠なテクニックです。 しかし、Terraform やその他の IaC ツヌルに関しおは、コヌド郚分の「倖郚動䜜」が䜕を意味するかに぀いお现心の泚意を払う必芁があり、そうしないず、予期しない問題が発生したす。

    たずえば、䞀般的なタむプのリファクタリングは、倉数たたは関数の名前をよりわかりやすい名前に眮き換えるこずです。 倚くの IDE にはリファクタリングのサポヌトが組み蟌たれおおり、プロゞェクト党䜓で倉数や関数の名前を自動的に倉曎できたす。 汎甚プログラミング蚀語では、これは考えもしないような些现な手順ですが、Terraform ではこれに现心の泚意を払う必芁があり、そうしないず機胜停止が発生する可胜性がありたす。

    たずえば、webserver-cluster モゞュヌルには入力倉数 cluster_name がありたす。

    variable "cluster_name" {
       description = "The name to use for all the cluster resources"
       type          = string
    }

    このモゞュヌルを䜿甚しお foo ずいうマむクロサヌビスをデプロむし始めたず想像しおください。 埌で、サヌビスの名前を bar に倉曎したいずしたす。 この倉曎は些现なこずのように思えるかもしれたせんが、実際にはサヌビスの䞭断を匕き起こす可胜性がありたす。

    実際には、webserver-cluster モゞュヌルは、XNUMX ぀のセキュリティ グルヌプず ALB の name パラメヌタヌを含む、いく぀かのリ゜ヌスでクラスタヌ名倉数を䜿甚したす。

    resource "aws_lb" "example" {
       name                    = var.cluster_name
       load_balancer_type = "application"
       subnets = data.aws_subnet_ids.default.ids
       security_groups      = [aws_security_group.alb.id]
    }

    リ゜ヌスの name パラメヌタヌを倉曎するず、Terraform はそのリ゜ヌスの叀いバヌゞョンを削陀し、代わりに新しいバヌゞョンを䜜成したす。 ただし、そのリ゜ヌスが ALB である堎合、そのリ゜ヌスを削陀しおから新しいバヌゞョンをダりンロヌドするたでの間に、トラフィックを Web サヌバヌにリダむレクトするメカニズムがありたせん。 同様に、セキュリティ グルヌプが削陀されるず、サヌバヌは新しいグルヌプが䜜成されるたでネットワヌク トラフィックを拒吊し始めたす。

    興味があるかもしれない別のタむプのリファクタリングは、Terraform ID の倉曎です。 䟋ずしお、webserver-cluster モゞュヌルの aws_security_group リ゜ヌスを芋おみたしょう。

    resource "aws_security_group" "instance" {
      # (...)
    }

    このリ゜ヌスの識別子をむンスタンスず呌びたす。 リファクタリング䞭に、よりわかりやすい (あなたの意芋では) 名前「cluster_instance」に倉曎するこずにしたず想像しおください。

    resource "aws_security_group" "cluster_instance" {
       # (...)
    }

    結局䜕が起こるのでしょうか そうです、混乱です。

    Terraform は、各リ゜ヌス ID をクラりド プロバむダヌ ID に関連付けたす。 たずえば、iam_user は AWS IAM ナヌザヌ ID に関連付けられ、aws_instance は AWS EC2 サヌバヌ ID に関連付けられたす。 リ゜ヌス ID を倉曎するず (aws_security_group の堎合のように、むンスタンスからクラスタヌむンスタンスに)、Terraform に倉曎するず、叀いリ゜ヌスを削陀しお新しいリ゜ヌスを远加したかのように衚瀺されたす。 これらの倉曎を適甚するず、Terraform は叀いセキュリティ グルヌプを削陀しお新しいセキュリティ グルヌプを䜜成し、サヌバヌはネットワヌク トラフィックを拒吊し始めたす。

    この議論から埗られる重芁な教蚓を XNUMX ぀挙げたす。

    • 垞に plan コマンドを䜿甚しおください。 これらすべおの障害を明らかにするこずができたす。 出力を泚意深く確認し、Terraform が削陀すべきでないリ゜ヌスの削陀を蚈画しおいる状況に泚意しおください。
    • 削陀する前に䜜成しおください。 リ゜ヌスを眮き換える堎合は、元のリ゜ヌスを削陀する前に、代替リ゜ヌスを䜜成する必芁があるかどうかを慎重に怜蚎しおください。 答えが「はい」の堎合は、create_before_destroy が圹に立ちたす。 同じ結果は、XNUMX ぀の手順を実行するこずによっお手動で実珟できたす。たず、新しいリ゜ヌスを構成に远加しお apply コマンドを実行し、次に叀いリ゜ヌスを構成から削陀しお、apply コマンドを再床䜿甚したす。
    • 識別子を倉曎するには、状態を倉曎する必芁がありたす。 リ゜ヌスを削陀しお新しいバヌゞョンを䜜成せずに、リ゜ヌスに関連付けられた ID を倉曎する (たずえば、aws_security_group の名前をむンスタンスからクラスタヌむンスタンスに倉曎する) 堎合は、それに応じお Terraform 状態ファむルを曎新する必芁がありたす。 これは決しお手動で行わないでください。代わりに terraform state コマンドを䜿甚しおください。 識別子の名前を倉曎する堎合は、次の構文を持぀ terraform state mv コマンドを実行する必芁がありたす。
      terraform state mv <ORIGINAL_REFERENCE> <NEW_REFERENCE>

      ORIGINAL_REFERENCE は珟圚の圢匏でリ゜ヌスを参照する匏で、NEW_REFERENCE は移動先の堎所です。 たずえば、aws_security_group グルヌプの名前をinstanceからcluster_instanceに倉曎する堎合は、次のコマンドを実行する必芁がありたす。

      $ terraform state mv 
         aws_security_group.instance 
         aws_security_group.cluster_instance

      これにより、以前に aws_security_group.instance に関連付けられおいた状態が、今埌は aws_security_group.cluster_instance に関連付けられる必芁があるこずが Terraform に䌝えられたす。 名前を倉曎しおこのコマンドを実行した埌、terraform plan に䜕も倉曎が衚瀺されない堎合は、すべおが正しく行われたこずになりたす。

    • 䞀郚の蚭定は倉曎できたせん。 倚くのリ゜ヌスのパラメヌタは倉曎できたせん。 それらを倉曎しようずするず、Terraform は叀いリ゜ヌスを削陀し、代わりに新しいリ゜ヌスを䜜成したす。 通垞、各リ゜ヌス ペヌゞには、特定の蚭定を倉曎したずきに䜕が起こるかが瀺されおいるため、必ずドキュメントを確認しおください。 垞に plan コマンドを䜿甚し、create_before_destroy 戊略の䜿甚を怜蚎しおください。

    遅延された䞀貫性は䞀貫性がありたす...遅延あり

    AWS などの䞀郚のクラりド プロバむダヌの API は非同期であり、䞀貫性が遅延しおいたす。 非同期ずは、芁求されたアクションが完了するのを埅たずに、むンタヌフェむスがすぐに応答を返すこずができるこずを意味したす。 遅延䞀貫性ずは、倉曎がシステム党䜓に反映されるたでに時間がかかる可胜性があるこずを意味したす。 この凊理が行われおいる間、応答は䞀貫性がなく、どのデヌタ ゜ヌス レプリカが API 呌び出しに応答しおいるかに䟝存する可胜性がありたす。

    たずえば、AWS に察しお EC2 サヌバヌの䜜成を芁求する API 呌び出しを行うず想像しおください。 API は、サヌバヌ自䜓が䜜成されるのを埅たずに、ほが即座に「成功」​​応答 (201 Created) を返したす。 すぐに接続しようずするず、その時点では AWS がただリ゜ヌスを初期化䞭であるか、サヌバヌがただ起動しおいないため、ほが確実に倱敗したす。 さらに、このサヌバヌに関する情報を取埗するために別の呌び出しを行うず、゚ラヌ (404 Not Found) が発生する可胜性がありたす。 問題は、この EC2 サヌバヌに関する情報がどこでも利甚できるようになるたでに、AWS 党䜓に䌝播される可胜性があり、数秒埅぀必芁があるずいうこずです。

    遅延敎合性を備えた非同期 API を䜿甚する堎合は、アクションが完了しおシステム党䜓に䌝播されるたで、定期的にリク゚ストを再詊行する必芁がありたす。 残念ながら、AWS SDK にはこれに適したツヌルが提䟛されおおらず、Terraform プロゞェクトは 6813 (https://github.com/bashicorp/terraform/issues/6813) のような倚くのバグに悩たされおいたした。

    $ terraform apply
    aws_subnet.private-persistence.2: InvalidSubnetID.NotFound:
    The subnet ID 'subnet-xxxxxxx' does not exist

    ぀たり、リ゜ヌス (サブネットなど) を䜜成し、それに関する情報 (新しく䜜成されたサブネットの ID など) を取埗しようずしたしたが、Terraform はそれを芋぀けるこずができたせん。 これらのバグ (6813 を含む) のほずんどは修正されおいたすが、特に Terraform が新しいリ゜ヌス タむプのサポヌトを远加した堎合には、䟝然ずしお時折発生したす。 これは面倒ですが、ほずんどの堎合、害はありたせん。 terraform apply を再床実行するず、この時点で情報がすでにシステム党䜓に広がっおいるため、すべおが機胜するはずです。

    この抜粋ぱフゲニヌ・ブリクマンの本からのものです 「Terraform: コヌドレベルのむンフラストラクチャ」.

出所 habr.com

コメントを远加したす