10 Kesilapan Biasa Apabila Menggunakan Kubernetes

Catatan. terjemah: Penulis artikel ini adalah jurutera dari sebuah syarikat kecil Czech, pipetail. Mereka berjaya menyusun senarai indah [kadang-kadang cetek, tetapi masih] masalah yang sangat mendesak dan salah tanggapan yang berkaitan dengan operasi kelompok Kubernetes.

10 Kesilapan Biasa Apabila Menggunakan Kubernetes

Selama bertahun-tahun menggunakan Kubernetes, kami telah bekerja dengan sejumlah besar kluster (terurus dan tidak terurus - pada GCP, AWS dan Azure). Dari masa ke masa, kami mula menyedari bahawa beberapa kesilapan sentiasa berulang. Walau bagaimanapun, tidak ada rasa malu dalam hal ini: kami telah melakukan kebanyakannya sendiri!

Artikel itu mengandungi ralat yang paling biasa dan juga menyebut cara membetulkannya.

1. Sumber: permintaan dan had

Item ini pastinya patut mendapat perhatian paling dekat dan tempat pertama dalam senarai.

Permintaan CPU biasanya sama ada tidak dinyatakan langsung atau mempunyai nilai yang sangat rendah (untuk meletakkan seberapa banyak pod pada setiap nod yang mungkin). Oleh itu, nod menjadi terlebih beban. Semasa masa beban tinggi, kuasa pemprosesan nod digunakan sepenuhnya dan beban kerja tertentu hanya menerima apa yang "diminta" olehnya. Pendikit CPU. Ini membawa kepada peningkatan kependaman aplikasi, tamat masa dan akibat lain yang tidak menyenangkan. (Baca lebih lanjut mengenai ini dalam terjemahan terbaru kami yang lain: β€œHad CPU dan pendikitan agresif dalam Kubernetes"- lebih kurang. terjemah.)

Usaha Terbaik (sangat tiada disyorkan):

resources: {}

Permintaan CPU yang sangat rendah (sangat tiada disyorkan):

   resources:
      Requests:
        cpu: "1m"

Sebaliknya, kehadiran had CPU boleh menyebabkan pelangkauan kitaran jam yang tidak munasabah oleh pod, walaupun pemproses nod tidak dimuatkan sepenuhnya. Sekali lagi, ini boleh menyebabkan peningkatan kelewatan. Kontroversi berterusan di sekitar parameter Kuota CFS CPU dalam kernel Linux dan pendikitan CPU bergantung pada had yang ditetapkan, serta melumpuhkan kuota CFS... Malangnya, had CPU boleh menyebabkan lebih banyak masalah daripada yang boleh diselesaikan. Maklumat lanjut mengenai perkara ini boleh didapati di pautan di bawah.

Pemilihan yang berlebihan (terlalu komited) masalah ingatan boleh membawa kepada masalah yang lebih besar. Mencapai had CPU memerlukan melangkau kitaran jam, manakala mencapai had memori memerlukan membunuh pod. Pernahkah anda memerhati OOMkill? Ya, itulah yang kami bincangkan.

Adakah anda ingin meminimumkan kemungkinan ini berlaku? Jangan terlalu memperuntukkan memori dan gunakan Guaranteed QoS (Kualiti Perkhidmatan) dengan menetapkan permintaan memori kepada had (seperti dalam contoh di bawah). Baca lebih lanjut tentang ini dalam Pembentangan Henning Jacobs (Jurutera Utama di Zalando).

Boleh pecah (peluang lebih tinggi untuk mendapat OOMkill):

   resources:
      requests:
        memory: "128Mi"
        cpu: "500m"
      limits:
        memory: "256Mi"
        cpu: 2

Dijamin:

   resources:
      requests:
        memory: "128Mi"
        cpu: 2
      limits:
        memory: "128Mi"
        cpu: 2

Apakah yang berpotensi membantu apabila menyediakan sumber?

Dengan pelayan metrik anda boleh melihat penggunaan sumber CPU semasa dan penggunaan memori oleh pod (dan bekas di dalamnya). Kemungkinan besar, anda sudah menggunakannya. Jalankan sahaja arahan berikut:

kubectl top pods
kubectl top pods --containers
kubectl top nodes

Walau bagaimanapun, mereka hanya menunjukkan penggunaan semasa. Ia boleh memberi anda gambaran kasar tentang susunan magnitud, tetapi akhirnya anda perlukan sejarah perubahan dalam metrik dari semasa ke semasa (untuk menjawab soalan seperti: β€œApakah beban CPU puncak?”, β€œApakah beban pagi semalam?”, dsb.). Untuk ini anda boleh gunakan Prometheus, DataDog dan alatan lain. Mereka hanya mendapatkan metrik daripada pelayan metrik dan menyimpannya, dan pengguna boleh menanyakannya dan memplotkannya dengan sewajarnya.

VerticalPodAutoscaler membolehkan automatik proses ini. Ia menjejaki sejarah penggunaan CPU dan memori serta menyediakan permintaan dan had baharu berdasarkan maklumat ini.

Menggunakan kuasa pengkomputeran dengan cekap bukanlah tugas yang mudah. Ia seperti bermain Tetris sepanjang masa. Jika anda membayar terlalu banyak untuk kuasa pengiraan dengan penggunaan purata yang rendah (katakan ~10%), kami mengesyorkan melihat produk berdasarkan AWS Fargate atau Kubelet Maya. Ia dibina pada model pengebilan tanpa pelayan/bayar setiap penggunaan, yang mungkin menjadi lebih murah dalam keadaan sedemikian.

2. Kuar keaktifan dan kesediaan

Secara lalai, semakan keaktifan dan kesediaan tidak didayakan dalam Kubernetes. Dan kadangkala mereka terlupa untuk menghidupkannya...

Tetapi bagaimana lagi anda boleh memulakan semula perkhidmatan sekiranya berlaku ralat yang membawa maut? Dan bagaimanakah pengimbang beban mengetahui bahawa pod sedia untuk menerima trafik? Atau ia boleh mengendalikan lebih banyak lalu lintas?

Ujian ini sering keliru antara satu sama lain:

  • Kehidupan β€” semakan "kebolehtahan hidup", yang memulakan semula pod jika ia gagal;
  • Utiliti β€” semakan kesediaan, jika gagal, ia memutuskan sambungan pod daripada perkhidmatan Kubernetes (ini boleh disemak menggunakan kubectl get endpoints) dan trafik tidak sampai kepadanya sehingga semakan seterusnya berjaya diselesaikan.

Kedua-dua cek ini DILAKUKAN SEPANJANG SELURUH KITARAN HAYAT POD. Ianya sangat penting.

Salah tanggapan yang lazim ialah probe kesediaan hanya dijalankan pada permulaan supaya pengimbang dapat mengetahui bahawa pod sudah sedia (Ready) dan boleh mula memproses trafik. Walau bagaimanapun, ini hanya salah satu pilihan untuk kegunaan mereka.

Satu lagi adalah kemungkinan untuk mengetahui bahawa trafik pada pod adalah berlebihan dan membebankannya (atau pod melakukan pengiraan intensif sumber). Dalam kes ini, semakan kesediaan membantu kurangkan beban pada pod dan "sejukkan" ia. Berjaya menyelesaikan semakan kesediaan pada masa hadapan membolehkan tambahkan lagi beban pada pod. Dalam kes ini (jika ujian kesediaan gagal), kegagalan ujian keaktifan akan menjadi sangat tidak produktif. Mengapa memulakan semula pod yang sihat dan bekerja keras?

Oleh itu, dalam beberapa kes, tiada semakan sama sekali adalah lebih baik daripada mendayakannya dengan parameter yang dikonfigurasikan dengan salah. Seperti yang dinyatakan di atas, jika semakan hidup salinan semakan kesediaan, maka anda berada dalam masalah besar. Pilihan yang mungkin adalah untuk mengkonfigurasi ujian kesediaan sahajaDan kehidupan yang berbahaya ketepikan.

Kedua-dua jenis semakan tidak sepatutnya gagal apabila kebergantungan biasa gagal, jika tidak, ini akan membawa kepada kegagalan berlatarkan (seperti longsoran) semua pod. Dalam kata lain, jangan membahayakan diri sendiri.

3. LoadBalancer untuk setiap perkhidmatan HTTP

Kemungkinan besar, anda mempunyai perkhidmatan HTTP dalam kluster anda yang anda ingin kirimkan ke dunia luar.

Jika anda membuka perkhidmatan sebagai type: LoadBalancer, pengawalnya (bergantung pada pembekal perkhidmatan) akan menyediakan dan merundingkan LoadBalancer luaran (tidak semestinya berjalan pada L7, malah pada L4), dan ini mungkin menjejaskan kos (alamat IPv4 statik luaran, kuasa pengkomputeran, pengebilan sesaat ) kerana keperluan untuk mencipta sejumlah besar sumber tersebut.

Dalam kes ini, adalah lebih logik untuk menggunakan satu pengimbang beban luaran, membuka perkhidmatan sebagai type: NodePort. Atau lebih baik lagi, kembangkan sesuatu seperti nginx-ingress-controller (Atau traefik), yang akan menjadi satu-satunya NodePort titik akhir yang dikaitkan dengan pengimbang beban luaran dan akan mengarahkan trafik dalam kluster menggunakan kemasukan-Sumber Kubernetes.

Perkhidmatan intra-kluster (mikro) lain yang berinteraksi antara satu sama lain boleh "berkomunikasi" menggunakan perkhidmatan seperti KlusterIP dan mekanisme penemuan perkhidmatan terbina dalam melalui DNS. Cuma jangan gunakan DNS/IP awam mereka, kerana ini boleh memberi kesan kependaman dan meningkatkan kos perkhidmatan awan.

4. Autoscaling gugusan tanpa mengambil kira ciri-cirinya

Apabila menambah nod dan mengalih keluarnya daripada kluster, anda tidak seharusnya bergantung pada beberapa metrik asas seperti penggunaan CPU pada nod tersebut. Perancangan pod mesti mengambil kira banyak perkara sekatan, seperti pertalian pod/nod, kotoran dan toleransi, permintaan sumber, QoS, dsb. Menggunakan autoscaler luaran yang tidak mengambil kira nuansa ini boleh membawa kepada masalah.

Bayangkan bahawa pod tertentu harus dijadualkan, tetapi semua kuasa CPU yang tersedia diminta/dibongkar dan pod terperangkap dalam keadaan Pending. Autoscaler luaran melihat purata beban CPU semasa (bukan yang diminta) dan tidak memulakan pengembangan (perkecilan) - tidak menambah nod lain. Akibatnya, pod ini tidak akan dijadualkan.

Dalam kes ini, penskalaan terbalik (skala masuk) β€” mengalih keluar nod daripada kluster sentiasa lebih sukar untuk dilaksanakan. Bayangkan anda mempunyai pod stateful (dengan storan berterusan disambungkan). Jumlah yang berterusan biasanya kepunyaan zon ketersediaan tertentu dan tidak direplikasi di rantau ini. Oleh itu, jika autoscaler luaran memadamkan nod dengan pod ini, maka penjadual tidak akan dapat menjadualkan pod ini pada nod lain, kerana ini hanya boleh dilakukan dalam zon ketersediaan di mana storan berterusan terletak. Pod akan tersangkut di negeri ini Pending.

Sangat popular dalam komuniti Kubernetes cluster-autoscaler. Ia berjalan pada kluster, menyokong API daripada penyedia awan utama, mengambil kira semua sekatan dan boleh berskala dalam kes di atas. Ia juga dapat meningkatkan skala sambil mengekalkan semua had yang ditetapkan, dengan itu menjimatkan wang (yang sebaliknya akan dibelanjakan untuk kapasiti yang tidak digunakan).

5. Mengabaikan keupayaan IAM/RBAC

Berhati-hati menggunakan pengguna IAM dengan rahsia berterusan untuk mesin dan aplikasi. Susun akses sementara menggunakan peranan dan akaun perkhidmatan (akaun perkhidmatan).

Kami sering menghadapi hakikat bahawa kunci akses (dan rahsia) dikodkan keras dalam konfigurasi aplikasi, serta mengabaikan penggiliran rahsia walaupun mempunyai akses kepada Cloud IAM. Gunakan peranan dan akaun perkhidmatan IAM dan bukannya pengguna jika sesuai.

10 Kesilapan Biasa Apabila Menggunakan Kubernetes

Lupakan tentang kube2iam dan pergi terus ke peranan IAM untuk akaun perkhidmatan (seperti yang diterangkan dalam nota dengan nama yang sama Ε tΔ›pΓ‘n VranΓ½):

apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/my-app-role
  name: my-serviceaccount
  namespace: default

Satu anotasi. Tidak begitu sukar, bukan?

Juga, jangan berikan keistimewaan akaun perkhidmatan dan profil contoh admin ΠΈ cluster-adminjika mereka tidak memerlukannya. Ini sedikit lebih sukar untuk dilaksanakan, terutamanya dalam RBAC K8, tetapi pastinya berbaloi dengan usaha.

6. Jangan bergantung pada anti-afiniti automatik untuk pod

Bayangkan anda mempunyai tiga replika beberapa penempatan pada nod. Nod jatuh, dan bersama-sama dengannya semua replika. Keadaan yang tidak menyenangkan, bukan? Tetapi mengapa semua replika berada pada nod yang sama? Bukankah Kubernetes sepatutnya menyediakan ketersediaan tinggi (HA)?!

Malangnya, penjadual Kubernetes, atas inisiatifnya sendiri, tidak mematuhi peraturan kewujudan berasingan (anti-afiniti) untuk buah polong. Mereka mesti dinyatakan dengan jelas:

// ΠΎΠΏΡƒΡ‰Π΅Π½ΠΎ для краткости
      labels:
        app: zk
// ΠΎΠΏΡƒΡ‰Π΅Π½ΠΎ для краткости
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: "app"
                    operator: In
                    values:
                    - zk
              topologyKey: "kubernetes.io/hostname"

Itu sahaja. Sekarang pod akan dijadualkan pada nod yang berbeza (keadaan ini disemak hanya semasa penjadualan, tetapi tidak semasa operasinya - oleh itu requiredDuringSchedulingIgnoredDuringExecution).

Di sini kita bercakap tentang podAntiAffinity pada nod yang berbeza: topologyKey: "kubernetes.io/hostname", - dan bukan tentang zon ketersediaan yang berbeza. Untuk melaksanakan HA sepenuhnya, anda perlu mendalami topik ini.

7. Mengabaikan PodDisruptionBudgets

Bayangkan anda mempunyai beban pengeluaran pada gugusan Kubernetes. Secara berkala, nod dan kluster itu sendiri perlu dikemas kini (atau dinyahaktifkan). PodDisruptionBudget (PDB) ialah sesuatu seperti perjanjian jaminan perkhidmatan antara pentadbir kluster dan pengguna.

PDB membolehkan anda mengelakkan gangguan perkhidmatan yang disebabkan oleh kekurangan nod:

apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  name: zk-pdb
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: zookeeper

Dalam contoh ini, anda, sebagai pengguna kluster, menyatakan kepada pentadbir: "Hei, saya mempunyai perkhidmatan penjaga zoo, dan tidak kira apa yang anda lakukan, saya ingin sekurang-kurangnya 2 replika perkhidmatan ini tersedia pada setiap masa .”

Anda boleh membaca lebih lanjut mengenai ini di sini.

8. Berbilang pengguna atau persekitaran dalam kelompok yang sama

Ruang nama Kubernetes (ruang nama) tidak memberikan penebat yang kuat.

Salah tanggapan yang biasa ialah jika anda menggunakan beban bukan prod ke dalam satu ruang nama dan beban prod ke dalam yang lain, maka ia tidak akan mempengaruhi satu sama lain dalam apa cara sekalipun... Walau bagaimanapun, tahap pengasingan tertentu boleh dicapai menggunakan permintaan/had sumber, menetapkan kuota dan menetapkan keutamaanKelas. Beberapa pengasingan "fizikal" dalam satah data disediakan oleh pertalian, toleransi, kotoran (atau pemilih nod), tetapi pemisahan sedemikian agak sukar melaksanakan.

Mereka yang perlu menggabungkan kedua-dua jenis beban kerja dalam kelompok yang sama perlu berhadapan dengan kerumitan. Jika tidak ada keperluan sedemikian, dan anda mampu untuk memilikinya satu kluster lagi (katakan, dalam awan awam), maka lebih baik berbuat demikian. Ini akan mencapai tahap penebat yang lebih tinggi.

9. Polisi Lalu Lintas luar: Kluster

Selalunya kami memerhatikan bahawa semua trafik di dalam kluster datang melalui perkhidmatan seperti NodePort, yang mana dasar lalainya ditetapkan externalTrafficPolicy: Cluster... Ia bermaksud bahawa NodePort dibuka pada setiap nod dalam kluster, dan anda boleh menggunakan mana-mana nod untuk berinteraksi dengan perkhidmatan yang dikehendaki (set pod).

10 Kesilapan Biasa Apabila Menggunakan Kubernetes

Pada masa yang sama, pod sebenar yang dikaitkan dengan perkhidmatan NodePort yang disebutkan di atas biasanya tersedia hanya pada yang tertentu subset nod ini. Dalam erti kata lain, jika saya menyambung ke nod yang tidak mempunyai pod yang diperlukan, ia akan memajukan trafik ke nod lain, menambah hop dan peningkatan kependaman (jika nod terletak di zon ketersediaan/pusat data yang berbeza, kependaman boleh menjadi agak tinggi; di samping itu, kos trafik jalan keluar akan meningkat).

Sebaliknya, jika perkhidmatan Kubernetes tertentu mempunyai dasar yang ditetapkan externalTrafficPolicy: Local, kemudian NodePort hanya dibuka pada nod tersebut di mana pod yang diperlukan sebenarnya sedang berjalan. Apabila menggunakan pengimbang beban luaran yang menyemak keadaan (pemeriksaan kesihatan) titik akhir (bagaimana ia berlaku AWS ELB), Dia akan menghantar trafik hanya ke nod yang diperlukan, yang akan memberi kesan yang baik pada kelewatan, keperluan pengkomputeran, bil keluar (dan akal fikiran menentukan perkara yang sama).

Terdapat kemungkinan besar anda sudah menggunakan sesuatu seperti itu traefik atau nginx-ingress-controller sebagai titik akhir NodePort (atau LoadBalancer, yang juga menggunakan NodePort) untuk menghalakan trafik masuk HTTP, dan menetapkan pilihan ini boleh mengurangkan kependaman untuk permintaan sedemikian dengan ketara.

Π’ penerbitan ini Anda boleh mengetahui lebih lanjut tentang externalTrafficPolicy, kelebihan dan kekurangannya.

10. Jangan terikat dengan kelompok dan jangan menyalahgunakan pesawat kawalan

Sebelum ini, adalah kebiasaan untuk memanggil pelayan dengan nama yang betul: Anton, HAL9000 dan Colossus... Hari ini ia telah digantikan dengan pengecam yang dijana secara rawak. Walau bagaimanapun, tabiat itu kekal, dan kini nama yang betul pergi ke kelompok.

Cerita biasa (berdasarkan peristiwa sebenar): semuanya bermula dengan bukti konsep, jadi gugusan itu mempunyai nama yang membanggakan ujian... Tahun telah berlalu dan ia MASIH digunakan dalam pengeluaran, dan semua orang takut untuk menyentuhnya.

Tiada apa-apa yang menyeronokkan tentang kluster yang bertukar menjadi haiwan peliharaan, jadi kami mengesyorkan mengalihkannya secara berkala semasa berlatih pemulihan bencana (ini akan membantu kejuruteraan huru-hara - lebih kurang terjemah.). Di samping itu, ia tidak rugi untuk bekerja pada lapisan kawalan (kapal terbang kawalan). Takut untuk menyentuhnya bukanlah petanda yang baik. dll mati? Kawan-kawan, kamu benar-benar dalam masalah!

Sebaliknya, anda tidak seharusnya terbawa-bawa dengan memanipulasinya. Dengan masa lapisan kawalan mungkin menjadi perlahan. Kemungkinan besar, ini disebabkan oleh sejumlah besar objek yang dicipta tanpa putarannya (situasi biasa apabila menggunakan Helm dengan tetapan lalai, itulah sebabnya keadaannya dalam peta konfigurasi/rahsia tidak dikemas kini - akibatnya, beribu-ribu objek terkumpul dalam lapisan kawalan) atau dengan penyuntingan berterusan objek kube-api (untuk penskalaan automatik, untuk CI/CD, untuk pemantauan, log peristiwa, pengawal, dsb.).

Selain itu, kami mengesyorkan agar anda menyemak perjanjian SLA/SLO dengan penyedia Kubernetes terurus dan memberi perhatian kepada jaminan. Penjual boleh memberi jaminan ketersediaan lapisan kawalan (atau subkomponennya), tetapi bukan kelewatan p99 permintaan yang anda hantar kepadanya. Dengan kata lain, anda boleh masuk kubectl get nodes, dan terima jawapan hanya selepas 10 minit, dan ini tidak akan melanggar syarat perjanjian perkhidmatan.

11. Bonus: menggunakan tag terkini

Tetapi ini sudah menjadi klasik. Akhir-akhir ini kami jarang menemui teknik ini, kerana ramai, setelah belajar dari pengalaman pahit, telah berhenti menggunakan tag :latest dan mula menyemat versi. Hooray!

ECR mengekalkan kebolehubahan tag imej; Kami mengesyorkan agar anda membiasakan diri dengan ciri yang luar biasa ini.

Ringkasan

Jangan mengharapkan segala-galanya berfungsi dalam sekelip mata: Kubernetes bukanlah ubat penawar. Apl buruk akan kekal seperti ini walaupun dalam Kubernetes (dan ia mungkin akan menjadi lebih teruk). Kecuaian akan membawa kepada kerumitan yang berlebihan, kerja lapisan kawalan yang perlahan dan tekanan. Selain itu, anda berisiko ditinggalkan tanpa strategi pemulihan bencana. Jangan harap Kubernetes menyediakan pengasingan dan ketersediaan tinggi di luar kotak. Luangkan sedikit masa menjadikan aplikasi anda benar-benar asli awan.

Anda boleh berkenalan dengan pengalaman tidak berjaya dari pelbagai pasukan di koleksi cerita ini oleh Henning Jacobs.

Mereka yang ingin menambah senarai ralat yang diberikan dalam artikel ini boleh menghubungi kami di Twitter (@MarekBartik, @MstrsObserver).

PS daripada penterjemah

Baca juga di blog kami:

Sumber: www.habr.com

Tambah komen