Sembilan Tips Performa Kubernetes

Sembilan Tips Performa Kubernetes

Halo semua! Nama saya Oleg Sidorenkov, saya bekerja di DomClick sebagai pemimpin tim infrastruktur. Kami telah menggunakan Cube untuk dijual selama lebih dari tiga tahun, dan selama ini kami telah mengalami banyak momen menarik yang berbeda dengannya. Hari ini saya akan memberi tahu Anda bagaimana, dengan pendekatan yang tepat, Anda dapat memeras lebih banyak lagi kinerja dari vanilla Kubernetes untuk kluster Anda. Siap mantap berangkat!

Anda semua tahu betul bahwa Kubernetes adalah sistem sumber terbuka yang dapat diskalakan untuk orkestrasi wadah; baik, atau 5 binari yang melakukan keajaiban dengan mengelola siklus hidup layanan mikro Anda di lingkungan server. Selain itu, ini adalah alat yang cukup fleksibel yang dapat dirangkai seperti konstruktor Lego untuk penyesuaian maksimum untuk berbagai tugas.

Dan semuanya tampak baik-baik saja: lempar server ke dalam cluster, seperti kayu bakar ke dalam kotak api, dan tidak tahu kesedihan. Tetapi jika Anda untuk lingkungan, maka Anda akan berpikir: "Bagaimana saya bisa menjaga api di tungku dan menyesali hutan?". Dengan kata lain, bagaimana menemukan cara untuk meningkatkan infrastruktur dan mengurangi biaya.

1. Lacak sumber daya tim dan aplikasi

Sembilan Tips Performa Kubernetes

Salah satu metode yang paling dangkal namun efektif adalah pengenalan permintaan/batasan. Pisahkan aplikasi menurut ruang nama, dan ruang nama menurut tim pengembangan. Setel aplikasi sebelum menerapkan nilai untuk konsumsi waktu prosesor, memori, penyimpanan sementara.

resources:
   requests:
     memory: 2Gi
     cpu: 250m
   limits:
     memory: 4Gi
     cpu: 500m

Berdasarkan pengalaman, kami sampai pada kesimpulan: tidak ada gunanya menaikkan permintaan dari batas lebih dari dua kali lipat. Ukuran cluster dihitung berdasarkan permintaan, dan jika Anda menyetel aplikasi ke perbedaan sumber daya, misalnya, 5-10 kali lipat, bayangkan apa yang akan terjadi pada node Anda ketika diisi dengan pod dan tiba-tiba menerima beban. Tidak ada yang baik. Minimal, pelambatan, dan maksimal, ucapkan selamat tinggal kepada pekerja dan dapatkan beban siklik di node lainnya setelah pod mulai bergerak.

Selain itu, dengan bantuan limitranges Anda dapat menetapkan nilai sumber daya untuk wadah di awal - minimum, maksimum, dan default:

➜  ~ kubectl describe limitranges --namespace ops
Name:       limit-range
Namespace:  ops
Type        Resource           Min   Max   Default Request  Default Limit  Max Limit/Request Ratio
----        --------           ---   ---   ---------------  -------------  -----------------------
Container   cpu                50m   10    100m             100m           2
Container   ephemeral-storage  12Mi  8Gi   128Mi            4Gi            -
Container   memory             64Mi  40Gi  128Mi            128Mi          2

Ingatlah untuk membatasi sumber daya namespace sehingga satu perintah tidak dapat mengambil semua sumber daya cluster:

➜  ~ kubectl describe resourcequotas --namespace ops
Name:                   resource-quota
Namespace:              ops
Resource                Used          Hard
--------                ----          ----
limits.cpu              77250m        80
limits.memory           124814367488  150Gi
pods                    31            45
requests.cpu            53850m        80
requests.memory         75613234944   150Gi
services                26            50
services.loadbalancers  0             0
services.nodeports      0             0

Seperti yang Anda lihat dari deskripsi resourcequotas, jika perintah ops ingin menyebarkan pod yang akan menggunakan 10 cpu lagi, maka penjadwal tidak akan mengizinkannya dilakukan dan akan mengeluarkan kesalahan:

Error creating: pods "nginx-proxy-9967d8d78-nh4fs" is forbidden: exceeded quota: resource-quota, requested: limits.cpu=5,requests.cpu=5, used: limits.cpu=77250m,requests.cpu=53850m, limited: limits.cpu=10,requests.cpu=10

Untuk mengatasi masalah serupa, Anda dapat menulis alat, misalnya sebagai ini, yang dapat menyimpan dan mengkomit status sumber daya perintah.

2. Pilih penyimpanan file terbaik

Sembilan Tips Performa Kubernetes

Di sini saya ingin menyentuh topik volume persisten dan subsistem disk dari node pekerja Kubernetes. Saya harap tidak ada yang menggunakan "Cube" pada HDD dalam produksi, tetapi terkadang bahkan SSD biasa saja tidak cukup. Kami menghadapi masalah sedemikian rupa sehingga log mematikan disk dengan operasi I / O, dan tidak banyak solusi di sini:

  • Gunakan SSD berperforma tinggi atau beralih ke NVMe (jika Anda mengelola perangkat keras Anda sendiri).

  • Turunkan level logging.

  • Lakukan penyeimbangan "pintar" dari pod yang memperkosa disk (podAntiAffinity).

Tangkapan layar di atas menunjukkan apa yang terjadi di bawah nginx-ingress-controller dengan disk saat access_logs diaktifkan (~12k log/detik). Keadaan seperti itu, tentu saja, dapat menyebabkan degradasi semua aplikasi di node ini.

Untuk PV, sayangnya, saya belum mencoba semuanya. macam-macam Volume yang terus-menerus. Gunakan opsi terbaik yang cocok untuk Anda. Secara historis terjadi di negara kita bahwa sebagian kecil layanan membutuhkan volume RWX, dan sejak lama mereka mulai menggunakan penyimpanan NFS untuk tugas ini. Murah dan ... cukup. Tentu saja, kami makan kotoran dengannya - jadilah sehat, tetapi kami belajar cara menyetelnya, dan kepalanya tidak lagi sakit. Dan jika memungkinkan, alihkan ke penyimpanan objek S3.

3. Bangun Gambar yang Dioptimalkan

Sembilan Tips Performa Kubernetes

Sebaiknya gunakan gambar yang dioptimalkan untuk wadah agar Kubernet dapat mengambilnya lebih cepat dan menjalankannya dengan lebih efisien. 

Pengoptimalan berarti bahwa gambar:

  • hanya berisi satu aplikasi atau hanya menjalankan satu fungsi;

  • ukuran kecil, karena gambar besar ditransmisikan lebih buruk melalui jaringan;

  • memiliki endpoint kesehatan dan kesiapan yang dapat digunakan Kubernetes untuk mengambil tindakan jika terjadi downtime;

  • gunakan sistem operasi ramah wadah (seperti Alpine atau CoreOS) yang lebih tahan terhadap kesalahan konfigurasi;

  • gunakan build multi-tahap sehingga Anda hanya dapat menerapkan aplikasi yang dikompilasi dan bukan sumber yang menyertainya.

Ada banyak alat dan layanan yang memungkinkan Anda memeriksa dan mengoptimalkan gambar dengan cepat. Penting untuk selalu memperbaruinya dan aman. Akibatnya, Anda mendapatkan:

  1. Mengurangi beban jaringan di seluruh cluster.

  2. Penurunan waktu startup kontainer.

  3. Ukuran lebih kecil dari seluruh registri Docker Anda.

4. Gunakan cache DNS

Sembilan Tips Performa Kubernetes

Jika kita berbicara tentang beban tinggi, maka tanpa menyetel sistem DNS cluster, hidup menjadi sangat buruk. Dahulu kala, pengembang Kubernetes mendukung solusi kube-dns mereka. Itu juga diterapkan di negara kita, tetapi perangkat lunak ini tidak terlalu selaras dan tidak memberikan kinerja yang diperlukan, meskipun tampaknya tugasnya sederhana. Kemudian coredns muncul, yang kami alihkan dan tidak tahu duka, kemudian menjadi layanan DNS default di K8s. Pada titik tertentu, kami meningkatkan hingga 40 ribu rps ke sistem DNS, dan solusi ini juga tidak cukup. Tapi, secara kebetulan, Nodelocaldns keluar, alias cache lokal node, alias DNSCache NodeLokal.

Mengapa kita menggunakan ini? Pada intinya Linux Terdapat bug yang, ketika beberapa permintaan dilakukan melalui NAT Conntrack melalui UDP, menyebabkan kondisi persaingan (race condition) untuk entri dalam tabel Conntrack, dan sebagian lalu lintas melalui NAT hilang (setiap hop melalui Layanan adalah NAT). Nodelocaldns menyelesaikan masalah ini dengan menghilangkan NAT dan meningkatkan koneksi ke TCP untuk DNS upstream, serta caching lokal permintaan DNS ke DNS upstream (termasuk cache negatif singkat selama 5 detik).

5. Menskalakan pod secara horizontal dan vertikal secara otomatis

Sembilan Tips Performa Kubernetes

Dapatkah Anda mengatakan dengan yakin bahwa semua layanan mikro Anda siap untuk peningkatan beban dua hingga tiga kali lipat? Bagaimana cara mengalokasikan sumber daya dengan benar ke aplikasi Anda? Mempertahankan beberapa pod yang berjalan melebihi beban kerja dapat menjadi mubazir, dan menjaganya dari belakang ke belakang berisiko mengalami downtime karena peningkatan lalu lintas yang tiba-tiba ke layanan. Rata-rata emas membantu mencapai mantra penggandaan layanan seperti Penskala Otomatis Pod Horisontal и Penskala Otomatis Pod Vertikal.

VPA memungkinkan Anda untuk secara otomatis menaikkan permintaan/batas wadah Anda di pod berdasarkan penggunaan sebenarnya. Bagaimana ini bisa berguna? Jika Anda memiliki Pod yang karena alasan tertentu tidak dapat diskalakan secara horizontal (yang tidak sepenuhnya dapat diandalkan), maka Anda dapat mencoba memercayai VPA untuk mengubah sumber dayanya. Fiturnya adalah sistem rekomendasi berdasarkan data historis dan terkini dari server metrik, jadi jika Anda tidak ingin mengubah permintaan/batasan secara otomatis, Anda cukup memantau sumber daya yang direkomendasikan untuk wadah Anda dan mengoptimalkan pengaturan untuk menghemat CPU dan memori dalam klaster.

Sembilan Tips Performa KubernetesGambar diambil dari https://levelup.gitconnected.com/kubernetes-autoscaling-101-cluster-autoscaler-horizontal-pod-autoscaler-and-vertical-pod-2a441d9ad231

Penjadwal di Kubernetes selalu berdasarkan permintaan. Nilai apa pun yang Anda masukkan di sana, penjadwal akan mencari node yang sesuai berdasarkan itu. Nilai batas diperlukan oleh kublet untuk mengetahui kapan harus mencekik atau membunuh pod. Dan karena satu-satunya parameter penting adalah nilai permintaan, VPA akan bekerja dengannya. Setiap kali Anda menskalakan aplikasi secara vertikal, Anda menentukan permintaan apa yang seharusnya. Dan apa yang akan terjadi pada limit? Parameter ini juga akan diskalakan secara proporsional.

Misalnya, berikut adalah pengaturan pod yang khas:

resources:
   requests:
     memory: 250Mi
     cpu: 200m
   limits:
     memory: 500Mi
     cpu: 350m

Mesin rekomendasi menentukan bahwa aplikasi Anda membutuhkan CPU 300m dan 500Mi untuk berjalan dengan baik. Anda akan mendapatkan pengaturan ini:

resources:
   requests:
     memory: 500Mi
     cpu: 300m
   limits:
     memory: 1000Mi
     cpu: 525m

Seperti disebutkan di atas, ini adalah penskalaan proporsional berdasarkan rasio permintaan/batas dalam manifes:

  • CPU: 200m → 300m: rasio 1:1.75;

  • Memori: 250Mi → 500Mi: rasio 1:2.

mengenai HPA, maka mekanisme pengoperasiannya lebih transparan. Ambang batas ditetapkan untuk metrik seperti prosesor dan memori, dan jika rata-rata semua replika melebihi ambang batas, aplikasi akan diskalakan dengan +1 pod hingga nilainya turun di bawah ambang batas, atau hingga jumlah maksimum replika tercapai.

Sembilan Tips Performa KubernetesGambar diambil dari https://levelup.gitconnected.com/kubernetes-autoscaling-101-cluster-autoscaler-horizontal-pod-autoscaler-and-vertical-pod-2a441d9ad231

Selain metrik biasa seperti CPU dan Memori, Anda dapat menetapkan ambang batas pada metrik Prometheus kustom Anda dan bekerja dengannya jika Anda merasa ini adalah cara paling akurat untuk menentukan kapan harus menskalakan aplikasi Anda. Setelah aplikasi stabil di bawah ambang batas metrik yang ditentukan, HPA akan mulai menurunkan Pod ke jumlah minimum replika atau hingga beban memenuhi ambang batas.

6. Jangan Lupa Tentang Afinitas Node dan Afinitas Pod

Sembilan Tips Performa Kubernetes

Tidak semua node berjalan pada perangkat keras yang sama, dan tidak semua pod perlu menjalankan aplikasi intensif komputasi. Kubernetes memungkinkan Anda menentukan spesialisasi node dan pod menggunakan Afinitas Node и Afinitas Pod.

Jika Anda memiliki node yang cocok untuk operasi intensif komputasi, maka untuk efisiensi maksimum, lebih baik ikat aplikasi ke node yang sesuai. Untuk melakukan ini, gunakan nodeSelector dengan label simpul.

Katakanlah Anda memiliki dua node: satu dengan CPUType=HIGHFREQ dan sejumlah besar inti cepat, lainnya dengan MemoryType=HIGHMEMORY lebih banyak memori dan kinerja lebih cepat. Cara termudah adalah dengan menetapkan penerapan pod ke sebuah node HIGHFREQdengan menambahkan ke bagian spec pemilih seperti ini:

…
nodeSelector:
	CPUType: HIGHFREQ

Cara yang lebih mahal dan spesifik untuk melakukan ini adalah dengan menggunakan nodeAffinity di lapangan affinity аздела spec. Ada dua opsi:

  • requiredDuringSchedulingIgnoredDuringExecution: pengaturan keras (penjadwal hanya akan menerapkan pod pada node tertentu (dan tidak di tempat lain));

  • preferredDuringSchedulingIgnoredDuringExecution: pengaturan lunak (penjadwal akan mencoba menerapkan ke node tertentu, dan jika gagal, ia akan mencoba menerapkan ke node berikutnya yang tersedia).

Anda dapat menentukan sintaks khusus untuk mengelola label simpul, misalnya, In, NotIn, Exists, DoesNotExist, Gt или Lt. Namun, ingatlah bahwa metode rumit dalam daftar label yang panjang akan memperlambat pengambilan keputusan dalam situasi kritis. Dengan kata lain, jangan terlalu rumit.

Seperti disebutkan di atas, Kubernetes memungkinkan Anda mengatur pengikatan pod saat ini. Artinya, Anda dapat membuat pod tertentu bekerja sama dengan pod lain di zona ketersediaan yang sama (relevan untuk cloud) atau node.

В podAffinity поля affinity аздела spec bidang yang sama tersedia seperti dalam kasus nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution и preferredDuringSchedulingIgnoredDuringExecution. Satu-satunya perbedaan adalah itu matchExpressions akan mengikat pod ke node yang sudah menjalankan pod dengan label tersebut.

Lebih banyak Kubernet menawarkan bidang podAntiAffinity, yang, sebaliknya, tidak mengikat sebuah pod ke sebuah node dengan pod tertentu.

Tentang ekspresi nodeAffinity Nasihat yang sama dapat diberikan: cobalah untuk menjaga aturan tetap sederhana dan logis, jangan mencoba membebani spesifikasi pod dengan seperangkat aturan yang rumit. Sangat mudah untuk membuat aturan yang tidak sesuai dengan kondisi klaster, memberikan beban ekstra pada penjadwal dan menurunkan kinerja secara keseluruhan.

7. Noda & Toleransi

Ada cara lain untuk mengelola penjadwal. Jika Anda memiliki klaster besar dengan ratusan node dan ribuan layanan mikro, sangat sulit untuk mencegah pod tertentu dihosting oleh node tertentu.

Mekanisme noda - aturan larangan - membantu dalam hal ini. Misalnya, Anda dapat mencegah node tertentu menjalankan pod dalam skenario tertentu. Untuk menerapkan taint ke node tertentu, gunakan opsi taint di kubectl. Tentukan key dan value lalu taint like NoSchedule или NoExecute:

$ kubectl taint nodes node10 node-role.kubernetes.io/ingress=true:NoSchedule

Perlu juga dicatat bahwa mekanisme noda mendukung tiga efek utama: NoSchedule, NoExecute и PreferNoSchedule.

  • NoSchedule berarti sampai ada entri yang sesuai dalam spesifikasi pod tolerations, itu tidak dapat diterapkan ke node (dalam contoh ini node10).

  • PreferNoSchedule - versi yang disederhanakan NoSchedule. Dalam hal ini, penjadwal akan mencoba untuk tidak mengalokasikan pod yang tidak memiliki entri yang cocok. tolerations per node, tapi ini bukan batas keras. Jika tidak ada sumber daya di kluster, maka pod akan mulai diterapkan di node ini.

  • NoExecute - efek ini memicu evakuasi langsung dari pod yang tidak memiliki entri yang cocok tolerations.

Anehnya, perilaku ini dapat diurungkan menggunakan mekanisme toleransi. Ini nyaman ketika ada node "terlarang" dan Anda hanya perlu menempatkan layanan infrastruktur di atasnya. Bagaimana cara melakukannya? Izinkan hanya pod yang memiliki toleransi yang sesuai.

Berikut tampilan spek pod:

spec:
   tolerations:
     - key: "node-role.kubernetes.io/ingress"
        operator: "Equal"
        value: "true"
        effect: "NoSchedule"

Ini tidak berarti bahwa selama redeploy berikutnya, pod akan tepat mengenai node ini, ini bukan mekanisme Afinitas Node dan nodeSelector. Namun dengan menggabungkan beberapa fitur, Anda dapat mencapai pengaturan penjadwalan yang sangat fleksibel.

8. Tetapkan Prioritas Penerapan Pod

Hanya karena Anda telah mengonfigurasi binding pod-ke-node tidak berarti bahwa semua pod harus diperlakukan dengan prioritas yang sama. Misalnya, Anda mungkin ingin menerapkan beberapa Pod sebelum yang lain.

Kubernetes menawarkan berbagai cara untuk menetapkan Prioritas dan Preemption Pod. Latar terdiri dari beberapa bagian: objek PriorityClass dan deskripsi lapangan priorityClassName dalam spesifikasi pod. Pertimbangkan sebuah contoh:

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: high-priority
value: 99999
globalDefault: false
description: "This priority class should be used for very important pods only"

Kami membuat PriorityClass, beri nama, deskripsi, dan nilai. Semakin tinggi value, semakin tinggi prioritasnya. Nilainya bisa berupa bilangan bulat 32-bit yang kurang dari atau sama dengan 1. Nilai yang lebih tinggi dicadangkan untuk pod sistem kritis, yang biasanya tidak dapat didahului. Pengusiran hanya akan terjadi jika pod dengan prioritas tinggi tidak memiliki tempat untuk berbalik, maka beberapa pod dari node tertentu akan dievakuasi. Jika mekanisme ini terlalu kaku untuk Anda, maka Anda dapat menambahkan opsi preemptionPolicy: Never, dan kemudian tidak akan ada preemption, pod akan menjadi yang pertama dalam antrean dan menunggu penjadwal menemukan sumber daya gratis untuknya.

Selanjutnya, kami membuat pod, di mana kami menentukan namanya priorityClassName:

apiVersion: v1
kind: Pod
metadata:
  name: static-web
  labels:
    role: myrole
 spec:
  containers:
    - name: web
      image: nginx
      ports:
        - name: web
          containerPort: 80
          protocol: TCP
  priorityClassName: high-priority
          

Anda dapat membuat kelas prioritas sebanyak yang Anda suka, meskipun disarankan untuk tidak terbawa oleh ini (katakanlah, batasi diri Anda pada prioritas rendah, sedang, dan tinggi).

Jadi, jika perlu, Anda dapat meningkatkan efisiensi penerapan layanan penting, seperti nginx-ingress-controller, coredns, dll.

9. Optimalkan klaster ETCD Anda

Sembilan Tips Performa Kubernetes

ETCD bisa disebut sebagai otak dari seluruh cluster. Sangat penting untuk menjaga operasi database ini pada level tinggi, karena kecepatan operasi di "Cube" bergantung padanya. Cukup standar, dan pada saat yang sama, solusi yang baik adalah dengan mempertahankan cluster ETCD pada node master agar memiliki penundaan minimum ke kube-apiserver. Jika ini tidak memungkinkan, tempatkan ETCD sedekat mungkin, dengan bandwidth yang baik antar peserta. Perhatikan juga berapa banyak node dari ETCD yang dapat jatuh tanpa merusak cluster.

Sembilan Tips Performa Kubernetes

Perlu diingat bahwa peningkatan jumlah peserta yang berlebihan dalam kluster dapat meningkatkan toleransi kesalahan dengan mengorbankan kinerja, semuanya harus secukupnya.

Jika kita berbicara tentang menyiapkan layanan, maka ada beberapa rekomendasi:

  1. Memiliki perangkat keras yang bagus, berdasarkan ukuran cluster (Anda dapat membaca di sini).

  2. Tweak beberapa parameter jika Anda telah menyebarkan cluster antara sepasang DC atau jaringan dan disk Anda meninggalkan banyak hal yang diinginkan (Anda dapat membaca di sini).

Kesimpulan

Artikel ini menjelaskan poin-poin yang coba dipatuhi oleh tim kami. Ini bukan deskripsi tindakan langkah demi langkah, tetapi opsi yang dapat berguna untuk mengoptimalkan overhead cluster. Jelas bahwa setiap klaster unik dengan caranya sendiri, dan solusi penyetelan bisa sangat bervariasi, jadi akan menarik untuk mendapatkan umpan balik dari Anda: bagaimana Anda memantau klaster Kubernetes Anda, bagaimana Anda meningkatkan kinerjanya. Bagikan pengalaman Anda di komentar, akan menarik untuk mengetahuinya.

Sumber: www.habr.com

Beli hosting yang andal untuk situs dengan perlindungan DDoS, server VPS VDS 🔥 Beli hosting website andal dengan perlindungan DDoS, server VPS VDS | ProHoster