Skip to content

Instantly share code, notes, and snippets.

@rezaindrag
Created January 4, 2021 07:20
Show Gist options
  • Save rezaindrag/523c685d8579faba3521a15091ef6cfd to your computer and use it in GitHub Desktop.
Save rezaindrag/523c685d8579faba3521a15091ef6cfd to your computer and use it in GitHub Desktop.
Kubernetes Basic

Terms in Kubernetes

Komponen & Arsitektur Kubernetes

K82 Component

Kubernetes Cluster

  • Ketika kita me-running sebuah Kubernetes, artinya kita me-running sebuah Cluster (Kubernetes Cluster).
  • Cluster terdiri dari dua bagian besar, yakni Kubernetes Master dan Kubernetes Worker/Node

Kubernetes Master

  • Kubernetes Master adalah orang/pihak yang melakukan management Kubernetes.
  • kubectl adalah CLI untuk berinteraksi dg Kubernetes Cluster

Kubernetes Worker/Node

  • Node adalah worker machine di Kubernetes, sebelumnya ada yang menyebutnya Minion.
  • Aplikasi yang dideploy ke Kubernetes akan jalan di Node/Worker, initinya inilah yang akan mengeksekusi aplikasi kita.
  • Node bisa saja dalam bentuk VM atau mesin fisik.
  • Di dalam Node selalu terdapat kubelet, kube-proxy dan container manager.

Pod

  • Unit terkecil yang bisa dideploy di Kubernetes Cluster.
  • Pod berisi satu atau lebih container.
  • Secara sederhana, Pod adalah aplikasi kita yang running di Kubernetes Cluster.

pod

Kubectl

// Get list pods and nodes
kubectl get nodes / kubectl get node
kubectl get pods / kubectl get pod
kubectl describe node <nod_name>
kubectl describe pod <pod_name>
kubectl get pod -o wide
kubectl get pod --show-labels

// Menghapus pod
kubectl delete pod <pod_name>
kubectl delete pod <pod_name1> <pod_name2> <pod_name3>
// Menghapus pod berdasarkan label tertentu
kubectl delete pod -l key=value
// Menghapus semua pod pada namespace tertentu
kubectl delete pod --all -n <namespace_name>

// Menghapus semua resources
kubectl delete all --all
// Menghapus semua resources pada namespace tertentu
kubectl delete all --all --namespace <namespace_name>

// Melihat log dari pod
kubectl logs <pod_name>

// Submit configurasi ke Kubernetes Cluster
kubectl create -f <config_file>

// Mengakses pod/mengecek apakah pod running
kubectl port-forward <pod_name> <port_akses>:<port_pod>

// Menambah atau merubah label di Pod/Node melalui command line
kubectl label pod/node <resource_name> key=value
kubectl label pod/node <resource_name> key=value --overwrite
// Mencari Pods dengan Label
kubectl get pods -l key
kubectl get pods -l key=value
kubectl get pods -l '!key'
kubectl get pods -l key!=value
kubectl get pods -l 'key in (value1,value2)'
kubectl get pods -l 'key notin (value1,value2)'
// Mencari Pods dengan beberapa label
kubectl get pods -l key,key2=value

// Menambah atau merubah annotation di Pod melalui command line
kubectl annotate pod <pod_name> key=value
kubectl annotate pod <pod_name> key=value --overwrite

// Cara melihat daftar namespace
kubectl get namespaces
kubectl get namespace
kubectl get ns
// Melihat daftar pod pada namespace
kubectl get pod --namespace <namespace_name>
kubectl get pod -n <namespace_name>
// Membuat pod pada namespace tertentu
kubectl create -f <config_file> -n <namespace_name>
// Menghapus namespace
kubectl delete namespace <namespace_name>

// Melihat replication controller
kubectl get replicationcontrollers
kubectl get replicationcontroller
kubectl get rc
// Menghapus replication controller
kubectl delete rc <rc_name>
// Menghapus replication controller tanpa menghapus Pod didalamnya
kubectl delete rc <rc_name> --cascade=false

// Melihat replica set
kubectl get replicasets
kubectl get replicaset
kubectl get rs
// Menghapus replica set
kubectl delete rs <rs_name>
// Menghapus replica set tanpa menghapus Pod didalamnya
kubectl delete rs <rs_name> --cascade=false

// Melihat daemon set
kubectl get daemonsets
kubectl get daemonset
kubectl get ds
// Menghapus daemon set
kubectl delete ds <ds_name>

// Melihat daftar job
kubectl get jobs

// Melihat daftar cronjob
kubectl get cronjobs

// Melihat semua daftar resources
kubectl get all

// Melihat service
kubectl get services
// Menghapus service
kubectl delete services <service_name>
// Mengakses service dari dalam cluster
kubectl exec <pod_name> -it -- /bin/sh
curl http://cluster-ip:port/

// Melihat environment variable pada Pod
kubectl exec <pod_name> -- env

// Melihat service endpoint
kubectl describe service <service_name>
kubectl get endpoints <service_name>

// Melihat ingress
kubectl get ingress
// Menghapus ingress
kubectl delete ingress <ingress_name>

// Melihat resource yang lain
kubectl get configmaps
kubectl get secrets

Label

  • Untuk memberi tanda pada Pod.
  • Untuk mengorganisir Pod.
  • Memberi informasi tambahan pada Pod.
  • Tidak hanya digunakan pada Pod, tapi juga untuk semua resource di Kubernetes, seperti Replication Controller, Replica Set, Service, dll.

Annotation

  • Annotation mirip seperti label tapi tidak dapat difilter.
  • Digunakan untuk memberikan informasi tambahan dalam ukuran besar.

Namespace

  • Namespace digunakan ketika resource Kubernetes sudah terlalu banyak.
  • Atau ketika butuh memisahkan resources untuk multi-tenant, team atau environment.
  • Nama resource bisa sama di namespace yang berbeda.
  • Namespace tidak bisa digunakan untuk mengisolasi pod, pod-pod yang berada pada namespace yang beda, tetap dapat saling berkomunikasi.
  • Jika ada kebutuhan untuk mengisolasi pod, buat pada cluster yang berbeda.
  • Jika kita menghapus sebuah namespace, maka semua pod dalam namaspace tersebut bakal terhapus.

Liveness, Readiness & Startup Probe (Pengecekan)

Liveness

  • Kubelet menggunakan Liveness untuk mengecek kapan harus me-restart Pod.
  • Kalau aplikasi kita tidak sehat, misalnya saat Pod tidak merespon kubelet, maka akan me-restrart secara otomatis.

Readiness

  • Kubelet menggunakan Readiness untuk mengecek apakah Pod siap menerima traffic.
  • Readiness akan men-stop traffic pada aplikasi yg tidak sehat (buka me-restart), setelah itu akan mengecek lagi sampai aplikasi berjalan dg baik. Lalu dia akan menerima traffic lagi.

Startup Probe

  • Kubelet menggunakan Startup Probe untuk apakah Pod sudah berjalan, jika belum, maka kubelet tidak akan melakukan pengecekan Liveness & Readiness.
  • Startup Probe cocok untuk Pod yang membutuhkan proses start yang lama, untuk memastikan Pod tidak mati sebelum berjalan dengan sempurna.

Mekanisme Pengecekan

  • HTTP Get
  • TCP Socket
  • Command Exec

Contoh

containers:
  ...
  livenessProbe:
    httpGet:
      path: /
      port: 80
    initialDelaySeconds: 5 # Waktu delay sebelum pengecekan (default 0)
    periodSeconds: 5 # Berapa detik sekali akan dilakukan pengecekan (default 10)
    timeoutSeconds: 1 # Maksimal waktu timeout untuk dianggap gagal (default 1)
    successThreshold: 1 # Berapa kali success checking agar dianggap sehat (default 1)
    failureThreshold: 3 # Berapa kali failure checking agar dianggap gagal (default 3)

Replication Controller

  • Replication controller bertugas untuk memastikan bahwa Pod selalu berjalan
  • Jika Pod tiba-tiba mati atau hilang, maka replication controller akan otomatis membuat Pod baru
  • Replication controller akan memastikan jumlah Pod yang berjalan sejumlah yang telah ditentukan. Jika kurang, maka akan membuat buat Pod baru, jika lebih mana akan menghapus Pod yang sudah ada.

Screen Shot 2020-12-03 at 14 05 41 Screen Shot 2020-12-03 at 14 06 02

Contoh

apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx-rc
spec:
  replicas: 3
  selector:
    app: nginx # selector.app ini mengarah ke template.metadata.labels.app
  template:
    metadata:
      name: nginx # nantinya, nama pod dari hasil replika akan secara otomatis ditambahkan code unik
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          ports:
            - containerPort: 80

Menghapus replication controller

  • Saat kita menghapus replication controller, semua Pod yang berada pada label selectornya akan ikut terhapus
  • Jika ingin menghapus replication controller, tanpa menghapus Podnya, kita bisa menambahkan --cascade=false

Replica Set

  • Replica Set adalah generasi baru sebagai pengganti Replication Controller
  • Replication Controller sendiri saat ini sudah tidak direkomendasikan
  • Replica Set memiliki label selector yang lebih expressive dibandingkan dengan Replication controller yang hanya memiliki fitur label selector secara match

Contoh

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx-rc
spec:
  replicas: 3
  selector:
    matchLabels: # selector query matchLabels
      app: nginx # selector.app ini mengarah ke template.metadata.labels.app
  template:
    metadata:
      name: nginx # nantinya, nama pod dari hasil replika akan secara otomatis ditambahkan code unik
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          ports:
            - containerPort: 80

Contoh dengan Match Expression

Operator pada match expressions:

  • In, value label harus ada di value in
  • NotIn, value label tidak boleh ada di value in
  • Exists, label harus ada
  • NotExists, label tidak boleh ada
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx-rs
spec:
  replicas: 3
  selector:
    matchExpressions: # match expression
      - key: app
        operator: In
        values:
          - nginx
      - key: env
        operator: In
        values:
          - prod
          - qa
          - dev
  template:
    metadata:
      name: nginx # nantinya, nama pod dari hasil replika akan secara otomatis ditambahkan code unik
      labels:
        app: nginx
        env: prod
    spec:
      containers:
        - name: nginx
          image: nginx
          ports:
            - containerPort: 80

Daemon Set

  • Saat menggunakan Replica Set atau Replication Controller, Pod akan dijalankan di Node secara random oleh K8s
  • Jika ingin menjalankan Pod di setiap Node, dan tiap Pod hanya boleh jalan 1 di Node, maka bisa menggunakan Daemon Set
  • Secara default, Daemon Set akan menjalankan Pod di setiap Node, kecuali jika kita meminta hanya jalan di Node tertentu

Screen Shot 2020-12-04 at 17 08 41

Contoh kasus penggunaan Daemon Set

  • Aplikasi untuk monitoring Node
  • Aplikasi untuk mengambil log di Node

Contoh

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: daemon-nginx
  labels:
    name: daemon-nginx
spec:
  selector:
    matchLabels:
      name: daemon-nginx
  template:
    metadata:
      name: daemon-nginx
      labels:
        name: daemon-nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          ports:
            - containerPort: 80

Job

  • Job adalah resource di Kubernetes yang digunakan untuk menjalankan Pod yang hanya butuh berjalan sekali, lalu berhenti.
  • Pada Replication Controller, Replica Set dan Daemon Set, jika Pod mati, maka akan secara otomatis Pod akan dijalankan ulang.
  • Berbeda dengan Job, yang justru Pod akan mati jika pekerjaannya selesai dilakukan.

Contoh

apiVersion: batch/v1
kind: Job
metadata:
  name: nodejs-job
spec:
  completions: 4 # berapa banyak job yg harus dijalankan sampai dianggap complete, default 1.
  parallelism: 2 # berapa banyak job yg berjalan pada satu waktu, default 1.
  template:
    spec:
      restartPolicy: Never # ini wajib Never
      containers:
        - name: nodejs-job
          image: khannedy/nodejs-job

Lihat Detail Job

$ kubectl describe job nodejs-job
...
Type    Reason            Age    From            Message
  ----    ------            ----   ----            -------
  Normal  SuccessfulCreate  7m39s  job-controller  Created pod: nodejs-job-6gmrd
  Normal  SuccessfulCreate  7m39s  job-controller  Created pod: nodejs-job-wpfgd
  Normal  SuccessfulCreate  7m3s   job-controller  Created pod: nodejs-job-mrvp5
  Normal  SuccessfulCreate  7m1s   job-controller  Created pod: nodejs-job-742kn
  Normal  Completed         6m53s  job-controller  Job completed

Cron Job

  • Cron Job sendiri adalah aplikasi untuk penjadwalan yang ada di sistem operasi unix.
  • Cron Job pada Kubernetes cara kerjanya mirip dengan Job, hanya saja kalau Job berjalan sekali, tapi Cron Job bisa berjalan berulang kali sesuai dengan jadwal yang kita inginkan.
  • Cron Job juga memungkinkan kita untuk menjalankan aplikasi dengan waktu yang telah ditentukan.

Contoh penggunaan Cron Job

  • Aplikasi untuk membuat laporan harian
  • Aplikasi untuk membackup data secara berkala
  • Aplikasi untuk mengirim data tagihan tiap bulan ke pihak lain

Contoh

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: nodejs-cronjob
  labels:
    name: nodejs-cronjob
spec:
  schedule: "* * * * *" # kapan cronjob akan dieksekusi
  jobTemplate:
    spec:
      template:
        metadata:
          name: nodejs-cronjob # nama Pod
          labels:
            name: nodejs-cronjob
        spec:
          restartPolicy: Never
          containers:
            - name: nodejs-cronjob
              image: khannedy/nodejs-job

Lihat Pod yang berjalan dengan Cronjob

$ ku get all
NAME                                  READY   STATUS      RESTARTS   AGE
pod/nodejs-cronjob-1607403060-sq9q7   0/1     Completed   0          2m57s
pod/nodejs-cronjob-1607403120-f8crb   0/1     Completed   0          2m7s
pod/nodejs-cronjob-1607403180-gw2n6   0/1     Completed   0          67s
pod/nodejs-cronjob-1607403240-55c5r   0/1     Completed   0          6s

NAME                                  COMPLETIONS   DURATION   AGE
job.batch/nodejs-cronjob-1607403060   1/1           7s         2m59s
job.batch/nodejs-cronjob-1607403120   1/1           6s         2m8s
job.batch/nodejs-cronjob-1607403180   1/1           7s         68s
job.batch/nodejs-cronjob-1607403240   1/1           6s         8s

NAME                           SCHEDULE    SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob.batch/nodejs-cronjob   * * * * *   False     1        8s              10m

Node Selector

  • Kadang kita membuat Node dengan spesifikasi berbeda dari Node biasanya.
  • Misal Node yang memiliki GPU, atau dengan hard disk SSD.
  • Dengan Node Selector, kita bisa meminta Kubernetes untuk menjalankan Pod pada Node tertentu.

Contoh

Pertama kita harus menambahkan label terlebih dahulu pada Node

kubectl label node <node_name> gpu=true

Kemudian tinggal menambahkan field nodeSelector pada yaml.

apiVersion: v1
kind: Pod
metadata:
  name: pod-name
spec:
  nodeSelector: # sode selector
    gpu: "true"
  containers:
    - name: container-name
      image: image-name
      ports:
        - containerPort: 80

Service

  • Service digunakan untuk membuat satu gerbang untuk mengakses satu atau lebih Pod.
  • Service memiliki IP Address dan Port yang tidak berubah selama service itu ada.
  • Client bisa mengakses service tersebut, dan secara otomatis akan meneruskan ke Pod yang ada di belakang service tersebut.
  • Dengan begini client tidak perlu tahu kolasi tiap Pod, dan Pod bisa bertambah, berkurang atau berpindah, tanpa harus menggangu client.

Screen Shot 2020-12-08 at 15 25 19

Menentukan Pod untuk Service

  • Service akan mendistibusikan trafik ke Pod yang ada di belakangnya secara seimbang.
  • Service menggunakan label selector untuk menentukan Pod mana yang ada di belakang service tersebut.

Mengakses Service dari dalam Cluster

kubectl exec <pod_name> -it -- /bin/sh
curl http://cluster-ip:port/

Template

apiVersion: v1
kind: Service
metadata:
  name: service-name
spec:
  selector:
    label-key1: label-value1
  ports:
  - port: 8080
    targetPort: 80

Contoh Penggunaan Service

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      name: nginx
  template:
    metadata:
      name: nginx
      labels:
        name: nginx # Label Pod
    spec:
      containers:
        - name: nginx
          image: nginx
          ports:
            - containerPort: 80

---

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    name: nginx # Menentukan Pod dengan label "nginx" yang akan diteruskan jika ada request dari client.
  ports:
    - port: 8080
      targetPort: 80

---

# Ini hanya sebagai contoh, nanti digunakan untuk mencoba mengakses IP address dari dalam Cluster.
# kubectl exec curl -it -- /bin/sh
# curl http://cluster-ip:port
apiVersion: v1
kind: Pod
metadata:
  name: curl
  labels:
    name: curl
spec:
  containers:
    - name: curl
      image: khannedy/nginx-curl

Cara mengakses Service dalam Cluster

  • Untuk mengakses service, ada 2 cara, yang pertama cara manual, yakni dengan melihat env variable terlebih dahulu
$ kubectl exec -it <pod_name> -- /bin/sh
# env // setelah masuk ke dalam Pod
...
  • Cara yang kedua, dengan menggunakan DNS, cara ini lebih direkomendasikan karena kita tidak perlu tahu IP addressnya, hanya perlu nama service dan namespace.
nama-service.nama-namespace.svc.cluster.local:port
// misalnya
nginx-service.default.svc.cluster.local:8080

External Service

  • Biasanya Service digunakan sebagai gateway untuk internal Pod.
  • Tapi Service juga bisa digunakan sebagai gateway untuk aplikasi yang berada di luar Kubernetes Cluster.

Screen Shot 2020-12-09 at 13 05 41

  • External service berperan sebagai gerbang untuk dapat mengakses aplikasi dari luar.

Melihat Service Endpoint

kubectl describe service <service_name>
kubectl get endpoints <service_name>

Contoh penggunaan External Service

apiVersion: v1
kind: Service
metadata:
  name: example-service
  labels:
    name: example-service
spec:
  type: ExternalName
  externalName: example.com
  ports:
    - port: 80

---

# Pod ini hanya digunakan untuk mengakses external service
apiVersion: v1
kind: Pod
metadata:
  name: curl
  labels:
    name: curl
spec:
  containers:
    - name: curl
      image: khannedy/nginx-curl

Kemudian, kita coba akses external service tersebut.

$ ku exec curl -it -- /bin/sh
/ # curl example-service.default.svc.cluster.local

Mengekspos Service

  • Kadang ada kebutuhan untuk mengekspos service keluar
  • Tujuannya adalah agar aplikasi dari luar dapat mengakses Pod yang berada di belakang service tersebut.

Screen Shot 2020-12-09 at 14 29 25

Tipe Service

  • ClusterIP: Mengekspos Service di dalam internal kubernetes cluster.
  • ExternalName: Memetakan Service ke ExternalName, misalnya example.com.
  • NodePort: Mengekspos Service pada setiap IP node dan port yang sama. Kita dapat mengakses Service dengan tipe ini dari luar cluster melalui <NodeIP>:<NodePort>.
  • LoadBalancer: Mengekspos Service secara eksternal dengan menggunakan LoadBalancer yang disediakan oleh penyedia layanan cloud.

Cara Untuk Mengekspos Service

  • Menggunakan NodePort, sehingga Node akan membuka port yang akan meneruskan request ke Service yang dituju.
  • Menggunakan LoadBalancer, sehingga Service bisa diakses via LoadBalancer, dan LoadBalancer akan meneruskan request ke NodePort dan dilanjutkan ke Service.
  • Menggunakan Ingress, dimana Ingress adalah resource yang memang ditujukan untuk mengekspos Service. Namun Ingress hanya beroperasi di level HTTP.

Service Node Port

Screen Shot 2020-12-09 at 15 38 52

  • Saat kita membuat Service dengan tipe NodePort, maka Node yang ada di Kubernetes akan membuka port.
  • Saat client mengakses <NodeIP>:<NodePort> pada Node 1, maka Node tsb akan meneruskan ke Service kemudian diteruskan lagi ke Pod.

Melihat NodePort di Minikube

$ minikube service kubernetes
|-----------|------------|-------------|--------------|
| NAMESPACE |    NAME    | TARGET PORT |     URL      |
|-----------|------------|-------------|--------------|
| default   | kubernetes |             | No node port |
|-----------|------------|-------------|--------------|
😿  service default/kubernetes has no node port
🏃  Starting tunnel for service kubernetes.
|-----------|------------|-------------|------------------------|
| NAMESPACE |    NAME    | TARGET PORT |          URL           |
|-----------|------------|-------------|------------------------|
| default   | kubernetes |             | http://127.0.0.1:52900 |
|-----------|------------|-------------|------------------------|
🎉  Opening service default/kubernetes in default browser...
❗  Because you are using a Docker driver on darwin, the terminal needs to be open to run it.

Contoh

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      name: nginx
  template:
    metadata:
      name: nginx
      labels:
        name: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          ports:
            - containerPort: 80

---

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: NodePort # default, type: ClusterIP
  selector:
    name: nginx
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30001
  • Kemudian jalankan minikube service nginx-service
$ ku get service
NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes      ClusterIP   10.96.0.1        <none>        443/TCP        3h8m
nginx-service   NodePort    10.109.193.143   <none>        80:30001/TCP   13m

$ minikube service nginx-service
|-----------|---------------|-------------|---------------------------|
| NAMESPACE |     NAME      | TARGET PORT |            URL            |
|-----------|---------------|-------------|---------------------------|
| default   | nginx-service |          80 | http://192.168.49.2:30001 |
|-----------|---------------|-------------|---------------------------|
🏃  Starting tunnel for service nginx-service.
|-----------|---------------|-------------|------------------------|
| NAMESPACE |     NAME      | TARGET PORT |          URL           |
|-----------|---------------|-------------|------------------------|
| default   | nginx-service |             | http://127.0.0.1:53204 |
|-----------|---------------|-------------|------------------------|
🎉  Opening service default/nginx-service in default browser...
❗  Because you are using a Docker driver on darwin, the terminal needs to be open to run it.

Service Load Balancer

  • Cloud provider seperti Google Cloud atau Amazon Web Service biasanya memiliki Cloud Load Balancer
  • Kubernetes bisa menggunakan Load Balancer bawaan dari Cloud Provider sebagai cara untuk mengekspos Service
  • Load Balancer akan melakukan load balance request ke NodePort
  • Sayangnya Service Load Balancer tidak bisa ditest di local seperti menggunakan Minikube

Screen Shot 2020-12-09 at 17 24 52

Contoh

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      name: nginx
  template:
    metadata:
      name: nginx
      labels:
        name: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          ports:
            - containerPort: 80

---

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: LoadBalancer # type LoadBalancer
  selector:
    name: nginx
  ports:
    - port: 80
      targetPort: 80

Ingress

Alasan Menggunakan Ingress

Ada beberapa masalah saat mengekspos service:

  1. Jika menggunakan NodePort
  • Maka semua Node harus terekspos ke public
  • Client harus tahu semua IP Address Node
  1. Jika menggunakan LoadBalancer
  • Maka semua LoadBalancer harus terekspos ke public
  • Client harus tahu semua IP Address LoadBalancer

Apa itu Ingress?

  • Ingress adalah salah satu cara yang bisa digunakan untuk mengekspos Service.
  • Berbeda dengan LoadBalancer atau NodePort, jika menggunakan Ingress, client hanya butuh tahu satu lokasi IP Address Ingress
  • Ketika client melakukan request ke Ingress, pemilihan servicenya ditentukan menggunakan hostname dari request (mis. service1.example.com)
  • Ingress hanya mendukung protocol HTTP

Screen Shot 2020-12-10 at 11 10 58

Menjalankan Ingress di Minikube

minikube addons list
minikube addons enable ingress
kubectl get pods --namespace kube-system

If there is trouble when enabling ingress, it should run:

minikube delete
minikube start --vm=true

Contoh

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      name: nginx
  template:
    metadata:
      name: nginx
      labels:
        name: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          ports:
            - containerPort: 80

---

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    name: nginx
  ports:
    - port: 80
      targetPort: 80

---

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: nginx-ingress
  labels:
    name: nginx-ingress
spec:
  rules:
    - host: nginx.khannedy.local # contoh domain
      http:
        paths:
          - path: /
            backend:
              serviceName: nginx-service
              servicePort: 80

Setelah kita create, kemudian kita lihat ingressnya

$ kubectl get ingress
NAME            CLASS    HOSTS                  ADDRESS        PORTS   AGE
nginx-ingress   <none>   nginx.khannedy.local   192.168.64.2   80      5m55s

Kemudian kita cek apakah Pods sudah running

$ ku get all
NAME              READY   STATUS    RESTARTS   AGE
pod/nginx-mhj8c   1/1     Running   0          4m25s
pod/nginx-rwkkj   1/1     Running   0          4m25s
pod/nginx-z48x8   1/1     Running   0          4m25s

NAME                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
service/kubernetes      ClusterIP   10.96.0.1        <none>        443/TCP   24m
service/nginx-service   ClusterIP   10.107.124.171   <none>        80/TCP    4m25s

NAME                    DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx   3         3         3       4m25s

Kalau sudah, kita coba setup host di local, caranya kita lihat dulu IP address ingressnya

$ minikube ip
192.168.64.2

Kemudian kita setup di /etc/hosts/

$ code /etc/hosts
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1	localhost
255.255.255.255	broadcasthost
::1             localhost
# Added by Docker Desktop
# To allow the same kube context to work on the host and the container:
127.0.0.1 kubernetes.docker.internal
# End of section

# Tambahkan ini
192.168.64.2 nginx.khannedy.local

Multi Container Pod

  • Saat menggunakan Docker, kita selalu diajarkan bahwa 1 aplikasi adalah 1 Container.
  • Di Kubernetes agak sedikit berbeda, saat kita deploy aplikasi kita, maka akan disimpan dalam 1 Pod. Kenapa Pod? tidak Container, karena sebenarnya di dalam Pod, kita bisa menambahkan banyak Container.
  • Ini cocok sekali jika memang kita butuh aplikasi yang berjalan di beberapa Container, dan jika ingin scale, harus semuanya ikut scale.

Screen Shot 2020-12-10 at 14 06 49

  • Saat running multiple container, IP dan Port nya sharing dalam 1 Pod, jadi kalau kita buat lebih dari satu container dalam Pod, Port tidak boleh sama.

Contoh

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      name: nginx
  template:
    metadata:
      name: nginx
      labels:
        name: nginx
    spec:
      containers: # Multiple Container
        - name: nginx
          image: nginx
          ports:
            - containerPort: 80
        - name: nodejs-web
          image: khannedy/nodejs-web
          ports:
            - containerPort: 3000

---

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    name: nginx
  ports:
    - port: 8080
      targetPort: 80
      name: nginx
    - port: 3000
      targetPort: 3000
      name: nodejs-web

---

apiVersion: v1
kind: Pod
metadata:
  name: curl
  labels:
    name: curl
spec:
  containers:
    - name: curl
      image: khannedy/nginx-curl

Tes akses service di dalam Kubernetes Cluster.

$ kubect exec -it curl -- /bin/sh

# curl http://custer-ip-service:port-container-1

#curl http://custer-ip-service:port-container-2

Volume

  • Agar data-data di dalam container tidak ikut terhapus saat Pod atau Container dihapus, maka kita perlu membuat Volume.
  • Volume secara sederhana adalah sebuah direktori yang bisa diakses oleh container-container di Pod.

Jenis-jenis Volume

Contoh

Kita buat aplikasi sederhana dengan Node.js

const fs = require("fs");
const process = require("process");
let location = process.env.HTML_LOCATION;

if (!location) {
    location = "/app/html"
}

setInterval(() => {
    const date = new Date();
    const html = `<html><body>${date}</body></html>`;

    fs.writeFile(location + "/index.html", html, err => {
        if (err) {
            console.log("Failed write file")
        } else {
            console.log("Success write file")
        }
    })

}, 5000);

Kemudian buat Dockerfile, kemudian build seperti biasa.

FROM node:12-alpine

RUN apk --no-cache add curl

RUN mkdir -p /app/html

ADD app.js app.js

CMD ["node", "app.js"]

Kemudian kita buat template Kubernetesnya, create seperti biasa.

apiVersion: v1
kind: Pod
metadata:
  name: nodejs-writer
  labels:
    name: nodejs-writer
spec:
  volumes:
    - name: html
      emptyDir: {}
  containers:
    - name: nodejs-writer
      image: khannedy/nodejs-writer
      volumeMounts:
        - mountPath: /app/html
          name: html

Cek volumenya

$ kubectl exec nodejs-writer -it -- /bin/sh
# cd /app/html
# ls
index.html
# cat index.html

Sharing Volume

  • Sharing Volume antar Container dalam 1 Pod.
  • Ini sangat cocok ketika kita butuh sharing direktori antar Container, misal container pertama membuat file, container kedua memproses file.

Contoh

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      name: nginx
  template:
    metadata:
      name: nginx
      labels:
        name: nginx
    spec:
      volumes:
        - name: html
          emptyDir: {}
      containers:
        - name: nodejs-writer
          image: khannedy/nodejs-writer
          volumeMounts:
            - mountPath: /app/html
              name: html
        - name: nginx
          image: nginx
          ports:
            - containerPort: 80
          volumeMounts:
            - mountPath: /usr/share/nginx/html
              name: html # container nginx mengambil data dari volume yang sama

---

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: NodePort
  selector:
    name: nginx
  ports:
    - port: 8080
      targetPort: 80
      nodePort: 30001

Gunakan minikube service nginx-service untuk mengakses public IP address.

Environment Variable

Contoh

apiVersion: v1
kind: Pod
metadata:
  name: nodejs-writer
  labels:
    name: nodejs-writer
spec:
  volumes:
    - name: html
      emptyDir: {}
  containers:
    - name: nodejs-writer
      image: khannedy/nodejs-writer
      volumeMounts:
        - mountPath: /app/folder-from-env
          name: html
      env:
        - name: HTML_LOCATION # Environment variable
          value: /app/folder-from-env

ConfigMap

  • ConfigMap digunakan untuk memisahkan environment variable dalam object yang berbeda dengan Pod. Hal ini bertujuan agar penulisan environment lebih konsisten.

Contoh

apiVersion: v1
kind: ConfigMap
metadata:
  name: nodejs-env-config
data:
  APPLICATION: My Cool Application
  VERSION: 1.0.0

---

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nodejs-env
spec:
  replicas: 3
  selector:
    matchLabels:
      name: nodejs-env
  template:
    metadata:
      name: nodejs-env
      labels:
        name: nodejs-env
    spec:
      containers:
        - name: nodejs-env
          image: khannedy/nodejs-env
          ports:
            - containerPort: 3000
          envFrom:
            - configMapRef:
                name: nodejs-env-config

---

apiVersion: v1
kind: Service
metadata:
  name: nodejs-env-service
spec:
  type: NodePort
  selector:
    name: nodejs-env
  ports:
    - port: 3000
      targetPort: 3000
      nodePort: 30001

Execute this command to run app on browser.

minikube service nodejs-env-service

Secret

  • Secret prinsipnya sama seperti ConfigMap, tapi Secret dikhususkan untuk menyimpan data yang sifatnya sensitif.

Template

apiVersion: v1
kind: Secret
metadata:
  name: configmap-name
data:
  ENV: base64(VALUE) # jika menggunakan ini, maka harus diencode ke base64 secara manual
stringData:
  ENV: VALUE # kalau tidak, bisa langsung menggunakan stringData tanpa harus harus encode ke base64

Contoh

apiVersion: v1
kind: ConfigMap
metadata:
  name: nodejs-env-config
data:
  APPLICATION: My Cool Application

---

apiVersion: v1
kind: Secret
metadata:
  name: nodejs-env-secret
stringData:
  VERSION: 1.0.0

---

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nodejs-env
spec:
  replicas: 3
  selector:
    matchLabels:
      name: nodejs-env
  template:
    metadata:
      name: nodejs-env
      labels:
        name: nodejs-env
    spec:
      containers:
        - name: nodejs-env
          image: khannedy/nodejs-env
          ports:
            - containerPort: 3000
          envFrom:
            - configMapRef:
                name: nodejs-env-config
            - secretRef:
                name: nodejs-env-secret

---

apiVersion: v1
kind: Service
metadata:
  name: nodejs-env-service
spec:
  type: NodePort
  selector:
    name: nodejs-env
  ports:
    - port: 3000
      targetPort: 3000
      nodePort: 30001

Perbedaan antara ConfigMap dan Secret adalah, ketika kita melihat describe ConfigMap, maka environment variable akan dieskpos.

$ kubectl describe configmap <configmap_name>
Data
====
APPLICATION:
----
My Cool Application

Sedangkan untuk Secret tidak (hanya size datanya saja)

$ kubectl describe secret <secret_name>
Data
====
VERSION: 5 bytes

Downward API

  • Downward API memungkinkan kita mengambil informasi seputar Pod dan Node melalui environment variable.
  • Jadi Downward API adalah environment bawaan dari Kubernetes yang bisa kita akses untuk keperluan deployment.
  • Jangan bingung dengan kata API, Downward API sendiri bukanlah RESTful API.

Downward API Metadata

Screen Shot 2020-12-11 at 14 35 38 Screen Shot 2020-12-11 at 14 36 13 Screen Shot 2020-12-11 at 14 36 33

Contoh

apiVersion: v1
kind: ConfigMap
metadata:
  name: nodejs-env-config
data:
  APPLICATION: My Cool Application
  VERSION: 1.0.0

---

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nodejs-env
spec:
  replicas: 3
  selector:
    matchLabels:
      name: nodejs-env
  template:
    metadata:
      name: nodejs-env
      labels:
        name: nodejs-env
    spec:
      containers:
        - name: nodejs-env
          image: khannedy/nodejs-env
          ports:
            - containerPort: 3000
          envFrom:
            - configMapRef:
                name: nodejs-env-config
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: POD_IP
              valueFrom:
                fieldRef:
                  fieldPath: status.podIP
            - name: POD_NODE
              valueFrom:
                fieldRef:
                  fieldPath: spec.nodeName
            - name: POD_NODE_IP
              valueFrom:
                fieldRef:
                  fieldPath: status.hostIP
---

apiVersion: v1
kind: Service
metadata:
  name: nodejs-env-service
spec:
  type: NodePort
  selector:
    name: nodejs-env
  ports:
    - port: 3000
      targetPort: 3000
      nodePort: 30001

Management Kubernetes Object

Imperative Management

Screen Shot 2020-12-11 at 14 53 37

Note:

  • kubectl get -f file.yaml sama artinya dengan kita menjalankan kubectl get pod nama-pod. Artinya Pod harus di-create terlebih dahulu.
  • kubectl replace hanya bisa me-replace sebagian kecil saja, tidak semua object.
  • kubectl delete -f file.yaml sama artinya dengan kita menjalankan kubectl get pod nama-pod.

Declarative Management

Screen Shot 2020-12-11 at 14 54 20

  • Perbedaan antara apply dan create adalah jika menggunakan apply (declarative management), file konfigurasi akan disimpan di dalam annotations.
  • Ini sangat bermanfaat saat menggunakan object Deployment.
  • Rata-rata saat ini declarative management lebih banyak digunakan dibandingkan Imperative Management.

Contoh

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
    - name: nginx
      image: nginx
      ports:
        - containerPort: 80

Coba menggunakan apply untuk meng-create Pod.

$ kubectl apply -f nginx.yaml

Kemudian kita get.

$ kubectl get -f nginx -o json

// Atau kita buka di VS Editor
$ kubectl get -f nginx -o json | code -

Deployment

  • Deployment digunakan untuk melakukan deployment aplikasi dan update aplikasi secara deklaratif menggunakan file konfigurasi.
  • Saat kita membuat deployment, secara otomatis Kubernetes akan membuat ReplicaSet, yg mana ReplicaSet akan secara otomatis membuat Pod.

Screen Shot 2020-12-17 at 14 15 26

Contoh

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodejs-web
  labels:
    name: nodejs-web
spec:
  replicas: 3
  selector:
    matchLabels:
      name: nodejs-web
  template:
    metadata:
      name: nodejs-web
      labels:
        name: nodejs-web
    spec:
      containers:
        - name: nodejs-web
          image: khannedy/nodejs-web:1
          ports:
            - containerPort: 3000

---

apiVersion: v1
kind: Service
metadata:
  name: nodejs-web-service
spec:
  type: NodePort
  selector:
    name: nodejs-web
  ports:
    - port: 3000
      targetPort: 3000
      nodePort: 30001

Create deployment dengan menggunakan kubectl apply -f deployment.yaml.

Jika kita lihat hasilnya, ReplicaSet secara otomatis telah dibuat.

Screen Shot 2020-12-17 at 14 23 44

Untuk menajalankan aplikasinya, tinggal execute minikube service nama-service.

Update Deployment

  • Untuk update deployment caranya sangat mudah, tinggal jalankan perintah kubectl apply -f new-deployment.yaml.
  • Saat deployment terbaru dieksekusi, secara otomatis deployment akan membuat ReplicaSet baru, lalu menjalankan Pod baru, setelah Pod siap, deployment akan menghapus Pod lama secara otomatis.
  • Ini membuat proses update berjalan mulus, dan tidak terjadi downtime.

Screen Shot 2020-12-17 at 15 25 32

  • Pod yang lama tidak serta merta langsung dihapus, tapi akan tetap disimpan terlebih dahulu untuk kebutuhan roll-back.
  • Maksimal kapasitas penyimpanan Pod lama, secara default sebanyak 10. Untuk mengubahnya tinggal tambahkan revisionHistoryLimit.
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodejs-web
  labels:
    name: nodejs-web
spec:
  revisionHistoryLimit: 5 # here
  replicas: 3
  selector:
    matchLabels:
      name: nodejs-web
  template:
    metadata:
      name: nodejs-web
      labels:
        name: nodejs-web
    spec:
      containers:
        - name: nodejs-web
          image: khannedy/nodejs-web:1
          ports:
            - containerPort: 3000

Rollback Deployment

Screen Shot 2020-12-17 at 15 39 49

Jadi untuk me-rollback bisa menggunakan perintah kubectl rollout undo deployment nama-deployment.

Persistent Volume

  • Persistent Volume sebenarnya mirip dengan Volume biasa, hanya saja cara kerjanya sedikit berbeda.
  • Cara membuat Persistent Volume sedikit lebih ribet dibanding Volume, namun ada benefit yg bisa didapat jika menggunakan Persistent Volume.

Jenis-jernis Persistent Volume

Tahapan Membuat Persistent Volume

Screen Shot 2020-12-17 at 15 59 27

  • Membuat Persistent Volume
  • Membuat Persistent Volume Claim
  • Menambahkan Persistent Volume Clain ke Pod
  • Persistent Volume Claim digunakan untuk menentukan berapa kapasitas storage untuk sebuat Pod. Ditentukan berdasarkan kapasitas Persistent Volume dibagi total Pod. Misalnya total storage Persistent Volume adalah 10, nanti akan dipakai untuk 3 Pod, maka tiga Pod itu bisa menentukan Persistent Volume Claim sebesar masing-masing 2 atau 3 (bebas).

Perintah Kubectl

kubectl get pv
kubectl describe pv nama-persistent-volume
kubectl get pvc
kubectl describe pvc nama-persistent-volume-claim
kubectl delete pv nama-persistent-volume
kubectl delete pvc nama-persistent-volume-claim

Contoh

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nodejs-writer-volume
spec:
  accessModes:
    - ReadWriteOnce
  capacity:
    storage: 5Gi
  hostPath:
    path: /data/location

---

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nodejs-writer-volume-claim
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 1Gi

---

apiVersion: v1
kind: Pod
metadata:
  name: nodejs-writer
  labels:
    name: nodejs-writer
spec:
  volumes:
    - name: html
      persistentVolumeClaim:
        claimName: nodejs-writer-volume-claim
  containers:
    - name: nodejs-writer
      image: khannedy/nodejs-writer
      volumeMounts:
        - mountPath: /app/html
          name: html

StatefulSet

  • Aplikasi stateful adalah aplikasi yang menyimpan data atau memiliki database, aplikasi jenis ini tidak bisa dihapus sembarangan.
  • Berbeda bengan aplikasi stateless, yang tidak menyimpan data dapat dihapus dan dibuat ulang, tidak menjadi masalah.

Stateless dengan Persistent Volume

  • PersistentVolume tidak tidak bisa membuat aplikasi statefull, karena semua Pod men-claim semua PersistentVolume yang sama dan direktori yang sama.

Screen Shot 2020-12-18 at 12 13 10

  • Sedangkan jika aplikasi stateful, umumnya memiliki data yang independen untuk tiap Pod, walaupun jenis Podnya sama.

Screen Shot 2020-12-18 at 12 15 16

Apa itu StatefulSet?

  • StatefulSet adalah object di Kubernetes yang digunakan untuk memanage aplikasi jenis stateful.
  • StatefulSet memastikan nama Pod yang konsisten, identitas network yang stabil, dan persisten volume yang independen untuk tiap Pod.
  • Jika Pod mati, maka StatefulSet akan membuat Pod baru dengan informasi yang sama dengan Pod yang mati.

Kubectl

kubectl get statefulset
kubectl describe statefulset nama-statefulset
kubectl delete statefulset nama-statefulset

Contoh

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nodejs-stateful-volume
spec:
  accessModes:
    - ReadWriteOnce
  capacity:
    storage: 5Gi
  hostPath:
    path: /data/location

---

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nodejs-stateful
  labels:
    name: nodejs-stateful
spec:
  # https://github.com/kubernetes/kubernetes/issues/69608
  serviceName: nodejs-stateful-service # bug
  replicas: 3
  selector:
    matchLabels:
      name: nodejs-stateful
  volumeClaimTemplates:
    - metadata:
        name: nodejs-stateful-volume-claim
      spec:
        accessModes:
          - ReadWriteOnce
        volumeMode: Filesystem
        resources:
          requests:
            storage: 1Gi
  template:
    metadata:
      name: nodejs-stateful
      labels:
        name: nodejs-stateful
    spec:
      containers:
        - name: nodejs-stateful
          image: khannedy/nodejs-stateful
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
          volumeMounts:
            - mountPath: /app/data
              name: nodejs-stateful-volume-claim

Coba hapus Pod, maka StatefulSet akan membuat Pod baru lagi dengan nama yang sama.

Screen Shot 2020-12-18 at 12 21 50

Kubernetes Dashboard

  • Kubenetes Dashboard adalah GUI untuk memanage kubernetes berbasis web.
  • Biasanya kalau kita menggunakan Cloud Provider, sudah disediakan web user interface untuk k8s.
  • Tapi jika ingin menginstall Kubernetes data center sendiri, bisa menggunakan GUI dari bawaan k8s, namanya Kubernetes Dashboard: https://github.com/kubernetes/dashboard

Kubectl

minikube addons enable dashboard
kubectl get all --namespace nama-namespace
minikube dashboard

Note: di dalam Kubernetes Dashboard kita juga bisa membuat object/resource kubernetes.

Computational Resources

  • Adalah mekanisme membatasi jumlah resource yang digunakan oleh Pod agar tidak terjadi perebutan resource antar Pod.
  • Misalnya sebuah Node memiliki memori 10 gb dan cpu 4 core, maka itu akan digunakan oleh Pod-pod yang ada di dalamnya.
  • Pod-pod dalam sebuah Node, akan menggunakan resource secara sharing. Jadi, jika ada 1 Pod yang sibuk, akan membuat Pod lain menjadi lambat, karena menggunakan resource yang besar.

Request dan Limit

  • Request dan Limit adalah mekanisme Kubernetes untuk mengontrol penggunaan memory dan CPU.
  • Request adalah menetapkan permintaan jumlah resource untuk Pod. Kubernetes hanya akan menjalankan di Node yang bisa memenuhi jumlah resource tersebut.
  • Limit adalah batas penggunaan resource pada sebuah container. Misalnya sebuah Pod memiliki limit 5 GB untuk memori, maka Pod tersebut tidak bisa menggunakaan lebih dari itu.

Contoh

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodejs-web
  labels:
    name: nodejs-web
spec:
  replicas: 3
  selector:
    matchLabels:
      name: nodejs-web
  template:
    metadata:
      name: nodejs-web
      labels:
        name: nodejs-web
    spec:
      containers:
        - name: nodejs-web
          image: khannedy/nodejs-web
          ports:
            - containerPort: 3000
          resources: # resources
            requests:
              cpu: 1000m # milli core
              memory: 1000Mi # mebibyte
            limits:
              cpu: 1000m
              memory: 1000Mi

---

apiVersion: v1
kind: Service
metadata:
  name: nodejs-web-service
spec:
  type: NodePort
  selector:
    name: nodejs-web
  ports:
    - port: 3000
      targetPort: 3000
      nodePort: 30001

Horizontal Pod Autoscaler

  • Saat aplikasi sedang sibuk, maka konsumsi memory atau CPU akan tinggi, maka ada kemungkinan performa aplikasi kita akan turun.
  • Saat hal ini terjadi, application scaling sangat dibutuhkan.
  • Secara garis besar, ada 2 jenis application scaling, yakni Vertical Scaling dan Horizontal Scaling.

Vertical Scaling

  • Vertical Scaling adalah cara application scaling dengan mengupgrade computational resource di aplikasi kita.
  • Misal dari 1 CPU menjadi 2 CPU, dari 1 GB memory menjadi 2 GB.
  • Namun permasalahannya Vertical Scaling akan ada batasnya. Pod di Kubernetes tidak bisa menggunakan resource melebihi yang telah tersedia di Node.

Horizontal Scaling

  • Horizontal Scaling adalah application scaling dengan cara membuat Pod baru, agar beban pekerjaan bisa didistribusikan ke Pod baru tersebut.
  • Scalability terbaik harusnya dicapai oleh Horizontal Scaling, karena tidak butuh upgrade Node dengan resource yang lebih tinggi.

Vertical Pod Autoscaler

Horizontal Pod Autoscaler (HPA)

  • Adalah kemampuan secara otomatis application scaling secara horizontal dengan cara menambah Pod baru dan mengurangi secara otomatis bila diperlukan.
  • HPA adalah object di Kubernetes.
  • HPA bekerja dengan cara melihat data metrics dari setiap Pod, dan jika sudah mencapai batas tertentu, HPA akan melakukan auto scaling (baik itu menaikan jumlah Pod atau menurunkan).

Screen Shot 2020-12-22 at 14 17 09

Enable Metrics Server di Minikube

minikube addons enable metrics-server
kubectl get pods --namespace kube-system

Contoh

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodejs-web
  labels:
    name: nodejs-web
spec:
  selector:
    matchLabels:
      name: nodejs-web
  template:
    metadata:
      name: nodejs-web
      labels:
        name: nodejs-web
    spec:
      containers:
        - name: nodejs-web
          image: khannedy/nodejs-web:1
          ports:
            - containerPort: 3000

---

apiVersion: v1
kind: Service
metadata:
  name: nodejs-web-service
spec:
  type: NodePort
  selector:
    name: nodejs-web
  ports:
    - port: 3000
      targetPort: 3000
      nodePort: 30001

---

# Horizontal Pod Autoscaler
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: hpa-name
spec:
  minReplicas: 3 # Jumlah minimal replica pada Pod, jika Pod hanya awalnya hanya 1 replica, maka akan dibuat menjadi 3 replica.
  maxReplicas: 5 # Jumlah maksimal replica jika resource menyentuh angkat tertentu
  scaleTargetRef: # Target object
    apiVersion: apps/v1
    kind: Deployment
    name: nodejs-web
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70 # Rata-rata penggunaan CPU 70%
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 70 # Rata-rata penggunaan memory 70%
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment