Scaling Scala: Cara Dockerize Menggunakan Kubernetes

Diterbitkan: 2022-03-11

Kubernetes adalah anak baru di blok tersebut, menjanjikan untuk membantu menyebarkan aplikasi ke cloud dan menskalakannya lebih cepat. Saat ini, ketika mengembangkan arsitektur layanan mikro, cukup standar untuk memilih Scala untuk membuat server API.

Layanan mikro menggantikan server back-end monolitik klasik dengan beberapa layanan independen yang berkomunikasi di antara mereka sendiri dan memiliki proses dan sumber daya mereka sendiri.

Jika ada aplikasi Scala dalam rencana Anda dan Anda ingin menskalakannya menjadi cloud, maka Anda berada di tempat yang tepat. Dalam artikel ini saya akan menunjukkan langkah demi langkah cara mengambil aplikasi Scala generik dan mengimplementasikan Kubernetes dengan Docker untuk meluncurkan beberapa instance aplikasi. Hasil akhirnya adalah aplikasi tunggal yang di-deploy sebagai beberapa instance, dan beban seimbang oleh Kubernetes.

Semua ini akan diimplementasikan hanya dengan mengimpor kit sumber Kubernetes di aplikasi Scala Anda. Harap dicatat, kit ini menyembunyikan banyak detail rumit yang terkait dengan instalasi dan konfigurasi, tetapi cukup kecil untuk dibaca dan mudah dipahami jika Anda ingin menganalisis fungsinya. Untuk kesederhanaan, kami akan menyebarkan semuanya di mesin lokal Anda. Namun, konfigurasi yang sama cocok untuk penerapan cloud Kubernetes di dunia nyata.

Skala Aplikasi Scala Anda dengan Kubernetes

Jadilah cerdas dan tidur nyenyak, skalakan Docker Anda dengan Kubernetes.
Menciak

Apa itu Kubernetes?

Sebelum masuk ke detail implementasi yang mengerikan, mari kita bahas apa itu Kubernetes dan mengapa itu penting.

Anda mungkin sudah pernah mendengar tentang Docker. Dalam arti tertentu, ini adalah mesin virtual yang ringan.

Docker memberikan keuntungan dengan menerapkan setiap server di lingkungan yang terisolasi, sangat mirip dengan mesin virtual yang berdiri sendiri, tanpa kerumitan mengelola mesin virtual yang lengkap.

Untuk alasan ini, ini sudah menjadi salah satu alat yang lebih banyak digunakan untuk menyebarkan aplikasi di awan. Gambar Docker cukup mudah dan cepat untuk dibuat dan dapat diduplikasi, jauh lebih mudah daripada mesin virtual tradisional seperti VMWare, VirtualBox, atau XEN.

Kubernetes melengkapi Docker, menawarkan lingkungan yang lengkap untuk mengelola aplikasi yang di-docker. Dengan menggunakan Kubernetes, Anda dapat dengan mudah menerapkan, mengonfigurasi, mengatur, mengelola, dan memantau ratusan atau bahkan ribuan aplikasi Docker.

Kubernetes adalah alat open source yang dikembangkan oleh Google dan telah diadopsi oleh banyak vendor lain. Kubernetes tersedia secara native di platform cloud Google, tetapi vendor lain juga telah mengadopsinya untuk layanan cloud OpenShift mereka. Itu dapat ditemukan di Amazon AWS, Microsoft Azure, RedHat OpenShift, dan bahkan lebih banyak lagi teknologi cloud. Kami dapat mengatakan bahwa ini adalah posisi yang baik untuk menjadi standar untuk menyebarkan aplikasi cloud.

Prasyarat

Sekarang setelah kita membahas dasar-dasarnya, mari kita periksa apakah Anda telah menginstal semua perangkat lunak prasyarat. Pertama-tama, Anda membutuhkan Docker. Jika Anda menggunakan Windows atau Mac, Anda memerlukan Docker Toolbox. Jika Anda menggunakan Linux, Anda perlu menginstal paket tertentu yang disediakan oleh distribusi Anda atau cukup ikuti petunjuk resmi.

Kita akan membuat kode dalam Scala, yang merupakan bahasa JVM. Anda tentu saja memerlukan Java Development Kit dan alat scala SBT yang diinstal dan tersedia di jalur global. Jika Anda sudah menjadi programmer Scala, kemungkinan Anda sudah menginstal alat-alat tersebut.

Jika Anda menggunakan Windows atau Mac, Docker secara default akan membuat mesin virtual bernama default dengan hanya 1GB memori, yang mungkin terlalu kecil untuk menjalankan Kubernetes. Dalam pengalaman saya, saya memiliki masalah dengan pengaturan default. Saya sarankan Anda membuka GUI VirtualBox, pilih default mesin virtual Anda, dan ubah memori menjadi setidaknya 2048MB.

Pengaturan memori VirtualBox

Aplikasi untuk Mengklasterisasi

Petunjuk dalam tutorial ini dapat diterapkan ke aplikasi atau proyek Scala. Agar artikel ini memiliki beberapa "daging" untuk dikerjakan, saya memilih contoh yang sangat sering digunakan untuk mendemonstrasikan layanan mikro REST sederhana di Scala, yang disebut Akka HTTP. Saya sarankan Anda mencoba menerapkan kit sumber ke contoh yang disarankan sebelum mencoba menggunakannya pada aplikasi Anda. Saya telah menguji kit terhadap aplikasi demo, tetapi saya tidak dapat menjamin bahwa tidak akan ada konflik dengan kode Anda.

Jadi pertama-tama, kita mulai dengan mengkloning aplikasi demo:

 git clone https://github.com/theiterators/akka-http-microservice

Selanjutnya, uji apakah semuanya berfungsi dengan benar:

 cd akka-http-microservice sbt run

Kemudian, akses ke http://localhost:9000/ip/8.8.8.8 , dan Anda akan melihat sesuatu seperti pada gambar berikut:

Layanan mikro HTTP Akka sedang berjalan

Menambahkan Kit Sumber

Sekarang, kita dapat menambahkan kit sumber dengan beberapa keajaiban Git:

 git remote add ScalaGoodies https://github.com/sciabarra/ScalaGoodies git fetch --all git merge ScalaGoodies/kubernetes

Dengan itu, Anda memiliki demo termasuk kit sumber, dan Anda siap untuk mencoba. Atau Anda bahkan dapat menyalin dan menempelkan kode dari sana ke dalam aplikasi Anda.

Setelah Anda menggabungkan atau menyalin file dalam proyek Anda, Anda siap untuk memulai.

Memulai Kubernetes

Setelah Anda mengunduh kit, kita perlu mengunduh biner kubectl yang diperlukan, dengan menjalankan:

 bin/install.sh

Pemasang ini cukup pintar (semoga) mengunduh biner kubectl yang benar untuk OSX, Linux, atau Windows, tergantung pada sistem Anda. Catatan, penginstal bekerja pada sistem yang saya miliki. Harap laporkan masalah apa pun, sehingga saya dapat memperbaiki kit.

Setelah Anda menginstal biner kubectl , Anda dapat memulai seluruh Kubernetes di Docker lokal Anda. Lari saja:

 bin/start-local-kube.sh

Saat pertama kali dijalankan, perintah ini akan mengunduh gambar dari seluruh tumpukan Kubernetes, dan registri lokal yang diperlukan untuk menyimpan gambar Anda. Ini bisa memakan waktu, jadi harap bersabar. Perhatikan juga, perlu akses langsung ke internet. Jika Anda berada di belakang proxy, itu akan menjadi masalah karena kit tidak mendukung proxy. Untuk mengatasinya, Anda harus mengkonfigurasi alat seperti Docker, curl, dan sebagainya untuk menggunakan proxy. Cukup rumit sehingga saya sarankan untuk mendapatkan akses tidak terbatas sementara.

Dengan asumsi Anda berhasil mengunduh semuanya, untuk memeriksa apakah Kubernetes berjalan dengan baik, Anda dapat mengetikkan perintah berikut:

 bin/kubectl get nodes

Jawaban yang diharapkan adalah:

 NAME STATUS AGE 127.0.0.1 Ready 2m

Perhatikan bahwa usia dapat bervariasi, tentu saja. Juga, karena memulai Kubernetes dapat memakan waktu, Anda mungkin harus menjalankan perintah beberapa kali sebelum Anda melihat jawabannya. Jika Anda tidak mendapatkan kesalahan di sini, selamat, Anda telah mengaktifkan dan menjalankan Kubernetes di komputer lokal Anda.

Dockerisasi Aplikasi Scala Anda

Sekarang setelah Kubernetes aktif dan berjalan, Anda dapat men-deploy aplikasi Anda di dalamnya. Di masa lalu, sebelum Docker, Anda harus men-deploy seluruh server untuk menjalankan aplikasi Anda. Dengan Kubernetes, yang perlu Anda lakukan untuk men-deploy aplikasi Anda adalah:

  • Buat gambar Docker.
  • Dorong dalam registri dari mana ia dapat diluncurkan.
  • Luncurkan instance dengan Kubernetes, yang akan mengambil gambar dari registri.

Untungnya, tampilannya tidak terlalu rumit, terutama jika Anda menggunakan alat pembuatan SBT seperti yang dilakukan banyak orang.

Dalam kit, saya menyertakan dua file yang berisi semua definisi yang diperlukan untuk membuat gambar yang dapat menjalankan aplikasi Scala, atau setidaknya apa yang diperlukan untuk menjalankan demo HTTP Akka. Saya tidak dapat menjamin bahwa ini akan bekerja dengan aplikasi Scala lainnya, tetapi ini adalah titik awal yang baik, dan harus bekerja untuk banyak konfigurasi yang berbeda. File yang harus dicari untuk membangun image Docker adalah:

 docker.sbt project/docker.sbt

Mari kita lihat apa yang ada di dalamnya. File project/docker.sbt berisi perintah untuk mengimpor plugin sbt-docker :

 addSbtPlugin("se.marcuslonnberg" % "sbt-docker" % "1.4.0")

Plugin ini mengelola pembuatan image Docker dengan SBT untuk Anda. Definisi Docker ada di file docker.sbt dan terlihat seperti ini:

 imageNames in docker := Seq(ImageName("localhost:5000/akkahttp:latest")) dockerfile in docker := { val jarFile: File = sbt.Keys.`package`.in(Compile, packageBin).value val classpath = (managedClasspath in Compile).value val mainclass = mainClass.in(Compile, packageBin).value.getOrElse(sys.error("Expected exactly one main class")) val jarTarget = s"/app/${jarFile.getName}" val classpathString = classpath.files.map("/app/" + _.getName) .mkString(":") + ":" + jarTarget new Dockerfile { from("anapsix/alpine-java:8") add(classpath.files, "/app/") add(jarFile, jarTarget) entryPoint("java", "-cp", classpathString, mainclass) } }

Untuk memahami sepenuhnya arti dari file ini, Anda perlu mengenal Docker dengan cukup baik untuk memahami file definisi ini. Namun, kami tidak akan membahas detail file definisi Docker, karena Anda tidak perlu memahaminya secara menyeluruh untuk membangun image.

Keindahan menggunakan SBT untuk membangun citra Docker adalah
SBT akan mengurus pengumpulan semua file untuk Anda.

Perhatikan classpath secara otomatis dihasilkan oleh perintah berikut:

 val classpath = (managedClasspath in Compile).value

Secara umum, cukup rumit untuk mengumpulkan semua file JAR untuk menjalankan aplikasi. Menggunakan SBT, file Docker akan dibuat dengan add(classpath.files, "/app/") . Dengan cara ini, SBT mengumpulkan semua file JAR untuk Anda dan membuat Dockerfile untuk menjalankan aplikasi Anda.

Perintah lain mengumpulkan bagian yang hilang untuk membuat gambar Docker. Gambar akan dibangun menggunakan gambar APT yang ada untuk menjalankan program Java ( anapsix/alpine-java:8 , tersedia di internet di Docker Hub). Instruksi lainnya adalah menambahkan file lain untuk menjalankan aplikasi Anda. Terakhir, dengan menentukan titik masuk, kita dapat menjalankannya. Perhatikan juga bahwa nama itu sengaja dimulai dengan localhost:5000 , karena localhost:5000 adalah tempat saya menginstal registri di skrip start-kube-local.sh .

Membangun Gambar Docker dengan SBT

Untuk membangun image Docker, Anda dapat mengabaikan semua detail Dockerfile. Anda hanya perlu mengetik:

 sbt dockerBuildAndPush

Plugin sbt-docker kemudian akan membuat image Docker untuk Anda, mengunduh dari internet semua bagian yang diperlukan, dan kemudian akan mendorong ke registri Docker yang telah dimulai sebelumnya, bersama dengan aplikasi Kubernetes di localhost . Jadi, yang Anda butuhkan hanyalah menunggu sedikit lagi agar gambar Anda matang dan siap.

Catatan, jika Anda mengalami masalah, hal terbaik yang harus dilakukan adalah mengatur ulang semuanya ke status yang diketahui dengan menjalankan perintah berikut:

 bin/stop-kube-local.sh bin/start-kube-local.sh

Perintah tersebut harus menghentikan semua wadah dan memulai ulang dengan benar agar registri Anda siap menerima gambar yang dibuat dan didorong oleh sbt .

Memulai Layanan di Kubernetes

Sekarang aplikasi dikemas dalam wadah dan didorong dalam registri, kami siap untuk menggunakannya. Kubernetes menggunakan baris perintah dan file konfigurasi untuk mengelola cluster. Karena baris perintah bisa menjadi sangat panjang, dan juga dapat meniru langkah-langkahnya, saya menggunakan file konfigurasi di sini. Semua sampel dalam kit sumber ada di folder kube .

Langkah kami selanjutnya adalah meluncurkan satu contoh gambar. Gambar yang sedang berjalan disebut, dalam bahasa Kubernetes, sebuah pod . Jadi mari kita buat pod dengan menjalankan perintah berikut:

 bin/kubectl create -f kube/akkahttp-pod.yml

Anda sekarang dapat memeriksa situasi dengan perintah:

 bin/kubectl get pods

Anda harus melihat:

 NAME READY STATUS RESTARTS AGE akkahttp 1/1 Running 0 33s k8s-etcd-127.0.0.1 1/1 Running 0 7d k8s-master-127.0.0.1 4/4 Running 0 7d k8s-proxy-127.0.0.1 1/1 Running 0 7d

Status sebenarnya bisa berbeda, misalnya “ContainerCreating”, bisa memakan waktu beberapa detik sebelum menjadi “Running”. Juga, Anda bisa mendapatkan status lain seperti "Error" jika, misalnya, Anda lupa membuat gambar sebelumnya.

Anda juga dapat memeriksa apakah pod Anda berjalan dengan perintah:

 bin/kubectl logs akkahttp

Anda akan melihat output yang diakhiri dengan sesuatu seperti ini:

 [DEBUG] [05/30/2016 12:19:53.133] [default-akka.actor.default-dispatcher-5] [akka://default/system/IO-TCP/selectors/$a/0] Successfully bound to /0:0:0:0:0:0:0:0:9000

Sekarang Anda memiliki layanan dan berjalan di dalam wadah. Namun, layanan tersebut belum dapat dijangkau. Perilaku ini adalah bagian dari desain Kubernetes. Pod Anda sedang berjalan, tetapi Anda harus mengeksposnya secara eksplisit. Jika tidak, layanan ini dimaksudkan untuk internal.

Membuat Layanan

Membuat layanan dan memeriksa hasilnya adalah masalah eksekusi:

 bin/kubectl create -f kube/akkahttp-service.yaml bin/kubectl get svc

Anda akan melihat sesuatu seperti ini:

 NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE akkahttp-service 10.0.0.54 9000/TCP 44s kubernetes 10.0.0.1 <none> 443/TCP 3m

Perhatikan bahwa port bisa berbeda. Kubernetes mengalokasikan port untuk layanan dan memulainya. Jika Anda menggunakan Linux, Anda dapat langsung membuka browser dan ketik http://10.0.0.54:9000/ip/8.8.8.8 untuk melihat hasilnya. Jika Anda menggunakan Windows atau Mac dengan Docker Toolbox, IP lokal ke mesin virtual yang menjalankan Docker, dan sayangnya masih tidak dapat dijangkau.

Saya ingin menekankan di sini bahwa ini bukan masalah Kubernetes, melainkan batasan dari Docker Toolbox, yang pada gilirannya tergantung pada batasan yang dikenakan oleh mesin virtual seperti VirtualBox, yang bertindak seperti komputer di dalam komputer lain. Untuk mengatasi keterbatasan ini, kita perlu membuat terowongan. Untuk mempermudah, saya menyertakan skrip lain yang membuka terowongan di port arbitrer untuk menjangkau layanan apa pun yang kami terapkan. Anda dapat mengetikkan perintah berikut:

 bin/forward-kube-local.sh akkahttp-service 9000

Perhatikan bahwa terowongan tidak akan berjalan di latar belakang, Anda harus membiarkan jendela terminal terbuka selama Anda membutuhkannya dan menutupnya saat Anda tidak membutuhkan terowongan lagi. Saat tunnel sedang berjalan, Anda dapat membuka: http://localhost:9000/ip/8.8.8.8 dan akhirnya melihat aplikasi berjalan di Kubernetes.

Sentuhan Terakhir: Skala

Sejauh ini kami telah “hanya” menempatkan aplikasi kami di Kubernetes. Meskipun ini merupakan pencapaian yang menarik, hal itu tidak terlalu menambah nilai bagi penerapan kami. Kami diselamatkan dari upaya mengunggah dan menginstal di server dan mengonfigurasi server proxy untuk itu.

Keunggulan Kubernetes adalah dalam penskalaan. Anda dapat menerapkan dua, sepuluh, atau seratus contoh aplikasi kami hanya dengan mengubah jumlah replika dalam file konfigurasi. Jadi mari kita lakukan.

Kami akan menghentikan pod tunggal dan memulai penerapan sebagai gantinya. Jadi mari kita jalankan perintah berikut:

 bin/kubectl delete -f kube/akkahttp-pod.yml bin/kubectl create -f kube/akkahttp-deploy.yaml

Selanjutnya, periksa statusnya. Sekali lagi, Anda dapat mencoba beberapa kali karena penerapan dapat memakan waktu cukup lama:

 NAME READY STATUS RESTARTS AGE akkahttp-deployment-4229989632-mjp6u 1/1 Running 0 16s akkahttp-deployment-4229989632-s822x 1/1 Running 0 16s k8s-etcd-127.0.0.1 1/1 Running 0 6d k8s-master-127.0.0.1 4/4 Running 0 6d k8s-proxy-127.0.0.1 1/1 Running 0 6d

Sekarang kami memiliki dua pod, bukan satu. Ini karena dalam file konfigurasi yang saya berikan, terdapat nilai replica: 2 , dengan dua nama berbeda yang dihasilkan oleh sistem. Saya tidak akan membahas detail file konfigurasi, karena cakupan artikel ini hanyalah pengantar bagi programmer Scala untuk memulai Kubernetes.

Bagaimanapun, sekarang ada dua pod yang aktif. Yang menarik adalah layanannya sama seperti sebelumnya. Kami mengonfigurasi layanan untuk memuat keseimbangan antara semua pod berlabel akkahttp . Ini berarti kami tidak perlu menerapkan ulang layanan, tetapi kami dapat mengganti satu instance dengan yang direplikasi.

Kami dapat memverifikasi ini dengan meluncurkan proxy lagi (jika Anda menggunakan Windows dan Anda telah menutupnya):

 bin/forward-kube-local.sh akkahttp-service 9000

Kemudian, kita dapat mencoba membuka dua jendela terminal dan melihat log untuk setiap pod. Misalnya, pada tipe pertama:

 bin/kubectl logs -f akkahttp-deployment-4229989632-mjp6u

Dan pada tipe kedua:

 bin/kubectl logs -f akkahttp-deployment-4229989632-s822x

Tentu saja, edit baris perintah sesuai dengan nilai yang Anda miliki di sistem Anda.

Sekarang, coba akses layanan dengan dua browser berbeda. Anda akan melihat permintaan untuk dibagi di antara beberapa server yang tersedia, seperti pada gambar berikut:

Kubernet beraksi

Kesimpulan

Hari ini kami nyaris tidak menggores permukaan. Kubernetes menawarkan lebih banyak kemungkinan, termasuk penskalaan dan restart otomatis, penerapan inkremental, dan volume. Selanjutnya, aplikasi yang kami gunakan sebagai contoh sangat sederhana, stateless dengan berbagai contoh tidak perlu saling mengenal. Di dunia nyata, aplikasi terdistribusi memang perlu saling mengenal, dan perlu mengubah konfigurasi sesuai ketersediaan server lain. Memang, Kubernetes menawarkan keystore terdistribusi ( etcd ) untuk memungkinkan aplikasi yang berbeda berkomunikasi satu sama lain ketika instance baru di-deploy. Namun, contoh ini sengaja dibuat cukup kecil dan disederhanakan untuk membantu Anda memulai, dengan fokus pada fungsionalitas inti. Jika Anda mengikuti tutorial, Anda seharusnya bisa mendapatkan lingkungan kerja untuk aplikasi Scala Anda di mesin Anda tanpa bingung dengan banyak detail dan tersesat dalam kerumitannya.

Terkait:
  • Mengembangkan untuk Cloud di Cloud: Pengembangan BigData dengan Docker di AWS
  • K8s/Kubernetes: AWS vs. GCP vs. Azure
  • Perbandingan Mesh Layanan Kubernetes