Provision Cluster #
Membangun cluster Kubernetes dari awal adalah proses yang melibatkan banyak langkah berurutan: setup OS yang konsisten di semua node, instalasi container runtime, instalasi komponen Kubernetes, inisialisasi control plane, dan join worker nodes. Melakukan ini secara manual di 10+ server adalah pekerjaan yang melelahkan dan rawan kesalahan. Ansible mengotomasi seluruh proses ini menjadi satu perintah yang bisa diulang dan menghasilkan cluster yang identik setiap kali.
Struktur Inventory untuk Kubernetes #
# inventory/k8s-cluster/hosts.ini
[control_plane]
k8s-master-01 ansible_host=10.0.1.10
k8s-master-02 ansible_host=10.0.1.11 # Untuk HA control plane
k8s-master-03 ansible_host=10.0.1.12
[worker_nodes]
k8s-worker-01 ansible_host=10.0.2.10
k8s-worker-02 ansible_host=10.0.2.11
k8s-worker-03 ansible_host=10.0.2.12
[k8s_cluster:children]
control_plane
worker_nodes
Persiapan OS di Semua Node #
Sebelum menginstal Kubernetes, semua node harus dikonfigurasi dengan cara yang sama:
# roles/k8s-common/tasks/main.yml
---
- name: Nonaktifkan swap (Kubernetes tidak support swap)
command: swapoff -a
changed_when: false
- name: Pastikan swap dinonaktifkan permanen
replace:
path: /etc/fstab
regexp: '^([^#].*?\sswap\s+sw\s+.*)$'
replace: '# \1'
- name: Load kernel module yang diperlukan
modprobe:
name: "{{ item }}"
state: present
loop:
- overlay
- br_netfilter
- name: Pastikan module dimuat saat boot
template:
src: k8s-modules.conf.j2
dest: /etc/modules-load.d/k8s.conf
- name: Konfigurasi sysctl untuk Kubernetes networking
sysctl:
name: "{{ item.key }}"
value: "{{ item.value }}"
state: present
reload: true
loop:
- { key: "net.bridge.bridge-nf-call-iptables", value: "1" }
- { key: "net.bridge.bridge-nf-call-ip6tables", value: "1" }
- { key: "net.ipv4.ip_forward", value: "1" }
Instalasi Container Runtime (containerd) #
Kubernetes modern menggunakan containerd sebagai container runtime:
# roles/containerd/tasks/main.yml
---
- name: Install containerd
apt:
name: containerd.io
state: present
- name: Buat direktori konfigurasi containerd
file:
path: /etc/containerd
state: directory
- name: Generate konfigurasi default containerd
command: containerd config default
register: containerd_default_config
changed_when: false
- name: Simpan konfigurasi containerd
copy:
content: "{{ containerd_default_config.stdout }}"
dest: /etc/containerd/config.toml
- name: Aktifkan SystemdCgroup di containerd
replace:
path: /etc/containerd/config.toml
regexp: 'SystemdCgroup = false'
replace: 'SystemdCgroup = true'
notify: Restart containerd
- name: Pastikan containerd berjalan
systemd:
name: containerd
state: started
enabled: true
Instalasi Komponen Kubernetes #
# roles/k8s-packages/tasks/main.yml
---
- name: Tambahkan GPG key Kubernetes
apt_key:
url: https://pkgs.k8s.io/core:/stable:/v{{ k8s_minor_version }}/deb/Release.key
state: present
- name: Tambahkan repository Kubernetes
apt_repository:
repo: "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v{{ k8s_minor_version }}/deb/ /"
state: present
- name: Install kubeadm, kubelet, kubectl
apt:
name:
- "kubelet={{ k8s_version }}-*"
- "kubeadm={{ k8s_version }}-*"
- "kubectl={{ k8s_version }}-*"
state: present
update_cache: true
- name: Pin versi Kubernetes agar tidak terupdate otomatis
dpkg_selections:
name: "{{ item }}"
selection: hold
loop:
- kubelet
- kubeadm
- kubectl
Inisialisasi Control Plane #
# playbooks/init-control-plane.yml
---
- name: Inisialisasi Kubernetes control plane
hosts: control_plane[0] # Hanya di control plane pertama
become: true
tasks:
- name: Cek apakah cluster sudah diinisialisasi
stat:
path: /etc/kubernetes/admin.conf
register: k8s_init_check
- name: Inisialisasi cluster dengan kubeadm
command: >
kubeadm init
--pod-network-cidr={{ pod_network_cidr }}
--control-plane-endpoint={{ control_plane_endpoint }}
--kubernetes-version={{ k8s_version }}
register: kubeadm_init
when: not k8s_init_check.stat.exists
- name: Buat direktori .kube untuk user current
file:
path: "{{ ansible_env.HOME }}/.kube"
state: directory
- name: Copy kubeconfig ke home directory
copy:
src: /etc/kubernetes/admin.conf
dest: "{{ ansible_env.HOME }}/.kube/config"
remote_src: true
owner: "{{ ansible_user }}"
- name: Ambil join command untuk worker nodes
command: kubeadm token create --print-join-command
register: join_command
changed_when: false
- name: Simpan join command sebagai fact
set_fact:
k8s_join_command: "{{ join_command.stdout }}"
delegate_to: localhost
delegate_facts: true
- name: Install CNI plugin (Calico)
command: kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
environment:
KUBECONFIG: /etc/kubernetes/admin.conf
when: not k8s_init_check.stat.exists
Join Worker Nodes #
# playbooks/join-workers.yml
---
- name: Join worker nodes ke cluster
hosts: worker_nodes
become: true
tasks:
- name: Cek apakah node sudah bergabung ke cluster
stat:
path: /etc/kubernetes/kubelet.conf
register: kubelet_conf
- name: Join node ke cluster
command: "{{ hostvars['localhost']['k8s_join_command'] }}"
when: not kubelet_conf.stat.exists
- name: Tunggu node menjadi Ready
command: >
kubectl get node {{ ansible_hostname }}
--kubeconfig /etc/kubernetes/admin.conf
-o jsonpath='{.status.conditions[-1].type}'
register: node_status
until: node_status.stdout == "Ready"
retries: 20
delay: 15
delegate_to: "{{ groups['control_plane'][0] }}"
changed_when: false
Ambil kubeconfig ke Control Node #
- name: Ambil kubeconfig ke control node lokal
hosts: control_plane[0]
tasks:
- name: Fetch kubeconfig
fetch:
src: /etc/kubernetes/admin.conf
dest: "{{ playbook_dir }}/kubeconfig/admin.conf"
flat: true
Ringkasan #
- Swap harus dinonaktifkan di semua node sebelum menginstal Kubernetes — Kubernetes tidak mendukung swap.
- Konfigurasi sysctl (
br_netfilter,ip_forward) wajib diaktifkan agar networking Kubernetes berfungsi.- Gunakan
containerddenganSystemdCgroup = truesebagai container runtime — ini adalah konfigurasi yang direkomendasikan.- Pin versi kubeadm, kubelet, dan kubectl dengan
hold— update yang tidak disengaja bisa merusak cluster.- Inisialisasi control plane hanya sekali di satu node — gunakan
control_plane[0]sebagai target host.- Simpan join command dari control plane sebagai fact dan gunakan di playbook join worker — jangan hardcode di inventory.
- Selalu fetch kubeconfig ke control node setelah cluster siap agar bisa mengelola cluster dari lokal.
← Sebelumnya: Apa itu Kubernetes? Berikutnya: Deploy Manifest →