0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

remote state를 사용하지 않고 GitHub Actions에서만 terraform apply실행

0
Last updated at Posted at 2026-05-13

Terraform + GitHub Actions + ECSデプロイ自動化でハマったことまとめ

個人プロジェクトでTerraformとGitHub Actionsを初めて一緒に使うと、よくやりがちなミスがあります。
それが、remote stateを使わずに、GitHub Actions上だけで terraform apply を実行してしまうことです。

自分も今回、ECSのデプロイ環境を構築する中で、まさに同じ問題に遭遇しました。

最初の構成はかなりシンプルでした。

  • GitHub ActionsでDockerイメージをビルド
  • ECRへpush
  • terraform apply でECSへの反映

デプロイ自体は問題なく動いていました。
本当の問題は、その後インフラを整理しようとして terraform destroy を実行したときに始まりました。

最初は普通に動く

GitHub Actionsのworkflowは、おおよそ次のような構成でした。

- name: Terraform Apply
  working-directory: ./infra
  run: |
    terraform init
    terraform apply -auto-approve \
      -var="container_image=$IMAGE_URI"

そして、Terraformのbackend設定は特にしていませんでした。

つまり、Terraform stateはデフォルトのローカル terraform.tfstate ファイルで管理されていたということです。

ここに大きな落とし穴がありました。

GitHub Actionsのrunnerは、実行されるたびに新しい一時的なVM環境で動作します。

つまり、実際には次のような流れになります。

workflow開始
→ terraform apply実行
→ terraform.tfstate作成
→ runner終了
→ terraform.tfstate削除

デプロイは成功します。
しかし、stateファイルはworkflowの実行が終わると一緒に消えてしまいます。

当時は単純に考えていました。

「AWS上にはリソースが作られているんだから、あとでdestroyすれば消せるだろう」

しかし、Terraformはそういう仕組みではありませんでした。

Terraform destroyはコードだけを見て削除するわけではない

よく誤解しがちな点ですが、terraform destroy は次のような処理ではありません。

コードに書かれているリソース名を探して削除する

Terraformはstateを基準にインフラを管理します。

例えば、次のようなコードがあるとします。

resource "aws_ecs_cluster" "main" {
  name = "teamspace-cluster"
}

Terraformが実際に管理しているのは、次のような対応関係です。

aws_ecs_cluster.main
→ 実際のAWS resource ID

このマッピング情報は、すべてstateファイルの中に保存されます。

問題は、GitHub Actionsのrunnerが終了したタイミングで、そのstateも一緒に消えていたことでした。

destroy時に遭遇した問題

1. container_image variable の問題

最初に destroy を実行したとき、次のようなエラーが出ました。

No value for required variable

terraform destroy も内部的にはplanを作成するため、variableの値が必要になります。

そのため、最終的には次のようにdummy値を渡す必要がありました。

terraform destroy -var="container_image=dummy"

削除するだけなのにDockerイメージURIを要求されるのは、なかなか不思議な状況でした。


2. Cloudflare provider の認証問題

次に、Cloudflare providerでエラーが発生しました。

must provide exactly one of "api_key", "api_token"

GitHub Actions上ではsecret経由で問題なく動いていた値でしたが、ローカル環境にはその環境変数が存在していませんでした。

最終的に、provider設定を直接修正しました。

provider "cloudflare" {
  api_token = var.cloudflare_api_token
}

そして、destroy 実行時にvariableとして直接渡しました。

terraform destroy \
  -var="cloudflare_api_token=..."

3. AWS provider のcredential問題

その次は、AWS providerの問題でした。

No valid credential sources found

少しややこしかったのは、AWS CLI自体は正常に動作していたことです。

aws sts get-caller-identity

このコマンドも問題なく実行できていました。

しかし、Terraform providerはまた別のcredential chainを使います。
Windows CMD、PowerShell、GitHub Actions、Terraform Cloud、AWS SDKの環境がそれぞれ微妙に違うため、credential周りがだんだん混乱していきました。

最終的にTerraformがEC2 metadata endpointまで見に行こうとしているのを見たときは、少し力が抜けました。

169.254.169.254

ローカルPCで実行しているのに、EC2 IAM Roleを探しに行っていたわけです。

結局、根本原因はstateだった

いろいろな問題に遭遇しましたが、結局のところ根本原因は一つでした。

Terraform stateがなければ、
terraform destroyはほとんど意味を持たない

Terraformはコードだけを見て、既存リソースを削除するわけではありません。

stateが存在しない場合、Terraformは次のように認識します。

管理中のリソース = 0

つまり、実際のAWS上には次のようなリソースが残っていても、

  • ECS cluster
  • ECR repository
  • Cloudflare record

Terraformから見ると、それらは「知らないリソース」になってしまいます。

stateを失ったあとの選択肢

最終的に取れる選択肢は、大きく分けて2つでした。

1. importを行う

Terraform stateに、既存リソースを再登録する必要があります。

terraform import aws_ecs_cluster.main teamspace-cluster

これをすべてのリソースに対して繰り返す必要があります。

実際にやろうとすると、思った以上に手間のかかる作業でした。


2. コンソールから直接削除する

個人プロジェクト規模であれば、AWSコンソールやCloudflareの画面から直接削除したほうが早い場合もあります。

最終的に感じたこと

Terraformを使うなら、remote stateは事実上必須だと感じました。

これは個人プロジェクトでも同じです。

少なくとも、次のどちらかは使うべきだと思います。

Terraform Cloud

terraform {
  cloud {
    organization = "my-org"

    workspaces {
      name = "teamspace"
    }
  }
}

メリットは次のとおりです。

  • stateを自動で管理できる
  • remote executionに対応している
  • variableを管理できる
  • GitHub Actionsと連携しやすい

S3 Backend

terraform {
  backend "s3" {
    bucket = "terraform-state"
    key    = "prod/terraform.tfstate"
    region = "ap-northeast-2"
  }
}

AWS環境内でstate管理を完結させることができます。

今回の経験から学んだこと

Terraformは単なる「インフラ作成ツール」というよりも、次のようなものに近いと感じました。

stateをもとにインフラを追跡するツール

そしてstateを失った瞬間、Terraformは既存のインフラをまったく認識できなくなります。

その状態で destroy を実行しても、
苦労するのは人間だけで、リソースはそのまま残ります。

今回の経験を通して、個人プロジェクトであってもremote stateを必ず構成すべき理由をはっきり実感しました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?