Terraformで「Could not load plugin」エラーが起きた

2022.06.20

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

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 initterraform 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.