Kubernetes ConfigMap pada Aplikasi Dinamis
Kubernetes memiliki fitur yang bernama ConfigMap yang biasa digunakan untuk menyimpan konfigurasi suatu aplikasi. Di artikel ini kita akan membahas tentang ConfigMap dan kita bisa pakai ConfigMap untuk apa saja.
Apa Itu ConfigMap?
ConfigMap allows you to decouple configuration artifacts from image content to keep containerized applications portable.
Menurut penjelasan resmi dari dokumentasi Kubernetes, ConfigMap adalah sebuah mekanisme untuk memisahkan konfigurasi dari sebuah aplikasi yang sudah dikontainerkan. Hal ini dapat membuat aplikasi tersebut lebih portabel dan membuat konfigurasinya lebih mudah untuk diubah dan dimanage, dan juga mengurangi kemungkinan konfigurasi yang langsung ditulis ke dalam sebuah Pod. ConfigMap cocok digunakan untuk menyimpan konfigurasi yang tidak sensitif atau konfigurasi yang tidak perlu dienkripsi, seperti variabel lingkungan.
Bagaimana Cara Kerja ConfigMap?
Pada Gambar 1.1 kita membuat ConfigMap terlebih dahulu. Ada 3 cara untuk membuat ConfigMap:
- Menggunakan opsi –from-file.
Contoh:
kubectl create configmap myConfigMap --from-file /my/path/to/directory/or/file
- Menggunakan opsi –from-literal.
Contoh:
kubectl create configmap myConfigMap --from-literal KEY1=VALUE1 KEY2=VALUE2
- Menggunakan manifest dengan tipe ConfigMap (lihat gambar 2.1).
Untuk menggunakan cara ini kita perlu membuat sebuah file dengan ekstensi .yaml dan sesuai dengan spesifikasi, lalu mengunggah file tersebut dengan perintah
kubectl apply -f myConfigMap.yaml
Perintah kubectl create configmap
maupun kubectl apply -f <file>
akan mengunggah ConfigMap tersebut ke Apiserver Kubernetes yang ada di dalam cluster Kubernetes.
Lalu apiserver akan mendistribusikan ConfigMap tersebut ke semua Pod yang membutuhkan yang berada di dalam cluster Kubernetes.
Bagaimana Cara Menggunakan ConfigMap?
Ada 2 cara untuk menggunakan ConfigMap:
1. Sebagai environment variable
Sebagai contoh, kita memiliki sebuah ConfigMap seperti berikut
Penjelasan nomor pada gambar:
1. Nama ConfigMap
2. Blok data untuk sebuah ConfigMap
Lalu kita gunakan nilai dari ConfigMap “special-config” (dari key “metadata.name”) tersebut ke sebuah Pod dengan menggunakan env seperti berikut
Penjelasan nomor pada gambar:
1. Nama environment variable yang akan digunakan oleh aplikasi
2. Referensi ke ConfigMap yang akan digunakan. Dalam contoh ini mengacu kepada ConfigMap di gambar 2.1
3. Key dari sebuah ConfigMap yang akan dipakai nilainya
4. Referensi ke ConfigMap lain tanpa harus mendefinisikan key yang akan digunakan
2. Sebagai volume yang dipasang ke sebuah pod
ConfigMap juga dapat digunakan dengan menggunakan plugin volume. Kita ambil contoh dengan menggunakan konfigurasi ConfigMap yang sama dengan di atas (gambar 2.1). Kita buat konfigurasi Pod seperti berikut:
Penjelasan nomor pada gambar:
1. Referensi ke nama volume yang akan digunakan. Dalam contoh ini nomor 1 akan menggunakan volume dari nomor 3, yaitu volume “config-volume”
2. Path yang akan digunakan oleh volume tersebut di dalam Pod
3. Nama volume
4. Nama ConfigMap yang dijadikan referensi oleh volume “config-volume” (nomor 3)
Menggunakan ConfigMap sebagai variabel lingkungan dengan menggunakan volume membuka peluang untuk mengubah variabel lingkungan yang ada didalam sebuah container atau Pod tanpa harus melakukan restart. Metode seperti ini biasa disebut dengan “live-update” atau “hot config”.
Kenapa “live-update” dibutuhkan? Karena di dalam dunia kontainerisasi, jika kita setel variabel lingkungan dengan docker run -e <KEY>=<VALUE>
atau menggunakan env
pada konfigurasi Pod, kita tidak bisa langsung menggantinya pada saat aplikasi berjalan. Sehingga kita perlu cara lain untuk membaca variabel lingkungan, yaitu dengan membaca dari sebuah file. Dalam konteks kali ini akan kita menggunakan ConfigMap yang sudah dipasang ke sebuah Pod.
Sebelum kita mulai, mari kita lihat apa yang terjadi jika ConfigMap berubah dengan contoh konfigurasi ConfigMap seperti berikut
Jika kita perhatikan, setiap variabel yang kita definisikan di dalam ConfigMap akan menjadi sebuah file di dalam kontainer yang ada di dalam setiap Pod. File-file ini memiliki tautan (symlink) ke dalam sebuah folder ..data
dengan nama file yang sama. Misal ENV_IS_MAINTENANCE
memiliki tautan ke file ..data/ENV_IS_MAINTENACE
, dst. Dan folder ..data
mengarah kepada sebuah folder yang memiliki nama ..2019_02_22_04_00_47.246998214
.
Sekarang mari kita coba membuat sebuah aplikasi sederhana menggunakan NodeJS dan ExpressJS yang membaca variabel lingkungan dari ConfigMap, lalu kita kemas ke dalam sebuah kontainer supaya kita bisa memvalidasi ide di atas.
- js
1 |
|
Kode di atas akan melihat dan melakukan perubahan jika terjadi event “rename” di dalam folder /etc/config
. Setelah itu kita buat sebuah konfigurasi Deployment dan Service untuk sebuah Pod seperti berikut, lalu kita unggah ke Kubernetes dengan kubectl apply -f test-k8s.yaml
.
- yaml
1 |
|
Selanjutnya mari kita ubah konfigurasi ConfigMap di atas menjadi
Dari gambar di atas dapat kita lihat bahwa tautan antara file-file variabel lingkungan tidak berubah sama sekali. Hanya tautan folder ..data yang berubah tautannya menuju folder baru yang namanya ..2019_02_23_19_01_09.591362024
.
Dari animasi di atas dapat kita lihat bagaimana mudahnya mengubah variabel lingkungan tanpa harus mengubah konfigurasi Deployment, Service, atau Pod sama sekali bahkan tanpa harus restart aplikasi tersebut.
Beberapa hal yang harus kita ingat jika menggunakan ConfigMap:
- ConfigMap hanya “hidup” di dalam satu namespace saja. Yang artinya kita tidak bisa menggunakan ConfigMap yang berada di namespace lain.
- Proses sinkronisasi ConfigMap tidak langsung terjadi atau biasa disebut “eventually consistent”. Hal ini terjadi karena frekuensi sinkronisasi dari kubelet standardnya adalah 60 detik. Jika ingin proses sinkronisasi lebih cepat dapat menggunakan opsi
--sync-frequency
. Untuk lebih jelasnya bisa baca dari dokumentasi resmi Kubernetes di sini
Ekstra!
Jika kita amati, implementasi “live-update” di atas hanya bisa bekerja untuk NodeJS saja karena NodeJS memiliki pustaka standar untuk sistem file yang bisa melihat perubahan suatu file (dengan menggunakan fs.watch
). Apabila kita ingin implementasi di bahasa lain, maka kode server dan konfigurasi Deployment, Service dan Pod di atas perlu sedikit penyesuaian.
- yaml
1 |
|
Mari kita perhatikan konfigurasi containers di atas
Jika kita perhatikan lagi, kita menambahkan kontainer jimmidyson/configmap-reload dengan beberapa konfigurasinya ke dalam Pod untuk membaca perubahan ConfigMap.
- js
1 |
|
Untuk kode server kita menambahkan satu endpoint supaya bisa menerima webhook dari kontainer “configmap-reload”.
Jika kita menggunakan metode seperti ini, maka alur kerjanya akan menjadi seperti berikut
- Kontainer configmap-reload akan melihat apakah ConfigMap yang dipasang sebagai volume mengalami perubahan atau tidak
- Jika ConfigMap mengalami perubahan, kontainer configmap-reload akan memberikan notifikasi kepada aplikasi yang memiliki endpoint
/-/reload
(sesuai dengan konfigurasi parameter--webhook-url
) - Aplikasi yang menerima notifikasi akan membaca ulang semua variabel lingkungan yang ada di ConfigMap lalu menyimpan ulang ke sebuah variabel global. Karena contoh di atas menggunakan NodeJS, maka akan disimpan ke variabel
process.env
Dengan metode seperti ini, kita bisa implementasi “live-update” dengan bahasa pemrograman apapun. Selamat bereksperimen!
Referensi
- https://unofficial-kubernetes.readthedocs.io/en/latest/tasks/configure-pod-container/configmap/
- https://cloud.google.com/kubernetes-engine/docs/concepts/configmap
- https://www.slideshare.net/kubecon/kubecon-eu-2016-keynote-kubernetes-state-of-the-union
- https://medium.com/@xcoulon/kubernetes-configmap-hot-reload-in-action-with-viper-d413128a1c9a
- https://github.com/kubernetes/kubernetes/issues/30189
- https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap
- https://github.com/jimmidyson/configmap-reload