1. Pengantar
Menjalankan situs web dan aplikasi itu sulit.
Ada yang salah ketika seharusnya tidak, server mogok, peningkatan permintaan menyebabkan lebih banyak sumber daya digunakan, dan membuat perubahan tanpa periode nonaktif merupakan hal yang rumit dan melelahkan.
Bayangkan sebuah alat yang dapat membantu Anda melakukan semua itu dan bahkan memungkinkan Anda untuk mengotomatiskannya. Dengan GKE, semuanya tidak hanya dapat dilakukan, tetapi juga mudah. Dalam codelab ini, Anda akan berperan sebagai developer yang menjalankan situs e-commerce untuk perusahaan fiktif—Fancy Store. Karena masalah penskalaan dan pemadaman layanan, Anda ditugaskan untuk men-deploy aplikasi ke GKE.
Latihan-latihan ini diurutkan untuk mencerminkan pengalaman developer cloud pada umumnya:
- Membuat cluster GKE.
- Membuat container Docker.
- Men-deploy container ke GKE.
- Mengekspos container melalui layanan.
- Menskalakan container ke beberapa replika.
- Memodifikasi situs.
- Luncurkan versi baru tanpa periode nonaktif.
Diagram arsitektur
Yang akan Anda pelajari
- Cara membuat cluster GKE
- Cara membuat image Docker
- Cara men-deploy image Docker ke Kubernetes
- Cara menskalakan aplikasi di Kubernetes
- Cara melakukan update berkelanjutan di Kubernetes
Prasyarat
- Akun Google dengan akses administratif untuk membuat project atau project dengan peran pemilik project
- Pemahaman dasar tentang Docker dan Kubernetes (jika Anda belum memiliki pemahaman dasar, silakan pelajari Docker dan Kubernetes sekarang.)
2. Penyiapan lingkungan
Penyiapan lingkungan mandiri
Jika belum memiliki Akun Google, Anda harus membuatnya. Login ke Konsol Google Cloud dan buat project baru.
Perlu diingat, project ID adalah nama unik di semua project Google Cloud (maaf, nama di atas telah digunakan dan tidak akan berfungsi untuk Anda). Properti tersebut nantinya akan disebut sebagai PROJECT_ID
.
Selanjutnya, Anda harus mengaktifkan penagihan di Cloud Console untuk menggunakan resource Google Cloud. Pengguna baru Google Cloud memenuhi syarat untuk mendapatkan uji coba gratis senilai$300. Jika Anda bukan pengguna baru, jangan khawatir karena codelab tidak akan menghabiskan biaya lebih dari beberapa dolar. Namun, codelab dapat menimbulkan biaya lebih banyak jika Anda menggunakan lebih banyak resource atau membiarkannya berjalan (lihat bagian "membersihkan" di akhir). Untuk mengetahui informasi selengkapnya, lihat Harga.
Cloud Shell
Meskipun dapat mengoperasikan Google Cloud dan GKE dari jarak jauh dengan laptop Anda, Anda akan menggunakan Cloud Shell—lingkungan command line yang berjalan di Cloud—untuk codelab ini.
Mesin virtual berbasis Debian ini memuat semua alat pengembangan yang akan Anda perlukan. Layanan ini menawarkan direktori beranda tetap sebesar 5 GB dan beroperasi di Google Cloud, sehingga sangat meningkatkan performa dan autentikasi jaringan. Ini berarti bahwa semua yang Anda perlukan untuk codelab ini adalah browser (ya, ini berfungsi di Chromebook).
- Untuk mengaktifkan Cloud Shell dari Cloud Console, cukup klik Aktifkan Cloud Shell (hanya perlu beberapa saat untuk melakukan penyediaan dan terhubung ke lingkungan).
Setelah terhubung ke Cloud Shell, Anda akan melihat bahwa Anda sudah diautentikasi dan project sudah ditetapkan ke PROJECT_ID
.
gcloud auth list
Output perintah
Credentialed accounts: - <myaccount>@<mydomain>.com (active)
gcloud config list project
Output perintah
[core] project = <PROJECT_ID>
Jika, untuk beberapa alasan, project belum disetel, cukup jalankan perintah berikut:
gcloud config set project <PROJECT_ID>
Mencari PROJECT_ID
Anda? Periksa ID yang Anda gunakan di langkah-langkah penyiapan atau cari di dasbor Cloud Console:
Cloud Shell juga menetapkan beberapa variabel lingkungan secara default, yang mungkin berguna saat Anda menjalankan perintah di masa mendatang.
echo $GOOGLE_CLOUD_PROJECT
Output perintah
<PROJECT_ID>
- Terakhir, tetapkan zona dan konfigurasi project default.
gcloud config set compute/zone us-central1-f
Anda dapat memilih berbagai zona yang berbeda. Untuk informasi selengkapnya, lihat Wilayah & Zona.
3. Membuat cluster GKE
Setelah memiliki lingkungan developer yang berfungsi, Anda memerlukan cluster GKE untuk men-deploy situs. Sebelum membuat cluster, Anda perlu memastikan bahwa API yang tepat telah diaktifkan. Jalankan perintah berikut untuk mengaktifkan container API:
gcloud services enable container.googleapis.com
Sekarang, Anda dapat membuat cluster. Ikuti langkah-langkah di bawah ini untuk membuat cluster bernama fancy-cluster dengan 3 node:
gcloud container clusters create fancy-cluster --num-nodes 3
Mungkin perlu waktu beberapa menit untuk membuat cluster. Setelah itu, jalankan perintah berikut dan lihat tiga instance mesin virtual (VM) pekerja di cluster:
gcloud compute instances list
Output:
NAME ZONE MACHINE_TYPE PREEMPTIBLE INTERNAL_IP EXTERNAL_IP STATUS gke-fancy-cluster-default-pool-ad92506d-1ng3 us-east4-a n1-standard-1 10.150.0.7 XX.XX.XX.XX RUNNING gke-fancy-cluster-default-pool-ad92506d-4fvq us-east4-a n1-standard-1 10.150.0.5 XX.XX.XX.XX RUNNING gke-fancy-cluster-default-pool-ad92506d-4zs3 us-east4-a n1-standard-1 10.150.0.6 XX.XX.XX.XX RUNNING
Anda juga dapat melihat cluster Anda dan informasi terkait di Konsol Cloud. Klik tombol menu di sudut kiri atas, scroll ke bawah ke Kubernetes Engine, lalu klik Clusters. Anda akan melihat cluster yang bernama fancy-cluster.
Selamat! Anda telah membuat cluster pertama!
4. Membuat clone repositori sumber
Karena ini adalah situs yang sudah ada, Anda hanya perlu meng-clone sumber dari repositori sehingga Anda dapat berfokus pada pembuatan image Docker dan melakukan deployment ke GKE.
Jalankan perintah berikut untuk meng-clone repositori sumber ke instance Cloud Shell Anda dan mengubahnya ke direktori yang sesuai. Anda juga akan menginstal dependensi Node.js sehingga Anda dapat menguji aplikasi sebelum men-deploy-nya.
cd ~ git clone https://github.com/googlecodelabs/monolith-to-microservices.git cd ~/monolith-to-microservices ./setup.sh
Tindakan ini akan meng-clone repositori, mengubah direktori, dan menginstal dependensi yang diperlukan untuk menjalankan aplikasi Anda secara lokal. Mungkin perlu waktu beberapa menit untuk menjalankan skrip tersebut.
Lakukan uji tuntas dan uji permohonan Anda. Jalankan perintah berikut untuk memulai server web Anda:
cd ~/monolith-to-microservices/monolith npm start
Output:
Monolith listening on port 8080!
Anda dapat melihat pratinjau aplikasi dengan mengklik ikon pratinjau web di menu Cloud Shell dan memilih Preview di port 8080.
Tindakan itu akan membuka jendela baru tempat Anda dapat melihat Fancy Store beraksi!
Anda dapat menutup jendela tersebut setelah melihat situs. Tekan Control+C
(Windows atau Mac) di jendela terminal untuk menghentikan proses server web.
5. Membuat container Docker dengan Cloud Build
Setelah file sumber siap digunakan, saatnya untuk melakukan Dockerisasi aplikasi Anda.
Biasanya, Anda harus menggunakan pendekatan dua langkah yang meliputi membangun container Docker dan mengirimkannya ke registry untuk menyimpan image yang diambil GKE. Namun, Anda dapat membuat hidup lebih mudah dengan menggunakan Cloud Build untuk membuat container Docker dan menempatkan image di Container Registry dengan satu perintah. (Untuk melihat proses manual pembuatan file Docker dan mengirimnya, lihat Panduan Memulai untuk Container Registry.)
Cloud Build mengompresi file dari direktori dan memindahkannya ke bucket Cloud Storage. Selanjutnya, proses build mengambil file dari bucket dan menggunakan Dockerfile untuk menjalankan proses build Docker. Karena Anda menentukan flag --tag
dengan host sebagai gcr.io
untuk image Docker, image Docker yang dihasilkan akan dikirim ke Container Registry.
Pertama, Anda harus mengaktifkan Cloud Build API dengan menjalankan perintah berikut:
gcloud services enable cloudbuild.googleapis.com
Setelah API diaktifkan, jalankan perintah berikut di Cloud Shell untuk memulai proses build:
cd ~/monolith-to-microservices/monolith gcloud builds submit --tag gcr.io/${GOOGLE_CLOUD_PROJECT}/monolith:1.0.0 .
Proses tersebut memerlukan waktu beberapa menit, tetapi setelah selesai, Anda dapat melihat output berikut di terminal:
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ID CREATE_TIME DURATION SOURCE IMAGES STATUS 1ae295d9-63cb-482c-959b-bc52e9644d53 2019-08-29T01:56:35+00:00 33S gs://<PROJECT_ID>_cloudbuild/source/1567043793.94-abfd382011724422bf49af1558b894aa.tgz gcr.io/<PROJECT_ID>/monolith:1.0.0 SUCCESS
Untuk melihat histori build atau menonton prosesnya secara real time, Anda dapat membuka Cloud Console. Klik tombol menu di pojok kiri atas, scroll ke bawah ke Ci/CD, lalu klik Cloud Build, dan terakhir klik History. Di sana, Anda dapat melihat daftar build sebelumnya, tetapi seharusnya hanya ada build yang Anda buat.
Jika mengklik Build id, Anda dapat melihat semua detail untuk build tersebut, termasuk output log.
Pada halaman detail build, Anda dapat melihat image container yang dibuat dengan mengklik nama Image di bagian informasi build.
6. Men-deploy container ke GKE
Setelah Anda memasukkan situs ke dalam container dan mengirim container ke Container Registry, Anda dapat men-deploy-nya ke Kubernetes.
Untuk men-deploy dan mengelola aplikasi di cluster GKE, Anda harus berkomunikasi dengan sistem pengelolaan cluster Kubernetes. Anda biasanya dapat melakukannya menggunakan alat command line kubectl.
Kubernetes merepresentasikan aplikasi sebagai Pod, yang merupakan unit yang mewakili sebuah container (atau grup container yang terkait erat). Pod adalah unit terkecil yang dapat di-deploy di Kubernetes. Di sini, setiap Pod hanya berisi container monolit.
Untuk men-deploy aplikasi, Anda perlu membuat Deployment. Deployment mengelola beberapa salinan aplikasi—yang disebut replika—dan menjadwalkannya untuk dijalankan pada setiap node di cluster Anda. Dalam hal ini, Deployment hanya akan menjalankan satu Pod aplikasi Anda. Deployment memastikannya dengan membuat ReplicaSet. ReplicaSet bertanggung jawab untuk memastikan bahwa jumlah replika yang ditentukan selalu berjalan.
Perintah kubectl create deployment
menyebabkan Kubernetes membuat Deployment bernama monolit di cluster Anda dengan 1 replika.
Jalankan perintah berikut untuk men-deploy aplikasi Anda:
kubectl create deployment monolith --image=gcr.io/${GOOGLE_CLOUD_PROJECT}/monolith:1.0.0
Memverifikasi deployment
Untuk memverifikasi bahwa Deployment berhasil dibuat, jalankan perintah berikut (Mungkin perlu waktu beberapa saat sampai status Pod menjadi "Running"):
kubectl get all
Output:
NAME READY STATUS RESTARTS AGE pod/monolith-7d8bc7bf68-htm7z 1/1 Running 0 6m21s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.27.240.1 <none> 443/TCP 24h NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE deployment.apps/monolith 1 1 1 1 20m NAME DESIRED CURRENT READY AGE replicaset.apps/monolith-7d8bc7bf68 1 1 1 20m
{i>Output<i} itu menunjukkan beberapa hal. Anda dapat melihat Deployment Anda, yang sudah terkini; ReplicaSet Anda, dengan jumlah Pod yang diinginkan: dan Pod, yang sedang berjalan. Sepertinya Anda berhasil membuat semuanya!
Untuk menampilkan resource satu per satu, Anda dapat menjalankan perintah berikut:
# Show pods kubectl get pods # Show deployments kubectl get deployments # Show replica sets kubectl get rs #You can also combine them kubectl get pods,deployments
Untuk melihat manfaat penuh Kubernetes, Anda dapat melakukan simulasi error server, menghapus Pod, dan melihat apa yang terjadi.
Salin nama pod Anda dari perintah sebelumnya dan jalankan perintah berikut untuk menghapusnya:
kubectl delete pod/<POD_NAME>
Jika sudah cukup cepat, Anda dapat menjalankan perintah sebelumnya untuk melihat semuanya lagi dan akan muncul dua Pod, satu Pod dihentikan dan yang lainnya membuat atau berjalan:
kubectl get all
Output:
NAME READY STATUS RESTARTS AGE pod/monolith-7d8bc7bf68-2bxts 1/1 Running 0 4s pod/monolith-7d8bc7bf68-htm7z 1/1 Terminating 0 9m35s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.27.240.1 <none> 443/TCP 24h NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE deployment.apps/monolith 1 1 1 1 24m NAME DESIRED CURRENT READY AGE replicaset.apps/monolith-7d8bc7bf68 1 1 1 24m
Mengapa hal ini terjadi? ReplicaSet melihat bahwa pod dihentikan dan memicu pod baru untuk mempertahankan jumlah replika yang diinginkan. Nantinya, Anda akan mengetahui cara melakukan penskalaan untuk memastikan ada beberapa instance yang berjalan sehingga jika salah satunya tidak aktif, pengguna tidak akan mengalami periode nonaktif.
7. Mengekspos deployment GKE
Anda telah men-deploy aplikasi ke GKE, tetapi Anda tidak memiliki cara untuk mengaksesnya di luar cluster. Secara default, container yang Anda jalankan di GKE tidak dapat diakses dari internet karena tidak memiliki alamat IP eksternal. Anda harus secara eksplisit mengekspos aplikasi ke traffic dari internet melalui resource Service. Service menyediakan dukungan jaringan dan IP untuk Pod aplikasi Anda. GKE membuat IP eksternal dan load balancer (tunduk kepada penagihan) untuk aplikasi Anda.
Jalankan perintah berikut untuk mengekspos situs Anda ke internet:
kubectl expose deployment monolith --type=LoadBalancer --port 80 --target-port 8080
Output:
service/monolith exposed
Mengakses layanan
GKE menetapkan alamat IP eksternal ke resource Service—bukan ke Deployment. Jika ingin menemukan IP eksternal yang disediakan GKE untuk aplikasi Anda, Anda dapat memeriksa Service dengan perintah kubectl get service:
kubectl get service
Output:
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE monolith 10.3.251.122 203.0.113.0 80:30877/TCP 3d
Setelah menentukan alamat IP eksternal untuk aplikasi Anda, salin alamat tersebut. Arahkan browser Anda ke URL tersebut (seperti http://203.0.113.0) untuk memeriksa apakah aplikasi Anda dapat diakses.
Anda akan melihat situs yang sama dengan yang Anda uji sebelumnya. Selamat! Situs Anda sepenuhnya berjalan di Kubernetes.
8. Menskalakan deployment GKE
Sekarang setelah Anda menjalankan instance aplikasi di GKE dan mengeksposnya ke internet, situs Anda telah menjadi sangat populer. Anda memerlukan cara untuk menskalakan aplikasi ke beberapa instance sehingga Anda dapat menangani traffic. Pelajari cara menskalakan aplikasi Anda hingga tiga replika.
Jalankan perintah berikut untuk menskalakan deployment Anda hingga tiga replika:
kubectl scale deployment monolith --replicas=3
Output:
deployment.apps/monolith scaled
Memverifikasi deployment yang diskalakan
Untuk memastikan Deployment berhasil diskalakan, jalankan perintah berikut:
kubectl get all
Output:
NAME READY STATUS RESTARTS AGE pod/monolith-7d8bc7bf68-2bxts 1/1 Running 0 36m pod/monolith-7d8bc7bf68-7ds7q 1/1 Running 0 45s pod/monolith-7d8bc7bf68-c5kxk 1/1 Running 0 45s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.27.240.1 <none> 443/TCP 25h service/monolith LoadBalancer 10.27.253.64 XX.XX.XX.XX 80:32050/TCP 6m7s NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE deployment.apps/monolith 3 3 3 3 61m NAME DESIRED CURRENT READY AGE replicaset.apps/monolith-7d8bc7bf68 3 3 3 61m
Anda akan melihat tiga instance Pod berjalan. Selain itu, perhatikan bahwa Deployment dan ReplicaSet Anda sekarang memiliki jumlah tiga set yang diinginkan.
9. Membuat perubahan pada situs
Tim pemasaran meminta Anda mengubah halaman beranda situs. Mereka berpikir bahwa gambar itu harus lebih informatif dengan menjelaskan apa yang perusahaan Anda dan apa yang sebenarnya Anda jual. Di bagian ini, Anda akan menambahkan beberapa teks ke halaman beranda untuk membuat tim pemasaran senang. Sepertinya salah satu developer kami sudah membuat perubahan dengan nama file index.js.new
. Anda dapat menyalin file ke index.js
dan perubahan Anda akan ditampilkan. Ikuti petunjuk di bawah ini untuk melakukan perubahan yang sesuai.
Jalankan perintah berikut, salin file yang diperbarui ke nama file yang benar, dan cetak isinya untuk memverifikasi perubahan:
cd ~/monolith-to-microservices/react-app/src/pages/Home mv index.js.new index.js cat ~/monolith-to-microservices/react-app/src/pages/Home/index.js
Kode yang dihasilkan akan terlihat seperti ini:
/* Copyright 2019 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ import React from "react"; import { makeStyles } from "@material-ui/core/styles"; import Paper from "@material-ui/core/Paper"; import Typography from "@material-ui/core/Typography"; const useStyles = makeStyles(theme => ({ root: { flexGrow: 1 }, paper: { width: "800px", margin: "0 auto", padding: theme.spacing(3, 2) } })); export default function Home() { const classes = useStyles(); return ( <div className={classes.root}> <Paper className={classes.paper}> <Typography variant="h5"> Fancy Fashion & Style Online </Typography> <br /> <Typography variant="body1"> Tired of mainstream fashion ideas, popular trends and societal norms? This line of lifestyle products will help you catch up with the Fancy trend and express your personal style. Start shopping Fancy items now! </Typography> </Paper> </div> ); }
Anda telah mengupdate komponen React, tetapi Anda perlu membangun aplikasi React untuk menghasilkan file statis. Jalankan perintah berikut untuk membangun aplikasi React dan salin ke direktori publik monolit:
cd ~/monolith-to-microservices/react-app npm run build:monolith
Setelah kode Anda diperbarui, Anda harus membangun ulang container Docker dan memublikasikannya ke Container Registry. Anda dapat menggunakan perintah yang sama seperti sebelumnya, tetapi kali ini, Anda akan mengupdate label versi.
Jalankan perintah berikut untuk memicu Cloud Build baru dengan versi image 2.0.0 yang telah diupdate:
cd ~/monolith-to-microservices/monolith #Feel free to test your application npm start gcloud builds submit --tag gcr.io/${GOOGLE_CLOUD_PROJECT}/monolith:2.0.0 .
Tekan Control+C
(Windows atau Mac) di jendela terminal untuk menghentikan proses server web.
Di bagian berikutnya, Anda akan menggunakan image tersebut untuk mengupdate aplikasi tanpa periode nonaktif.
10. Memperbarui situs tanpa periode nonaktif
Perubahan telah selesai dan tim pemasaran senang dengan pembaruan Anda. Saatnya memperbarui situs tanpa gangguan bagi pengguna. Ikuti petunjuk di bawah untuk memperbarui situs Anda.
Update berkelanjutan GKE memastikan aplikasi Anda tetap aktif dan tersedia bahkan saat sistem mengganti instance image container lama dengan yang baru di semua replika yang berjalan.
Dari command line, Anda dapat memberi tahu Kubernetes bahwa Anda ingin mengupdate image untuk Deployment ke versi baru dengan perintah berikut:
kubectl set image deployment/monolith monolith=gcr.io/${GOOGLE_CLOUD_PROJECT}/monolith:2.0.0
Output:
deployment.apps/monolith image updated
Memverifikasi Deployment
Anda dapat memvalidasi update Deployment dengan menjalankan perintah berikut:
kubectl get pods
Output:
NAME READY STATUS RESTARTS AGE monolith-584fbc994b-4hj68 1/1 Terminating 0 60m monolith-584fbc994b-fpwdw 1/1 Running 0 60m monolith-584fbc994b-xsk8s 1/1 Terminating 0 60m monolith-75f4cf58d5-24cq8 1/1 Running 0 3s monolith-75f4cf58d5-rfj8r 1/1 Running 0 5s monolith-75f4cf58d5-xm44v 0/1 ContainerCreating 0 1s
Anda melihat tiga Pod baru sedang dibuat dan pod lama Anda sedang dimatikan. Anda dapat membedakan usia mana yang baru dan mana yang lama. Pada akhirnya, Anda hanya akan melihat tiga Pod lagi, yang merupakan tiga Pod terupdate.
Untuk memverifikasi perubahan, buka lagi IP eksternal load balancer dan perhatikan bahwa aplikasi Anda telah diupdate.
Jalankan perintah berikut untuk menampilkan layanan dan melihat alamat IP jika Anda lupa:
kubectl get svc
{i>Website<i} Anda akan menampilkan teks yang telah ditambahkan ke komponen beranda.
11. Pembersihan
Menghapus repositori Git
cd ~ rm -rf monolith-to-microservices
Menghapus image Container Registry
CATATAN: Jika membuat versi lain, Anda juga dapat menggunakan sintaksis yang sama untuk menghapus gambar tersebut. Codelab ini mengasumsikan bahwa Anda hanya memiliki dua tag.
# Delete the container image for version 1.0.0 of our monolith gcloud container images delete gcr.io/${GOOGLE_CLOUD_PROJECT}/monolith:1.0.0 --quiet # Delete the container image for version 2.0.0 of our monolith gcloud container images delete gcr.io/${GOOGLE_CLOUD_PROJECT}/monolith:2.0.0 --quiet
Menghapus artefak Cloud Build dari Cloud Storage
CATATAN: Jika menggunakan Cloud Build untuk artefak selain codelab ini, Anda harus menghapus sumber secara manual dari bucket Cloud Storage gs://<PROJECT_ID>_cloudbuild/source
.
# The following command will take all source archives from all builds and delete them from cloud storage # Run this command to print all sources: # gcloud builds list | awk 'NR > 1 {print $4}' gcloud builds list | awk 'NR > 1 {print $4}' | while read line; do gsutil rm $line; done
Menghapus layanan GKE
kubectl delete service monolith kubectl delete deployment monolith
Menghapus cluster GKE
gcloud container clusters delete fancy-cluster
CATATAN: Perintah ini mungkin memerlukan waktu beberapa saat.
12. Selamat!
Anda telah men-deploy, menskalakan, dan memperbarui situs di GKE. Sekarang Anda telah berpengalaman dalam menggunakan Docker dan Kubernetes!