25/05/2023 - AWS, TERRAFORM
Terraform yerel olarak Terraform ile çalışırken, durumunu .terraform.tfstate
dosyasında saklamak için varsayılan yerel arka ucu kullanır. Durum dosyası, gizli bilgileri açığa çıkarabileceği için sürüm kontrol sisteminde kaydedilmemelidir. Bazı Terraform komutları çalıştığında, bu dosya değiştirilir. Bu nedenle, sistemdeki değişiklikler mühendislere derhal sunulmalıdır. Ancak durum dosyası yerel olarak yönetiliyorsa bu mümkün değildir. Bu sorunların üstesinden gelmek için, durum dosyasını depolamak için AWS S3'ü ve kilitleme bilgileri için DynamoDB'yi kullanacağız. Kilitleme mekanizması, aynı anda değiştirildiğinde durum dosyasının bozulmasını önlemek için önemli bir özelliktir. Terraform, durumu aynı anda birden fazla kullanıcı tarafından yazılmasını önlemek için bir durum kilidi edinir.
Bu adımları AWS konsolunda manuel olarak gerçekleştirmelisiniz, ancak şimdilik bunu halletmek için Terraform'u kullanacağım. Bu arada, kullanıcı/grubunuz en fazla iam:*, ec2:*, s3:*, dynamodb:*
izinlerine ihtiyaç duyar, ancak en az ayrıcalıklı izinleri kullanmayı tercih edin.
├── dynamodb.tf
├── local.tf
├── main.tf
└── s3.tf
locals {
terraform_state_bucket_name = "inanzzz-development-terraform"
terraform_state_bucket_key = "terraform.tfstate"
terraform_state_dynamodb_table = "terraform_tfstate"
}
terraform {
required_version = "~> 1.4.4"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.30.0"
}
}
}
provider "aws" {
profile = "development"
region = "eu-west-1"
}
resource "aws_s3_bucket" "terraform_state" {
bucket = local.terraform_state_bucket_name
force_destroy = true
}
resource "aws_s3_bucket_versioning" "versioning_example" {
bucket = aws_s3_bucket.terraform_state.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket_public_access_block" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
resource "aws_dynamodb_table" "terraform_state" {
name = local.terraform_state_dynamodb_table
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}
terraform init
ve terraform apply
komutlarını çalıştırın. Bu, AWS konsolunda S3 kovası ve DynamoDB tablosu oluşturacaktır. Yerel ortamda .terraform
klasörü ile birlikte .terraform.lock.hcl
ve .terraform.tfstate
dosyaları oluşturulacaktır.
├── group.tf
└── main.tf
terraform {
required_version = "~> 1.4.4"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.30.0"
}
}
}
provider "aws" {
profile = "development"
region = "eu-west-1"
}
terraform {
backend "s3" {
profile = "development"
region = "eu-west-1"
encrypt = true
bucket = "inanzzz-development-terraform"
key = "terraform.tfstate"
dynamodb_table = "terraform_tfstate"
}
}
Bu isteğe bağlıdır, ancak durum dosyasının yerel ortamda nasıl depolanmadığını göstermek için kullanacağız.
# resource "aws_iam_group" "dummy_team" {
# name = "dummy-team"
# }
terraform init
komutunu çalıştırın. Bu herhangi bir kaynak oluşturmaz. Ancak, .terraform
klasörü ve .terraform.lock.hcl
dosyası oluşturacak, ancak .terraform.tfstate
dosyasını oluşturmayacaktır.
aws_iam_group
bloğunu aktif hale getirin ve terraform apply
komutunu çalıştırın. Bu, S3 klasöründe .terraform.tfstate
dosyası oluşturacak ve kilitleme mekanizması için DynamoDB tablosunda LockID
özelliğini ayarlayacaktır.
Bundan sonra, terraform apply
komutlarını her çalıştırdığınızda, yerel .terraform.tfstate
dosyası içinde listelenen hiçbir kaynağa sahip olmayacak. Bunun yerine S3 kovasındaki .terraform.tfstate
dosyasında görünecekler. İçeriğini indirip kontrol edebilirsiniz. Ayrıca DynamoDB tablosundaki LockID
özelliği güncellenecektir.
Yeni bir kaynak (lock_team
) eklemek için bir terminal açın ve uygulamayı çalıştırın, ancak istemi yanıtlamayın.
$ terraform apply
2023/05/25 21:26:26 Enabling CSM
2023/05/25 21:26:27 Enabling CSM
aws_iam_group.dummy_team: Refreshing state... [id=dummy-team]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_iam_group.lock_team will be created
+ resource "aws_iam_group" "lock_team" {
+ arn = (known after apply)
+ id = (known after apply)
+ name = "lock-team"
+ path = "/"
+ unique_id = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value:
Başka bir terminal açın ve plan komutunu çalıştırın. Kilitleme hatası göreceksiniz.
$ terraform plan
2023/05/25 21:26:39 Enabling CSM
2023/05/25 21:26:39 Enabling CSM
╷
│ Error: Error acquiring the state lock
│
│ Error message: ConditionalCheckFailedException: The conditional request failed
│ Lock Info:
│ ID: 12345-qwer-asdf-34e5-1234567890
│ Path: inanzzz-development-terraform/terraform.tfstate
│ Operation: OperationTypeApply
│ Who: me@home
│ Version: 1.4.4
│ Created: 2023-05-25 20:26:29.120347 +0000 UTC
│ Info:
│
│
│ Terraform acquires a state lock to protect the state from being written
│ by multiple users at the same time. Please resolve the issue above and try
│ again. For most commands, you can disable locking with the "-lock=false"
│ flag, but this is not recommended.
╵
Normal kullanıcılar için, S3 klasörü için aşağıdaki politikayı kullanabilirsiniz.
data "aws_iam_policy_document" "terraform_state" {
version = "2012-10-17"
statement {
actions = [
"s3:ListBucket",
]
resources = [
"arn:aws:s3:::inanzzz-development-terraform"
]
}
statement {
actions = [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
]
resources = [
"arn:aws:s3:::inanzzz-development-terraform/terraform.tfstate"
]
}
}
resource "aws_s3_bucket_policy" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
policy = data.aws_iam_policy_document.terraform_state.json
}