Belajar Kubernetes - Episode 25 - Managing Kubernetes Objects

Belajar Kubernetes - Episode 25 - Managing Kubernetes Objects

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.

Arman Dwi Pangestu
Arman Dwi PangestuMarch 31, 2026
0 views
9 min read

Pendahuluan

Catatan

Untuk kalian yang ingin membaca episode sebelumnya, bisa click thumbnail episode 24 di bawah ini

Episode 24Episode 24

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).

Apa Itu Object Management?

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:

  • Two approach - Imperative dan declarative
  • Different workflow - Command-line vs configuration file
  • Version control - Declarative enable Git workflow
  • Reproducibility - Declarative ensure consistency
  • Collaboration - Declarative facilitate team work
  • Automation - Declarative enable GitOps

Imperative Management

Imperative management berarti telling Kubernetes exactly what action perform menggunakan command.

Imperative Command

Create object directly dengan kubectl command.

Membuat Deployment:

Kubernetesbash
sudo kubectl create deployment nginx --image=nginx:1.25

Membuat Service:

Kubernetesbash
sudo kubectl expose deployment nginx --port=80 --type=NodePort

Scaling Deployment:

Kubernetesbash
sudo kubectl scale deployment nginx --replicas=3

Setting Image:

Kubernetesbash
sudo kubectl set image deployment/nginx nginx=nginx:1.26

Membuat ConfigMap:

Kubernetesbash
sudo kubectl create configmap app-config --from-literal=key1=value1 --from-literal=key2=value2

Membuat Secret:

Kubernetesbash
sudo kubectl create secret generic db-credentials --from-literal=username=admin --from-literal=password=secret123

Imperative Object Configuration

Gunakan configuration file dengan imperative command.

Create dari file:

Kubernetesbash
sudo kubectl create -f deployment.yml

Replace object:

Kubernetesbash
sudo kubectl replace -f deployment.yml

Delete object:

Kubernetesbash
sudo kubectl delete -f deployment.yml

Keuntungan Imperative Management

  • Quick dan simple - Fast untuk one-off task
  • Easy to learn - Straightforward command
  • Interactive - Immediate feedback
  • Good untuk testing - Rapid experimentation
  • No file needed - Work directly dari command line

Kekurangan Imperative Management

  • Not reproducible - Hard recreate exact state
  • No version control - Tidak bisa track change di Git
  • Error-prone - Easy make mistake
  • Limited collaboration - Hard share dengan team
  • No audit trail - Difficult track who changed what
  • Manual update - Harus remember semua command

Declarative Management

Declarative management berarti describing desired state di configuration file dan letting Kubernetes figure out cara achieve it.

Declarative Object Configuration

Gunakan kubectl apply dengan configuration file.

Contoh: Deployment Configuration

Kubernetesnginx-deployment.yml
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: 80

Apply configuration:

Kubernetesbash
sudo kubectl apply -f nginx-deployment.yml

Update configuration (edit file dan reapply):

Kubernetesbash
# Edit nginx-deployment.yml (change replica ke 5)
sudo kubectl apply -f nginx-deployment.yml

Apply directory:

Kubernetesbash
sudo kubectl apply -f ./manifests/

Apply recursively:

Kubernetesbash
sudo kubectl apply -f ./manifests/ --recursive

Cara kubectl apply Work

kubectl apply perform three-way merge:

  1. Current configuration - Apa yang di file
  2. Live configuration - Apa yang running di cluster
  3. Last applied configuration - Stored di annotation

Ini enable intelligent update yang preserve manual change ketika possible.

Keuntungan Declarative Management

  • Reproducible - Same file produce same result
  • Version control - Track change di Git
  • Collaboration - Easy share dan review
  • Audit trail - Git history show semua change
  • Automation - Enable CI/CD dan GitOps
  • Self-documenting - File describe infrastructure
  • Idempotent - Safe apply multiple time

Kekurangan Declarative Management

  • More setup - Need create file
  • Learning curve - Harus understand YAML
  • Slower untuk quick test - More overhead
  • File management - Need organize file

Membandingkan Approach

Mari kita compare imperative dan declarative management untuk common task.

Membuat Deployment

Imperative:

Kubernetesbash
sudo kubectl create deployment web --image=nginx:1.25 --replicas=3
sudo kubectl expose deployment web --port=80 --type=LoadBalancer

Declarative:

Kubernetesweb-deployment.yml
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: 80
Kubernetesbash
sudo kubectl apply -f web-deployment.yml

Scaling Deployment

Imperative:

Kubernetesbash
sudo kubectl scale deployment web --replicas=5

Declarative:

Kubernetesweb-deployment.yml
# Edit file: change replica dari 3 ke 5
spec:
    replicas: 5
Kubernetesbash
sudo kubectl apply -f web-deployment.yml

Update Image

Imperative:

Kubernetesbash
sudo kubectl set image deployment/web nginx=nginx:1.26

Declarative:

Kubernetesweb-deployment.yml
# Edit file: change image version
containers:
    - name: nginx
      image: nginx:1.26
Kubernetesbash
sudo kubectl apply -f web-deployment.yml

Best Practice

Gunakan Declarative untuk Production

Selalu gunakan declarative management untuk production environment:

Kubernetesbash
# Bagus: Declarative
sudo kubectl apply -f production/
 
# Hindari: Imperative di production
sudo kubectl create deployment ...

Gunakan Imperative untuk Quick Test

Imperative fine untuk development dan testing:

Kubernetesbash
# Quick test
sudo kubectl run test-pod --image=nginx:1.25 --rm -it -- /bin/bash

Organize Configuration File

Structure manifest kalian logically:

plaintext
manifests/
├── base/
│   ├── deployment.yml
│   ├── service.yml
│   └── configmap.yml
├── dev/
│   └── kustomization.yml
├── staging/
│   └── kustomization.yml
└── production/
    └── kustomization.yml

Gunakan Version Control

Selalu commit configuration file ke Git:

Kubernetesbash
git add manifests/
git commit -m "Add nginx deployment"
git push

Add Label dan Annotation

Include metadata untuk organization:

Kubernetesyml
metadata:
    name: nginx
    labels:
        app: nginx
        version: v1.0
        environment: production
    annotations:
        description: "Production web server"
        owner: "platform-team"

Gunakan Namespace

Organize resource by namespace:

Kubernetesyml
metadata:
    name: nginx
    namespace: production

Document Configuration Kalian

Add comment untuk explain complex configuration:

Kubernetesyml
# Nginx deployment untuk production web traffic
# Configured dengan 3 replica untuk high availability
apiVersion: apps/v1
kind: Deployment
metadata:
    name: nginx

Contoh Praktis

Contoh 1: Complete Application Stack

Declarative approach:

Kubernetesapp-stack.yml
# 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: 8080

Apply everything:

Kubernetesbash
sudo kubectl apply -f app-stack.yml

Contoh 2: Multi-Environment Configuration

Base configuration:

Kubernetesbase/deployment.yml
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: 8080

Development overlay:

Kubernetesdev/deployment-patch.yml
apiVersion: apps/v1
kind: Deployment
metadata:
    name: app
spec:
    replicas: 1
    template:
        spec:
            containers:
                - name: app
                  env:
                      - name: ENVIRONMENT
                        value: "development"

Production overlay:

Kubernetesprod/deployment-patch.yml
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"

Contoh 3: GitOps Workflow

Directory structure:

plaintext
kubernetes/
├── apps/
│   ├── frontend/
│   │   ├── deployment.yml
│   │   ├── service.yml
│   │   └── ingress.yml
│   └── backend/
│       ├── deployment.yml
│       ├── service.yml
│       └── configmap.yml
└── infrastructure/
    ├── namespaces.yml
    └── rbac.yml

Apply dengan Git workflow:

Kubernetesbash
# 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/

kubectl apply vs kubectl create

Memahami perbedaan:

kubectl create

  • Create new resource only
  • Fail jika resource already exist
  • Imperative approach
  • No three-way merge
Kubernetesbash
# Create new deployment
sudo kubectl create -f deployment.yml
 
# Fail jika deployment exist
# Error: deployments.apps "nginx" already exists

kubectl apply

  • Create atau update resource
  • Idempotent (safe run multiple time)
  • Declarative approach
  • Perform three-way merge
  • Store last-applied-configuration
Kubernetesbash
# Create deployment jika not exist
sudo kubectl apply -f deployment.yml
 
# Update deployment jika exist
sudo kubectl apply -f deployment.yml

kubectl replace vs kubectl apply

kubectl replace

  • Replace entire resource
  • Require complete configuration
  • Remove field not di new config
  • Fail jika resource tidak exist
Kubernetesbash
sudo kubectl replace -f deployment.yml

kubectl apply

  • Merge change intelligently
  • Preserve unspecified field
  • Create jika tidak exist
  • Preferred untuk declarative management
Kubernetesbash
sudo kubectl apply -f deployment.yml

Dry Run dan Diff

Test change sebelum applying.

Dry Run

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:


FiturClientServer
Validasi schemalokalserver
Admission controller
Default value dari server
Real behavior simulation
Kubernetesbash
# 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 yaml

Contoh hasil dari dry run client dan server side

apiVersion: v1
items:
- apiVersion: apps/v1
  kind: Deployment
  metadata:
    annotations:
      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}]}]}}}}
    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
- apiVersion: v1
  kind: Service
  metadata:
    annotations:
      kubectl.kubernetes.io/last-applied-configuration: |
        {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"web","namespace":"default"},"spec":{"ports":[{"port":80,"targetPort":80}],"selector":{"app":"web"},"type":"LoadBalancer"}}
    name: web
    namespace: default
  spec:
    ports:
    - port: 80
      targetPort: 80
    selector:
      app: web
    type: LoadBalancer
kind: List
metadata: {}

Diff

Lihat difference sebelum applying:

Kubernetesbash
sudo kubectl diff -f deployment.yml

Output show apa yang akan change:

Kubernetesyml
--- /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:

Kesalahan Umum dan Pitfall

Kesalahan 1: Mixing Imperative dan Declarative

Problem: Gunakan both approach cause confusion.

Solusi: Pilih satu approach per environment:

Kubernetesbash
# 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.yml

Kesalahan 2: Tidak Gunakan Version Control

Problem: No history dari change.

Solusi: Selalu commit configuration:

Kubernetesbash
git add manifests/
git commit -m "Update deployment"

Kesalahan 3: Imperative Change di Production

Problem: Manual change tidak tracked.

Solusi: Selalu update file dan apply:

Kubernetesbash
# Buruk: Direct change
sudo kubectl scale deployment nginx --replicas=5
 
# Bagus: Update file dan apply
# Edit deployment.yml
sudo kubectl apply -f deployment.yml

Kesalahan 4: Tidak Test Change

Problem: Apply untested configuration.

Solusi: Gunakan dry-run dan diff:

Kubernetesbash
sudo kubectl diff -f deployment.yml
sudo kubectl apply -f deployment.yml --dry-run=server

Kesalahan 5: Incomplete Configuration

Problem: Missing required field.

Solusi: Gunakan complete, valid YAML:

Kubernetesyml
# 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

Kapan Gunakan Setiap Approach

Gunakan Imperative Ketika:

  • Quick testing dan experimentation
  • Learning Kubernetes
  • One-off debugging task
  • Development environment
  • Interactive troubleshooting
Kubernetesbash
# Quick test
sudo kubectl run test --image=nginx:1.25 --rm -it -- /bin/bash

Gunakan Declarative Ketika:

  • Production environment
  • Team collaboration
  • CI/CD pipeline
  • GitOps workflow
  • Infrastructure as Code
  • Reproducible deployment
Kubernetesbash
# Production deployment
sudo kubectl apply -f production/

Viewing dan Managing Object

List Object

Kubernetesbash
sudo kubectl get deployments
sudo kubectl get pods
sudo kubectl get services

Describe Object

Kubernetesbash
sudo kubectl describe deployment nginx

View YAML

Kubernetesbash
sudo kubectl get deployment nginx -o yaml

Edit Object

Kubernetesbash
# Open editor (not recommended untuk production)
sudo kubectl edit deployment nginx

Delete Object

Kubernetesbash
# Imperative
sudo kubectl delete deployment nginx
 
# Declarative
sudo kubectl delete -f deployment.yml

Penutup

Pada 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:

  • Two approach - Imperative (command) dan declarative (file)
  • Imperative tell Kubernetes what to do step-by-step
  • Declarative describe desired state di configuration file
  • Gunakan kubectl create/scale/set untuk imperative management
  • Gunakan kubectl apply untuk declarative management
  • Declarative preferred untuk production environment
  • Version control enable collaboration dan audit trail
  • kubectl apply perform intelligent three-way merge
  • Dry run dan diff help test change sebelum applying
  • Organize file di logical directory structure
  • GitOps enable automated deployment dari Git
  • Imperative fine untuk quick test dan learning
  • Jangan mix approach di same environment
  • Selalu test dengan dry-run sebelum applying
  • Document configuration dengan comment dan annotation

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

Episode 26Episode 26

Related Posts