Kubernetes Local Development dengan Minikube

by Marcus Chen
Kubernetes Local Development dengan Minikube

Masalahnya: Deploy ke Staging Cuma Buat Test Satu Baris Config

Skenario yang familiar: kamu ubah satu environment variable di Deployment manifest, push ke repo, tunggu CI pipeline jalan 8 menit, baru ketahuan ada typo di nama key. Ulangi dari awal.

Kalau tim kamu pakai shared staging cluster, masalahnya lebih parah — kamu nggak bisa seenaknya eksperimen karena bisa ganggu orang lain yang lagi kerja di environment yang sama.

Solusinya simpel: jalankan Kubernetes di laptop kamu sendiri. Kubernetes local development dengan Minikube adalah cara paling cepat untuk dapat full Kubernetes cluster tanpa bayar cloud, tanpa ganggu siapapun.

Artikel ini akan setup Minikube dari nol, deploy aplikasi nyata, expose service-nya, dan bahas gotcha yang sering bikin orang stuck di awal.


Kenapa Minikube, Bukan Kind atau K3s?

Ada beberapa opsi untuk local Kubernetes:

  • Kind (Kubernetes in Docker) — bagus untuk CI, tapi kurang nyaman untuk development interaktif.
  • K3s — lightweight, cocok untuk Raspberry Pi atau VM, tapi setup-nya lebih manual.
  • Minikube — punya built-in addons (ingress, dashboard, metrics-server), driver yang fleksibel, dan tooling yang mature.

Untuk developer yang mau langsung produktif tanpa banyak konfigurasi manual, Minikube adalah pilihan yang masuk akal. Bukan berarti yang lain jelek — tapi untuk use case "gue mau coba manifest ini sekarang", Minikube paling sedikit friction-nya.


Install Minikube dan kubectl

macOS

# Install via Homebrew
brew install minikube
brew install kubectl

Linux (Ubuntu/Debian)

# Download binary Minikube
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube

# Install kubectl
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl

Windows

# Pakai winget
winget install minikube
winget install Kubernetes.kubectl

Pastikan kamu sudah punya Docker Desktop atau VirtualBox terinstall sebelum lanjut. Minikube butuh hypervisor atau container runtime untuk spin up cluster-nya.


Start Cluster Pertama Kamu

# Start dengan Docker driver (paling umum)
minikube start --driver=docker

# Kalau mau set resource lebih besar
minikube start --driver=docker --cpus=4 --memory=4096

Output yang normal kira-kira seperti ini:

😄  minikube v1.33.0 on Darwin 14.4
✨  Using the docker driver based on existing profile
👍  Starting "minikube" primary control-plane node in "minikube" cluster
🚜  Pulling base image v0.0.44 ...
🔄  Restarting existing docker container for "minikube" ...
🐳  Preparing Kubernetes v1.30.0 on Docker 26.1.1 ...
🔎  Verifying Kubernetes components...
🌟  Enabled addons: storage-provisioner, default-storageclass
🏄  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default

Verifikasi cluster sudah jalan:

kubectl cluster-info
kubectl get nodes
NAME       STATUS   ROLES           AGE   VERSION
minikube   Ready    control-plane   2m    v1.30.0

Deploy Aplikasi Pertama ke Cluster Lokal

Kita akan deploy aplikasi sederhana — nginx dengan custom config — supaya kamu bisa lihat full flow dari manifest sampai bisa diakses di browser.

Buat file deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-app
  labels:
    app: demo-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: demo-app
  template:
    metadata:
      labels:
        app: demo-app
    spec:
      containers:
      - name: demo-app
        image: nginx:alpine
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: "64Mi"
            cpu: "100m"
          limits:
            memory: "128Mi"
            cpu: "200m"

Buat juga service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: demo-app-svc
spec:
  selector:
    app: demo-app
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: NodePort

Apply kedua manifest:

kubectl apply -f deployment.yaml
kubectl apply -f service.yaml

Cek status pod:

kubectl get pods -w
NAME                        READY   STATUS    RESTARTS   AGE
demo-app-7d9f8b6c4-k2xpq   1/1     Running   0          30s
demo-app-7d9f8b6c4-m8rvt   1/1     Running   0          30s

Akses service-nya:

minikube service demo-app-svc

Perintah ini otomatis buka browser ke URL yang benar. Kalau mau URL-nya saja:

minikube service demo-app-svc --url

Pakai Image Lokal Tanpa Push ke Registry

Ini salah satu bagian yang paling sering bikin frustrasi saat development: kamu build image baru di laptop, tapi Kubernetes tetap pull image lama karena dia nggak tahu image lokal kamu.

Ada dua cara handle ini:

Cara 1: Pakai Minikube Docker Daemon

# Point Docker CLI ke daemon minikube
eval $(minikube docker-env)

# Build image — sekarang image masuk ke daemon minikube, bukan Docker desktop kamu
docker build -t my-app:dev .

# Deploy dengan imagePullPolicy: Never

Pastikan di manifest kamu set imagePullPolicy: Never:

spec:
  containers:
  - name: my-app
    image: my-app:dev
    imagePullPolicy: Never

Kalau kamu skip imagePullPolicy: Never, Kubernetes akan coba pull dari registry dan gagal karena image my-app:dev nggak ada di Docker Hub.

Cara 2: Load Image Langsung

# Build dulu di Docker normal
docker build -t my-app:dev .

# Load ke minikube
minikube image load my-app:dev

Cara kedua lebih lambat untuk image besar, tapi lebih straightforward dan nggak perlu ingat untuk eval setiap buka terminal baru.


Enable Ingress untuk Routing yang Lebih Realistis

NodePort bagus untuk quick test, tapi production setup biasanya pakai Ingress. Minikube punya addon ingress yang bisa di-enable dengan satu perintah:

minikube addons enable ingress

# Verifikasi
kubectl get pods -n ingress-nginx

Tunggu sampai pod ingress-nginx-controller statusnya Running, biasanya 1-2 menit.

Buat ingress.yaml:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demo-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: demo.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: demo-app-svc
            port:
              number: 80
kubectl apply -f ingress.yaml

Dapatkan IP minikube:

minikube ip
# Output: 192.168.49.2 (atau IP lain)

Tambahkan ke /etc/hosts:

echo "$(minikube ip) demo.local" | sudo tee -a /etc/hosts

Sekarang kamu bisa akses http://demo.local di browser, persis seperti setup production.


Gotcha yang Sering Bikin Stuck

1. Pod stuck di ImagePullBackOff

Hampir selalu karena image nggak ada di registry atau typo nama image. Cek dengan:

kubectl describe pod <pod-name>

Lihat bagian Events di paling bawah output. Kalau kamu pakai image lokal, pastikan sudah eval $(minikube docker-env) sebelum build, atau sudah minikube image load.

2. minikube start gagal karena Docker nggak jalan

# Cek status Docker
docker ps

# Kalau error, restart Docker daemon dulu
sudo systemctl restart docker  # Linux

3. Service NodePort nggak bisa diakses langsung

Di macOS dan Windows, Minikube jalan di dalam VM atau container, jadi IP node-nya nggak langsung accessible dari host. Selalu pakai minikube service <service-name> atau kubectl port-forward:

kubectl port-forward svc/demo-app-svc 8080:80
# Akses di http://localhost:8080

4. Cluster lambat setelah laptop sleep

# Stop dan start ulang
minikube stop
minikube start

Jangan langsung minikube delete kecuali kamu memang mau reset semua. stop + start biasanya cukup.

5. Disk penuh karena image numpuk

# Lihat image di minikube
minikube image ls

# Hapus image yang nggak dipakai
minikube image rm <image-name>

# Nuclear option: hapus semua dan mulai fresh
minikube delete
minikube start

Workflow yang Gue Pakai Sehari-hari

Setup Kubernetes local development dengan Minikube jadi jauh lebih smooth kalau kamu punya workflow yang consistent. Ini yang gue pakai:

# Pagi: start cluster
minikube start

# Sebelum build image baru
eval $(minikube docker-env)

# Build dan deploy
docker build -t my-app:dev .
kubectl rollout restart deployment/my-app

# Monitor
kubectl get pods -w
kubectl logs -f deployment/my-app

# Malam: stop supaya nggak makan resource
minikube stop

Satu hal yang gue tambahkan ke .zshrc / .bashrc supaya nggak lupa:

alias mk='minikube'
alias kc='kubectl'
alias mk-env='eval $(minikube docker-env)'

Untuk langkah lanjutan, coba explore:

  • Helm untuk manage complex deployments — minikube addons enable helm-tiller sudah deprecated, install Helm CLI langsung.
  • Skaffold atau Tilt untuk hot-reload otomatis setiap kali kamu ubah kode — ini yang benar-benar mengubah development loop jadi cepat.
  • Minikube dashboard (minikube dashboard) untuk visualisasi cluster kalau kamu lebih nyaman dengan UI.
  • Multi-node cluster untuk test behavior yang lebih mirip production: minikube start --nodes=3.

Kalau kamu sudah comfortable dengan Minikube, langkah logis berikutnya adalah setup Skaffold supaya setiap git save otomatis rebuild dan redeploy ke cluster lokal kamu. Itu topik untuk artikel berikutnya.