1. Mengapa Kubernetes di Raspberry Pi?
Kubernetes di Raspberry Pi bukan hanya untuk belajar — ini adalah cara yang sangat efektif untuk mengelola edge computing, IoT gateway, dan microservices di lingkungan resource-limited. Dengan k3s (lightweight Kubernetes dari Rancher/SUSE), kita bisa menjalankan cluster production-grade di hardware yang hemat listrik.
k3s vs K8s vs MicroK8s
| Fitur | k3s | Full K8s | MicroK8s |
|---|---|---|---|
| Memory | ~512 MB | ~2 GB | ~1 GB |
| Disk | ~100 MB | ~1 GB | ~300 MB |
| Binary | Single binary | Multiple | Snap package |
| ARM Support | Native | Manual | Native |
| HA Cluster | Ya (embedded etcd) | Ya (etcd) | Ya (dqlite) |
| Install | 1 command | kubeadm (kompleks) | snap install |
| Cocok untuk | Edge, IoT, Homelab | Production cloud | Development |
- ✅ Single binary ~100MB
- ✅ SQLite atau embedded etcd
- ✅ Built-in Traefik ingress
- ✅ CNCF certified
- ✅ Install 1 command
- ✅ IoT edge computing
- ✅ Home automation
- ✅ CI/CD homelab
- ✅ Microservices learning
- ✅ Low-power server
2. Hardware yang Dibutuhkan
| Komponen | Rekomendasi | Estimasi Harga |
|---|---|---|
| Raspberry Pi 4 (x3-4) | 4GB RAM per unit | Rp 800rb × 4 |
| MicroSD Card | 32GB Class 10 / A2 per unit | Rp 80rb × 4 |
| Power Supply | USB-C 5V/3A per unit | Rp 80rb × 4 |
| Ethernet Switch | Gigabit 5-8 port | Rp 150rb |
| Ethernet Cable | Cat5e/Cat6 | Rp 20rb × 4 |
| Case + Fan (opsional) | Cluster case 3D-printed | Rp 200rb |
| NAS/USB HDD (opsional) | Untuk persistent storage | Rp 300rb |
Untuk belajar, 2 unit Raspberry Pi 4 (2GB) sudah cukup — 1 server + 1 worker. Tapi untuk cluster yang lebih robust, 3-4 unit (4GB) direkomendasikan.
3. Setup OS Raspberry Pi
# 1. Download Raspberry Pi OS Lite (64-bit)
# dari https://www.raspberrypi.com/software/
# Pilih "Raspberry Pi OS Lite (64-bit)"
# 2. Flash ke SD card menggunakan Raspberry Pi Imager
# Atau gunakan dd:
sudo dd if=rpios-lite-arm64.img of=/dev/sdX bs=4M status=progress
# 3. Sebelum eject, aktifkan SSH dan set hostname
# Mount boot partition lalu buat file:
touch /media/$USER/boot/ssh
# 4. Set hostname unik untuk setiap node
echo "k3s-master" > /media/$USER/etc/hostname
# Atau gunakan Raspberry Pi Imager untuk advanced settings
# 5. Boot Pi dan SSH masuk
ssh pi@raspberrypi.local
# 6. Update sistem
sudo apt update && sudo apt upgrade -y
# 7. Install essentials
sudo apt install -y curl git vim net-tools
# 8. Set static IP (opsional tapi recommended)
# Edit /etc/dhcpcd.conf:
sudo tee -a /etc/dhcpcd.conf <<'EOF'
interface eth0
static ip_address=192.168.1.10/24
static routers=192.168.1.1
static domain_name_servers=8.8.8.8 1.1.1.1
EOF
# 9. Disable swap (required untuk Kubernetes)
sudo dphys-swapfile swapoff
sudo dphys-swapfile uninstall
sudo systemctl disable dphys-swapfile
# 10. Enable cgroup memory (required untuk k3s)
# Edit /boot/firmware/cmdline.txt, tambahkan:
# cgroup_memory=1 cgroup_enable=memory
echo " cgroup_memory=1 cgroup_enable=memory" | sudo tee -a /boot/firmware/cmdline.txt
# 11. Reboot
sudo reboot
4. Install k3s Cluster
k3s terkenal karena kemudahan install-nya — cukup satu command!
# Install k3s server (master node)
# --disable servicelb: kita pakai MetalLB sebagai gantinya
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--disable servicelb --write-kubeconfig-mode 644" sh -
# Cek status
sudo systemctl status k3s
kubectl get nodes
kubectl get pods -A
# Dapatkan node token (untuk join worker)
sudo cat /var/lib/rancher/k3s/server/node-token
# Export kubeconfig untuk remote access
# (jalankan di laptop kamu, bukan di Pi)
mkdir -p ~/.kube
scp pi@192.168.1.10:/etc/rancher/k3s/k3s.yaml ~/.kube/config
# Edit server URL di kubeconfig
sed -i 's/127.0.0.1/192.168.1.10/g' ~/.kube/config
# Verifikasi dari laptop
kubectl get nodes
kubectl cluster-info
5. Multi-Node: Worker Nodes
# Di setiap worker node (k3s-worker1, k3s-worker2, dll):
# Install k3s agent dan join ke cluster
# Ganti SERVER_IP dan TOKEN sesuai master
curl -sfL https://get.k3s.io | K3S_URL="https://192.168.1.10:6443" K3S_TOKEN="TOKEN_DARI_MASTER" sh -
# Verifikasi dari master node
kubectl get nodes
# Harusnya terlihat:
# NAME STATUS ROLES AGE VERSION
# k3s-master Ready control-plane,master 5m v1.30+k3s1
# k3s-worker1 Ready <none> 2m v1.30+k3s1
# k3s-worker2 Ready <none> 1m v1.30+k3s1
# Label worker nodes
kubectl label node k3s-worker1 node-role.kubernetes.io/worker=worker
kubectl label node k3s-worker2 node-role.kubernetes.io/worker=worker
# Cek semua pods berjalan
kubectl get pods -A -o wide
6. MetalLB Load Balancer
k3s default menggunakan ServiceLB yang terbatas. MetalLB menyediakan LoadBalancer service yang proper dengan IP address pool dari jaringan lokal kita.
# Install MetalLB
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.5/config/manifests/metallb-native.yaml
# Tunggu hingga pods ready
kubectl wait --namespace metallb-system --for=condition=ready pod --selector=app=metallb --timeout=120s
# Buat IP address pool
cat <<'EOF' | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: default-pool
namespace: metallb-system
spec:
addresses:
- 192.168.1.200-192.168.1.250
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: default
namespace: metallb-system
spec:
ipAddressPools:
- default-pool
EOF
# Verifikasi
kubectl get ipaddresspool -n metallb-system
# MetalLB akan assign IP dari pool ini ke LoadBalancer services
7. Ingress Controller (Nginx)
# Install Nginx Ingress Controller
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.10.1/deploy/static/provider/baremetal/deploy.yaml
# Tunggu hingga ready
kubectl wait --namespace ingress-nginx --for=condition=ready pod --selector=app.kubernetes.io/component=controller --timeout=120s
# Cek External IP (dari MetalLB)
kubectl get svc -n ingress-nginx
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
# ingress-nginx-controller LoadBalancer 10.43.x.x 192.168.1.200 80:xxxxx/TCP,443:xxxxx/TCP
# Contoh Ingress rule
cat <<'EOF' | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: grafana-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: grafana.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: grafana
port:
number: 3000
EOF
# Tambahkan DNS di laptop: /etc/hosts
# 192.168.1.200 grafana.local
8. Persistent Storage dengan NFS
Persistent storage sangat penting untuk database dan stateful applications. Di RPi cluster, NFS server adalah solusi yang paling praktis.
# Install NFS server di master node
sudo apt install -y nfs-kernel-server
# Buat shared directory
sudo mkdir -p /srv/nfs/k3s
sudo chown nobody:nogroup /srv/nfs/k3s
# Configure exports
echo "/srv/nfs/k3s 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)" | sudo tee /etc/exports
sudo exportfs -ra
# Restart NFS
sudo systemctl restart nfs-kernel-server
sudo systemctl enable nfs-kernel-server
# Install NFS CSI driver di k3s
cat <<'EOF' | kubectl apply -f -
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-storage
provisioner: nfs.csi.k8s.io
parameters:
server: 192.168.1.10
share: /srv/nfs/k3s
reclaimPolicy: Retain
volumeBindingMode: Immediate
mountOptions:
- nfsvers=4.1
EOF
# Contoh PersistentVolumeClaim
cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: grafana-pvc
spec:
storageClassName: nfs-storage
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
EOF
9. Deploy Aplikasi IoT
Deploy aplikasi monitoring IoT menggunakan MQTT broker (Mosquitto), Grafana, dan InfluxDB di cluster.
apiVersion: apps/v1
kind: Deployment
metadata:
name: mosquitto
spec:
replicas: 1
selector:
matchLabels:
app: mosquitto
template:
metadata:
labels:
app: mosquitto
spec:
containers:
- name: mosquitto
image: eclipse-mosquitto:2
ports:
- containerPort: 1883
name: mqtt
- containerPort: 9001
name: websocket
volumeMounts:
- name: config
mountPath: /mosquitto/config
- name: data
mountPath: /mosquitto/data
resources:
limits:
memory: "128Mi"
cpu: "200m"
volumes:
- name: config
configMap:
name: mosquitto-config
- name: data
persistentVolumeClaim:
claimName: mosquitto-pvc
---
apiVersion: v1
kind: Service
metadata:
name: mosquitto
spec:
type: LoadBalancer
selector:
app: mosquitto
ports:
- port: 1883
targetPort: 1883
name: mqtt
- port: 9001
targetPort: 9001
name: websocket