Cloud-init adalah framework open-source yang digunakan untuk menginisialisasi dan mengonfigurasi VM secara otomatis saat first boot. Cloud-init memungkinkan otomatisasi konfigurasi seperti:
- Pembuatan user
- Pengaturan password & SSH key
- Konfigurasi jaringan
- Instalasi paket dan service
Cloud-init membaca data konfigurasi dari berbagai datasource, seperti:
- File ISO (NoCloud)
- Metadata provider cloud (AWS, GCP, OpenStack, dsb.)
- Layanan metadata jaringan
Setelah membaca konfigurasi, cloud-init mengeksekusi instruksi sesuai file yang diberikan.
Prerequisites #
Pastikan sistem sudah terinstal:
- QEMU / KVM
- Libvirt
- genisoimage
Contoh instalasi di Ubuntu / Debian:
sudo apt install qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils genisoimage
Struktur File Konfigurasi Cloud-init #
Buat direktori untuk menyimpan file konfigurasi:
mkdir -p /opt/cloudinit
Cloud-init menggunakan tiga file utama:
| File | Fungsi |
|---|---|
meta-data |
Identitas instance |
user-data |
Konfigurasi sistem & user |
network-config |
Konfigurasi jaringan (opsional) |
File meta-data #
Buat file meta-data (minimal):
instance-id: 215b8931ab97deea82032a53cfcd8b0fb4302241
local-hostname: cloud-vm
Generate instance-id:
openssl rand -hex 20
File user-data #
Buat file user-data:
#cloud-config
hostname: cloud-vm
manage_etc_hosts: true
fqdn: cloud-vm.example.com
ssh_pwauth: false
disable_root: true
chpasswd:
expire: false
users:
- name: devops
gecos: DevOps Admin
groups:
- sudo
- wheel
sudo: ALL=(ALL) NOPASSWD:ALL
lock_passwd: true
ssh_authorized_keys:
- ssh-rsa AAAAB3NzaC1yc2E... devops@host
shell: /bin/bash
write_files:
- path: /etc/ssh/sshd_config.d/99-hardening.conf
content: |
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AllowUsers devops
swap:
filename: /swapfile
size: auto
maxsize: 1G
package_update: true
package_upgrade: false
package_reboot_if_required: true
packages:
- curl
- wget
- nano
- zip
- unzip
- lsof
- net-tools
- screen
- git
- python3-pip
- htop
- unzip
timezone: Asia/Jakarta
runcmd:
- sort -u /etc/fstab -o /etc/fstab
- pip3 install "resolvelib>=0.5.3,<0.9.0"
- echo "Cloud-init completed on $(date)" > /root/cloud-init.log
final_message: |
Cloud-init completed successfully.
Host: $hostname
Version: $version
Datasource: $datasource
Uptime: $uptime
File network-config #
Buat file network-config untuk konfigurasi network statis (opsional).
version: 1
config:
- type: physical
name: eth0
mac_address: 'bc:24:11:79:f9:5e'
subnets:
- type: static
address: '192.168.100.111'
netmask: '255.255.255.0'
gateway: '192.168.100.208'
- type: dhcp6
- type: nameserver
address:
- '192.168.100.10'
- '1.1.1.1'
search:
- 'example.com'
Buat Cloud-init ISO atau Disk Image #
Cloud-init NoCloud datasource membutuhkan media (ISO atau disk) berisi file:
user-datameta-datanetwork-config(opsional)
Membuat Cloud-init ISO (Recommended) #
Gunakan genisoimage atau mkisofs:
genisoimage -quiet -iso-level 3 -J -R -V cidata \
-o /opt/cloudinit.iso \
/opt/cloudinit/user-data \
/opt/cloudinit/meta-data \
/opt/cloudinit/network-config
👉 Best practice: sebut file satu per satu, jangan folder, agar kompatibel dengan semua hypervisor.
Alternatif Modern (Cloud-Localds – Lebih Rapi).
cloud-localds /opt/cloudinit.iso user-data meta-data --network-config=network-config
Membuat Cloud-init Disk Image (QCOW2) #
genisoimage -quiet -iso-level 3 -J -R -V cidata -o /opt/cloudinit.iso /opt/cloudinit | qemu-img convert -f raw -O qcow2 /opt/cloudinit.iso /opt/cloudinit.qcow2
Deploy VM dengan virt-install #
virt-install \
--name ubuntu-vm \
--memory 2048 \
--vcpus 2 \
--disk path=vm1.qcow2,format=qcow2,bus=virtio \
--disk path=/opt/cloudinit.iso,device=cdrom \
--network network=default \
--os-variant ubuntu24.04 \
--import \
--graphics none \
--noautoconsole
Integrasi Cloud-init ke Libvirt XML Template #
Menggunakan File ISO #
<disk type="file" device="cdrom">
<driver name="qemu" type="raw"/>
<source file="/opt/cloudinit.iso"/>
<target dev="sda" bus="sata"/>
<readonly/>
</disk>
Menggunakan Disk Image (Virtio) #
<disk type="file" device="disk">
<driver name="qemu" type="qcow2"/>
<source file="/opt/cloudinit.qcow2"/>
<target dev="vda" bus="virtio"/>
</disk>
Re-run Cloud-init (Reset State) #
Cloud-init hanya berjalan sekali saat first boot.
Untuk menjalankan ulang:
cloud-init clean --logs
reboot
Notes #
1. Cloud-init Datasource Check #
cloud-init status --long
cloud-init query ds
2. Debug Cloud-init #
less /var/log/cloud-init.log
less /var/log/cloud-init-output.log
3. Force Re-run Specific Modules #
cloud-init clean
cloud-init init
cloud-init modules --mode=config
cloud-init modules --mode=final
Cloud-config Reference #
Ansible Integration (cloud-init) #
Cloud-init dapat menginstal dan menjalankan Ansible secara otomatis.
ansible:
install_method: distro # distro | pip | none
package_name: ansible # default: ansible
pull:
url: https://github.com/holmanb/vmboot.git
playbook_name: ubuntu.yml
galaxy:
actions:
- ['ansible-galaxy', 'collection', 'install', 'community.general']
- ['ansible-galaxy', 'collection', 'install', 'ansible.posix']
Catatan:
pullmode cocok untuk immutable bootstrap- Untuk production CI/CD biasanya pakai Ansible controller terpisah, bukan cloud-init
Disk Setup (Partition + Filesystem + Mount) #
Cloud-init bisa membuat partition otomatis pada disk baru.
device_aliases:
disk1: /dev/sdb
disk_setup:
disk1:
table_type: gpt
layout: true
overwrite: true
fs_setup:
- device: disk1
filesystem: ext4
label: fs1
mounts:
- [/dev/sdb1, /mnt1]
Growpart (Resize Disk Partition) #
Digunakan untuk auto-resize disk (cloud volume).
growpart:
devices:
- /dev/sdb1
ignore_growroot_disabled: false
mode: auto
NTP Configuration #
ntp:
enabled: true
ntp_client: chrony
servers:
- 0.pool.ntp.org
- 1.pool.ntp.org
Cloud-config examples #
Writing Arbitrary Files (write_files)
#
Cloud-init dapat menulis file dengan berbagai encoding.
Base64 encoded file:
#cloud-config
write_files:
- encoding: b64
content: CiMgVGhpcyBmaWxlIGNvbnRyb2xzIHRoZSBzdGF0ZSBvZiBTRUxpbnV4...
owner: root:root
path: /etc/sysconfig/selinux
permissions: '0644'
Multi-line text file:
- content: |
# My new /etc/sysconfig/samba file
SMBDOPTIONS="-D"
path: /etc/sysconfig/samba
permissions: '0644'
Binary file (ELF, scripts, tools):
- content: !!binary |
f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAAwARAAAAAAABAAAAAAAAAAJAV...
path: /bin/arch
permissions: '0555'
Gzip compressed binary:
- encoding: gzip
content: !!binary |
H4sIAIDb/U8C/1NW1E/KzNMvzuBKTc7IV8hIzcnJVyjPL8pJ4QIA6N+MVxsAAAA=
path: /usr/bin/hello
permissions: '0755'
Run Commands Very Early at Every Boot (boothook) #
#cloud-boothook dieksekusi sangat awal, bahkan sebelum network fully configured.
#cloud-boothook
#!/bin/sh
echo "192.168.1.130 us.archive.ubuntu.com" >> /etc/hosts
Run Script Every Boot (script-per-boot) #
Cocok untuk compliance check, auto-healing, ephemeral cloud workloads.
#cloud-config
runcmd:
- curl -fsSL https://bootstrap.corp.local/agent.sh | bash
write_files:
- path: /var/lib/cloud/scripts/per-boot/healthcheck.sh
permissions: '0755'
content: |
#!/bin/bash
curl -X POST https://health.corp.local/report
Cloud-init memiliki mekanisme untuk menjalankan skrip shell secara otomatis tergantung di mana skrip tersebut ditempatkan.
| Direktori | Kapan Skrip Dijalankan | Karakteristik |
|---|---|---|
/var/lib/cloud/scripts/per-instance |
Sekali per instance (biasanya saat boot pertama setelah VM dibuat) | Skrip hanya dijalankan sekali untuk setiap instance baru. Jika instance di-reboot, skrip tidak dijalankan lagi. Cocok untuk inisialisasi khusus instance. |
/var/lib/cloud/scripts/per-once |
Sekali saja, tidak peduli berapa kali instance dibuat atau di-reboot | Skrip dijalankan hanya sekali sepanjang hidup sistem. Setelah itu tidak akan pernah dijalankan lagi. Biasanya untuk konfigurasi permanen yang tidak boleh diulang. |
/var/lib/cloud/scripts/per-boot |
Setiap kali sistem boot | Skrip dijalankan setiap kali mesin di-reboot. Cocok untuk tugas yang harus dilakukan berulang kali, misalnya membersihkan cache atau memulai ulang layanan. |
/var/lib/cloud/scripts/vendor |
Tergantung vendor cloud atau distribusi | Direktori ini biasanya digunakan oleh penyedia cloud atau distribusi OS untuk menaruh skrip bawaan. Perilakunya bisa berbeda tergantung vendor, tapi umumnya digunakan untuk konfigurasi tambahan dari penyedia. |