Ebook Syafi
Koleksi
Admin
← DevOps Dari Homelab ke Production
Edit Bab
💾 Simpan
Batal
Syarat
Mukadimah
Bab
Penutup
B
I
H2
H3
List
1.
Quote
Code
Link
Img
Table
Edit
Split
Preview
0 perkataan
# Bab 6: Infrastructure as Code Bayangkan anda perlu setup 10 server baru untuk projek baru. Anda SSH satu per satu, install packages, configure firewall, setup users. Lepas dua jam, server ketiga ada masalah sebab anda terlupa satu langkah. Sound familiar? Inilah masalah yang Infrastructure as Code (IaC) selesaikan. Daripada klik-klik manual atau taip command satu-satu, kita tulis code yang describe infrastructure kita. Code ini boleh di-version, di-review, dan di-reuse. Sama macam anda tulis code untuk application, kita tulis code untuk infrastructure. Kalau anda pernah setup Proxmox VM secara manual dan rasa frustrated bila kena buat benda yang sama berulang kali, bab ini untuk anda. ## Apa yang anda akan belajar: - Konsep Infrastructure as Code dan kenapa ia penting - Ansible untuk configuration management (inventory, playbooks, roles) - Terraform untuk provisioning infrastructure - Bila guna Ansible, bila guna Terraform - GitOps workflow untuk manage infrastructure code - Practical examples yang boleh terus digunakan ## Apa Itu Infrastructure as Code? Infrastructure as Code bermaksud kita define dan manage infrastructure menggunakan code files, bukan manual process. Daripada login ke server dan run commands, kita tulis semua dalam files yang boleh disimpan dalam Git. Kenapa ini penting? Sebab manual setup ada banyak masalah. **Masalah manual setup:** - Tidak consistent. Server A mungkin berbeza daripada Server B walaupun sepatutnya sama. - Tidak reproducible. Kalau server crash, boleh ke anda setup semula exactly sama? - Tidak scalable. Setup 3 server okay, macam mana 30? 300? - Tidak auditable. Siapa yang buat perubahan itu? Bila? Kenapa? **Kelebihan IaC:** - **Consistency.** Setiap server di-setup exactly sama. - **Version control.** Semua perubahan di-track dalam Git. - **Reusability.** Tulis sekali, guna banyak kali. - **Self-documenting.** Code itu sendiri adalah dokumentasi. - **Testable.** Boleh test infrastructure changes sebelum apply. > **Nota Beginner:** Kalau anda pernah tulis script Bash untuk automate server setup, anda sebenarnya sudah buat IaC dalam bentuk paling basic. Tools macam Ansible dan Terraform bawa konsep ini ke level yang lebih structured dan powerful. ### Declarative vs Imperative Ada dua pendekatan dalam IaC yang anda perlu faham. **Imperative** bermaksud anda tulis step-by-step instructions. "Install Nginx, then copy config file, then restart service." Bash scripts adalah imperative. Anda beritahu sistem apa nak buat, langkah demi langkah. **Declarative** bermaksud anda describe end state yang anda mahukan. "Saya mahu Nginx installed, config file ini di tempat ini, dan service running." Tools akan figure out sendiri macam mana nak sampai ke state tersebut. Terraform adalah fully declarative. Anda describe infrastructure yang anda mahu, dan Terraform determine langkah-langkah untuk capai state tersebut. Ansible berada di tengah-tengah. Playbooks ditulis secara imperative (step by step), tapi banyak modules bersifat declarative (mereka check current state sebelum buat changes). Kelebihan declarative approach adalah idempotency. Anda boleh run code yang sama banyak kali dan hasilnya akan sentiasa sama. Kalau Nginx sudah installed, Ansible tidak akan install lagi. Kalau VM sudah exist, Terraform tidak akan create duplicate. ### Mutable vs Immutable Infrastructure Satu lagi konsep penting. Mutable infrastructure bermaksud anda update server yang sedia ada. SSH masuk, upgrade packages, tukar config. Server itu terus hidup dan berubah over time. Immutable infrastructure bermaksud anda tidak pernah update server. Bila ada changes, anda create server baru dengan config terbaru dan destroy yang lama. Container-based deployments biasanya mengikut pendekatan ini. Dalam practice, kebanyakan team guna combination kedua-dua pendekatan. Homelab biasanya mutable (anda SSH masuk dan tweak). Production yang mature biasanya move towards immutable (deploy new, destroy old). ## Ansible: Configuration Management Ansible adalah tool untuk automate configuration dan management server. Ia agentless, bermaksud anda tidak perlu install apa-apa pada target server. Ansible guna SSH untuk connect dan jalankan tasks. Ini menjadikan Ansible sangat sesuai untuk homelab sebab anda tidak perlu setup agent pada setiap VM atau container. Berbanding tools lain macam Puppet atau Chef yang require agent pada setiap node, Ansible hanya perlukan SSH access dan Python pada target. Kebanyakan Linux distributions sudah ada kedua-duanya secara default. ### Install Ansible Pada Ubuntu atau Debian: ```bash sudo apt update sudo apt install ansible -y ``` Pada macOS: ```bash brew install ansible ``` Verify installation: ```bash ansible --version ``` ### Inventory: Senarai Server Anda Inventory adalah file yang senaraikan semua server yang Ansible akan manage. Paling simple, ia adalah text file dengan IP addresses. Buat file `inventory.ini`: ```ini [webservers] web1 ansible_host=192.168.1.101 ansible_user=syafi web2 ansible_host=192.168.1.102 ansible_user=syafi [databases] db1 ansible_host=192.168.1.110 ansible_user=syafi [monitoring] monitor1 ansible_host=192.168.1.120 ansible_user=syafi [homelab:children] webservers databases monitoring [all:vars] ansible_python_interpreter=/usr/bin/python3 ``` Anda boleh group server mengikut fungsi. `[homelab:children]` adalah group yang mengandungi group lain. `[all:vars]` set variables untuk semua hosts. Test connection ke semua server: ```bash ansible all -i inventory.ini -m ping ``` Kalau semuanya okay, anda akan nampak output `SUCCESS` untuk setiap host. > **Nota Beginner:** Pastikan SSH key anda sudah di-copy ke semua target server menggunakan `ssh-copy-id`. Ansible bergantung pada SSH untuk connect, jadi passwordless SSH sangat disyorkan. ### Playbooks: Resipi Automation Anda Playbook adalah YAML file yang describe tasks yang Ansible perlu jalankan. Ia macam resipi. Anda tulis langkah-langkah, dan Ansible akan ikut satu per satu. Contoh playbook `setup-webserver.yml` untuk setup Nginx web server: ```yaml --- - name: Setup Nginx Web Server hosts: webservers become: yes vars: domain_name: "myapp.homelab.local" app_port: 3000 tasks: - name: Update apt cache apt: update_cache: yes cache_valid_time: 3600 - name: Install required packages apt: name: - nginx - certbot - python3-certbot-nginx - ufw state: present - name: Configure UFW firewall ufw: rule: allow port: "{{ item }}" proto: tcp loop: - "22" - "80" - "443" - name: Enable UFW ufw: state: enabled default: deny - name: Copy Nginx config template: src: templates/nginx.conf.j2 dest: "/etc/nginx/sites-available/{{ domain_name }}" notify: Reload Nginx - name: Enable site file: src: "/etc/nginx/sites-available/{{ domain_name }}" dest: "/etc/nginx/sites-enabled/{{ domain_name }}" state: link notify: Reload Nginx - name: Remove default site file: path: /etc/nginx/sites-enabled/default state: absent notify: Reload Nginx handlers: - name: Reload Nginx service: name: nginx state: reloaded ``` Buat template file `templates/nginx.conf.j2`: ```nginx server { listen 80; server_name {{ domain_name }}; location / { proxy_pass http://127.0.0.1:{{ app_port }}; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } ``` Jalankan playbook: ```bash ansible-playbook -i inventory.ini setup-webserver.yml ``` Beberapa perkara penting dalam playbook di atas: - `become: yes` bermaksud run sebagai root (sudo). - `vars` define variables yang boleh digunakan dalam tasks. - `template` module guna Jinja2 templating. Variables dalam `{{ }}` akan diganti dengan nilai sebenar. - `handlers` hanya run bila di-trigger oleh `notify`. Ini elakkan restart service yang tidak perlu. - `loop` membolehkan anda repeat task untuk multiple items. ### Roles: Organisasi Yang Lebih Baik Bila playbook anda makin besar, ia jadi susah nak maintain. Roles membantu anda organise tasks, templates, files, dan variables dalam structure yang standard. Buat role structure: ```bash mkdir -p roles/common/{tasks,handlers,templates,files,vars,defaults} mkdir -p roles/docker/{tasks,handlers,templates,vars,defaults} ``` File `roles/common/tasks/main.yml`: ```yaml --- - name: Update and upgrade packages apt: update_cache: yes upgrade: safe cache_valid_time: 3600 - name: Install common packages apt: name: - curl - wget - vim - htop - git - ufw - fail2ban - unattended-upgrades state: present - name: Set timezone timezone: name: "{{ timezone }}" - name: Configure fail2ban template: src: jail.local.j2 dest: /etc/fail2ban/jail.local notify: Restart fail2ban - name: Enable and start fail2ban service: name: fail2ban state: started enabled: yes ``` File `roles/common/defaults/main.yml`: ```yaml --- timezone: "Asia/Kuala_Lumpur" ``` File `roles/docker/tasks/main.yml`: ```yaml --- - name: Install Docker prerequisites apt: name: - ca-certificates - curl - gnupg - lsb-release state: present - name: Add Docker GPG key apt_key: url: https://download.docker.com/linux/ubuntu/gpg state: present - name: Add Docker repository apt_repository: repo: "deb https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable" state: present - name: Install Docker apt: name: - docker-ce - docker-ce-cli - containerd.io - docker-compose-plugin state: present update_cache: yes - name: Add user to docker group user: name: "{{ ansible_user }}" groups: docker append: yes - name: Start and enable Docker service: name: docker state: started enabled: yes ``` Guna roles dalam playbook `site.yml`: ```yaml --- - name: Setup all servers hosts: all become: yes roles: - common - name: Setup Docker hosts hosts: webservers become: yes roles: - docker ``` Jalankan: ```bash ansible-playbook -i inventory.ini site.yml ``` > **Nota Beginner:** Saya sangat recommend guna roles dari awal walaupun projek kecil. Bila projek membesar nanti, anda akan berterima kasih pada diri sendiri. ### Ansible Galaxy: Roles Dari Community Anda tidak perlu tulis semua roles dari scratch. Ansible Galaxy menyediakan ribuan roles yang sedia untuk digunakan. ```bash # Install role dari Galaxy ansible-galaxy install geerlingguy.docker ansible-galaxy install geerlingguy.nodejs # Atau guna requirements.yml ``` Buat file `requirements.yml`: ```yaml --- roles: - name: geerlingguy.docker version: "7.1.0" - name: geerlingguy.nodejs version: "6.2.0" ``` Install semua roles sekaligus: ```bash ansible-galaxy install -r requirements.yml ``` ### Ansible Vault: Manage Secrets Dalam real-world usage, anda pasti ada passwords, API keys, dan secrets lain yang perlu digunakan dalam playbooks. Jangan hardcode secrets dalam playbook files. Guna Ansible Vault untuk encrypt sensitive data. ```bash # Create encrypted file ansible-vault create secrets.yml # Edit encrypted file ansible-vault edit secrets.yml # Encrypt existing file ansible-vault encrypt vars/production.yml # Run playbook dengan vault ansible-playbook -i inventory.ini site.yml --ask-vault-pass ``` Contoh encrypted variables file `secrets.yml`: ```yaml db_password: "super-secret-password-123" api_key: "sk-1234567890abcdef" registry_token: "ghp_xxxxxxxxxxxx" ``` Guna dalam playbook: ```yaml --- - name: Deploy with secrets hosts: webservers become: yes vars_files: - secrets.yml tasks: - name: Set database password template: src: templates/env.j2 dest: /opt/myapp/.env mode: "0600" ``` Anda boleh commit encrypted files ke Git dengan selamat. Tanpa vault password, tiada siapa boleh baca content sebenar. Ini membolehkan anda version control secrets bersama code tanpa risiko security. > **Nota Beginner:** Untuk team, consider guna vault password file instead of typing password setiap kali. Simpan password file di tempat selamat dan tambahkan dalam `.gitignore`. Jangan sesekali commit vault password file ke Git. ## Terraform: Infrastructure Provisioning Kalau Ansible adalah untuk configure server yang sudah ada, Terraform adalah untuk create infrastructure itu sendiri. Terraform boleh provision VMs, networks, DNS records, cloud resources, dan banyak lagi. Terraform guna pendekatan declarative. Anda describe apa yang anda mahu, dan Terraform akan figure out macam mana nak capai state tersebut. ### Install Terraform ```bash # Ubuntu/Debian wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list sudo apt update && sudo apt install terraform # macOS brew tap hashicorp/tap brew install hashicorp/tap/terraform ``` ### Konsep Asas Terraform **Providers** adalah plugins yang membolehkan Terraform interact dengan platform tertentu. Ada providers untuk AWS, GCP, Azure, DigitalOcean, Proxmox, dan banyak lagi. **Resources** adalah infrastructure objects yang anda mahu create. Contohnya VM, network, firewall rule. **State** adalah record tentang infrastructure yang Terraform manage. Terraform simpan state dalam file `terraform.tfstate`. File ini sangat penting. Jangan delete atau edit secara manual. **Plan** adalah preview tentang apa yang Terraform akan buat sebelum ia buat. Ini membolehkan anda review changes sebelum apply. **Variables** membolehkan anda parameterize configuration. Daripada hardcode values, guna variables supaya code lebih flexible dan reusable. **Outputs** adalah values yang Terraform display selepas apply. Contohnya IP address VM yang baru dibuat. Outputs juga boleh digunakan oleh modules lain. **Data Sources** membolehkan anda query information daripada provider tanpa create resources. Contohnya, query AMI ID terbaru atau existing VPC ID. Terraform workflow sangat straightforward. Anda tulis code, run `terraform init` untuk download providers, run `terraform plan` untuk preview, dan run `terraform apply` untuk execute. Kalau anda mahu destroy semua resources, run `terraform destroy`. Setiap langkah memberikan anda kawalan penuh terhadap apa yang berlaku kepada infrastructure anda. ### Practical: Provision VM di Proxmox Ini contoh yang sangat relevan untuk homelab. Kita akan guna Terraform untuk create VM di Proxmox. Buat file `main.tf`: ```hcl terraform { required_providers { proxmox = { source = "telmate/proxmox" version = "3.0.1-rc4" } } } provider "proxmox" { pm_api_url = "https://192.168.1.10:8006/api2/json" pm_api_token_id = "terraform@pam!terraform-token" pm_api_token_secret = var.proxmox_api_token pm_tls_insecure = true } variable "proxmox_api_token" { description = "Proxmox API token secret" type = string sensitive = true } variable "vm_count" { description = "Number of VMs to create" type = number default = 2 } resource "proxmox_vm_qemu" "web_server" { count = var.vm_count name = "web-${count.index + 1}" target_node = "pve" clone = "ubuntu-template" cores = 2 memory = 2048 sockets = 1 disk { storage = "local-lvm" size = "20G" type = "scsi" } network { model = "virtio" bridge = "vmbr0" } os_type = "cloud-init" ipconfig0 = "ip=192.168.1.${110 + count.index}/24,gw=192.168.1.1" ciuser = "syafi" sshkeys = file("~/.ssh/id_rsa.pub") lifecycle { ignore_changes = [ network, ] } } output "vm_ips" { value = [for vm in proxmox_vm_qemu.web_server : vm.default_ipv4_address] } ``` Buat file `terraform.tfvars` (jangan commit file ini ke Git): ```hcl proxmox_api_token = "your-api-token-secret-here" vm_count = 3 ``` Jalankan Terraform: ```bash # Initialize - download providers terraform init # Preview changes terraform plan # Apply changes - create the VMs terraform apply # Bila nak destroy semua terraform destroy ``` `terraform plan` akan tunjukkan apa yang akan dibuat. Review dengan teliti sebelum run `terraform apply`. Ini salah satu kekuatan Terraform. Anda boleh nampak exactly apa yang akan berubah sebelum ia berlaku. > **Nota Beginner:** Sentiasa run `terraform plan` sebelum `terraform apply`. Jadikan ia habit. Dalam production, ini boleh selamatkan anda daripada accidentally delete database atau resources penting. ### Practical: Provision di DigitalOcean Untuk cloud, prosesnya sangat serupa. Cuma provider yang berbeza. ```hcl terraform { required_providers { digitalocean = { source = "digitalocean/digitalocean" version = "~> 2.0" } } } provider "digitalocean" { token = var.do_token } variable "do_token" { description = "DigitalOcean API token" type = string sensitive = true } resource "digitalocean_droplet" "web" { image = "ubuntu-24-04-x64" name = "web-production" region = "sgp1" size = "s-1vcpu-1gb" ssh_keys = [digitalocean_ssh_key.default.fingerprint] tags = ["web", "production"] } resource "digitalocean_ssh_key" "default" { name = "my-ssh-key" public_key = file("~/.ssh/id_rsa.pub") } resource "digitalocean_firewall" "web" { name = "web-firewall" droplet_ids = [digitalocean_droplet.web.id] inbound_rule { protocol = "tcp" port_range = "22" source_addresses = ["0.0.0.0/0"] } inbound_rule { protocol = "tcp" port_range = "80" source_addresses = ["0.0.0.0/0"] } inbound_rule { protocol = "tcp" port_range = "443" source_addresses = ["0.0.0.0/0"] } outbound_rule { protocol = "tcp" port_range = "1-65535" destination_addresses = ["0.0.0.0/0"] } } output "web_ip" { value = digitalocean_droplet.web.ipv4_address } ``` Perhatikan pattern yang sama. Define provider, declare resources, run plan dan apply. Ini keindahan Terraform. Workflow yang sama untuk mana-mana platform. > **Nota Beginner:** Satu kesilapan yang biasa pada permulaan ialah meletakkan semua resources dalam satu file `main.tf` yang panjang. Walaupun Terraform membenarkan ini, practice yang lebih baik ialah pecahkan kepada beberapa files. Contohnya `providers.tf` untuk provider configuration, `variables.tf` untuk variable declarations, `main.tf` untuk resources utama, `outputs.tf` untuk output values, dan `firewall.tf` untuk security rules. Terraform akan automatically load semua `.tf` files dalam satu directory. ### Terraform Modules: Reusable Components Modules membolehkan anda package Terraform code untuk digunakan semula. Bayangkan anda selalu create VM dengan pattern yang sama. Jadikan ia module. Structure: ``` terraform/ modules/ web-server/ main.tf variables.tf outputs.tf environments/ staging/ main.tf production/ main.tf ``` File `modules/web-server/variables.tf`: ```hcl variable "name" { description = "Server name" type = string } variable "size" { description = "Droplet size" type = string default = "s-1vcpu-1gb" } variable "region" { description = "Droplet region" type = string default = "sgp1" } ``` File `modules/web-server/main.tf`: ```hcl resource "digitalocean_droplet" "this" { image = "ubuntu-24-04-x64" name = var.name region = var.region size = var.size } ``` File `modules/web-server/outputs.tf`: ```hcl output "ip_address" { value = digitalocean_droplet.this.ipv4_address } output "id" { value = digitalocean_droplet.this.id } ``` Guna module dalam `environments/production/main.tf`: ```hcl module "web_app" { source = "../../modules/web-server" name = "production-web" size = "s-2vcpu-4gb" region = "sgp1" } module "web_staging" { source = "../../modules/web-server" name = "staging-web" size = "s-1vcpu-1gb" region = "sgp1" } output "production_ip" { value = module.web_app.ip_address } ``` ### Terraform State Management State file adalah jantung Terraform. Ia track mapping antara code anda dan real infrastructure. Untuk projek solo atau homelab, local state file okay. Tetapi untuk team, anda perlu remote state. Contoh remote state menggunakan S3 (atau DigitalOcean Spaces): ```hcl terraform { backend "s3" { bucket = "my-terraform-state" key = "production/terraform.tfstate" region = "ap-southeast-1" endpoint = "https://sgp1.digitaloceanspaces.com" skip_credentials_validation = true skip_metadata_api_check = true skip_requesting_account_id = true skip_s3_checksum = true } } ``` > **Nota Beginner:** Jangan sekali-kali commit `terraform.tfstate` ke Git. File ini mungkin mengandungi sensitive data seperti passwords dan API keys. Tambahkan `*.tfstate` dan `*.tfstate.backup` dalam `.gitignore` anda. ### Terraform Commands Yang Perlu Anda Tahu Selain `init`, `plan`, `apply`, dan `destroy`, ada beberapa commands lain yang berguna dalam daily workflow. ```bash # Format semua Terraform files mengikut standard style terraform fmt # Validate configuration tanpa access provider APIs terraform validate # Tunjuk current state terraform show # List semua resources dalam state terraform state list # Import existing resource ke Terraform state terraform import aws_instance.web i-1234567890abcdef0 # Remove resource dari state tanpa destroy terraform state rm aws_instance.old_server # Refresh state untuk match actual infrastructure terraform refresh # Output values terraform output ``` `terraform import` sangat berguna bila anda ada existing infrastructure yang anda mahu start manage dengan Terraform. Daripada recreate, anda boleh import resource tersebut ke state file. `terraform fmt` pastikan semua files anda mengikut standard formatting. Saya recommend run command ini sebelum setiap commit. Anda boleh setup pre-commit hook untuk automate ini. ## Ansible vs Terraform: Bila Guna Yang Mana? Soalan ini sering ditanya. Jawapan ringkas: guna kedua-duanya, untuk tujuan yang berbeza. **Terraform** untuk provisioning. Create VMs, networks, DNS records, cloud resources. Terraform tahu macam mana nak create, update, dan destroy infrastructure. **Ansible** untuk configuration. Install software, configure services, deploy applications, manage users. Ansible tahu macam mana nak configure server yang sudah wujud. Workflow yang biasa: 1. Terraform create VM baru. 2. Terraform output IP address VM tersebut. 3. Ansible ambil IP address itu dan configure VM. Install Docker, setup firewall, deploy app. Contoh integration. Terraform create VM, kemudian trigger Ansible: ```hcl resource "proxmox_vm_qemu" "app_server" { name = "app-server" target_node = "pve" clone = "ubuntu-template" cores = 4 memory = 4096 provisioner "local-exec" { command = "sleep 30 && ansible-playbook -i '${self.default_ipv4_address},' setup.yml" } } ``` Ini adalah pattern yang sangat powerful. Infrastructure provisioning dan configuration management dalam satu workflow. Satu lagi scenario biasa. Anda guna Terraform untuk create cloud resources (VMs, databases, load balancers), kemudian Ansible untuk deploy dan configure applications pada VMs tersebut. Terraform output boleh dijadikan Ansible inventory secara dynamic. Contoh generate Ansible inventory daripada Terraform output: ```bash # Dapatkan IP dari Terraform output dan run Ansible terraform output -json vm_ips | jq -r '.[]' > /tmp/inventory.txt ansible-playbook -i /tmp/inventory.txt deploy.yml ``` Ini membolehkan anda automate keseluruhan flow dari infrastructure creation sampai application deployment dalam satu pipeline. ## GitOps: Manage Infrastructure Dengan Git GitOps bermaksud Git menjadi single source of truth untuk infrastructure anda. Semua changes melalui Git. Tiada manual changes. ### Structure Repository ``` infra/ ansible/ inventory/ homelab.ini production.ini playbooks/ setup-webserver.yml deploy-app.yml roles/ common/ docker/ nginx/ ansible.cfg requirements.yml terraform/ modules/ web-server/ database/ environments/ homelab/ main.tf terraform.tfvars production/ main.tf terraform.tfvars .gitignore README.md ``` ### .gitignore Untuk IaC ```gitignore # Terraform *.tfstate *.tfstate.backup .terraform/ *.tfvars !*.tfvars.example crash.log # Ansible *.retry # Secrets .env *secret* *credential* ``` > **Nota Beginner:** Buat file `terraform.tfvars.example` dengan dummy values sebagai reference. Ini membantu team members baru tahu variables apa yang diperlukan tanpa expose actual secrets. ### Workflow GitOps Workflow yang saya recommend: 1. **Buat branch baru** untuk setiap infrastructure change. 2. **Tulis code** Terraform atau Ansible. 3. **Run plan/check** untuk preview changes. 4. **Buat Pull Request** untuk review. 5. **Merge** selepas approved. 6. **Apply** changes (boleh automate dengan CI/CD). ```bash # Buat branch untuk infrastructure change git checkout -b feat/add-monitoring-server # Buat perubahan pada Terraform files # Edit main.tf # Run terraform plan untuk verify terraform plan -out=plan.out # Commit dan push git add . git commit -m "feat: add monitoring server" git push origin feat/add-monitoring-server # Buat PR, review, merge, then apply ``` Dalam production environment yang mature, `terraform apply` dijalankan oleh CI/CD pipeline selepas PR di-merge. Ini bermakna tiada siapa yang run Terraform dari laptop mereka. Semua melalui pipeline yang controlled dan auditable. ## Ringkasan Infrastructure as Code mengubah cara kita manage infrastructure daripada manual, error-prone process kepada automated, repeatable, dan version-controlled workflow. **Perkara penting yang anda belajar:** - IaC menyelesaikan masalah consistency, reproducibility, dan scalability. - Ansible sesuai untuk configuration management. Guna inventories untuk senarai server, playbooks untuk tasks, dan roles untuk organisasi. - Terraform sesuai untuk infrastructure provisioning. Guna providers untuk connect ke platform, resources untuk define infrastructure, dan modules untuk reusability. - Guna Terraform untuk create infrastructure, Ansible untuk configure. Kedua-dua tools saling melengkapi. - GitOps menjadikan Git sebagai single source of truth. Semua changes melalui Git dan boleh di-track, di-review, dan di-audit. - Jangan commit secrets dan state files ke Git. Pada bab seterusnya, kita akan belajar tentang monitoring dan observability. Sebab infrastructure yang automated tanpa monitoring adalah macam kereta tanpa dashboard. Anda tidak tahu apa yang sedang berlaku. \newpage