Di episode ini kita akan coba bahas managing Kubernetes object menggunakan imperative dan declarative approach. Kita akan mempelajari perbedaan, kapan gunakan setiap method, dan best practice untuk object management.

Catatan
Untuk kalian yang ingin membaca episode sebelumnya, bisa click thumbnail episode 24 di bawah ini
Di episode sebelumnya kita sudah belajar tentang Downward API dan cara expose Pod metadata ke application. Selanjutnya di episode 25 kali ini, kita akan coba bahas Managing Kubernetes Objects, exploring both imperative dan declarative approach untuk creating dan managing resource.
Catatan: Disini saya akan menggunakan Kubernetes Cluster yang di install melalui K3s.
Memahami cara manage Kubernetes object fundamental untuk working effectively dengan Kubernetes. Ada dua main approach: imperative (telling Kubernetes what to do) dan declarative (telling Kubernetes what you want).
Object Management refer ke bagaimana kalian create, update, dan delete Kubernetes resource. Approach yang kalian pilih affect maintainability, reproducibility, dan collaboration.
Bayangkan object management seperti cooking - imperative seperti following step-by-step instruction ("chop onion, heat oil, add onion"), sementara declarative seperti describing desired outcome ("I want onion soup"). Keduanya get kalian ke same place, tapi approach berbeda.
Karakteristik kunci Object Management:
Imperative management berarti telling Kubernetes exactly what action perform menggunakan command.
Create object directly dengan kubectl command.
Membuat Deployment:
sudo kubectl create deployment nginx --image=nginx:1.25Membuat Service:
sudo kubectl expose deployment nginx --port=80 --type=NodePortScaling Deployment:
sudo kubectl scale deployment nginx --replicas=3Setting Image:
sudo kubectl set image deployment/nginx nginx=nginx:1.26Membuat ConfigMap:
sudo kubectl create configmap app-config --from-literal=key1=value1 --from-literal=key2=value2Membuat Secret:
sudo kubectl create secret generic db-credentials --from-literal=username=admin --from-literal=password=secret123Gunakan configuration file dengan imperative command.
Create dari file:
sudo kubectl create -f deployment.ymlReplace object:
sudo kubectl replace -f deployment.ymlDelete object:
sudo kubectl delete -f deployment.ymlDeclarative management berarti describing desired state di configuration file dan letting Kubernetes figure out cara achieve it.
Gunakan kubectl apply dengan configuration file.
Contoh: Deployment Configuration
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80Apply configuration:
sudo kubectl apply -f nginx-deployment.ymlUpdate configuration (edit file dan reapply):
# Edit nginx-deployment.yml (change replica ke 5)
sudo kubectl apply -f nginx-deployment.ymlApply directory:
sudo kubectl apply -f ./manifests/Apply recursively:
sudo kubectl apply -f ./manifests/ --recursivekubectl apply perform three-way merge:
Ini enable intelligent update yang preserve manual change ketika possible.
Mari kita compare imperative dan declarative management untuk common task.
Imperative:
sudo kubectl create deployment web --image=nginx:1.25 --replicas=3
sudo kubectl expose deployment web --port=80 --type=LoadBalancerDeclarative:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: web
spec:
type: LoadBalancer
selector:
app: web
ports:
- port: 80
targetPort: 80sudo kubectl apply -f web-deployment.ymlImperative:
sudo kubectl scale deployment web --replicas=5Declarative:
# Edit file: change replica dari 3 ke 5
spec:
replicas: 5sudo kubectl apply -f web-deployment.ymlImperative:
sudo kubectl set image deployment/web nginx=nginx:1.26Declarative:
# Edit file: change image version
containers:
- name: nginx
image: nginx:1.26sudo kubectl apply -f web-deployment.ymlSelalu gunakan declarative management untuk production environment:
# Bagus: Declarative
sudo kubectl apply -f production/
# Hindari: Imperative di production
sudo kubectl create deployment ...Imperative fine untuk development dan testing:
# Quick test
sudo kubectl run test-pod --image=nginx:1.25 --rm -it -- /bin/bashStructure manifest kalian logically:
manifests/
├── base/
│ ├── deployment.yml
│ ├── service.yml
│ └── configmap.yml
├── dev/
│ └── kustomization.yml
├── staging/
│ └── kustomization.yml
└── production/
└── kustomization.ymlSelalu commit configuration file ke Git:
git add manifests/
git commit -m "Add nginx deployment"
git pushInclude metadata untuk organization:
metadata:
name: nginx
labels:
app: nginx
version: v1.0
environment: production
annotations:
description: "Production web server"
owner: "platform-team"Organize resource by namespace:
metadata:
name: nginx
namespace: productionAdd comment untuk explain complex configuration:
# Nginx deployment untuk production web traffic
# Configured dengan 3 replica untuk high availability
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginxDeclarative approach:
# ConfigMap untuk application configuration
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
DATABASE_HOST: "postgres"
DATABASE_PORT: "5432"
LOG_LEVEL: "info"
---
# Secret untuk sensitive data
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
type: Opaque
stringData:
DATABASE_PASSWORD: "secretpassword"
API_KEY: "abc123xyz789"
---
# Deployment untuk application
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
labels:
app: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: app
image: myapp:latest
ports:
- containerPort: 8080
envFrom:
- configMapRef:
name: app-config
- secretRef:
name: app-secrets
---
# Service untuk expose application
apiVersion: v1
kind: Service
metadata:
name: app
spec:
type: LoadBalancer
selector:
app: myapp
ports:
- port: 80
targetPort: 8080Apply everything:
sudo kubectl apply -f app-stack.ymlBase configuration:
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: app
image: myapp:latest
ports:
- containerPort: 8080Development overlay:
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
spec:
replicas: 1
template:
spec:
containers:
- name: app
env:
- name: ENVIRONMENT
value: "development"Production overlay:
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
spec:
replicas: 5
template:
spec:
containers:
- name: app
env:
- name: ENVIRONMENT
value: "production"
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"Directory structure:
kubernetes/
├── apps/
│ ├── frontend/
│ │ ├── deployment.yml
│ │ ├── service.yml
│ │ └── ingress.yml
│ └── backend/
│ ├── deployment.yml
│ ├── service.yml
│ └── configmap.yml
└── infrastructure/
├── namespaces.yml
└── rbac.ymlApply dengan Git workflow:
# Clone repository
git clone https://github.com/company/kubernetes-manifests.git
cd kubernetes-manifests
# Apply infrastructure
sudo kubectl apply -f infrastructure/
# Apply application
sudo kubectl apply -f apps/
# Make change
vim apps/frontend/deployment.yml
# Commit dan push
git add apps/frontend/deployment.yml
git commit -m "Update frontend to v2.0"
git push
# Apply change
sudo kubectl apply -f apps/frontend/Memahami perbedaan:
# Create new deployment
sudo kubectl create -f deployment.yml
# Fail jika deployment exist
# Error: deployments.apps "nginx" already exists# Create deployment jika not exist
sudo kubectl apply -f deployment.yml
# Update deployment jika exist
sudo kubectl apply -f deployment.ymlsudo kubectl replace -f deployment.ymlsudo kubectl apply -f deployment.ymlTest change sebelum applying.
Preview apa yang akan happen:
Tip
Dry run client side dia hanya melakukan parsing file YAML dan melakukan validasi, tidak melakukan validasi ke API Server.
Sedangkan server side dia akan melakukan full lifecycle valiadasi hingga ke API Server nya tanpa benar-benar di commit sehingga tidak diterapkan ke etcd. Berikut adalah perbedannya:
| Fitur | Client | Server |
|---|---|---|
| Validasi schema | lokal | server |
| Admission controller | ❌ | ✅ |
| Default value dari server | ❌ | ✅ |
| Real behavior simulation | ❌ | ✅ |
# Client-side dry run
sudo kubectl apply -f deployment.yml --dry-run=client -o yaml
# Server-side dry run
sudo kubectl apply -f deployment.yml --dry-run=server -o yamlContoh hasil dari dry run client dan server side
Lihat difference sebelum applying:
sudo kubectl diff -f deployment.ymlOutput show apa yang akan change:
--- /tmp/LIVE-2656508399/apps.v1.Deployment.default.web
+++ /tmp/MERGED-975783886/apps.v1.Deployment.default.web
@@ -6,14 +6,14 @@
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"name":"web","namespace":"default"},"spec":{"replicas":3,"selector":{"matchLabels":{"app":"web"}},"template":{"metadata":{"labels":{"app":"web"}},"spec":{"containers":[{"image":"nginx:1.25","name":"nginx","ports":[{"containerPort":80}]}]}}}}
creationTimestamp: "2026-03-26T16:55:41Z"
- generation: 1
+ generation: 2
name: web
namespace: default
resourceVersion: "480086"
uid: 69e521b0-5556-4354-a788-db0463e1a935
spec:
progressDeadlineSeconds: 600
- replicas: 3
+ replicas: 5
revisionHistoryLimit: 10
selector:
matchLabels:Problem: Gunakan both approach cause confusion.
Solusi: Pilih satu approach per environment:
# Buruk: Mixing approach
sudo kubectl create deployment nginx --image=nginx:1.25
sudo kubectl apply -f service.yml
# Bagus: Consistent approach
sudo kubectl apply -f deployment.yml
sudo kubectl apply -f service.ymlProblem: No history dari change.
Solusi: Selalu commit configuration:
git add manifests/
git commit -m "Update deployment"Problem: Manual change tidak tracked.
Solusi: Selalu update file dan apply:
# Buruk: Direct change
sudo kubectl scale deployment nginx --replicas=5
# Bagus: Update file dan apply
# Edit deployment.yml
sudo kubectl apply -f deployment.ymlProblem: Apply untested configuration.
Solusi: Gunakan dry-run dan diff:
sudo kubectl diff -f deployment.yml
sudo kubectl apply -f deployment.yml --dry-run=serverProblem: Missing required field.
Solusi: Gunakan complete, valid YAML:
# Buruk: Incomplete
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
# Bagus: Complete
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25# Quick test
sudo kubectl run test --image=nginx:1.25 --rm -it -- /bin/bash# Production deployment
sudo kubectl apply -f production/sudo kubectl get deployments
sudo kubectl get pods
sudo kubectl get servicessudo kubectl describe deployment nginxsudo kubectl get deployment nginx -o yaml# Open editor (not recommended untuk production)
sudo kubectl edit deployment nginx# Imperative
sudo kubectl delete deployment nginx
# Declarative
sudo kubectl delete -f deployment.ymlPada episode 25 ini, kita telah membahas Managing Kubernetes Objects menggunakan both imperative dan declarative approach. Kita sudah belajar perbedaan, keuntungan, dan kapan gunakan setiap method.
Key takeaway:
Memahami object management fundamental untuk working effectively dengan Kubernetes. Dengan choosing right approach untuk use case kalian, kalian bisa build maintainable, reproducible, dan collaborative infrastructure.
Bagaimana, makin jelas kan tentang Managing Kubernetes Objects? Jadi, pastikan tetap semangat belajar dan nantikan episode selanjutnya!
Catatan
Untuk kalian yang ingin melanjutkan ke episode selanjutnya, bisa click thumbnail episode 26 di bawah ini