Terraformで「Could not load plugin」エラーが起きた
Terraformを使っている際に、以下のようなCould not load plugin
エラーに遭遇しました。
Error: Could not load plugin Plugin reinitialization required. Please run "terraform init". Plugins are external binaries that Terraform uses to access and manipulate resources. The configuration provided requires plugins which can't be located, don't satisfy the version constraints, or are otherwise incompatible. Terraform automatically discovers provider requirements from your configuration, including providers used in child modules. To see the requirements and constraints, run "terraform providers". Failed to instantiate provider "registry.terraform.io/hashicorp/random" to obtain schema: there is no package for registry.terraform.io/hashicorp/random 3.3.1 cached in .terraform/providers
どうやらRandom Providerが関係しているようですね。
状況
このエラーが発生したのは、EKS公開モジュールをアップグレードした後のterraform plan
です。v14.0.0からv17.24.0にアップグレードしました。
module "eks" { source = "terraform-aws-modules/eks/aws" - version = "14.0.0" + version = "17.24.0" (他inputs割愛) }
ローカルから実行した際にはエラーが起こらなかったのですが、CDパイプラインのCodeBuildにてterraform init
してterraform plan
すると上記エラーが発生しました。
調査
ローカルでも一度.terraform
ディレクトリを削除して、 terraform init
とterraform plan
をやってみました。CodeBuild上の状況に近づけようとしたわけです。するとローカルでもエラーを再現することができました。
また、前述のeks moduleは、もともと使っていたv14.0.0ではrandom providerを使用していましたが、アップグレード先のv17.24.0では使用していないことが判明しました。
原因
つまり、改修後のコードではterraform init
にrandom providerがダウンロードされないからエラーになっている、ということのようです。v14.0.0のeks moduleではrequired_providers
にrandom providerの記述があるのですが、v17.24.0には無いのでダウンロードされなかったわけです。
.terraform.lock.hcl
ファイルには依然random providerの定義があったのでダウンロードされるものだと思っていのですが勘違いでした。.terraform.lock.hcl
はあくまでtfファイル上で定義されたproviderのversion constraintsから導出され使用実績のあるバージョンを記録しているだけで、どのproviderをダウンロードすべきかはtfファイルのコード上で定義されるものです。
また、「アップグレード後のeks module(v17.24.0)はrandom providerを使用していないんだから、random providerがダウンロードされないのは問題ないのでは?」とも思いましたが、これも単なる理解不足でした。現状アップグレード前のv14.0.0でプロビジョニングしたリソース群があり、その中には当然random provider下のリソースもあります。terraform plan
でこのリソースの現状を取得する際にrandom providerが必要であり、さらにいうと最後にこのリソースを削除する際にも必要です。
対応方法
結局ルートモジュール内でrandom providerへの依存関係を定義しました。
terraform { (他attirubtes割愛) required_providers { (他のproviderの定義割愛) + random = { + version = "3.3.1" + } } }
ちなみにこうするとTFLintがしっかりWarning: provider 'random' is declared in required_providers but not used by the module (terraform_unused_required_providers)
と警告してくれたので、この警告を無視するコメントも足しましたw
terraform { (他attirubtes割愛) required_providers { (他のproviderの定義割愛) + # tflint-ignore: terraform_unused_required_providers random = { version = "3.3.1" } } }
このコードでeks moduleのアップグレードを完了した後、あらためてrequired_providers
からrandom providerを削除しました。また、.terraform.lock.hcl
に残っていたrandom providerの定義も併せて削除しました。
この.terraform.lock.hcl
内の定義の削除は今回手動で行ないました。が、Terraform v1.1以降では、required_providers
からproviderの記述を削除した後terraform init
をすると自動で削除してくれるそうです。(今回のバージョンは0.14.9でした。)
Note: In Terraform v1.0 and earlier, terraform init does not automatically remove now-unneeded providers from the lock file, and instead just ignores them. If you removed a provider dependency while using an earlier version of Terraform and then upgraded to Terraform v1.1 or later then you may see the error "missing or corrupted provider plugins", referring to the stale lock file entries. If so, run terraform init with the new Terraform version to tidy those unneeded entries and then retry the previous operation.