terraform.tfstateがなぜかS3にアップできなかった記録
terraform.tfstateの管理方法は色々ありますがよく使われるs3に保存する方法でエラーが出て解消した記録です。
エラー
initしたら以下のエラーが出ました。
% terraform init
Initializing the backend...
╷
│ Error: Error loading state:
│ AccessDenied: Access Denied
│ status code: 403, request id: xxxxxxxxxxxxxxxxxx, host id: xxxxxxxxxxxxxxxxxx
│
│ Terraform failed to load the default state from the "s3" backend.
│ State migration cannot occur unless the state can be loaded. Backend
│ modification and state migration has been aborted. The state in both the
│ source and the destination remain unmodified. Please resolve the
│ above error and try again.
解決方法
terraform workspaceを設定したらデプロイできました。
tfファイル|エラー解消後
以下はエラーを解消し反映できた時のtfファイルです。
resource "aws_instance" "sandbox" {
ami = "ami-0ca38c7440de1749a"
instance_type = "t2.micro"
subnet_id = aws_subnet.public_subnet.id
}
resource "aws_vpc" "vpc" {
cidr_block = "10.0.0.0/16"
instance_tenancy = "default"
}
resource "aws_subnet" "public_subnet" {
vpc_id = aws_vpc.vpc.id
cidr_block = "10.0.16.0/20"
availability_zone = "ap-northeast-1a"
}
terraform {
backend "s3" {
bucket = "bucketname"
key = "testprofile/terraform.tfstate"
region = "ap-northeast-1"
shared_credentials_file = "$HOME/.aws/credentials"
profile = "profilename"
}
required_providers {
aws = ">= 2.43.0"
}
}
provider "aws" {
profile = "${terraform.workspace}"
region = "ap-northeast-1"
}
前提
ローカルPC1台で複数のAWSアカウント、terraformプロジェクトを運用、今回はテスト的な動作確認をしていたという状況でした。
原因
terraformブロックで指定するbackendはterraform workspaceと紐づいていて、workspaceを設定しないとdefaultのworkspaceを参照するためにエラーが発生していた。
調査経緯
調査しているとS3に権限を与える。IAMに権限を与えるという記事によく当たりました。これは403エラーなので当然と言えばそうでしたが、今回は同様の環境を以前作った経験があり、そちらを確認することができたので今回との差分、設定の違いを見ていったところS3とIAMには違いがありませんでした。
そこで閃いたのが複数のAWSアカウントをローカルPCが持っている(.aws/credentials)に複数のユーザーが登録してあるということでした。
結果としてIAMとS3に特別な追加ポリシーを設定する必要はなく余分な権限の付与をせずに解決できました。
またterraform.tfstateをS3にアップロードする前にEC2の起動には成功しているという事実もあったのでS3、IAMに権限を与えるという部分も慎重に調査したのが良かったと感じています。
tfファイル|エラー発生時
tfファイルは以下のようなとてもシンプルなものです。
provider "aws" {
profile = "awscredentials"
region = "ap-northeast-1"
}
resource "aws_instance" "sandbox" {
ami = "ami-0ca38c7440de1749a"
instance_type = "t2.micro"
subnet_id = aws_subnet.public_subnet.id
}
resource "aws_vpc" "vpc" {
cidr_block = "10.0.0.0/16"
instance_tenancy = "default"
}
resource "aws_subnet" "public_subnet" {
vpc_id = aws_vpc.vpc.id
cidr_block = "10.0.16.0/20"
availability_zone = "ap-northeast-1a"
}
terraform {
backend "s3" {
bucket = "BUCKETNAME"
key = "testproject/terraform.tfstate"
region = "ap-northeast-1"
}
}
この設定ではprofileでaws/credentials設定を読み込んでおり、指定したAWSアカウントにてEC2を起動することに成功しています。
所感
terraform自体久々に触って忘れていた部分もあったと思います。providerのprofileで指定しただけの状態とterraform workspaceを設定した状態で差分があることが体験できました。「providerのprofileでAWSアカウントを指定できる」「terraform workspaceとterraformブロックで指定するbackend(tfstateの保存方法)が紐づいている」という部分は正直理解がふわっとしていましたが今回理解が深まりました。
Discussion