142 lines
3.1 KiB
Markdown
142 lines
3.1 KiB
Markdown
# Terraform Infrastructure as Code
|
|
|
|
## AWS ECS Fargate Setup
|
|
|
|
```hcl
|
|
terraform {
|
|
required_providers {
|
|
aws = { source = "hashicorp/aws", version = "~> 5.0" }
|
|
}
|
|
backend "s3" {
|
|
bucket = "terraform-state"
|
|
key = "app/terraform.tfstate"
|
|
region = "us-east-1"
|
|
}
|
|
}
|
|
|
|
resource "aws_ecs_cluster" "main" {
|
|
name = "app-cluster"
|
|
setting {
|
|
name = "containerInsights"
|
|
value = "enabled"
|
|
}
|
|
}
|
|
|
|
resource "aws_ecs_task_definition" "app" {
|
|
family = "app"
|
|
network_mode = "awsvpc"
|
|
requires_compatibilities = ["FARGATE"]
|
|
cpu = "256"
|
|
memory = "512"
|
|
execution_role_arn = aws_iam_role.ecs_execution.arn
|
|
|
|
container_definitions = jsonencode([{
|
|
name = "app"
|
|
image = "${var.ecr_repository}:${var.image_tag}"
|
|
portMappings = [{ containerPort = 3000 }]
|
|
logConfiguration = {
|
|
logDriver = "awslogs"
|
|
options = {
|
|
awslogs-group = aws_cloudwatch_log_group.app.name
|
|
awslogs-region = var.region
|
|
awslogs-stream-prefix = "app"
|
|
}
|
|
}
|
|
secrets = [
|
|
{ name = "DATABASE_URL", valueFrom = aws_ssm_parameter.db_url.arn }
|
|
]
|
|
}])
|
|
}
|
|
|
|
resource "aws_ecs_service" "app" {
|
|
name = "app"
|
|
cluster = aws_ecs_cluster.main.id
|
|
task_definition = aws_ecs_task_definition.app.arn
|
|
desired_count = 2
|
|
launch_type = "FARGATE"
|
|
|
|
network_configuration {
|
|
subnets = var.private_subnets
|
|
security_groups = [aws_security_group.app.id]
|
|
}
|
|
|
|
load_balancer {
|
|
target_group_arn = aws_lb_target_group.app.arn
|
|
container_name = "app"
|
|
container_port = 3000
|
|
}
|
|
}
|
|
```
|
|
|
|
## AWS RDS PostgreSQL
|
|
|
|
```hcl
|
|
resource "aws_db_instance" "postgres" {
|
|
identifier = "app-db"
|
|
engine = "postgres"
|
|
engine_version = "16.1"
|
|
instance_class = "db.t3.micro"
|
|
allocated_storage = 20
|
|
storage_encrypted = true
|
|
|
|
db_name = "app"
|
|
username = "admin"
|
|
password = var.db_password
|
|
|
|
vpc_security_group_ids = [aws_security_group.db.id]
|
|
db_subnet_group_name = aws_db_subnet_group.main.name
|
|
|
|
backup_retention_period = 7
|
|
skip_final_snapshot = false
|
|
final_snapshot_identifier = "app-db-final"
|
|
|
|
tags = { Environment = var.environment }
|
|
}
|
|
```
|
|
|
|
## Variables and Outputs
|
|
|
|
```hcl
|
|
# variables.tf
|
|
variable "environment" {
|
|
type = string
|
|
description = "Environment name"
|
|
}
|
|
|
|
variable "region" {
|
|
type = string
|
|
default = "us-east-1"
|
|
}
|
|
|
|
# outputs.tf
|
|
output "ecs_cluster_arn" {
|
|
value = aws_ecs_cluster.main.arn
|
|
}
|
|
|
|
output "alb_dns_name" {
|
|
value = aws_lb.main.dns_name
|
|
}
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
| Practice | Implementation |
|
|
|----------|----------------|
|
|
| State locking | S3 backend with DynamoDB |
|
|
| Secrets | Use AWS Secrets Manager / SSM |
|
|
| Modules | Reusable components |
|
|
| Workspaces | Environment separation |
|
|
| Tagging | Consistent resource tags |
|
|
| Validation | `terraform validate`, `tflint` |
|
|
|
|
## Common Commands
|
|
|
|
```bash
|
|
terraform init
|
|
terraform plan -out=tfplan
|
|
terraform apply tfplan
|
|
terraform destroy
|
|
terraform state list
|
|
terraform import aws_instance.app i-1234567890
|
|
```
|