Terraform ile Infrastructure as Code: AWS Örnek Projesi
Terraform ile Infrastructure as Code: AWS Örnek Projesi
Manuel AWS Console click-click infrastructure oluşturmak 2025'te kabul edilemez. Infrastructure as Code (IaC) ile her şey versiyonlanabilir, tekrarlanabilir, review edilebilir.
Neden Terraform?
- Cloud Agnostic: AWS, Azure, GCP, DigitalOcean - hepsi tek tool
- State Management: Terraform mevcut infrastructure'ı biliyor
- Plan Before Apply: Değişiklikleri önizle
- Modular: Reusable modules, DRY principle
Örnek Proje: Production-Ready VPC
# main.tf
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
backend "s3" {
bucket = "mycompany-terraform-state"
key = "prod/vpc/terraform.tfstate"
region = "eu-central-1"
encrypt = true
dynamodb_table = "terraform-locks"
}
}
provider "aws" {
region = var.aws_region
default_tags {
tags = {
Environment = var.environment
ManagedBy = "Terraform"
Project = var.project_name
}
}
}
# VPC
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "${var.project_name}-vpc"
}
}
# Public Subnets
resource "aws_subnet" "public" {
count = length(var.public_subnet_cidrs)
vpc_id = aws_vpc.main.id
cidr_block = var.public_subnet_cidrs[count.index]
availability_zone = data.aws_availability_zones.available.names[count.index]
map_public_ip_on_launch = true
tags = {
Name = "${var.project_name}-public-${count.index + 1}"
Type = "Public"
}
}
# Private Subnets
resource "aws_subnet" "private" {
count = length(var.private_subnet_cidrs)
vpc_id = aws_vpc.main.id
cidr_block = var.private_subnet_cidrs[count.index]
availability_zone = data.aws_availability_zones.available.names[count.index]
tags = {
Name = "${var.project_name}-private-${count.index + 1}"
Type = "Private"
}
}
# Internet Gateway
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = {
Name = "${var.project_name}-igw"
}
}
# NAT Gateway
resource "aws_eip" "nat" {
count = var.enable_nat_gateway ? length(var.public_subnet_cidrs) : 0
domain = "vpc"
tags = {
Name = "${var.project_name}-nat-eip-${count.index + 1}"
}
}
resource "aws_nat_gateway" "main" {
count = var.enable_nat_gateway ? length(var.public_subnet_cidrs) : 0
allocation_id = aws_eip.nat[count.index].id
subnet_id = aws_subnet.public[count.index].id
tags = {
Name = "${var.project_name}-nat-${count.index + 1}"
}
}
# Route Tables
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
tags = {
Name = "${var.project_name}-public-rt"
}
}
resource "aws_route_table" "private" {
count = length(var.private_subnet_cidrs)
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = var.enable_nat_gateway ? aws_nat_gateway.main[count.index].id : null
}
tags = {
Name = "${var.project_name}-private-rt-${count.index + 1}"
}
}
Best Practices
1. Remote State Backend
State file S3'te, DynamoDB lock ile. Team collaboration için şart.
2. Variables ve Outputs
# variables.tf
variable "environment" {
description = "Environment name"
type = string
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Environment must be dev, staging, or prod."
}
}
3. Modules
Reusable infrastructure components. DRY principle.
4. Pre-commit Hooks
# .pre-commit-config.yaml
repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform
hooks:
- id: terraform_fmt
- id: terraform_validate
- id: terraform_tflint
CI/CD Integration
# .gitlab-ci.yml
terraform:plan:
image: hashicorp/terraform:latest
script:
- terraform init
- terraform plan -out=tfplan
artifacts:
paths:
- tfplan
terraform:apply:
image: hashicorp/terraform:latest
script:
- terraform init
- terraform apply tfplan
when: manual
only:
- main
Sonuç
Terraform ile infrastructure versiyonlanabilir, testable, reproducible hale gelir. Devups ile IaC migration başlayın.