Pengelolaan Objek Kubernetes secara Deklaratif dengan Menggunakan Berkas Konfigurasi

Objek-objek Kubernetes dapat dibuat, diperbarui, dan dihapus dengan menjalankan perintah kubectl apply terhadap file-file konfigurasi objek yang disimpan dalam sebuah direktori secara rekursif sesuai dengan kebutuhan. Perintah kubectl diff bisa digunakan untuk menampilkan pratinjau tentang perubahan apa saja yang akan dibuat oleh perintah kubectil apply.

Kelebihan dan kekurangan

Perintah kubectl memungkinkan tiga cara untuk mengelola objek:

  • Perintah imperatif
  • Konfigurasi objek imperatif
  • Konfigurasi objek deklaratif

Lihat Pengelolaan Objek Kubernetes untuk menyimak diskusi mengenai kelebihan dan kekurangan dari tiap cara pengelolaan objek.

Sebelum kamu mulai

Konfigurasi objek secara deklaratif membutuhkan pemahaman yang baik tentang definisi dan konfigurasi objek-objek Kubernetes. Jika belum pernah, kamu disarankan untuk membaca terlebih dulu dokumen-dokumen berikut:

Berikut adalah beberapa defnisi dari istilah-istilah yang digunakan dalam dokumen ini:

  • objek berkas konfigurasi / berkas konfigurasi: Sebuah file yang mendefinisikan konfigurasi untuk sebuah objek Kubernetes. Dokumen ini akan memperlihatkan cara menggunakan file konfigurasi dengan perintah kubectl apply. File-file konfigurasi biasanya disimpan di sebuah source control seperti Git.
  • konfigurasi objek live / konfigurasi live: nilai konfigurasi live dari sebuah objek, sebagaimana yang tersimpan di klaster Kubernetes. Nilai-nilai ini disimpan di storage klaster Kubernetes, biasanya etcd.
  • writer konfigurasi deklaratif / writer deklaratif: Seseorang atau sebuah komponen perangkat lunak yang membuat pembaruan ke objek live. Live writer yang disebut pada dokumen ini adalah writer yang membuat perubahan terhadap file konfigurasi objek dan menjalankan perintah kubectl apply untuk menulis perubahan-perubahan tersebut.

Cara membuat objek

Gunakan perintah kubectl apply untuk membuat semua objek, kecuali objek-objek yang sudah ada sebelumnya, yang didefinisikan di file-file konfigurasi dalam direktori yang ditentukan:

kubectl apply -f <directory>/

Perintah di atas akan memberi anotasi kubectl.kubernetes.io/last-applied-configuration: '{...}' pada setiap objek yang dibuat. Anotasi ini berisi konten dari file konfigurasi objek yang digunakan untuk membuat objek tersebut.

Berikut sebuah contoh file konfigurasi objek:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  minReadySeconds: 5
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

Jalankan perintah kubectl diff untuk menampilkan objek yang akan dibuat:

kubectl diff -f https://k8s.io/examples/application/simple_deployment.yaml

Buat objek dengan perintah kubectl apply:

kubectl apply -f https://k8s.io/examples/application/simple_deployment.yaml

Tampilkan konfigurasi live dengan perintah kubectl get:

kubectl get -f https://k8s.io/examples/application/simple_deployment.yaml -o yaml

Keluaran perintah di atas akan menunjukkan bahwa anotasi kubectl.kubernetes.io/last-applied-configuration sudah dituliskan ke konfigurasi live, dan anotasi tersebut sesuai dengan file konfigurasi:

kind: Deployment
metadata:
  annotations:
    # ...
    # Ini merupakan representasi dari simple_deployment.yaml dalam format json
    # Ini ditulis oleh perintah `kubectl apply` ketika objek dibuat
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"apps/v1","kind":"Deployment",
      "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},
      "spec":{"minReadySeconds":5,"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},
      "spec":{"containers":[{"image":"nginx:1.7.9","name":"nginx",
      "ports":[{"containerPort":80}]}]}}}}      
  # ...
spec:
  # ...
  minReadySeconds: 5
  selector:
    matchLabels:
      # ...
      app: nginx
  template:
    metadata:
      # ...
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.7.9
        # ...
        name: nginx
        ports:
        - containerPort: 80
        # ...
      # ...
    # ...
  # ...

Cara memperbarui objek

Kamu juga bisa menggunakan kubectl apply untuk memperbarui semua objek yang didefinisikan dalam sebuah direktori, termasuk objek-objek yang sudah ada sebelumnya. Cara ini akan melakukan hal-hal berikut:

  1. Menyimpan nilai field-field yang ada di file konfigurasi ke konfigurasi live.
  2. Menghapus field-field yang dihapus di file konfigurasi dari konfigurasi live.
kubectl diff -f <directory>/
kubectl apply -f <directory>/

Berikut sebuah contoh file konfigurasi:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  minReadySeconds: 5
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

Buat objek dengan perintah kubectl apply::

kubectl apply -f https://k8s.io/examples/application/simple_deployment.yaml

Tampilkan konfigurasi live dengan perintah kubectl get:

kubectl get -f https://k8s.io/examples/application/simple_deployment.yaml -o yaml

Keluaran perintah di atas akan menunjukkan bahwa anotasi kubectl.kubernetes.io/last-applied-configuration sudah dituliskan ke konfigurasi live, dan anotasi tersebut sesuai dengan file konfigurasi:

kind: Deployment
metadata:
  annotations:
    # ...
    # Berikut merupakan representasi dari simple_deployment.yaml dalam format json
    # Representasi berikut ditulis oleh perintah kubectl apply ketika objek dibuat
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"apps/v1","kind":"Deployment",
      "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},
      "spec":{"minReadySeconds":5,"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},
      "spec":{"containers":[{"image":"nginx:1.7.9","name":"nginx",
      "ports":[{"containerPort":80}]}]}}}}      
  # ...
spec:
  # ...
  minReadySeconds: 5
  selector:
    matchLabels:
      # ...
      app: nginx
  template:
    metadata:
      # ...
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.7.9
        # ...
        name: nginx
        ports:
        - containerPort: 80
        # ...
      # ...
    # ...
  # ...

Perbarui nilai replicas secara langsung di konfigurasi live dengan menggunakan perintah kubectl scale. Pembaruan ini tidak menggunakan perintah kubectl apply:

kubectl scale deployment/nginx-deployment --replicas=2

Tampilkan konfigurasi live dengan perintah kubectl get:

kubectl get -f https://k8s.io/examples/application/simple_deployment.yaml -o yaml

Keluaran perintah di atas akan menunjukkan bahwa nilai replicas telah diubah menjadi 2, dan anotasi last-applied-configuration tidak memuat nilai replicas:

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    # ...
    # perhatikan bahwa anotasi tidak memuat nilai replicas
    # karena nilai tersebut tidak diperbarui melalui perintah kubectl-apply
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"apps/v1","kind":"Deployment",
      "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},
      "spec":{"minReadySeconds":5,"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},
      "spec":{"containers":[{"image":"nginx:1.7.9","name":"nginx",
      "ports":[{"containerPort":80}]}]}}}}      
  # ...
spec:
  replicas: 2 # ditulis oleh perintah kubectl scale
  # ...
  minReadySeconds: 5
  selector:
    matchLabels:
      # ...
      app: nginx
  template:
    metadata:
      # ...
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.7.9
        # ...
        name: nginx
        ports:
        - containerPort: 80
      # ...

Perbarui file konfigurasi simple_deployment.yaml, ubah image dari nginx:1.7.9 ke nginx:1.11.9, dan hapus field minReadySeconds:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.11.9 # perbarui image
        ports:
        - containerPort: 80

Terapkan perubahan yang telah dibuat di file konfigurasi:

kubectl diff -f https://k8s.io/examples/application/update_deployment.yaml
kubectl apply -f https://k8s.io/examples/application/update_deployment.yaml

Tampilkan konfigurasi live dengan perintah kubectl get:

kubectl get -f https://k8s.io/examples/application/simple_deployment.yaml -o yaml

Keluaran perintah di atas akan menunjukkan perubahan-perubahan berikut pada konfiguasi live:

  • Field replicas tetap bernilai 2 sesuai dengan nilai yang diatur oleh perintah kubectl scale. Hal ini karena field replicas dihapuskan dari file konfigurasi.
  • Nilai field image telah diperbarui menjadi nginx:1.11.9 dari nginx:1.7.9.
  • Anotasi last-applied-configuration telah diperbari dengan image terbaru.
  • Field minReadySeconds telah dihapus.
  • Anotasi last-applied-configuration tidak lagi memuat field minReadySeconds.
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    # ...
    # Anotasi memuat image yang telah diperbarui ke nginx 1.11.9,
    # tetapi tidak memuat nilai replica yang telah diperbarui menjadi 2
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"apps/v1","kind":"Deployment",
      "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},
      "spec":{"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},
      "spec":{"containers":[{"image":"nginx:1.11.9","name":"nginx",
      "ports":[{"containerPort":80}]}]}}}}      
    # ...
spec:
  replicas: 2 # Diatur oleh `kubectl scale`, tidak diubah oleh `kubectl apply`.
  # minReadySeconds dihapuskan oleh `kubectl apply`
  # ...
  selector:
    matchLabels:
      # ...
      app: nginx
  template:
    metadata:
      # ...
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.11.9 # Diatur oleh `kubectl apply`
        # ...
        name: nginx
        ports:
        - containerPort: 80
        # ...
      # ...
    # ...
  # ...

Cara menghapus objek

Ada dua cara untuk menghapus objek-objek yang dikelola dengan kubectl apply.

Rekomendasi: kubectl delete -f <filename>

Penghapusan objek secara manual dengan menggunakan perintah imperatif merupakan cara yang direkomendasikan karena lebih eksplisit dalam menentukan objek apa yang akan dihapus dan lebih kecil kemungkinannya untuk pengguna menghapus objek lain secara tidak sengaja:

kubectl delete -f <filename>

Alternatif: kubectl apply -f <directory/> --prune -l your=label

Lakukan ini hanya jika kamu benar-benar mengetahui apa yang kamu lakukan.

Sebagai alternatif dari kubectl delete, kamu bisa menggunakan kubectl apply untuk mengidentifikasi objek-objek yang hendak dihapus setelah berkas konfigurasi objek-objek tersebut dihapus dari direktori. Ketika dijalankan dengan argumen --prune, perintah kubectl apply akan melakukan query ke API server untuk mencari semua objek yang sesuai dengan himpunan label-label tertentu, dan berusaha untuk mencocokkan kofigurasi objek live yg diperoleh terhadap file konfigurasi objek. Jika sebuah objek cocok dengan query yang dilakukan, dan objek tersebut tidak memiliki file konfigurasi di direktori serta tidak memiliki anotasi last-applied-configuration, objek tersebut akan dihapus.

kubectl apply -f <directory/> --prune -l <labels>

Cara melihat objek

Kamu bisa menggunakan perintah kubectl get dengan parameter -o yaml untuk melihat konfigurasi dari sebuah objek live:

kubectl get -f <filename|url> -o yaml

Cara kubectl apply menghitung perbedaan dan menggabungkan perubahan

Ketika memperbarui konfigurasi live dari sebuah objek, kubectl apply melakukannya dengan mengirimkan request untuk melakukan patch ke API server. Patch mendefinisikan pembaruan-pembaruan yang likungpnya sepsifik terhadap sejumlah field dari objek konfigurasi live. Perintah kubectl apply menghitung patch request ini menggunakan file konfigurasi, konfigurasi live, dan anotasi last-applied-configuration yang tersimpan di konfigurasi live.

Perhitungan penggabungan patch

Perintah kubectl apply menulis konten dari berkas konfigurasi ke anotasi kubectl.kubernetes.io/last-applied-configuration. Ini digunakan untuk mengidentifikasi field apa saja yang telah dihapus dari file konfigurasi dan perlu dihapus dari konfigurasi live. Berikut adalah langkah-langkah yang digunakan untuk menghitung field apa saja yang harus dihapus atau diubah:

  1. Hitung field-field yang perlu dihapus. Ini mencakup field-field yang ada di last-applied-configuration tapi tidak ada di file konfigurasi.
  2. Hitung field-field yang perlu ditambah atau diubah. Ini mencakup field-field yang ada di file konfigurasi yang nilainya tidak sama dengan konfigurasi live.

Agar lebih jelas, simak contoh berikut. Misalkan, berikut adalah file konfigurasi untuk sebuah objek Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.11.9 # perbarui image
        ports:
        - containerPort: 80

Juga, misalkan, berikut adalah konfigurasi live dari objek Deployment yang sama:

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    # ...
    # perhatikan bagaimana anotasi berikut tidak memuat replicas
    # karena replicas tidak diperbarui melalui perintah kubectl apply
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"apps/v1","kind":"Deployment",
      "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},
      "spec":{"minReadySeconds":5,"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},
      "spec":{"containers":[{"image":"nginx:1.7.9","name":"nginx",
      "ports":[{"containerPort":80}]}]}}}}      
  # ...
spec:
  replicas: 2 # ditulis oleh perintah kubectl scale
  # ...
  minReadySeconds: 5
  selector:
    matchLabels:
      # ...
      app: nginx
  template:
    metadata:
      # ...
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.7.9
        # ...
        name: nginx
        ports:
        - containerPort: 80
      # ...

Berikut merupakan perhitungan penggabungan yang akan dilakukan oleh perintah kubectl apply:

  1. Hitung semua field yang akan dihapus dengan membaca nilai dari last-applied-configuration dan membandingkannya dengan nilai yang ada di file konfigurasi. Hapus semua field yang nilainya secara eksplisit diubah menjadi null pada file konfigurasi objek lokal terlepas dari apakah field-field tersebut ada di anotasi last-applied-configuration atau tidak. Pada contoh di atas, field minReadySeconds muncul pada anotasi last-applied-configuration, tapi tidak ada di file konfigurasi. Aksi: Hapus minReadySeconds dari konfigurasi live.
  2. Hitung semua field yang akan diubah dengan membaca nilai-nilai dari file konfigurasi dan membandingkannya dengan nilai-nilai yang ada di konfigurasi live. Pada contoh ini, nilai dari field image di file konfigurasi tidak sama dengan nilai dari konfigurasi live. Aksi: Ubah nilai image pada konfigurasi live.
  3. Ubah anotasi last-applied-configuration agar sesuai dengan nilai yang ada di file konfigurasi.
  4. Gabungkan hasil-hasil dari langkah 1, 2, dan 3 ke dalam satu patch request ke API server.

Berikut konfigurasi live yang dihasilkan oleh proses penggabungan pada contoh di atas:

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    # ...
    # Anotasi memuat pembaruan image menjadi nginx 1.11.9,
    # tetapi tidak memuat pembaruan replicas menjadi 2
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"apps/v1","kind":"Deployment",
      "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},
      "spec":{"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},
      "spec":{"containers":[{"image":"nginx:1.11.9","name":"nginx",
      "ports":[{"containerPort":80}]}]}}}}      
    # ...
spec:
  selector:
    matchLabels:
      # ...
      app: nginx
  replicas: 2 # Diubah oleh `kubectl scale`, tidak diubah oleh `kubectl apply`.
  # minReadySeconds dihapus oleh `kubectl apply`
  # ...
  template:
    metadata:
      # ...
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.11.9 # Diubah oleh `kubectl apply`
        # ...
        name: nginx
        ports:
        - containerPort: 80
        # ...
      # ...
    # ...
  # ...

Cara penggabungan tipe-tipe field yang berbeda

Cara sebuah field terentu dalam sebuah file konfigurasi digabungkan dengan konfigurasi live bergantung pada tipe field tersebut. Ada beberapa tipe field:

  • primitif: field yang bertipe string, integer, atau boolean. Sebagai contoh, image dan replicas termasuk sebagai field primitif. Aksi: Replace.

  • map, atau objek: field yang bertipe map atau tipe kompleks yang mengandung sub field. Sebagai contoh, labels, annotations, spec, dan metadata termasuk sebagai map. Aksi: Lakukan penggabungan tiap-tiap elemen atau sub field.

  • list: field yang berisi sejumlah item yang tiap itemnya bisa berupa tipe primitif maupun map. Sebagai contoh, containers, ports, dan args termasuk sebagai list. Aksi: Bervariasi.

Ketika digunakan untuk memperbarui sebuah field bertipe map atau list, perintah kubectl apply memperbarui nilai tiap-tiap sub elemen ketimbang mengganti nilai semua field. Misalnya, ketika menggabungkan field spec pada sebuah Deployment, bukan keseluruhan field spec yang diubah nilainya. Alih-alih, sub field dari spec seperti replicas yang kemudian dibandingkan nilainya dan digabungkan.

Menggabungkan perubahan pada field primitif

Field primitif diganti nilainya atau dihapus sama sekali.

Field pada file konfigurasi objek Field pada objek konfigurasi live Field pada last-applied-configuration Aksi
Ya Ya - Ubah nilai di konfigurasi live mengikuti nilai pada file konfigurasi.
Ya Tidak - Ubah nilai di konfigurasi live mengikuti nilai pada konfigurasi lokal.
Tidak - Ya Hapus dari konfigurasi live.
Tidak - Tidak Tidak melakukan apa-apa, pertahankan nilai konfigurasi live.

Menggabungkan perubahan pada field bertipe map

Field yang bertipe map digabungkan dengan membandingkan tiap sub field atau elemen dari map:

Key pada file konfigurasi objek Key pada objek konfigurasi live Field pada last-applied-configuration Aksi
Ya Ya - Bandingkan nilai tiap sub field.
Ya Tidak - Ubah nilai pada konfigurasi live mengikuti nilai pada konfigurasi lokal.
Tidak - Ya Hapus dari konfigurasi live.
Tidak - Tidak Tidak melakukan apa-apa, pertahankan nilai konfigurasi live.

Menggabungkan perubahan pada field yang bertipe list

Penggabungan perubahan pada sebuah list bisa menggunakan salah satu dari tiga strategi:

  • Ganti nilai keseluruhan list.
  • Gabungkan nilai tiap-tiap elemen di dalam sebuah list yang elemennya kompleks.
  • Gabungkan list yang elemennya primitif.

Pilihan strategi dibuat berbeda-beda bergantung tipe tiap field.

Ganti nilai keseluruhan list

Perlakukan list sama dengan field primitif. Ganti atau hapus keseluruhan list. Ini akan menjaga urutan dari list.

Contoh: Gunakan kubectl apply untuk memperbarui field args pada sebuah kontainer di dalam sebuah pod. Ini akan mengubah nilai args di konfigurasi live mengikuti nilai di file konfigurasi. Elemen args apapun yang sebelumnya ditambahkan ke konfigurasi live akan hilang. Urutan dari elemen-elemen args yang didefinisikan di file konfigurasi akan dipertahankan ketika ditulis ke konfigurasi live.

# nilai last-applied-configuration*
    args: ["a", "b"]

# nilai berkas konfigurasi
    args: ["a", "c"]

# nilai konfigurasi live
    args: ["a", "b", "d"]

# hasil setelah penggabungan
    args: ["a", "c"]

Penjelasan: Penggabungan menggunakan nilai pada file konfigurasi sebagai nilai baru untuk list args.

Menggabungkan tiap-tiap elemen dari sebuah list dengan elemen kompleks:

Perlakukan list selayaknya sebuah map, perlakukan field spesifik dari tiap element sebagai sebuah key. Tambah, hapus, atau perbarui tiap-tiap elemen. Operasi ini tidak mempertahankan urutan elemen di dalam list.

Strategi penggabungan ini menggunakan tag khusus patchMergeKey pada tiap field. Tag patchMergeKey didefinisikan untuk tiap field pada source code Kubernetes: types.go. Ketika menggabungkan sebuah list yang berisi map, field yang dispesifikasikan sebagai patchMergeKey untuk tiap elemen digunakan sebagai map key untuk elemen tersebut.

Contoh: Gunakan kubectl apply untuk memperbarui field containers pada sebuah PodSpec. Perintah ini akan menggabungkan list containers seolah-olah list tersebut adalah sebuah map dan tiap elemennya menggunakan name sebagai key.

# nilai last-applied-configuration
    containers:
    - name: nginx
      image: nginx:1.10
    - name: nginx-helper-a # key: nginx-helper-a; akan dihapus pada hasil akhir
      image: helper:1.3
    - name: nginx-helper-b # key: nginx-helper-b; akan dipertahankan pada hasil akhir
      image: helper:1.3

# nilai berkas konfigurasi
    containers:
    - name: nginx
      image: nginx:1.10
    - name: nginx-helper-b
      image: helper:1.3
    - name: nginx-helper-c # key: nginx-helper-c; akan ditambahkan pada hasil akhir
      image: helper:1.3

# konfigurasi live
    containers:
    - name: nginx
      image: nginx:1.10
    - name: nginx-helper-a
      image: helper:1.3
    - name: nginx-helper-b
      image: helper:1.3
      args: ["run"] # Field ini akan dipertahankan pada hasil akhir
    - name: nginx-helper-d # key: nginx-helper-d; akan dipertahankan pada hasil akhir
      image: helper:1.3

# hasil akhir setelah penggabungan
    containers:
    - name: nginx
      image: nginx:1.10
      # Elemen nginx-helper-a dihapus
    - name: nginx-helper-b
      image: helper:1.3
      args: ["run"] # Field dipertahankan
    - name: nginx-helper-c # Elemen ditambahkan
      image: helper:1.3
    - name: nginx-helper-d # Elemen tidak diubah
      image: helper:1.3

Penjelasan:

  • Kontainer dengan nama "nginx-helper-a" dihapus karena tidak ada kontainer dengan nama tersebut di file konfigurasi.
  • Kontainer dengan nama "nginx-helper-b" tetap mempertahankan nilai args pada konfigurasi live. Perintah kubectl apply bisa mengenali bahwa "nginx-helper-b" di konfigurasi live sama dengan "ngnix-helper-b" di file konfigurasi, meskipun keduanya memiliki field yang berbeda (tidak ada args pada file konfigurasi). Ini karena nilai patchMergeKey di kedua konfigurasi identik.
  • Kontainer dengan nama "nginx-helper-c" ditambahkan karena tidak ada kontainer dengan nama tersebut di konfigurasi live, tapi ada di file konfigurasi.
  • Kontainer dengan nama "nginx-helper-d" dipertahankan karena tidak ada elemen dengan nama tersebut pada last-applied-configuration.

Menggabungkan sebuah list dengan elemen-elemen primitif

Pada versi Kubernetes 1.5, penggabungan list dengan elemen-elemen primitif tidak lagi didukung.

Nilai default dari sebuah field

API server mengisi field tertentu dengan nilai default pada konfigurasi live jika nilai field-field tersebut tidak dispesifikasikan ketika objek dibuat.

Berikut adalah sebuah file konfigurasi untuk sebuah Deployment. Berkas berikut tidak menspesifikasikan strategy:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  minReadySeconds: 5
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

Buat objek dengan perintah kubectl apply:

kubectl apply -f https://k8s.io/examples/application/simple_deployment.yaml

Tampilkan konfigurasi live dengan perintah kubectl get:

kubectl get -f https://k8s.io/examples/application/simple_deployment.yaml -o yaml

Keluaran dari perintah tadi menunjukkan bahwa API server mengisi beberapa field dengan nilai default pada konfigurasi live. Field-field berikut tidak dispesifikan pada file konfigurasi.

apiVersion: apps/v1
kind: Deployment
# ...
spec:
  selector:
    matchLabels:
      app: nginx
  minReadySeconds: 5
  replicas: 1 # nilai default dari apiserver
  strategy:
    rollingUpdate: # nilai default dari apiserver - diturunkan dari strategy.type
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate # nilai default dari apiserver
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.7.9
        imagePullPolicy: IfNotPresent # nilai default dari apiserver
        name: nginx
        ports:
        - containerPort: 80
          protocol: TCP # nilai default dari apiserver
        resources: {} # nilai default dari apiserver
        terminationMessagePath: /dev/termination-log # nilai default dari apiserver
      dnsPolicy: ClusterFirst # nilai default dari apiserver
      restartPolicy: Always # nilai default dari apiserver
      securityContext: {} # nilai default dari apiserver
      terminationGracePeriodSeconds: 30 # nilai default dari apiserver
# ...

Dalam sebuah patch request, field-field dengan nilai default tidak diisi kembali dengan nilai default kecuali secara eksplisit nilainya dihapuskan sebagai bagian dari patch request. Ini bisa menimbulkan hasil yang tak terduga jika sebagian field diisi dengan nilai default yang diturunkan dari nilai field lainnya. Ketika field lain tersebut nilainya diubah, field-field yang diisi dengan nilai default berdasarkan field yang berubah tadi tidak akan diperbarui kecuali secara eksplisit dihapus.

Oleh karena itu, beberapa field yang nilainya diisi secara default oleh server perlu didefinisikan secara eksplisit di file konfigurasi, meskipun nilai yang diinginkan sudah sesuai dengan nilai default dari server. Ini untuk mempermudah mengenali nilai-nilai yang berselisih yang tidak akan diisi dengan nilai default oleh server.

Contoh:

# last-applied-configuration
spec:
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

# berkas konfigurasi
spec:
  strategy:
    type: Recreate # nilai yang diperbarui
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

# konfigurasi live
spec:
  strategy:
    type: RollingUpdate # nilai default
    rollingUpdate: # nilai default yang diturunkan dari type
      maxSurge : 1
      maxUnavailable: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

# hasil setelah penggabungan - ERROR!
spec:
  strategy:
    type: Recreate # nilai yang diperbarui: tidak kompatibel dengan field rollingUpdate
    rollingUpdate: # nilai default: tidak kompatibel dengan "type: Recreate"
      maxSurge : 1
      maxUnavailable: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

Penjelasan:

  1. Pengguna sebelumnya sudah membuat sebuah Deployment tanpa mendefinisikan strategy.type (seperti yang bisa dilihat pada last-applied-configuration).
  2. Server mengisi strategy.type dengan nilai default RollingUpdate dan mengisi strategy.rollingUpdate dengan nilai default pada konfigurasi live.
  3. Pengguna mengubah nilai field strategy.type menjadi Recreate pada file konfigurasi. Nilai strategy.rollingUpdate tidak berubah dari nilai default, meskipun server sekarang berekspektasi nilai tersebut dihapus. Jika nilai strategy.rollingUpdate didefinisikan di awal pada file konfigurasi, akan jelas bagi server bahwa field tersebut perlu dihapus.
  4. Perintah kubect apply gagal karena strategy.rollingUpdate tidak dihapus. Field strategy.rollingUpdate tidak bisa didefinisikan jika field strategy.type berisi Recreate.

Rekomendasi: Field-field ini harus didefinisikan secara eksplisit di file konfigurasi objek:

  • Label Selectors dan PodTemplate pada workloads, misalnya Deployment, StatefulSet, Job, DaemonSet, ReplicaSet, dan ReplicationController
  • Strategi Deployment rollout

Cara menghilangkan field-field yang diisi dengan nilai default atau diisi oleh writer lainnya

Field-field yang tidak muncul di file konfigurasi bisa dihilangkan dengan mengisi nilainya dengan null dan kemudian jalankan kubectl apply dengan file konfigurasi tersebut. Untuk field-field yang nilainya diisi dengan nilai default oleh server, aksi ini akan mmenyebabkan pengisian ulang field dengan nilai default.

Cara mengubah kepemilikan sebuah field antara file konfigurasi dan writer imperatif

Hanya metode-metode berikut yang bisa kamu gunakan untuk mengubah satu field objek:

  • Gunakan kubectl apply.
  • Tulis secara langsung ke konfigurasi live tanpa memodifikasi file konfigurasi: misalnya, dengan perintah kubectl scale.

Mengubah kepemilikan dari writer imperatif ke file konfigurasi

Tambahkan field ke file konfigurasi. Hentikan pembaruan secara langsung ke konfigurasi live tanpa melalui kubectl apply.

Mengubah kepemilikan dari file konfigurasi ke writer imperatif

Pada versi Kubernetes 1.5, mengubah kepemilikan sebuah field dari file konfigurasi memerlukan langkah-langkah manual:

  • Hapus field dari file konfigurasi.
  • Hapus field dari anotasi kubectl.kubernetes.io/last-applied-configuration pada objek live.

Mengubah metode-metode pengelolaan objek

Objek-objek Kubernetes sebaiknya dikelola dengan satu metode dalam satu waktu. Berpindah dari satu metode ke metode lain dimungkinkan, tetapi memerlukan proses manual.

Migrasi dari pengelolaan dengan perintah imperatif ke konfigurasi objek deklaratif

Migrasi dari pengelolaan objek dengan perintah imperatif ke pengelolaan objek dengan konfigurasi deklaratif memerlukan beberapa langkah manual:

  1. Ekspor objek live ke file konfigurasi lokal:

    kubectl get <kind>/<name> -o yaml > <kind>_<name>.yaml
    
  2. Hapus secara manual field status dari file konfigurasi.

  3. Ubah anotasi kubectl.kubernetes.io/last-applied-configuration pada objek:

    kubectl replace --save-config -f <kind>_<name>.yaml
    
  4. Selanjutnya gunakan kubectl apply secara eksklusif untuk mengelola objek.

Migrasi dari konfigurasi objek imperatif ke konfigurasi objek deklaratif

  1. Atur anotasi kubectl.kubernetes.io/last-applied-configuration pada objek:

    kubectl replace --save-config -f <kind>_<name>.yaml
    
  2. Gunakan selalu perintah kubectl apply saja untuk mengelola objek.

Pendefinisian selektor controller dan label PodTemplate

Cara yang disarankan adalah dengan mendefinisikan sebuah PodTemplate immutable yang hanya digunakan oleh selektor controller tanpa memiliki arti semantik lainnya.

Contoh:

selector:
  matchLabels:
      controller-selector: "extensions/v1beta1/deployment/nginx"
template:
  metadata:
    labels:
      controller-selector: "extensions/v1beta1/deployment/nginx"

Selanjutnya

Last modified November 07, 2020 at 5:22 PM PST: fix typo file on declarative-config page (ea6cbc04a)