Cara memperpanjang Kubernetes

Hari ini kita akan berbicara tentang DevOps, atau lebih tepatnya, terutama tentang Ops. Mereka mengatakan bahwa ada sangat sedikit orang yang puas dengan tingkat otomatisasi operasi mereka. Tapi situasinya sepertinya bisa diperbaiki. Dalam artikel ini, Nikolai Ryzhikov akan berbicara tentang pengalamannya mengembangkan Kubernetes.



Materi disusun berdasarkan pidato Nikolai di konferensi musim gugur DevOops 2017. Di bawah potongan - video dan teks transkrip laporan.



Saat ini, Nikolai Ryzhikov bekerja di sektor Kesehatan-TI untuk membuat sistem informasi medis. Anggota komunitas programmer fungsional St. Petersburg FPROG. Anggota aktif dari komunitas Clojure Online, anggota dari standar pertukaran informasi medis HL7 FHIR. Telah pemrograman selama 15 tahun.


Sisi apa yang kita miliki untuk DevOps? Selama 10 tahun, formula DevOps kami cukup sederhana: pengembang bertanggung jawab atas operasi, pengembang dikerahkan, pengembang dipelihara. Dengan pengaturan ini, yang terlihat agak keras, Anda akan menjadi DevOps. Jika Anda ingin menerapkan DevOps dengan cepat dan menyakitkan - buat pengembang bertanggung jawab atas produksi Anda. Jika para pria itu cerdas, maka mereka akan mulai keluar dan memahami segalanya.

Kisah kami: dahulu kala, ketika tidak ada Chef dan otomatisasi, kami sudah menggunakan Capistrano otomatis. Kemudian mereka mulai membosankan dia, sehingga dia akan membuat mode. Tapi kemudian Chef muncul. Kami beralih ke sana dan pergi ke cloud: kami bosan dengan pusat data kami. Kemudian Ansible muncul, Docker muncul. Setelah itu, kami pindah ke Terraform dengan atasan Condo docker tulisan tangan di Camel. Dan sekarang kita pindah ke Kubernetes.

Apa hal terburuk tentang operasi? Sangat sedikit orang yang puas dengan tingkat otomatisasi operasi mereka. Ini menakutkan, saya tegaskan: kami menghabiskan banyak sumber daya dan upaya untuk mengumpulkan semua tumpukan ini untuk diri kami sendiri, dan hasilnya tidak memuaskan.

Ada perasaan bahwa dengan kedatangan Kubernetes, sesuatu dapat berubah. Saya berkomitmen untuk lean manufacturing dan, dari sudut pandangnya, operasi pada umumnya tidak bermanfaat. Operasi ideal adalah tidak adanya atau minimum operasi dalam suatu proyek. Nilai dibuat ketika pengembang membuat produk. Ketika sudah siap, pengiriman tidak menambah nilai. Tetapi Anda perlu mengurangi biaya.

Bagi saya, cita-cita itu selalu heroku. Kami menggunakannya untuk aplikasi sederhana, di mana pengembang untuk menyebarkan layanannya, itu sudah cukup untuk mengatakan git push dan mengkonfigurasi heroku. Butuh satu menit.

Bagaimana menjadi Anda dapat membeli NoOps - juga heroku. Dan saya menyarankan Anda untuk membeli, jika tidak, ada peluang untuk menghabiskan lebih banyak uang untuk pengembangan operasi normal.

Ada Deis guys, mereka mencoba melakukan sesuatu seperti heroku di Kubernetes. Ada cloud foundry, yang juga menyediakan platform untuk bekerja.

Tetapi jika Anda peduli dengan sesuatu yang lebih kompleks atau besar, Anda bisa melakukannya sendiri. Sekarang, bersama dengan Docker dan Kubernetes, ini menjadi tugas yang dapat diselesaikan dalam jumlah waktu yang wajar dan dengan biaya yang masuk akal. Dulu terlalu keras.

Sedikit tentang Docker dan Kubernetes


Salah satu masalah operasi adalah pengulangan. Hal hebat yang dibawa oleh buruh pelabuhan adalah dua fase. Kami memiliki fase pembangunan.

Poin kedua yang menyenangkan di buruh pelabuhan adalah antarmuka universal untuk meluncurkan layanan sewenang-wenang. Seseorang merakit Docker, memasukkan sesuatu ke dalam, dan mengoperasikannya sudah cukup untuk mengatakan Docker menjalankan dan memulai.



Apa itu Kubernet? Jadi kami membuat Docker dan kami perlu meluncurkan, mengintegrasikan, mengkonfigurasi dan menghubungkannya dengan orang lain di suatu tempat. Kubernetes memungkinkan Anda untuk melakukan ini. Dia memperkenalkan serangkaian abstraksi, yang disebut "sumber daya". Kami akan dengan cepat melewati mereka dan bahkan mencoba untuk membuat.

Abstraksi


Abstraksi pertama adalah POD atau satu set wadah. Dilakukan dengan benar, apa sebenarnya satu set wadah, dan bukan satu. Set dapat mengaduk-aduk volume yang saling melihat melalui localhost. Ini memungkinkan Anda untuk menggunakan pola seperti sespan (ini adalah saat kami meluncurkan wadah utama, dan ada wadah tambahan di sekitarnya yang membantunya).

Misalnya, pendekatan duta besar. Ini adalah saat Anda tidak ingin wadah berpikir di mana beberapa layanan berada. Anda meletakkan wadah di sebelahnya yang tahu di mana layanan ini berada. Dan mereka menjadi tersedia untuk wadah utama di localhost. Dengan demikian, lingkungan mulai terlihat seperti Anda bekerja secara lokal.

Mari kita meningkatkan POD dan melihat bagaimana itu dijelaskan. Secara lokal Anda dapat mengembangkan minikube. Ini memakan banyak CPU, tetapi memungkinkan Anda untuk meningkatkan sekelompok Kubernet kecil di virtualbox dan bekerja dengannya.

Mari kita gunakan POD. Saya mengatakan Kubernet menerapkan dan membanjiri POD. Saya dapat melihat POD apa yang saya miliki: Saya melihat satu POD digunakan. Ini berarti bahwa Kubernetes telah meluncurkan kontainer ini.


Saya bahkan bisa masuk ke wadah ini.


Dari perspektif ini, Kubernet dibuat untuk orang-orang. Memang, apa yang terus-menerus kita lakukan dalam operasi, dalam pengikatan Kubernetes, misalnya, menggunakan utilitas kubectl, dapat dilakukan dengan mudah.

Tapi POD itu fana. Ini dimulai saat Docker dijalankan: jika seseorang menghentikannya, tidak ada yang akan mengangkatnya. Di atas abstraksi ini, Kubernetes mulai membangun yang berikut - misalnya, sebuah replaset. Ini adalah pengawas yang memantau POD, memantau jumlah mereka, dan jika POD jatuh, dia mengangkatnya. Ini adalah konsep penyembuhan diri yang penting di Kubernetes yang memungkinkan Anda tidur nyenyak di malam hari.

Replika di atas ada abstraksi penyebaran - juga sumber daya yang memungkinkan Anda melakukan penyebaran nol waktu. Sebagai contoh, satu replika bekerja. Ketika kami menyebarkan dan mengubah versi wadah, misalnya milik kami, di dalam penyebaran, replika lain muncul. Kami menunggu sampai wadah-wadah ini mulai, memeriksa pemeriksaan kesehatannya, dan kemudian kami dengan cepat beralih ke replaset baru. Juga latihan klasik dan bagus.

Mari kita ambil layanan sederhana. Misalnya, kami memiliki penempatan. Di dalam, ia menggambarkan pola POD yang akan diambilnya. Kita dapat menerapkan penyebaran ini, lihat apa yang kita miliki. Fitur keren dari Kubernetes - semuanya terletak di basis data, dan kita dapat menyaksikan apa yang terjadi di sistem.

Di sini kita melihat satu penyebaran. Jika kita mencoba melihat POD, kita melihat bahwa beberapa POD telah meningkat. Kita dapat mengambil dan menghapus POD ini. Apa yang terjadi pada POD? Satu dihancurkan, dan yang kedua segera naik. Kontroler replika ini tidak menemukan POD yang diinginkan dan meluncurkan yang lain.


Lebih lanjut, jika ini semacam layanan web, atau di dalam layanan kami harus berkomunikasi, kami memerlukan penemuan layanan. Anda harus memberi layanan nama dan titik masuk. Kubernetes menawarkan layanan yang disebut sumber daya untuk ini. Ia dapat menangani keseimbangan muatan dan bertanggung jawab atas penemuan layanan.

Mari kita lihat layanan sederhana. Kami menghubungkannya dengan penyebaran dan POD melalui label: tautan dinamis tersebut. Konsep yang sangat penting di Kubernetes: sistemnya dinamis. Tidak masalah dalam urutan apa semua ini akan dibuat. Layanan akan mencoba menemukan POD dengan label tersebut dan memulai keseimbangan bebannya.


Terapkan layanan, lihat layanan apa yang kami miliki. Kami masuk ke POD pengujian kami, yang dinaikkan, dan lakukan nslookup. Kubernetes memberi kami DNS-ku di mana layanan dapat melihat dan menemukan satu sama lain.


Layanan lebih merupakan antarmuka. Ada beberapa implementasi yang berbeda, karena tugas-tugas penyeimbangan beban dan layanan cukup rumit: dalam satu cara kami bekerja dengan database biasa, yang lain dengan yang dimuat, dan beberapa yang sederhana dibuat cukup sederhana. Ini juga merupakan konsep penting dalam Kubernetes: beberapa hal dapat disebut antarmuka daripada implementasi. Mereka tidak diperbaiki secara kaku, dan berbeda, misalnya, penyedia cloud memberikan implementasi yang berbeda. Misalnya, ada volume persisten sumber daya, yang sudah diterapkan di setiap cloud tertentu dengan cara regulernya.

Selanjutnya, kami biasanya ingin mengeluarkan layanan web. Kubernetes memiliki abstraksi masuknya. Biasanya SSL ditambahkan di sana.

Masuknya paling sederhana terlihat seperti ini. Di sana kami menulis aturan: untuk url mana, untuk host mana, layanan internal mana untuk mengarahkan permintaan. Dengan cara yang sama, kita dapat meningkatkan masuknya kita.


Setelah itu, setelah mendaftar secara lokal di host, Anda dapat melihat layanan ini dari sini.


Ini adalah tugas yang biasa: kami mengerahkan layanan web tertentu, bertemu sedikit dengan Kubernetes.


Kami akan membersihkan semuanya, menghapus masuknya dan melihat semua sumber daya.


Ada sejumlah sumber daya, seperti configmap dan rahasia. Ini murni sumber daya informasi yang dapat Anda pasang di wadah dan transfer di sana, misalnya, kata sandi dari postgres. Anda bisa mengaitkan ini dengan variabel lingkungan yang akan disuntikkan ke wadah saat startup. Anda dapat memasang sistem file. Semuanya cukup nyaman: tugas standar, solusi bagus.

Ada volume persisten - sebuah antarmuka yang diimplementasikan secara berbeda oleh penyedia cloud yang berbeda. Ini dibagi menjadi dua bagian: ada klaim volume persisten (permintaan), dan kemudian beberapa EBS dibuat yang menyeret ke wadah. Anda dapat bekerja dengan layanan stateful.



Tetapi bagaimana cara kerjanya di dalam? Konsepnya sendiri sangat sederhana dan transparan. Kubernetes memiliki dua bagian. Salah satunya hanyalah sebuah database di mana kita memiliki semua sumber daya ini. Sumber daya dapat dianggap sebagai tablet: khusus, contoh ini hanya catatan di tablet. Di atas Kubernetes, server API dikonfigurasi. Artinya, ketika Anda memiliki kluster Kubernetes, Anda biasanya berkomunikasi dengan server API (lebih tepatnya, klien berkomunikasi dengannya).

Dengan demikian, apa yang kami buat (POD, layanan, dll.) Hanya ditulis ke basis data. Basis data ini diimplementasikan oleh ETCD, mis. sehingga stabil di level tinggi yang tersedia.

Apa yang terjadi selanjutnya? Selanjutnya di bawah setiap jenis sumber daya ada pengontrol tertentu. Ini hanyalah layanan yang memonitor jenis sumber dayanya dan melakukan sesuatu di dunia luar. Misalnya, apakah Docker berjalan. Jika kita memiliki POD, untuk setiap Node ada layanan kubelet yang memonitor POD yang terhubung ke node ini. Dan semua yang dia lakukan adalah Docker dijalankan setelah pemeriksaan berkala berikutnya jika POD ini tidak ada.

Selanjutnya, yang sangat penting - semuanya terjadi secara real time, sehingga kekuatan kontroler ini lebih tinggi dari minimum. Seringkali, pengontrol masih mengambil metrik dan melihat apa yang dimulai. Yaitu menghapus umpan balik dari dunia nyata dan menulisnya ke database, sehingga Anda atau pengontrol lain dapat melihatnya. Misalnya, status POD yang sama akan ditulis kembali ke ETCD.

Dengan demikian, semuanya diimplementasikan di Kubernetes. Sangat keren bahwa model informasi dipisahkan dari ruang operasi. Dalam database melalui antarmuka CRUD biasa kami menyatakan apa yang seharusnya. Kemudian serangkaian pengontrol mencoba untuk membuat semuanya menjadi benar. Benar, ini tidak selalu terjadi.

Ini adalah model cybernetic. Kami memiliki preset tertentu, ada beberapa jenis mesin yang mencoba mengarahkan dunia nyata atau mesin ke tempat yang dibutuhkan. Tidak selalu berubah seperti ini: kita harus memiliki umpan balik. Terkadang mesin tidak dapat melakukan ini dan harus beralih ke seseorang.



Dalam sistem nyata, kami berpikir dalam abstraksi dari tingkat berikutnya: kami memiliki beberapa layanan, basis data, dan kami semua menghubungkannya. Kami tidak memikirkan POD dan Ingress, dan kami ingin membangun beberapa tingkat abstraksi berikutnya.

Sehingga pengembang semudah mungkin: sehingga dia hanya berkata, "Saya ingin memulai layanan ini dan itu," dan segala sesuatu yang terjadi di dalam.

Ada yang namanya HELM. Ini adalah cara yang salah - gaya templating mungkin, di mana kami hanya mencoba untuk menelurkan satu set sumber daya yang dikonfigurasi dan menjatuhkannya ke cluster Kubernetes.

Masalahnya, pertama, adalah ini hanya dilakukan pada saat bergulir. Artinya, dia tidak bisa menerapkan banyak logika. Kedua, dalam runtime abstraksi ini menghilang. Ketika saya pergi untuk melihat cluster saya, saya hanya melihat POD dan layanan. Saya tidak melihat bahwa layanan ini dan itu digunakan, bahwa basis ini dan itu dengan replikasi dinaikkan di sana. Saya hanya melihat puluhan perapian di sana. Abstraksi menghilang seperti dalam matriks.

Model Solusi Internal


Di sisi lain, Kubernetes sendiri sudah menyediakan model ekstensi yang sangat menarik dan sederhana di dalamnya. Kami dapat mendeklarasikan jenis sumber daya baru, misalnya penyebaran. Ini adalah sumber daya yang dibangun di atas POD atau replaset. Kita dapat menulis pengontrol untuk sumber daya ini, menempatkan sumber daya ini dalam database dan menjalankan lingkaran cybernetic kami sehingga semuanya berfungsi. Ini kedengarannya menarik, dan menurut saya ini adalah cara yang tepat untuk memperluas Kubernetes.

Saya ingin dapat menulis manifes untuk layanan gaya heroku saya. Contoh yang sangat sederhana: Saya ingin menggunakan beberapa jenis aplikasi di lingkungan saya yang sebenarnya. Sudah memiliki perjanjian, SSL, domain yang dibeli. Saya hanya ingin memberi para pengembang antarmuka sesederhana mungkin. Manifest memberitahu saya wadah mana yang harus diangkat, sumber daya apa yang masih dibutuhkan wadah ini. Dia melempar pengumuman ini ke cluster, dan semuanya mulai bekerja.


Bagaimana ini akan terlihat dalam hal sumber daya kustom dan pengontrol? Di sini kita akan memiliki aplikasi sumber daya dalam database. Dan pengontrol aplikasi akan menelurkan tiga sumber. Artinya, ia akan menuliskan aturan tentang cara rute ke layanan ini, memulai layanan untuk menyeimbangkan beban dan meluncurkan penyebaran dengan beberapa jenis konfigurasi.



Sebelum kita membuat sumber daya khusus di Kubernetes, kita perlu mendeklarasikannya. Untuk ini, ada sumber daya meta yang disebut CustomResourceDefinition.

Untuk mendeklarasikan sumber daya baru di Kubernetes, cukup bagi kami untuk mengirim pengumuman seperti itu. Pertimbangkan ini buat tabel.


Membuat tabel. Setelah itu, kita dapat melihat melalui kubectl mendapatkan sumber daya pihak ketiga yang kita miliki. Segera setelah kami mengumumkannya, kami juga mendapat spanduk. Kita dapat melakukan, misalnya, kubeclt mendapatkan aplikasi. Namun sejauh ini tidak ada aplikasi.


Mari kita menulis beberapa aplikasi. Setelah itu, kita dapat membuat instance sumber daya kustom. Mari kita melihatnya di YAML dan membuatnya dengan memposting ke URL tertentu.


Jika kita menjalankan dan melihat kubectl, maka satu aplikasi muncul. Tetapi sementara tidak ada yang terjadi, itu hanya terletak di database. Anda dapat, misalnya, mengambil dan meminta semua sumber daya aplikasi.


Kita dapat membuat sumber daya kedua dari templat yang sama hanya dengan mengubah namanya. Ini sumber kedua.


Selanjutnya, controller kita harus melakukan templating, mirip dengan apa yang dilakukan HELM. Yaitu, setelah menerima deskripsi aplikasi kami, saya harus menghasilkan penyebaran sumber daya dan layanan sumber daya, serta membuat entri masuk. Ini adalah bagian yang paling mudah: di sini di clojure adalah erlmacro. Saya melewati struktur data, itu menarik fungsi penyebaran, lolos ke debug, yang merupakan pipa. Dan ini adalah fungsi murni: templating sederhana. Oleh karena itu, dalam bentuk yang paling naif, saya dapat segera membuatnya, mengubahnya menjadi utilitas konsol dan mulai mendistribusikannya.


Kami melakukan hal yang sama untuk layanan: fungsi layanan menerima deklarasi dan menghasilkan sumber daya Kubernetes untuk kami.


Kami melakukan hal yang sama untuk baris masuknya.


Bagaimana ini semua bekerja? Akan ada sesuatu di dunia nyata dan akan ada yang kita inginkan. Apa yang kita inginkan - kita mengambil sumber daya aplikasi dan menghasilkan apa yang seharusnya. Dan sekarang kita perlu melihat apa itu. Apa yang kami minta melalui REST API. Kami bisa mendapatkan semua layanan, semua penyebaran.

Bagaimana cara kerja kontroler kustom kami? Dia akan menerima apa yang kita inginkan dan apa yang ada, ambil dari div ini dan berlaku untuk Kubernetes. Ini mirip dengan Bereaksi. Saya datang dengan DOM virtual ketika beberapa fungsi hanya menghasilkan pohon objek JS. Dan kemudian algoritma tertentu menghitung tambalan dan menerapkannya ke DOM nyata.

Kami akan melakukan hal yang sama di sini. Ini dilakukan dalam 50 baris kode. Ingin - semuanya ada di Github. Pada akhirnya, kita harus mendapatkan fungsi tindakan rekonsiliasi.

Kami memiliki fungsi tindakan rekonsiliasi yang tidak melakukan apa-apa dan hanya menghitung div ini. Dia mengambil apa yang ada, ditambah apa yang dibutuhkan. Dan kemudian memberikan apa yang perlu dilakukan untuk membawa yang pertama ke yang kedua.


Mari kita tarik dia. Tidak ada yang salah dengan dirinya, dia bisa dihancurkan. Dia mengatakan bahwa Anda perlu membuat layanan masuknya, buat dua entri di dalamnya, buat penyebaran 1 dan 2, buat layanan 1 dan 2.


Dalam hal ini, seharusnya hanya ada satu layanan. Kami melihat dari ingress bahwa hanya satu entri yang tersisa.

Kemudian yang tersisa adalah menulis fungsi yang menerapkan tambalan ini ke kluster Kubernetes. Untuk melakukan ini, kita cukup meneruskan aksi rekonsiliasi ke fungsi rekonsiliasi, dan semuanya akan berlaku. Dan sekarang kita melihat bahwa POD telah meningkat, penyebaran telah menjadi dan layanan telah dimulai.


Mari kita tambahkan layanan lain: jalankan fungsi rekonsiliasi tindakan lagi. Mari kita lihat apa yang terjadi. Semuanya dimulai, semuanya baik-baik saja.


Bagaimana cara menghadapinya? Kami mengemas semua ini dalam wadah Docker. Setelah itu, kita menulis fungsi yang secara berkala bangun, membuat rekonsiliasi, dan tertidur. Kecepatan tidak terlalu penting, ia bisa tidur selama lima detik dan melakukan aksi rekonsiliasi yang tidak begitu sering.


Pengontrol khusus kami hanyalah layanan yang akan bangun dan menghitung tambalan secara berkala.

Sekarang kami memiliki dua layanan zaddeloino, mari kita hapus salah satu aplikasi. Mari kita lihat bagaimana gugus kita bereaksi: semuanya baik-baik saja. Kami menghapus yang kedua: semuanya sudah dihapus.


Mari kita lihat melalui mata pengembang. Dia hanya perlu mengatakan Kubernetes mendaftar dan memberi nama layanan baru. Kami melakukan ini, pengontrol kami mengambil semuanya dan menciptakannya.


Lalu kami mengumpulkan semua ini di layanan penerapan, dan kami melemparkan pengontrol khusus ini ke dalam cluster menggunakan alat standar Kubernetes. Kami membuat abstraksi untuk 200 baris kode.

Semuanya terlihat seperti BANTUAN, tetapi sebenarnya lebih kuat. Pengontrol bekerja dalam sebuah cluster: ia melihat pangkalan, melihat dunia luar dan dapat dibuat cukup pintar.

CI sendiri


Perhatikan contoh ekstensi Kubernetes. Kami memutuskan bahwa CI harus menjadi bagian dari infrastruktur. Ini bagus, nyaman dari sudut pandang keamanan - repositori pribadi. Kami mencoba menggunakan jenkins, tetapi ini adalah alat yang sudah ketinggalan zaman. Saya ingin seorang hacker CI. Kami tidak membutuhkan antarmuka, kami suka ChatOps: biarkan saja yang mengatakan dalam obrolan apakah build telah jatuh atau belum. Selain itu, saya ingin men-debug semuanya secara lokal.

Kami duduk dan menulis CI kami dalam seminggu. Sama seperti ekstensi ke Kubernetes. Jika Anda berpikir tentang CI, maka ini hanyalah alat yang menjalankan beberapa jenis pekerjaan. Sebagai bagian dari pekerjaan ini, kami membangun sesuatu, menjalankan tes, dan sering menggunakan.

Bagaimana cara kerjanya? Itu dibangun pada konsep pengendali kustom yang sama. -, Kubernetes , . web-hook. .

web-hook, — JSON build, Kubernetes. build build controller, manifest, , POD. POD- .

POD- agent, travis circleci, YAML . . Telegram.

, Kubernetes — , CI continuous delivery while true sleep 10, POD . kubectl exec, .

— , . 300 .



postgres


postgres, . extensions. RDS -.

postgres. . «, postgres, ». , , , . , cluster controller . pginstance-, istance postgres. cluster postgres.

pginstance controller, , POD deployment postgres. persistent volume. postgres. Docker-container, binary postgres. : postgres . , , , , .. POD persistent volume postgres cluster master.

deployment master. persistent volume. POD , , , deployment slave.

Selanjutnya, pengontrol kluster membuat sumber daya cadangan (setelah dijelaskan dengan cadangan). Dan pengendali cadangan sudah mengambilnya dan melemparkannya ke beberapa S3.



Apa selanjutnya


. , , , « postgres, kafka, CI ». .

, , , , . operations information-. , , , , resource application. . . . logical relation .

Kubernetes — REST API , . , , : « , ». sql . generic , . .


DevOops 2018 ! — .

«The DevOps Handbook» , «Learning Chef: A Guide to Configuration Management and Automation» , «How to containerize your Go code» «Liquid Software: How to Achieve Trusted Continuous Updates in the DevOps World» — . - .

: !

: 1 DevOops 2018 .

Source: https://habr.com/ru/post/id424609/


All Articles