Lima terlepas apabila menggunakan aplikasi pertama pada Kubernetes

Lima terlepas apabila menggunakan aplikasi pertama pada KubernetesGagal oleh Aris Dreamer

Ramai orang berfikir bahawa cukup untuk memindahkan aplikasi ke Kubernetes (sama ada menggunakan Helm atau secara manual) - dan akan ada kebahagiaan. Tetapi tidak semuanya begitu mudah.

Pasukan Penyelesaian Awan Mail.ru menterjemah artikel oleh jurutera DevOps Julian Gindy. Dia memberitahu apa masalah yang dihadapi syarikatnya semasa proses penghijrahan supaya anda tidak memijak rake yang sama.

Langkah Satu: Sediakan Permintaan dan Had Pod

Mari kita mulakan dengan menyediakan persekitaran yang bersih di mana pod kita akan dijalankan. Kubernetes hebat dalam penjadualan pod dan failover. Tetapi ternyata penjadual kadang-kadang tidak dapat meletakkan pod jika sukar untuk menganggarkan berapa banyak sumber yang diperlukan untuk berfungsi dengan jayanya. Di sinilah permintaan untuk sumber dan had timbul. Terdapat banyak perdebatan tentang pendekatan terbaik untuk menetapkan permintaan dan had. Kadang-kadang nampaknya ini lebih kepada seni daripada sains. Inilah pendekatan kami.

Permintaan pod ialah nilai utama yang digunakan oleh penjadual untuk meletakkan pod secara optimum.

Daripada dokumentasi Kubernetes: Langkah penapis mentakrifkan set nod di mana Pod boleh dijadualkan. Sebagai contoh, penapis PodFitsResources menyemak untuk melihat sama ada nod mempunyai sumber yang mencukupi untuk memenuhi permintaan sumber tertentu daripada pod.

Kami menggunakan permintaan aplikasi sedemikian rupa sehingga kami boleh menganggarkan jumlah sumber sebenarnya Aplikasi memerlukannya untuk berfungsi dengan baik. Dengan cara ini penjadual boleh meletakkan nod secara realistik. Pada mulanya, kami ingin terlalu menjadualkan permintaan untuk memastikan sumber yang mencukupi untuk setiap Pod, tetapi kami mendapati bahawa masa penjadualan meningkat dengan ketara, dan beberapa Pod tidak dijadualkan sepenuhnya, seolah-olah tiada permintaan sumber untuknya.

Dalam kes ini, penjadual selalunya akan "memerah" pod dan tidak dapat menjadualkannya semula kerana pesawat kawalan tidak tahu berapa banyak sumber yang diperlukan oleh aplikasi, yang merupakan komponen utama algoritma penjadualan.

Had pod ialah had yang lebih jelas untuk pod. Ia mewakili jumlah maksimum sumber yang akan diperuntukkan oleh kluster kepada bekas.

Sekali lagi, dari dokumentasi rasmi: Jika bekas mempunyai had memori sebanyak 4 GiB, maka kubelet (dan masa jalan kontena) akan menguatkuasakannya. Masa jalan menghalang bekas daripada menggunakan lebih daripada had sumber yang ditentukan. Sebagai contoh, apabila proses dalam bekas cuba menggunakan lebih daripada jumlah memori yang dibenarkan, kernel sistem menamatkan proses dengan ralat "kehabisan memori" (OOM).

Bekas boleh sentiasa menggunakan lebih banyak sumber daripada permintaan sumber yang ditentukan, tetapi ia tidak boleh menggunakan lebih daripada had. Nilai ini sukar untuk ditetapkan dengan betul, tetapi ia sangat penting.

Sebaik-baiknya, kami mahu keperluan sumber pod berubah semasa kitaran hayat proses tanpa mengganggu proses lain dalam sistem - ini adalah tujuan menetapkan had.

Malangnya, saya tidak dapat memberikan arahan khusus tentang nilai yang perlu ditetapkan, tetapi kami sendiri mematuhi peraturan berikut:

  1. Menggunakan alat ujian beban, kami mensimulasikan tahap asas trafik dan memerhatikan penggunaan sumber pod (memori dan pemproses).
  2. Tetapkan permintaan pod kepada nilai rendah sewenang-wenangnya (dengan had sumber kira-kira 5 kali ganda nilai permintaan) dan perhatikan. Apabila permintaan berada pada tahap yang terlalu rendah, proses tidak boleh dimulakan, selalunya menyebabkan ralat masa jalan Go yang samar.

Saya perhatikan bahawa had sumber yang lebih tinggi menjadikan penjadualan lebih sukar kerana pod memerlukan nod sasaran dengan sumber yang mencukupi.

Bayangkan situasi di mana anda mempunyai pelayan web yang ringan dengan had sumber yang sangat tinggi, seperti memori 4 GB. Proses ini mungkin perlu dikecilkan secara mendatar, dan setiap pod baharu perlu dijadualkan pada nod dengan sekurang-kurangnya 4 GB memori tersedia. Jika tiada nod sedemikian wujud, kluster mesti memperkenalkan nod baharu untuk memproses pod ini, yang mungkin mengambil sedikit masa. Adalah penting untuk mencapai perbezaan minimum antara permintaan dan had sumber untuk memastikan penskalaan yang cepat dan lancar.

Langkah Kedua: Sediakan Ujian Keaktifan dan Kesediaan

Ini adalah satu lagi topik halus yang sering dibincangkan dalam komuniti Kubernetes. Adalah penting untuk mempunyai pemahaman yang baik tentang ujian Liveness dan Kesediaan kerana ia menyediakan mekanisme untuk pengendalian perisian yang stabil dan meminimumkan masa henti. Walau bagaimanapun, ia boleh memberi kesan serius kepada prestasi aplikasi anda jika tidak dikonfigurasikan dengan betul. Di bawah ialah ringkasan tentang kedua-dua sampel itu.

Kehidupan menunjukkan sama ada bekas sedang berjalan. Jika gagal, kubelet membunuh bekas dan dasar mulakan semula didayakan untuknya. Jika bekas tidak dilengkapi dengan Probe Liveness, maka keadaan lalai akan berjaya - seperti yang dinyatakan dalam dokumentasi Kubernetes.

Probe liveness harus murah, iaitu tidak menggunakan banyak sumber, kerana ia dijalankan dengan kerap dan harus memaklumkan Kubernetes bahawa aplikasi sedang berjalan.

Jika anda menetapkan pilihan untuk menjalankan setiap saat, ini akan menambah 1 permintaan sesaat, jadi maklum bahawa sumber tambahan akan diperlukan untuk memproses trafik ini.

Di syarikat kami, ujian Liveness menguji komponen teras aplikasi, walaupun data (contohnya, daripada pangkalan data jauh atau cache) tidak tersedia sepenuhnya.

Kami telah menyediakan titik akhir "kesihatan" dalam aplikasi yang hanya mengembalikan kod respons 200. Ini adalah penunjuk bahawa proses sedang berjalan dan mampu mengendalikan permintaan (tetapi belum lagi trafik).

Contoh Utiliti menunjukkan sama ada bekas sedia untuk melayani permintaan. Jika probe kesediaan gagal, pengawal titik akhir mengalih keluar alamat IP pod dari titik akhir semua perkhidmatan yang sepadan dengan pod. Ini juga dinyatakan dalam dokumentasi Kubernetes.

Siasatan kesediaan menggunakan lebih banyak sumber, kerana ia mesti memukul bahagian belakang sedemikian rupa untuk menunjukkan bahawa aplikasi itu bersedia untuk menerima permintaan.

Terdapat banyak perdebatan dalam komuniti sama ada untuk mengakses pangkalan data secara langsung. Memandangkan overhed (semakan adalah kerap, tetapi ia boleh dikawal), kami memutuskan bahawa untuk sesetengah aplikasi, kesediaan untuk melayani trafik hanya dikira selepas menyemak bahawa rekod dikembalikan daripada pangkalan data. Percubaan kesediaan yang direka bentuk dengan baik memastikan tahap ketersediaan yang lebih tinggi dan menghapuskan masa henti semasa penggunaan.

Jika anda memutuskan untuk menanyakan pangkalan data untuk menguji kesediaan aplikasi anda, pastikan ia semurah mungkin. Mari kita ambil pertanyaan ini:

SELECT small_item FROM table LIMIT 1

Berikut ialah contoh cara kami mengkonfigurasi dua nilai ini dalam Kubernetes:

livenessProbe: 
 httpGet:   
   path: /api/liveness    
   port: http 
readinessProbe:  
 httpGet:    
   path: /api/readiness    
   port: http  periodSeconds: 2

Anda boleh menambah beberapa pilihan konfigurasi tambahan:

  • initialDelaySeconds - berapa saat akan berlalu antara pelancaran kontena dan permulaan pelancaran probe.
  • periodSeconds β€” selang menunggu antara larian sampel.
  • timeoutSeconds β€” bilangan saat selepas itu pod dianggap sebagai kecemasan. tamat masa biasa.
  • failureThreshold ialah bilangan kegagalan ujian sebelum isyarat mulakan semula dihantar ke pod.
  • successThreshold ialah bilangan percubaan yang berjaya sebelum pod beralih kepada keadaan sedia (selepas kegagalan apabila pod dimulakan atau pulih).

Langkah Tiga: Menetapkan Dasar Rangkaian Lalai Pod

Kubernetes mempunyai topografi rangkaian "rata", secara lalai semua pod berkomunikasi secara langsung antara satu sama lain. Dalam sesetengah kes ini tidak diingini.

Isu keselamatan yang berpotensi ialah penyerang boleh menggunakan satu aplikasi yang terdedah untuk menghantar trafik ke semua pod pada rangkaian. Seperti dalam banyak bidang keselamatan, prinsip keistimewaan paling rendah digunakan di sini. Sebaik-baiknya, dasar rangkaian harus menyatakan secara eksplisit sambungan antara pod yang dibenarkan dan yang tidak.

Sebagai contoh, berikut ialah dasar mudah yang menafikan semua trafik masuk untuk ruang nama tertentu:

---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:  
 name: default-deny-ingress
spec:  
 podSelector: {}  
 policyTypes:  
   - Ingress

Visualisasi konfigurasi ini:

Lima terlepas apabila menggunakan aplikasi pertama pada Kubernetes
(https://miro.medium.com/max/875/1*-eiVw43azgzYzyN1th7cZg.gif)
Maklumat lanjut di sini.

Langkah Empat: Gelagat Tersuai dengan Cangkuk dan Bekas Init

Salah satu matlamat utama kami adalah untuk menyediakan penggunaan dalam Kubernetes tanpa masa henti untuk pembangun. Ini sukar kerana terdapat banyak pilihan untuk menutup aplikasi dan melepaskan sumber terpakainya.

Kesukaran tertentu timbul dengan Nginx. Kami mendapati bahawa apabila menggunakan Pod ini dalam urutan, sambungan aktif telah terganggu sebelum berjaya dilengkapkan.

Selepas penyelidikan menyeluruh di Internet, ternyata Kubernetes tidak menunggu sambungan Nginx meletihkan diri sebelum menutup pod. Dengan bantuan cangkuk pra henti, kami melaksanakan fungsi berikut dan menyingkirkan sepenuhnya masa henti:

lifecycle: 
 preStop:
   exec:
     command: ["/usr/local/bin/nginx-killer.sh"]

Tetapi nginx-killer.sh:

#!/bin/bash
sleep 3
PID=$(cat /run/nginx.pid)
nginx -s quit
while [ -d /proc/$PID ]; do
   echo "Waiting while shutting down nginx..."
   sleep 10
done

Satu lagi paradigma yang sangat berguna ialah penggunaan bekas init untuk mengendalikan pelancaran aplikasi tertentu. Ini amat berguna jika anda mempunyai proses pemindahan pangkalan data intensif sumber yang mesti dijalankan sebelum aplikasi bermula. Anda juga boleh menentukan had sumber yang lebih tinggi untuk proses ini tanpa menetapkan had sedemikian untuk aplikasi utama.

Satu lagi skim biasa ialah untuk mengakses rahsia dalam bekas init, yang menyediakan kelayakan ini kepada modul utama, yang menghalang akses tanpa kebenaran kepada rahsia daripada modul aplikasi utama itu sendiri.

Seperti biasa, petikan daripada dokumentasi: bekas init selamat menjalankan kod pengguna atau utiliti yang sebaliknya akan menjejaskan keselamatan imej kontena aplikasi. Dengan mengasingkan alat yang tidak diperlukan, anda mengehadkan permukaan serangan imej kontena aplikasi.

Langkah Kelima: Konfigurasi Kernel

Akhir sekali, mari kita bercakap tentang teknik yang lebih maju.

Kubernetes ialah platform yang sangat fleksibel yang membolehkan anda menjalankan beban kerja walau bagaimanapun anda rasa sesuai. Kami mempunyai beberapa aplikasi yang sangat cekap yang sangat intensif sumber. Selepas melakukan ujian beban yang meluas, kami mendapati bahawa salah satu aplikasi mengalami kesukaran untuk mengikuti beban trafik yang dijangkakan apabila tetapan Kubernetes lalai berkuat kuasa.

Walau bagaimanapun, Kubernetes membenarkan anda menjalankan bekas istimewa yang hanya menukar parameter kernel untuk pod tertentu. Inilah yang kami gunakan untuk menukar bilangan maksimum sambungan terbuka:

initContainers:
  - name: sysctl
     image: alpine:3.10
     securityContext:
         privileged: true
      command: ['sh', '-c', "sysctl -w net.core.somaxconn=32768"]

Ini adalah teknik yang lebih maju yang selalunya tidak diperlukan. Tetapi jika aplikasi anda bergelut untuk menampung beban yang berat, anda boleh cuba mengubah suai beberapa tetapan ini. Maklumat lanjut tentang proses ini dan menetapkan nilai yang berbeza - seperti biasa dalam dokumentasi rasmi.

Kesimpulannya

Walaupun Kubernetes mungkin kelihatan seperti penyelesaian luar biasa, terdapat beberapa langkah utama yang mesti diambil untuk memastikan aplikasi berjalan lancar.

Sepanjang pemindahan ke Kubernetes, adalah penting untuk mengikuti "kitaran ujian beban": jalankan aplikasi, uji aplikasi di bawah beban, amati metrik dan gelagat penskalaan, laraskan konfigurasi berdasarkan data ini, kemudian ulangi kitaran ini sekali lagi.

Jadi realistik tentang trafik yang dijangkakan dan cuba melampauinya untuk melihat komponen mana yang pecah dahulu. Dengan pendekatan berulang ini, hanya beberapa cadangan yang disenaraikan mungkin cukup untuk mencapai kejayaan. Atau ia mungkin memerlukan penyesuaian yang lebih mendalam.

Sentiasa tanya diri anda soalan ini:

  1. Berapa banyak sumber yang digunakan oleh aplikasi dan bagaimanakah jumlah ini akan berubah?
  2. Apakah keperluan penskalaan sebenar? Berapakah jumlah trafik yang akan dikendalikan oleh apl secara purata? Bagaimana dengan trafik puncak?
  3. Berapa kerapkah perkhidmatan perlu dipertingkatkan? Seberapa cepat pod baharu perlu disediakan dan dijalankan untuk menerima trafik?
  4. Seberapa baik pod ditutup? Adakah ia perlu sama sekali? Adakah mungkin untuk mencapai penggunaan tanpa masa henti?
  5. Bagaimana untuk meminimumkan risiko keselamatan dan mengehadkan kerosakan daripada mana-mana pod yang terjejas? Adakah mana-mana perkhidmatan mempunyai kebenaran atau akses yang mereka tidak perlukan?

Kubernetes menyediakan platform yang luar biasa yang membolehkan anda menggunakan amalan terbaik untuk menggunakan beribu-ribu perkhidmatan dalam kelompok. Walau bagaimanapun, semua aplikasi adalah berbeza. Kadangkala pelaksanaan memerlukan lebih sedikit kerja.

Nasib baik, Kubernetes menyediakan tetapan yang diperlukan untuk mencapai semua matlamat teknikal. Dengan menggunakan gabungan permintaan dan had sumber, probe Liveness dan Kesediaan, bekas init, dasar rangkaian dan penalaan kernel tersuai, anda boleh mencapai prestasi tinggi bersama-sama dengan toleransi kesalahan dan skalabiliti pantas.

Apa lagi yang perlu dibaca:

  1. Amalan Terbaik dan Amalan Terbaik untuk Menjalankan Bekas dan Kubernetes dalam Persekitaran Pengeluaran.
  2. 90+ Alat Berguna untuk Kubernetes: Penerapan, Pengurusan, Pemantauan, Keselamatan dan Banyak Lagi.
  3. Saluran kami Sekitar Kubernetes dalam Telegram.

Sumber: www.habr.com

Tambah komen