Langsung ke konten
KamusNgoding
Menengah Cicd 7 menit baca

Memahami Konsep Infrastructure as Code (IaC) di DevOps

#iac #devops #terraform #ansible

Memahami Konsep Infrastructure as Code (IaC) di DevOps

Pendahuluan: Apa itu Infrastructure as Code (IaC) dan Mengapa Penting?

Bayangkan kamu bekerja di startup yang aplikasinya tiba-tiba viral — seperti jika ingin membangun layanan seperti Tokopedia atau Shopee saat kampanye harbolnas. Server kamu kewalahan, dan kamu harus menambah 50 server baru dalam hitungan jam. Tanpa otomasi, ini bisa memakan waktu berhari-hari dan rentan terhadap kesalahan manusia.

Di sinilah Infrastructure as Code (IaC) hadir sebagai solusi. IaC adalah pendekatan di mana infrastruktur IT — server, jaringan, database, load balancer — dikelola menggunakan kode yang dapat di-versioning, di-review, dan di-otomatis, persis seperti kode aplikasi biasa.

Sebelum IaC, tim ops harus mengkonfigurasi server secara manual melalui antarmuka web atau perintah SSH satu per satu. Pendekatan ini disebut ClickOps — lambat, tidak konsisten, dan sulit direproduksi. IaC mengubah paradigma ini: infrastruktur didefinisikan dalam file teks yang bisa disimpan di Git, di-review lewat pull request, dan di-deploy secara otomatis.

Manfaat utama IaC:

  • Konsistensi: Infrastruktur yang sama selalu di-deploy dengan cara yang sama
  • Reproducibility: Environment dev, staging, dan production identik
  • Kecepatan: Deploy ratusan server dalam menit
  • Audit trail: Setiap perubahan tercatat di Git history
  • Disaster recovery: Infrastruktur bisa di-rebuild dari nol dalam hitungan menit

Prasyarat dan Setup Lingkungan

Sebelum mencoba contoh-contoh kode di artikel ini, pastikan kamu sudah memiliki:

Tools yang diperlukan:

  • Terraform CLI versi >= 1.6.0
  • AWS CLI versi >= 2.0
  • Ansible versi >= 8.0 (opsional, untuk contoh Ansible)
  • Akun AWS (bisa menggunakan Free Tier)

Instalasi Terraform di Linux/macOS:

# Download dan install Terraform
wget https://releases.hashicorp.com/terraform/1.6.0/terraform_1.6.0_linux_amd64.zip
unzip terraform_1.6.0_linux_amd64.zip
sudo mv terraform /usr/local/bin/

# Verifikasi instalasi
terraform version
# Output: Terraform v1.6.0

Setup AWS credentials:

# Install AWS CLI
pip install awscli

# Konfigurasi credentials
aws configure
# AWS Access Key ID [None]: <masukkan access key kamu>
# AWS Secret Access Key [None]: <masukkan secret key kamu>
# Default region name [None]: ap-southeast-1
# Default output format [None]: json

# Verifikasi konfigurasi
aws sts get-caller-identity
# Output: {"UserId": "...", "Account": "123456789", "Arn": "arn:aws:iam::..."}

Instalasi Ansible:

# Ubuntu/Debian
sudo apt update && sudo apt install -y ansible

# macOS
brew install ansible

# Verifikasi instalasi
ansible --version
# Output: ansible [core 2.15.x]

Prinsip-Prinsip Kunci dalam IaC

Memahami prinsip IaC membantu kamu menulis kode infrastruktur yang lebih baik dan maintainable.

1. Idempotency

Menjalankan kode IaC berkali-kali harus menghasilkan state yang sama. Jika server sudah ada, jangan buat lagi — update jika perlu.

2. Declarative vs Imperative

Ada dua pendekatan dalam IaC:

Declarative — kamu mendeskripsikan apa yang kamu inginkan, bukan bagaimana caranya:

# Terraform (declarative)
resource "aws_instance" "web_server" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t3.micro"
  
  tags = {
    Name        = "KamusNgoding-WebServer"
    Environment = "production"
  }
}

Imperative — kamu mendeskripsikan langkah-langkah yang harus dilakukan:

# Ansible (lebih imperative)
- name: Install nginx
  apt:
    name: nginx
    state: present
    
- name: Start nginx service
  service:
    name: nginx
    state: started
    enabled: yes

3. Version Control Everything

Semua file konfigurasi infrastruktur harus masuk ke Git:

# Buat struktur repository IaC
mkdir -p infrastructure/{terraform/modules/{networking,compute},ansible/{playbooks,inventory}}
cd infrastructure

# Struktur repository IaC yang baik
# infrastructure/
# ├── terraform/
# │   ├── main.tf
# │   ├── variables.tf
# │   ├── outputs.tf
# │   └── modules/
# │       ├── networking/
# │       └── compute/
# ├── ansible/
# │   ├── playbooks/
# │   └── inventory/
# └── .gitignore

# Buat .gitignore untuk IaC
cat > .gitignore << 'EOF'
# Terraform state files (sensitif!)
*.tfstate
*.tfstate.backup
.terraform/

# Secrets
*.pem
*.key
.env

# Ansible
*.retry
EOF

4. Immutable Infrastructure

Daripada mengupdate server yang sudah ada, lebih baik buat server baru dengan konfigurasi baru lalu hapus yang lama. Ini menghilangkan “configuration drift” — kondisi di mana server prod dan dev perlahan menjadi berbeda.


Alat-Alat Populer untuk IaC: Terraform, Ansible, dan Lainnya

Terraform

Terraform dari HashiCorp adalah tools IaC paling populer untuk provisioning infrastruktur cloud. Terraform mendukung AWS, GCP, Azure, dan ratusan provider lainnya.

# main.tf — Membuat VPC dan subnet di AWS
# Jalankan: terraform init && terraform plan && terraform apply

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = var.aws_region
}

data "aws_availability_zones" "available" {
  state = "available"
}

resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  
  tags = {
    Name = "${var.project_name}-vpc"
  }
}

resource "aws_subnet" "public" {
  count             = 2
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.${count.index}.0/24"
  availability_zone = data.aws_availability_zones.available.names[count.index]
  
  map_public_ip_on_launch = true

  tags = {
    Name = "${var.project_name}-public-subnet-${count.index + 1}"
  }
}
# variables.tf
variable "aws_region" {
  description = "AWS region untuk deployment"
  type        = string
  default     = "ap-southeast-1"  # Singapore — dekat Indonesia
}

variable "project_name" {
  description = "Nama project"
  type        = string
  default     = "kamusngoding"
}
# outputs.tf
output "vpc_id" {
  description = "ID dari VPC yang dibuat"
  value       = aws_vpc.main.id
}

output "public_subnet_ids" {
  description = "ID subnet publik"
  value       = aws_subnet.public[*].id
}

Cara menjalankan:

# 1. Inisialisasi Terraform (download providers)
terraform init

# 2. Preview perubahan
terraform plan

# 3. Apply perubahan
terraform apply

# Ketik 'yes' saat diminta konfirmasi
# Apply complete! Resources: 3 added, 0 changed, 0 destroyed.

# 4. Lihat output
terraform output vpc_id

Ansible

Ansible lebih cocok untuk konfigurasi server dan deployment aplikasi setelah infrastruktur siap.

# inventory/hosts.ini
[webservers]
web1 ansible_host=10.0.0.10 ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/id_rsa
web2 ansible_host=10.0.0.11 ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/id_rsa

[all:vars]
ansible_python_interpreter=/usr/bin/python3
# playbook/setup-webserver.yml
# Jalankan: ansible-playbook -i inventory/hosts.ini playbook/setup-webserver.yml
---
- name: Setup Web Server Production
  hosts: webservers
  become: yes
  
  vars:
    app_user: "deploy"
    app_dir: "/var/www/kamusngoding"
    
  tasks:
    - name: Update apt cache
      apt:
        update_cache: yes
        cache_valid_time: 3600
        
    - name: Install dependencies
      apt:
        name:
          - nginx
          - nodejs
          - npm
          - git
        state: present
        
    - name: Create application directory
      file:
        path: "{{ app_dir }}"
        state: directory
        owner: "{{ app_user }}"
        mode: '0755'
        
    - name: Deploy Nginx config
      template:
        src: templates/nginx.conf.j2
        dest: /etc/nginx/sites-available/kamusngoding
      notify: Reload nginx
        
  handlers:
    - name: Reload nginx
      service:
        name: nginx
        state: reloaded
# Cara menjalankan Ansible playbook
# Test koneksi ke semua host dulu
ansible -i inventory/hosts.ini webservers -m ping

# Jalankan playbook dengan dry-run (--check)
ansible-playbook -i inventory/hosts.ini playbook/setup-webserver.yml --check

# Apply sesungguhnya
ansible-playbook -i inventory/hosts.ini playbook/setup-webserver.yml

# Output:
# PLAY RECAP *******
# web1 : ok=5  changed=3  unreachable=0  failed=0
# web2 : ok=5  changed=3  unreachable=0  failed=0

Tools IaC Lainnya

ToolKegunaanBahasa
PulumiIaC dengan bahasa pemrograman umumPython, TypeScript, Go
AWS CDKIaC khusus AWSTypeScript, Python
CloudFormationIaC native AWSYAML/JSON
HelmPackage manager untuk KubernetesYAML

Mengintegrasikan IaC dalam Pipeline CI/CD

IaC paling powerful ketika diintegrasikan ke dalam pipeline CI/CD. Setiap perubahan infrastruktur bisa di-review, di-test, dan di-apply secara otomatis — mirip seperti cara menjalankan tes otomatis dengan GitHub Actions untuk kode aplikasi.

# .github/workflows/terraform.yml
name: Terraform Infrastructure CI/CD

on:
  push:
    branches: [main]
    paths: ['infrastructure/**']
  pull_request:
    paths: ['infrastructure/**']

env:
  TF_VERSION: '1.6.0'
  AWS_REGION: 'ap-southeast-1'

jobs:
  terraform-plan:
    name: Terraform Plan
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: infrastructure/terraform
        
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        
      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v3
        with:
          terraform_version: ${{ env.TF_VERSION }}
          
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ env.AWS_REGION }}
          
      - name: Terraform Init
        run: terraform init
        
      - name: Terraform Format Check
        run: terraform fmt -check -recursive
        
      - name: Terraform Validate
        run: terraform validate
        
      - name: Terraform Plan
        run: terraform plan -out=tfplan
        
      - name: Upload plan artifact
        uses: actions/upload-artifact@v4
        with:
          name: terraform-plan
          path: infrastructure/terraform/tfplan

  terraform-apply:
    name: Terraform Apply
    needs: terraform-plan
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main' && github.event_name == 'push'
    environment: production  # Requires manual approval
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        
      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v3
        with:
          terraform_version: ${{ env.TF_VERSION }}
          
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ env.AWS_REGION }}

      - name: Terraform Init
        working-directory: infrastructure/terraform
        run: terraform init

      - name: Download plan
        uses: actions/download-artifact@v4
        with:
          name: terraform-plan
          path: infrastructure/terraform/
          
      - name: Terraform Apply
        working-directory: infrastructure/terraform
        run: terraform apply -auto-approve tfplan

Pola ini — Plan on PR, Apply on merge — adalah best practice IaC dalam CI/CD. Tim bisa mereview perubahan infrastruktur sebelum di-apply, mengurangi risiko outage produksi. Konsep ini mirip dengan yang dijelaskan dalam membangun CI/CD Pipeline untuk aplikasi Node.js dengan GitHub Actions.


Contoh Kasus Nyata: Deploy Infrastruktur Web dengan Terraform

Mari kita lihat contoh nyata: deploy infrastruktur untuk web application sederhana dengan load balancer, auto-scaling, dan database.

# modules/compute/main.tf — Auto Scaling Group
# Prasyarat: VPC dan subnet sudah dibuat (lihat contoh main.tf di atas)
# Jalankan dari direktori root: terraform apply -target=module.compute

variable "project_name" { type = string }
variable "ami_id" { type = string }
variable "instance_type" { default = "t3.micro" }
variable "subnet_ids" { type = list(string) }
variable "artifact_bucket" { type = string }

resource "aws_security_group" "app" {
  name_prefix = "${var.project_name}-app-"
  vpc_id      = data.aws_vpc.main.id

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_launch_template" "app" {
  name_prefix   = "${var.project_name}-"
  image_id      = var.ami_id
  instance_type = var.instance_type
  
  user_data = base64encode(<<-EOF
    #!/bin/bash
    apt-get update
    apt-get install -y nginx awscli
    
    # Deploy app dari S3
    aws s3 cp s3://${var.artifact_bucket}/app.tar.gz /tmp/
    tar -xzf /tmp/app.tar.gz -C /var/www/html
    
    systemctl start nginx
    systemctl enable nginx
    EOF
  )
  
  vpc_security_group_ids = [aws_security_group.app.id]
  
  tag_specifications {
    resource_type = "instance"
    tags = {
      Name = "${var.project_name}-app-server"
    }
  }
}

resource "aws_autoscaling_group" "app" {
  desired_capacity    = 2
  max_size            = 10
  min_size            = 1
  target_group_arns   = [aws_lb_target_group.app.arn]
  vpc_zone_identifier = var.subnet_ids
  
  launch_template {
    id      = aws_launch_template.app.id
    version = "$Latest"
  }
  
  tag {
    key                 = "Name"
    value               = "${var.project_name}-asg"
    propagate_at_launch = true
  }
}

resource "aws_autoscaling_policy" "scale_up" {
  name                   = "${var.project_name}-scale-up"
  autoscaling_group_name = aws_autoscaling_group.app.name
  adjustment_type        = "ChangeInCapacity"
  scaling_adjustment     = 2
  cooldown               = 300
}

resource "aws_cloudwatch_metric_alarm" "high_cpu" {
  alarm_name          = "${var.project_name}-high-cpu"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = 2
  metric_name         = "CPUUtilization"
  namespace           = "AWS/EC2"
  period              = 120
  statistic           = "Average"
  threshold           = 80
  
  alarm_actions = [aws_autoscaling_policy.scale_up.arn]
}

Dengan konfigurasi ini, jika CPU usage naik di atas 80% (misalnya saat traffic spike seperti flash sale di aplikasi e-commerce), sistem otomatis akan menambah 2 server baru.


Troubleshooting: Error yang Sering Muncul saat Bekerja dengan IaC

Error: “Error acquiring the state lock”

Penyebab: Terraform menggunakan state locking untuk mencegah dua operasi berjalan bersamaan. Error ini muncul jika proses sebelumnya crash atau state lock tidak dilepas dengan benar.

Solusi:

# Lihat detail lock ID dari pesan error, lalu jalankan:
terraform force-unlock <LOCK_ID>

# Jika menggunakan S3 backend, cek DynamoDB untuk lock yang tersangkut
aws dynamodb scan \
  --table-name terraform-state-lock \
  --filter-expression "attribute_exists(LockID)"

# Force unlock (gunakan dengan hati-hati — pastikan tidak ada proses lain yang berjalan!)
terraform force-unlock -force <LOCK_ID>

# Output jika berhasil:
# Do you really want to force-unlock?
# Terraform will remove the lock on the remote state.
# yes
# Terraform state has been successfully unlocked!

Error: “Error: Provider configuration not present”

Penyebab: Terraform tidak bisa menemukan konfigurasi provider (misalnya AWS credentials) saat menjalankan terraform apply di environment CI/CD.

Solusi:

# Pastikan environment variables tersedia sebelum menjalankan terraform
export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
export AWS_DEFAULT_REGION="ap-southeast-1"

# Verifikasi credentials aktif
aws sts get-caller-identity
# Output yang benar:
# {
#   "UserId": "AIXXXXXXXXXXXXXXXXX",
#   "Account": "123456789012",
#   "Arn": "arn:aws:iam::123456789012:user/terraform-user"
# }

# Baru jalankan terraform
terraform apply

Error: “Failed to load module” saat terraform init

Penyebab: Terraform tidak bisa menemukan atau mengakses modul yang dipanggil di konfigurasi, bisa karena path salah atau koneksi internet terputus.

Solusi:

# Periksa path modul di main.tf
# Contoh yang salah:
# source = "./module/compute"  ❌

# Contoh yang benar:
# source = "./modules/compute"  ✓

# Jika modul dari registry, pastikan koneksi internet aktif lalu jalankan ulang:
terraform init -upgrade

# Output jika berhasil:
# Initializing modules...
# - compute in modules/compute
# Terraform has been successfully initialized!

Error: “ResourceAlreadyExists” atau resource sudah ada di cloud

Penyebab: Terraform mencoba membuat resource yang sudah ada secara manual di cloud (tidak dikelola oleh Terraform), sehingga terjadi konflik.

Solusi:

# Import resource yang sudah ada ke Terraform state
# Format: terraform import <resource_type>.<resource_name> <resource_id_di_cloud>

# Contoh import EC2 instance yang sudah ada:
terraform import aws_instance.web_server i-0123456789abcdef0

# Contoh import S3 bucket:
terraform import aws_s3_bucket.app_bucket nama-bucket-kamu

# Setelah import, pastikan konfigurasi .tf kamu sesuai dengan resource yang ada
terraform plan
# Jika output: "No changes. Infrastructure is up-to-date." — berhasil!

Pertanyaan yang Sering Diajukan

Apakah IaC hanya untuk cloud, atau bisa untuk server on-premise?

IaC bisa digunakan untuk keduanya. Terraform mendukung provider untuk VMware, Proxmox, dan platform virtualisasi on-premise lainnya. Ansible bahkan lebih fleksibel — bisa mengkonfigurasi server fisik maupun virtual di mana saja selama bisa diakses via SSH. Jadi, meski cloud adalah use case paling umum, IaC sama bermanfaatnya untuk data center tradisional.

Apa perbedaan utama antara Terraform dan Ansible, dan kapan sebaiknya menggunakan masing-masing?

Terraform unggul dalam provisioning infrastruktur — membuat dan menghapus resource cloud seperti VPC, EC2, database, dan load balancer. Ansible lebih cocok untuk konfigurasi dan manajemen software di server yang sudah ada, seperti menginstall paket, mendeploy aplikasi, atau mengatur konfigurasi sistem. Dalam praktiknya, keduanya sering digunakan bersama: Terraform membuat server, lalu Ansible mengkonfigurasinya.

Bagaimana cara menyimpan secrets (password, API key) dengan aman di IaC?

Jangan pernah menyimpan secrets langsung di file .tf atau di Git. Ada beberapa pendekatan yang aman: gunakan environment variables untuk credentials sementara, AWS Secrets Manager atau HashiCorp Vault untuk secrets yang dikelola secara terpusat, atau Terraform Cloud yang menyediakan penyimpanan variabel terenkripsi. Untuk CI/CD, simpan secrets di GitHub Actions Secrets dan inject sebagai environment variable saat pipeline berjalan.

Berapa lama waktu yang dibutuhkan untuk belajar Terraform dari nol?

Dengan latihan konsisten, konsep dasar Terraform (resource, variable, output, state) bisa dipahami dalam 1-2 minggu. Untuk bisa produktif membangun infrastruktur sederhana di AWS, biasanya butuh 1-2 bulan. Yang paling penting adalah langsung praktik — buat akun AWS Free Tier, ikuti tutorial resmi Terraform, dan coba deploy infrastruktur sederhana sendiri.

Apakah perlu menguasai satu cloud provider dulu sebelum belajar IaC?

Tidak harus, tapi sangat membantu. Memahami konsep dasar cloud (apa itu VPC, EC2, S3, IAM) akan mempercepat proses belajar IaC karena kamu sudah tahu apa yang sedang kamu otomasi. Jika mulai dari nol, belajar konsep cloud dasar AWS selama 2-3 minggu terlebih dahulu, kemudian mulai eksplorasi Terraform — prosesnya akan jauh lebih lancar.


Kesimpulan: Masa Depan Infrastruktur Otomatis

Infrastructure as Code bukan lagi “nice to have” — ini adalah keahlian wajib bagi engineer modern. Di era cloud-native, kemampuan untuk mendefinisikan, memversioning, dan mengotomasi infrastruktur adalah yang membedakan tim yang bisa scale dari yang tidak.

Kita sudah membahas prinsip-prinsip IaC (idempotency, pendekatan deklaratif, infrastruktur imut), tools utama (Terraform untuk provisioning, Ansible untuk konfigurasi), cara mengintegrasikan IaC ke pipeline CI/CD dengan GitHub Actions, hingga kasus nyata deploy infrastruktur auto-scaling.

Tren ke depan sangat menarik: GitOps membawa IaC satu level lebih jauh dengan menjadikan Git sebagai single source of truth untuk seluruh sistem. Tools seperti ArgoCD dan Flux secara otomatis menyinkronkan state Git dengan state cluster Kubernetes. Jika kamu ingin membangun aplikasi berskala besar seperti layanan streaming atau e-commerce, menguasai IaC adalah investasi karir yang sangat berharga.

Selamat bereksperimen dan terus tingkatkan skill infrastruktur kamu! Jika ada pertanyaan atau ingin eksplorasi topik DevOps lainnya, jangan ragu untuk menjelajahi artikel-artikel lain di KamusNgoding — komunitas developer Indonesia ada untuk saling mendukung.

Artikel Terkait