View a markdown version of this page

Pesawat Kontrol Kubernetes - Amazon EKS

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

Pesawat Kontrol Kubernetes

Tip

Jelaj ahi praktik terbaik melalui lokakarya Amazon EKS.

Bidang kontrol Kubernetes terdiri dari Kubernetes API Server, Kubernetes Controller Manager, Scheduler dan komponen lain yang diperlukan agar Kubernetes berfungsi. Batas skalabilitas komponen ini berbeda tergantung pada apa yang Anda jalankan di cluster, tetapi area dengan dampak terbesar terhadap penskalaan termasuk versi Kubernetes, pemanfaatan, dan penskalaan Node individual.

Anda dapat menjalankan bidang kontrol cluster Anda dalam salah satu dari dua mode untuk memenuhi persyaratan beban kerja yang berbeda:

  • Mode standar — Secara default, semua cluster EKS menggunakan mode Standar. Bidang kontrol secara otomatis menskalakan naik dan turun berdasarkan tuntutan beban kerja Anda. Mode standar secara dinamis mengalokasikan kapasitas bidang kontrol yang cukup dan merupakan opsi yang disarankan untuk sebagian besar kasus penggunaan.

  • Mode yang disediakan — Jika beban kerja Anda tidak dapat mentolerir variabilitas kinerja dari penskalaan bidang kontrol, atau jika beban kerja memerlukan kapasitas bidang kontrol yang sangat tinggi, Anda dapat menggunakan mode Penyediaan. Dengan mode Penyediaan, Anda melakukan pra-alokasi kapasitas pesawat kontrol yang selalu siap untuk menangani persyaratan yang menuntut. Anda mendapatkan kinerja yang konsisten dan dapat diprediksi.

Dengan mode EKS Provisioned, Anda memilih dari serangkaian tingkatan penskalaan (XL, 2XL, 4XL, dan 8XL). Dengan setiap tingkat, Anda mendapatkan kinerja tinggi dan dapat diprediksi dari bidang kontrol cluster. Mode yang disediakan sangat berharga untuk kasus penggunaan berikut:

  • Performance-critical beban kerja

  • Large-scale Operasi AI dan pembelajaran mesin

  • Acara dengan permintaan tinggi yang diantisipasi

  • Lingkungan yang membutuhkan konsistensi di seluruh pementasan dan produksi

Dengan mode Penyediaan, Anda dapat mengalokasikan kapasitas pesawat kontrol sebelumnya dan mendapatkan manfaat dari Perjanjian Tingkat Layanan (SLA) 99,99% yang ditingkatkan yang diukur dalam interval 1 menit. Untuk informasi selengkapnya tentang mode Penyediaan EKS, termasuk spesifikasi tingkat dan harga, lihat EKS Provisioned Control Plane di Panduan Pengguna EKS.

Batasi beban kerja dan ledakan simpul

penting

Untuk menghindari mencapai batas API pada bidang kontrol, Anda harus membatasi lonjakan penskalaan yang meningkatkan ukuran cluster dengan persentase dua digit pada satu waktu (misalnya 1000 node hingga 1100 node atau 4000 hingga 4500 pod sekaligus).

Bidang kontrol EKS akan secara otomatis berskala saat cluster Anda tumbuh, tetapi ada batasan seberapa cepat skalanya. Ketika Anda pertama kali membuat cluster EKS, Control Plane tidak akan segera dapat menskalakan ke ratusan node atau ribuan pod. Untuk membaca lebih lanjut tentang bagaimana EKS telah melakukan peningkatan penskalaan, lihat posting blog ini.

Penskalaan aplikasi besar membutuhkan infrastruktur untuk beradaptasi agar siap sepenuhnya (misalnya penyeimbang beban pemanasan). Untuk mengontrol kecepatan penskalaan, pastikan Anda melakukan penskalaan berdasarkan metrik yang tepat untuk aplikasi Anda. Penskalaan CPU dan memori mungkin tidak secara akurat memprediksi kendala aplikasi Anda dan menggunakan metrik khusus (misalnya permintaan per detik) di Kubernetes Horizontal Pod Autoscaler (HPA) mungkin merupakan opsi penskalaan yang lebih baik.

Untuk menggunakan metrik khusus lihat contoh dalam dokumentasi Kubernetes. Jika Anda memiliki kebutuhan penskalaan yang lebih maju atau perlu menskalakan berdasarkan sumber eksternal (misalnya antrian AWS SQS), gunakan KEDA untuk penskalaan beban kerja berbasis peristiwa.

Menskalakan node dan pod dengan aman

Ganti instance yang berjalan lama

Mengganti node secara teratur membuat cluster Anda tetap sehat dengan menghindari penyimpangan konfigurasi dan masalah yang hanya terjadi setelah waktu aktif yang diperpanjang (misalnya kebocoran memori yang lambat). Penggantian otomatis akan memberi Anda proses dan praktik yang baik untuk peningkatan node dan tambalan keamanan. Jika setiap node di cluster Anda diganti secara teratur maka ada lebih sedikit kerja keras yang diperlukan untuk mempertahankan proses terpisah untuk pemeliharaan berkelanjutan.

Gunakan pengaturan waktu hidup (TTL) Karpenter untuk mengganti instance setelah berjalan selama jangka waktu tertentu. Grup node yang dikelola sendiri dapat menggunakan max-instance-lifetime pengaturan untuk memutar node secara otomatis. Grup node terkelola saat ini tidak memiliki fitur ini tetapi Anda dapat melacak permintaan di sini GitHub.

Hapus node yang kurang dimanfaatkan

Anda dapat menghapus node ketika mereka tidak memiliki beban kerja yang sedang berjalan menggunakan ambang batas penurunan skala di Kubernetes Cluster Autoscaler dengan --scale-down-utilization-threshold atau di Karpenter Anda dapat menggunakan pengaturan penyediaan. ttlSecondsAfterEmpty

Gunakan anggaran gangguan pod dan penghentian node yang aman

Menghapus pod dan node dari cluster Kubernetes memerlukan pengontrol untuk melakukan pembaruan ke beberapa sumber daya (mis.). EndpointSlices Melakukan hal ini sering atau terlalu cepat dapat menyebabkan pelambatan server API dan pemadaman aplikasi saat perubahan menyebar ke pengontrol. Anggaran Gangguan Pod adalah praktik terbaik untuk memperlambat churn guna melindungi ketersediaan beban kerja saat node dihapus atau dijadwal ulang dalam cluster.

Gunakan Client-Side Cache saat menjalankan Kubectl

Menggunakan perintah kubectl secara tidak efisien dapat menambahkan beban tambahan ke Server API Kubernetes. Anda harus menghindari menjalankan skrip atau otomatisasi yang menggunakan kubectl berulang kali (misalnya dalam for loop) atau menjalankan perintah tanpa cache lokal.

kubectlmemiliki cache sisi klien yang menyimpan informasi penemuan dari cluster untuk mengurangi jumlah panggilan API yang diperlukan. Cache diaktifkan secara default dan diperbarui setiap 10 menit.

Jika Anda menjalankan kubectl dari wadah atau tanpa cache sisi klien, Anda mungkin mengalami masalah pelambatan API. Disarankan untuk mempertahankan cache cluster Anda dengan memasang --cache-dir untuk menghindari melakukan panggilan API yang tidak diperlukan.

Nonaktifkan kompresi kubectl

Menonaktifkan kompresi kubectl di file kubeconfig Anda dapat mengurangi penggunaan API dan CPU klien. Secara default server akan mengompres data yang dikirim ke klien untuk mengoptimalkan bandwidth jaringan. Ini menambah beban CPU pada klien dan server untuk setiap permintaan dan menonaktifkan kompresi dapat mengurangi overhead dan latensi jika Anda memiliki bandwidth yang memadai. Untuk menonaktifkan kompresi, Anda dapat menggunakan --disable-compression=true flag atau set disable-compression: true di file kubeconfig Anda.

apiVersion: v1
clusters:
- cluster:
    server: serverURL
    disable-compression: true
  name: cluster

Shard Cluster Autoscaler

Kubernetes Cluster Autoscaler telah diuji untuk menskalakan hingga 1000 node. Pada cluster besar dengan lebih dari 1000 node, disarankan untuk menjalankan beberapa instance Cluster Autoscaler dalam mode shard. Setiap instance Cluster Autoscaler dikonfigurasi untuk menskalakan satu set grup node. Contoh berikut menunjukkan 2 konfigurasi penskalaan otomatis cluster yang dikonfigurasi untuk setiap skala 4 grup node.

ClusterAutoscaler-1

autoscalingGroups:
- name: eks-core-node-grp-20220823190924690000000011-80c1660e-030d-476d-cb0d-d04d585a8fcb
  maxSize: 50
  minSize: 2
- name: eks-data_m1-20220824130553925600000011-5ec167fa-ca93-8ca4-53a5-003e1ed8d306
  maxSize: 450
  minSize: 2
- name: eks-data_m2-20220824130733258600000015-aac167fb-8bf7-429d-d032-e195af4e25f5
  maxSize: 450
  minSize: 2
- name: eks-data_m3-20220824130553914900000003-18c167fa-ca7f-23c9-0fea-f9edefbda002
  maxSize: 450
  minSize: 2

ClusterAutoscaler-2

autoscalingGroups:
- name: eks-data_m4-2022082413055392550000000f-5ec167fa-ca86-6b83-ae9d-1e07ade3e7c4
  maxSize: 450
  minSize: 2
- name: eks-data_m5-20220824130744542100000017-02c167fb-a1f7-3d9e-a583-43b4975c050c
  maxSize: 450
  minSize: 2
- name: eks-data_m6-2022082413055392430000000d-9cc167fa-ca94-132a-04ad-e43166cef41f
  maxSize: 450
  minSize: 2
- name: eks-data_m7-20220824130553921000000009-96c167fa-ca91-d767-0427-91c879ddf5af
  maxSize: 450
  minSize: 2

Prioritas dan Keadilan API

APF

Gambaran umum

Untuk melindungi diri dari kelebihan beban selama periode permintaan yang meningkat, Server API membatasi jumlah permintaan dalam penerbangan yang dapat diselesaikan pada waktu tertentu. Setelah batas ini terlampaui, API Server akan mulai menolak permintaan dan mengembalikan kode respons 429 HTTP untuk “Terlalu Banyak Permintaan” kembali ke klien. Server menghentikan permintaan dan meminta klien mencoba lagi nanti lebih baik daripada tidak memiliki batasan sisi server pada jumlah permintaan dan membebani bidang kontrol, yang dapat mengakibatkan penurunan kinerja atau tidak ketersediaan.

Mekanisme yang digunakan oleh Kubernetes untuk mengonfigurasi bagaimana permintaan penerbangan ini dibagi di antara jenis permintaan yang berbeda disebut Prioritas dan Keadilan API. Server API mengonfigurasi jumlah total permintaan dalam penerbangan yang dapat diterimanya dengan menjumlahkan nilai-nilai yang ditentukan oleh flag and. --max-requests-inflight --max-mutating-requests-inflight EKS menggunakan nilai default 400 dan 200 permintaan untuk bendera ini, memungkinkan total 600 permintaan dikirim pada waktu tertentu. Namun, karena menskalakan bidang kontrol ke ukuran yang lebih besar sebagai respons terhadap peningkatan pemanfaatan dan churn beban kerja, itu juga meningkatkan kuota permintaan dalam penerbangan hingga tahun 2000 (dapat berubah). APF menentukan bagaimana kuota permintaan dalam penerbangan ini dibagi lagi di antara jenis permintaan yang berbeda. Perhatikan bahwa pesawat kontrol EKS sangat tersedia dengan setidaknya 2 Server API terdaftar untuk setiap cluster. Ini berarti jumlah total permintaan dalam penerbangan yang dapat ditangani cluster Anda adalah dua kali (atau lebih tinggi jika diskalakan secara horizontal lebih jauh) kuota dalam penerbangan yang ditetapkan per kube-apiserver. Ini berjumlah beberapa ribu requests/second pada cluster EKS terbesar.

Dua jenis objek Kubernetes, disebut PriorityLevelConfigurations dan FlowSchemas, mengkonfigurasi bagaimana jumlah total permintaan dibagi antara jenis permintaan yang berbeda. Objek ini dikelola oleh API Server secara otomatis dan EKS menggunakan konfigurasi default objek ini untuk versi minor Kubernetes yang diberikan. PriorityLevelConfigurations mewakili sebagian kecil dari jumlah total permintaan yang diizinkan. Misalnya, beban kerja tinggi dialok PriorityLevelConfiguration asikan 98 dari total 600 permintaan. Jumlah permintaan yang dialokasikan untuk semua PriorityLevelConfigurations akan sama dengan 600 (atau sedikit di atas 600 karena Server API akan membulatkan jika level tertentu diberikan sebagian kecil dari permintaan). Untuk memeriksa PriorityLevelConfigurations di cluster Anda dan jumlah permintaan yang dialokasikan untuk masing-masing, Anda dapat menjalankan perintah berikut. Ini adalah default pada EKS 1.32:

$ kubectl get --raw /metrics | grep apiserver_flowcontrol_nominal_limit_seats apiserver_flowcontrol_nominal_limit_seats{priority_level="catch-all"} 13 apiserver_flowcontrol_nominal_limit_seats{priority_level="exempt"} 0 apiserver_flowcontrol_nominal_limit_seats{priority_level="global-default"} 49 apiserver_flowcontrol_nominal_limit_seats{priority_level="leader-election"} 25 apiserver_flowcontrol_nominal_limit_seats{priority_level="node-high"} 98 apiserver_flowcontrol_nominal_limit_seats{priority_level="system"} 74 apiserver_flowcontrol_nominal_limit_seats{priority_level="workload-high"} 98 apiserver_flowcontrol_nominal_limit_seats{priority_level="workload-low"} 245

Jenis objek kedua adalah FlowSchemas. Permintaan Server API dengan serangkaian properti tertentu diklasifikasikan di bawah yang sama FlowSchema. Properti ini mencakup pengguna atau atribut yang diautentikasi dari permintaan, seperti grup API, namespace, atau sumber daya. A FlowSchema juga menentukan jenis PriorityLevelConfiguration permintaan mana yang harus dipetakan. Kedua objek bersama-sama mengatakan, “Saya ingin jenis permintaan ini diperhitungkan dalam bagian permintaan dalam penerbangan ini.” Ketika permintaan mengenai API Server, ia akan memeriksa masing-masing FlowSchemas hingga menemukan satu yang cocok dengan semua properti yang diperlukan. Jika beberapa FlowSchemas cocok dengan permintaan, Server API akan memilih FlowSchema dengan prioritas pencocokan terkecil yang ditentukan sebagai properti dalam objek.

Pemetaan FlowSchemas to PriorityLevelConfigurations dapat dilihat menggunakan perintah ini:

$ kubectl get flowschemas NAME PRIORITYLEVEL MATCHINGPRECEDENCE DISTINGUISHERMETHOD AGE MISSINGPL exempt exempt 1 <none> 7h19m False eks-exempt exempt 2 <none> 7h19m False probes exempt 2 <none> 7h19m False system-leader-election leader-election 100 ByUser 7h19m False endpoint-controller workload-high 150 ByUser 7h19m False workload-leader-election leader-election 200 ByUser 7h19m False system-node-high node-high 400 ByUser 7h19m False system-nodes system 500 ByUser 7h19m False kube-controller-manager workload-high 800 ByNamespace 7h19m False kube-scheduler workload-high 800 ByNamespace 7h19m False kube-system-service-accounts workload-high 900 ByNamespace 7h19m False eks-workload-high workload-high 1000 ByUser 7h14m False service-accounts workload-low 9000 ByUser 7h19m False global-default global-default 9900 ByUser 7h19m False catch-all catch-all 10000 ByUser 7h19m False

PriorityLevelConfigurations dapat memiliki jenis Antrian, Tolak, atau Dikecualikan. Untuk jenis Antrian dan Penolakan, batas diberlakukan pada jumlah maksimum permintaan dalam penerbangan untuk tingkat prioritas tersebut, namun perilaku berbeda ketika batas tersebut tercapai. Misalnya, workload-high PriorityLevelConfiguration menggunakan tipe Queue dan memiliki 98 permintaan yang tersedia untuk digunakan oleh controller-manager, endpoint-controller, penjadwal, pengontrol terkait eks dan dari pod yang berjalan di namespace sistem kube. Karena tipe Queue digunakan, API Server akan mencoba menyimpan permintaan dalam memori dan berharap bahwa jumlah permintaan dalam penerbangan turun di bawah 98 sebelum permintaan ini habis. Jika permintaan tertentu habis waktu dalam antrian atau jika terlalu banyak permintaan yang sudah mengantri, Server API tidak punya pilihan selain membatalkan permintaan dan mengembalikan klien 429. Perhatikan bahwa antrian dapat mencegah permintaan menerima 429, tetapi itu datang dengan pertukaran peningkatan latensi ujung ke ujung pada permintaan.

Sekarang pertimbangkan catch-all FlowSchema yang dipetakan ke catch-all PriorityLevelConfiguration dengan tipe Reject. Jika klien mencapai batas 13 permintaan dalam penerbangan, API Server tidak akan melakukan antrian dan akan menghapus permintaan secara instan dengan kode respons 429. Akhirnya, permintaan pemetaan ke PriorityLevelConfiguration dengan tipe Excepted tidak akan pernah menerima 429 dan selalu dikirim segera. Ini digunakan untuk permintaan prioritas tinggi seperti permintaan healthz atau permintaan yang berasal dari grup system:masters.

Memantau APF dan Permintaan yang Ditutup

Untuk mengonfirmasi apakah ada permintaan yang dibatalkan karena APF, metrik Server API untuk apiserver_flowcontrol_rejected_requests_total dapat dipantau untuk memeriksa dampak FlowSchemas dan PriorityLevelConfigurations. Misalnya, metrik ini menunjukkan bahwa 100 permintaan dari akun layanan dihapus karena waktu permintaan FlowSchema habis dalam antrian beban kerja rendah:

% kubectl get --raw /metrics | grep apiserver_flowcontrol_rejected_requests_total
apiserver_flowcontrol_rejected_requests_total{flow_schema="service-accounts",priority_level="workload-low",reason="time-out"} 100

Untuk memeriksa seberapa dekat suatu pemberian PriorityLevelConfiguration untuk menerima 429 detik atau mengalami peningkatan latensi karena antrian, Anda dapat membandingkan perbedaan antara batas konkurensi dan konkurensi yang digunakan. Dalam contoh ini, kita memiliki buffer 100 permintaan.

% kubectl get --raw /metrics | grep 'apiserver_flowcontrol_nominal_limit_seats.*workload-low'
apiserver_flowcontrol_nominal_limit_seats{priority_level="workload-low"} 245

% kubectl get --raw /metrics | grep 'apiserver_flowcontrol_current_executing_seats.*workload-low'
apiserver_flowcontrol_current_executing_seats{flow_schema="service-accounts",priority_level="workload-low"} 145

Untuk memeriksa apakah permintaan tertentu PriorityLevelConfiguration mengalami antrian tetapi tidak harus dibatalkan, metrik untuk apiserver_flowcontrol_current_inqueue_requests dapat direferensikan:

% kubectl get --raw /metrics | grep 'apiserver_flowcontrol_current_inqueue_requests.*workload-low'
apiserver_flowcontrol_current_inqueue_requests{flow_schema="service-accounts",priority_level="workload-low"} 10

Metrik Prometheus berguna lainnya meliputi:

  • apiserver_flowcontrol_dispatched_request_total

  • apiserver_flowcontrol_request_eksekusi detik

  • apiserver_flowcontrol_request_tunggu durasi_detik

Lihat dokumentasi hulu untuk daftar lengkap metrik APF.

Mencegah Permintaan yang Dibatalkan

Cegah 429s dengan mengubah beban kerja Anda

Ketika APF membatalkan permintaan karena suatu permintaan PriorityLevelConfiguration melebihi jumlah maksimum permintaan dalam penerbangan yang diizinkan, klien di pihak yang terpengaruh FlowSchemas dapat mengurangi jumlah permintaan yang dieksekusi pada waktu tertentu. Ini dapat dicapai dengan mengurangi jumlah total permintaan yang dibuat selama periode di mana 429 terjadi. Perhatikan bahwa permintaan yang berjalan lama seperti panggilan daftar mahal sangat bermasalah karena mereka dihitung sebagai permintaan dalam penerbangan untuk seluruh durasi yang mereka jalankan. Mengurangi jumlah permintaan mahal ini atau mengoptimalkan latensi panggilan daftar ini (misalnya, dengan mengurangi jumlah objek yang diambil per permintaan atau beralih menggunakan permintaan tontonan) dapat membantu mengurangi total konkurensi yang diperlukan oleh beban kerja yang diberikan.

Cegah 429s dengan mengubah pengaturan APF Anda

Awas

Hanya mengubah pengaturan APF default jika Anda tahu apa yang Anda lakukan. Setelan APF yang salah konfigurasi dapat mengakibatkan permintaan Server API terputus dan gangguan beban kerja yang signifikan.

Salah satu pendekatan lain untuk mencegah permintaan yang dijatuhkan adalah mengubah default FlowSchemas atau PriorityLevelConfigurations diinstal pada cluster EKS. EKS menginstal pengaturan default hulu untuk FlowSchemas dan PriorityLevelConfigurations untuk versi minor Kubernetes yang diberikan. Server API akan secara otomatis merekonsiliasi objek-objek ini kembali ke defaultnya jika dimodifikasi kecuali anotasi berikut pada objek diatur ke false:

  metadata:
    annotations:
      apf.kubernetes.io/autoupdate-spec: "false"

Pada tingkat tinggi, pengaturan APF dapat dimodifikasi menjadi:

  • Alokasikan lebih banyak kapasitas dalam penerbangan untuk permintaan yang Anda pedulikan.

  • Isolasi permintaan yang tidak penting atau mahal yang dapat mengurangi kapasitas untuk jenis permintaan lainnya.

Ini dapat dicapai dengan mengubah default FlowSchemas dan PriorityLevelConfigurations atau dengan membuat objek baru dari jenis ini. Operator dapat meningkatkan nilai jaminan ConcurrencyShares untuk PriorityLevelConfigurations objek yang relevan untuk meningkatkan fraksi permintaan dalam penerbangan yang dialokasikan. Selain itu, jumlah permintaan yang dapat diantri pada waktu tertentu juga dapat ditingkatkan jika aplikasi dapat menangani latensi tambahan yang disebabkan oleh permintaan yang diantri sebelum dikirim.

Atau, PriorityLevelConfigurations objek baru FlowSchema dan objek dapat dibuat yang spesifik untuk beban kerja pelanggan. Ketahuilah bahwa mengalokasikan lebih terjamin ConcurrencyShares ke yang sudah ada PriorityLevelConfigurations atau yang baru PriorityLevelConfigurations akan menyebabkan jumlah permintaan yang dapat ditangani oleh bucket lain berkurang karena batas keseluruhan akan tetap sebesar 600 dalam pesawat per Server API.

Saat membuat perubahan pada default APF, metrik ini harus dipantau pada cluster non-produksi untuk memastikan perubahan pengaturan tidak menyebabkan 429 yang tidak diinginkan:

  1. Metrik untuk apiserver_flowcontrol_rejected_requests_total harus dipantau untuk semua FlowSchemas untuk memastikan bahwa tidak ada bucket yang mulai menjatuhkan permintaan.

  2. Nilai untuk apiserver_flowcontrol_nominal_limit_seats dan apiserver_flowcontrol_current_executing_seats harus dibandingkan untuk memastikan bahwa konkurensi yang digunakan tidak berisiko melanggar batas untuk tingkat prioritas tersebut.

Salah satu kasus penggunaan umum untuk mendefinisikan yang baru FlowSchema dan PriorityLevelConfiguration adalah untuk isolasi. Misalkan kita ingin mengisolasi panggilan acara daftar yang berjalan lama dari pod ke bagian permintaan mereka sendiri. Ini akan mencegah permintaan penting dari pod yang menggunakan akun layanan FlowSchema yang ada menerima 429 dan kekurangan kapasitas permintaan. Ingatlah bahwa jumlah total permintaan dalam penerbangan terbatas, namun, contoh ini menunjukkan pengaturan APF dapat dimodifikasi untuk membagi kapasitas permintaan dengan lebih baik untuk beban kerja yang diberikan:

Contoh FlowSchema objek untuk mengisolasi permintaan acara daftar:

apiVersion: flowcontrol.apiserver.k8s.io/v1
kind: FlowSchema
metadata:
  name: list-events-default-service-accounts
spec:
  distinguisherMethod:
    type: ByUser
  matchingPrecedence: 8000
  priorityLevelConfiguration:
    name: catch-all
  rules:
  - resourceRules:
    - apiGroups:
      - '*'
      namespaces:
      - default
      resources:
      - events
      verbs:
      - list
    subjects:
    - kind: ServiceAccount
      serviceAccount:
        name: default
        namespace: default
  • Ini FlowSchema menangkap semua panggilan acara daftar yang dilakukan oleh akun layanan di namespace default.

  • Prioritas pencocokan 8000 lebih rendah dari nilai 9000 yang digunakan oleh akun-layanan yang ada FlowSchema sehingga panggilan acara daftar ini akan cocok dengan list-events-default-service-accounts daripada service-accounts.

  • Kami menggunakan catch-all PriorityLevelConfiguration untuk mengisolasi permintaan ini. Bucket ini hanya mengizinkan 13 permintaan dalam penerbangan untuk digunakan oleh panggilan acara daftar yang sudah berjalan lama ini. Pod akan mulai menerima 429 segera setelah mereka mencoba mengeluarkan lebih dari 13 permintaan ini secara bersamaan.

Mengambil sumber daya di server API

Mendapatkan informasi dari server API adalah perilaku yang diharapkan untuk cluster dengan ukuran apa pun. Saat Anda menskalakan jumlah sumber daya dalam cluster, frekuensi permintaan dan volume data dapat dengan cepat menjadi hambatan untuk bidang kontrol dan akan menyebabkan latensi dan kelambatan API. Tergantung pada tingkat keparahan latensi, hal itu menyebabkan downtime yang tidak terduga jika Anda tidak berhati-hati.

Menyadari apa yang Anda minta dan seberapa sering langkah pertama untuk menghindari jenis masalah ini. Berikut adalah panduan untuk membatasi volume kueri berdasarkan praktik terbaik penskalaan. Saran di bagian ini disediakan dalam urutan dimulai dengan opsi yang diketahui memiliki skala terbaik.

Gunakan Informan Bersama

Saat membangun pengontrol dan otomatisasi yang terintegrasi dengan API Kubernetes, Anda sering perlu mendapatkan informasi dari sumber daya Kubernetes. Jika Anda melakukan polling untuk sumber daya ini secara teratur, hal itu dapat menyebabkan beban yang signifikan pada server API.

Menggunakan informan dari pustaka client-go akan memberi Anda manfaat mengamati perubahan sumber daya berdasarkan peristiwa alih-alih melakukan polling untuk perubahan. Informan lebih lanjut mengurangi beban dengan menggunakan cache bersama untuk peristiwa dan perubahan sehingga beberapa pengontrol yang menonton sumber daya yang sama tidak menambahkan beban tambahan.

Pengontrol harus menghindari polling sumber daya luas cluster tanpa label dan pemilih bidang terutama di cluster besar. Setiap polling yang tidak difilter membutuhkan banyak data yang tidak perlu untuk dikirim dari etcd melalui server API untuk difilter oleh klien. Dengan memfilter berdasarkan label dan ruang nama, Anda dapat mengurangi jumlah pekerjaan yang perlu dilakukan server API untuk memenuhi permintaan dan data yang dikirim ke klien.

Optimalkan penggunaan API Kubernetes

Saat memanggil API Kubernetes dengan pengontrol khusus atau otomatisasi, penting bagi Anda untuk membatasi panggilan hanya pada sumber daya yang Anda butuhkan. Tanpa batasan Anda dapat menyebabkan beban yang tidak diperlukan pada server API dan etcd.

Disarankan agar Anda menggunakan argumen arloji bila memungkinkan. Tanpa argumen perilaku default adalah daftar objek. Untuk menggunakan watch alih-alih daftar, Anda dapat ?watch=true menambahkan ke akhir permintaan API Anda. Misalnya, untuk mendapatkan semua pod di namespace default dengan jam tangan gunakan:

/api/v1/namespaces/default/pods?watch=true

Jika Anda mencantumkan objek, Anda harus membatasi ruang lingkup apa yang Anda daftarkan dan jumlah data yang dikembalikan. Anda dapat membatasi data yang dikembalikan dengan menambahkan limit=500 argumen ke permintaan. fieldSelectorArgumen dan /namespace/ jalur dapat berguna untuk memastikan daftar Anda memiliki cakupan sempit yang diperlukan. Misalnya, untuk mencantumkan hanya pod yang sedang berjalan di namespace default gunakan jalur dan argumen API berikut.

/api/v1/namespaces/default/pods?fieldSelector=status.phase=Running&limit=500

Atau daftar semua pod yang berjalan dengan:

/api/v1/pods?fieldSelector=status.phase=Running&limit=500

Pilihan lain untuk membatasi panggilan tontonan atau objek terdaftar adalah dengan menggunakan resourceVersions yang dapat Anda baca di dokumentasi Kubernetes. Tanpa resourceVersion argumen, Anda akan menerima versi terbaru yang tersedia yang memerlukan pembacaan kuorum etcd yang merupakan pembacaan paling mahal dan paling lambat untuk database. ResourceVersion tergantung pada sumber daya apa yang Anda coba kueri dan dapat ditemukan di lapangan. metadata.resourseVersion Ini juga disarankan jika menggunakan panggilan tonton dan bukan hanya daftar panggilan

Ada khusus yang resourceVersion=0 tersedia yang akan mengembalikan hasil dari cache server API. Ini dapat mengurangi beban etcd tetapi tidak mendukung pagination.

/api/v1/namespaces/default/pods?resourceVersion=0

Disarankan untuk menggunakan jam tangan dengan ResourceVersion yang disetel menjadi nilai terbaru yang diketahui yang diterima dari daftar atau jam tangan sebelumnya. Ini ditangani secara otomatis di client-go. Tetapi disarankan untuk memeriksa ulang jika Anda menggunakan klien k8s dalam bahasa lain.

/api/v1/namespaces/default/pods?watch=true&resourceVersion=362812295

Jika Anda memanggil API tanpa argumen apa pun, itu akan menjadi sumber daya yang paling intensif untuk server API dan etcd. Panggilan ini akan mendapatkan semua pod di semua ruang nama tanpa paginasi atau membatasi ruang lingkup dan memerlukan kuorum yang dibaca dari etcd.

/api/v1/pods

Mencegah DaemonSet kawanan gemuruh

A DaemonSet memastikan bahwa semua (atau beberapa) node menjalankan salinan pod. Saat node bergabung dengan cluster, daemonset-controller membuat pod untuk node tersebut. Saat node meninggalkan cluster, pod tersebut adalah sampah yang dikumpulkan. Menghapus a DaemonSet akan membersihkan pod yang dibuatnya.

Beberapa kegunaan khas dari a DaemonSet adalah:

  • Menjalankan daemon penyimpanan cluster di setiap node

  • Menjalankan daemon koleksi log di setiap node

  • Menjalankan daemon pemantauan node pada setiap node

Pada cluster dengan ribuan node, membuat yang baru DaemonSet, memperbarui DaemonSet, atau meningkatkan jumlah node dapat menghasilkan beban tinggi yang ditempatkan pada bidang kontrol. Jika DaemonSet pod mengeluarkan permintaan server API yang mahal saat startup pod, mereka dapat menyebabkan penggunaan sumber daya yang tinggi pada bidang kontrol dari sejumlah besar permintaan bersamaan.

Dalam operasi normal, Anda dapat menggunakan a RollingUpdate untuk memastikan peluncuran pod baru secara bertahap DaemonSet . Dengan strategi RollingUpdate pembaruan, setelah Anda memperbarui DaemonSet template, pengontrol membunuh pod lama dan DaemonSet membuat pod baru secara DaemonSet otomatis dengan cara yang terkontrol. Paling banyak satu pod DaemonSet akan berjalan pada setiap node selama seluruh proses pembaruan. Anda dapat melakukan peluncuran bertahap dengan mengatur maxUnavailable ke 1, maxSurge ke 0, dan minReadySeconds ke 60. Jika Anda tidak menentukan strategi pembaruan, Kubernetes akan membuat default RollingUpdate dengan 1, maxUnavailable sebagai 0, dan maxSurge minReadySeconds sebagai 0.

minReadySeconds: 60 strategy: type: RollingUpdate rollingUpdate: maxSurge: 0 maxUnavailable: 1

A RollingUpdate memastikan peluncuran pod baru DaemonSet secara bertahap jika DaemonSet sudah dibuat dan memiliki jumlah pod yang diharapkan Ready di semua node. Masalah kawanan yang menggelegar dapat terjadi dalam kondisi tertentu yang tidak tercakup oleh RollingUpdate strategi.

Mencegah kawanan gemuruh saat penciptaan DaemonSet

Secara default, terlepas dari RollingUpdate konfigurasinya, daemonset-controller di kube-controller-manager akan membuat pod untuk semua node yang cocok secara bersamaan saat Anda membuat yang baru. DaemonSet Untuk memaksa peluncuran pod secara bertahap setelah Anda membuat DaemonSet, Anda dapat menggunakan a NodeSelector atauNodeAffinity. Ini akan membuat node DaemonSet yang cocok dengan nol dan kemudian Anda dapat memperbarui node secara bertahap untuk membuatnya memenuhi syarat untuk menjalankan pod dari DaemonSet pada tingkat yang terkontrol. Anda dapat mengikuti pendekatan ini:

  • Tambahkan label ke semua node untukrun-daemonset=false.

kubectl label nodes --all run-daemonset=false
  • Buat Anda DaemonSet dengan NodeAffinity pengaturan untuk mencocokkan simpul apa pun tanpa run-daemonset=false label. Awalnya, ini akan mengakibatkan Anda tidak DaemonSet memiliki pod yang sesuai.

affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: run-daemonset
          operator: NotIn
          values:
          - "false"
  • Hapus run-daemonset=false label dari node Anda pada tingkat yang terkontrol. Anda dapat menggunakan skrip bash ini sebagai contoh:

#!/bin/bash

nodes=$(kubectl get --raw "/api/v1/nodes" | jq -r '.items | .[].metadata.name')

for node in ${nodes[@]}; do
   echo "Removing run-daemonset label from node $node"
   kubectl label nodes $node run-daemonset-
   sleep 5
done
  • Secara opsional, hapus NodeAffinity pengaturan dari DaemonSet objek Anda. Perhatikan bahwa ini juga akan memicu a RollingUpdate dan secara bertahap mengganti semua pod DaemonSet yang ada karena DaemonSet template berubah.

Mencegah kawanan gemuruh pada skala simpul

Demikian pula dengan DaemonSet pembuatan, membuat node baru dengan kecepatan cepat dapat menghasilkan sejumlah besar pod yang DaemonSet dimulai secara bersamaan. Anda harus membuat node baru pada tingkat yang terkontrol sehingga pengontrol membuat DaemonSet pod pada kecepatan yang sama. Jika ini tidak memungkinkan, Anda dapat membuat node baru awalnya tidak memenuhi syarat untuk yang sudah ada DaemonSet dengan menggunakanNodeAffinity. Selanjutnya, Anda dapat menambahkan label ke node baru secara bertahap sehingga daemonset-controller membuat pod dengan kecepatan terkontrol. Anda dapat mengikuti pendekatan ini:

  • Tambahkan label ke semua node yang ada untuk run-daemonset=true

kubectl label nodes --all run-daemonset=true
  • Perbarui Anda DaemonSet dengan NodeAffinity pengaturan untuk mencocokkan node apa pun dengan run-daemonset=true label. Perhatikan bahwa ini juga akan memicu a RollingUpdate dan secara bertahap mengganti semua pod DaemonSet yang ada karena DaemonSet template berubah. Anda harus menunggu RollingUpdate sampai selesai sebelum melanjutkan ke langkah berikutnya.

affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: run-daemonset
          operator: In
          values:
          - "true"
  • Buat node baru di cluster Anda. Perhatikan bahwa node ini tidak akan memiliki run-daemonset=true label sehingga tidak DaemonSet akan cocok dengan node tersebut.

  • Tambahkan run-daemonset=true label ke node baru Anda (yang saat ini tidak memiliki run-daemonset label) pada tingkat yang terkontrol. Anda dapat menggunakan skrip bash ini sebagai contoh:

#!/bin/bash

nodes=$(kubectl get --raw "/api/v1/nodes?labelSelector=%21run-daemonset" | jq -r '.items | .[].metadata.name')

for node in ${nodes[@]}; do
   echo "Adding run-daemonset=true label to node $node"
   kubectl label nodes $node run-daemonset=true
   sleep 5
done
  • Secara opsional, hapus NodeAffinity pengaturan dari DaemonSet objek Anda dan hapus run-daemonset label dari semua node.

Mencegah kawanan gemuruh pada pembaruan DaemonSet

RollingUpdateKebijakan hanya akan menghormati maxUnavailable pengaturan untuk DaemonSet pod yang adaReady. Jika a hanya DaemonSet memiliki pod NotReady atau persentase besar pod dan NotReady Anda memperbarui template-nya, daemonset-controller akan membuat pod baru secara bersamaan untuk pod apa pun. NotReady Hal ini dapat mengakibatkan masalah kawanan yang menggelegar jika ada sejumlah NotReady besar pod, misalnya jika pod terus melakukan crash looping atau gagal menarik gambar.

Untuk memaksa peluncuran pod secara bertahap saat Anda memperbarui DaemonSet a dan ada NotReady pod, Anda dapat mengubah strategi pembaruan untuk sementara DaemonSet dari RollingUpdate keOnDelete. DenganOnDelete, setelah Anda memperbarui DaemonSet template, pengontrol membuat pod baru setelah Anda menghapus yang lama secara manual sehingga Anda dapat mengontrol peluncuran pod baru. Anda dapat mengikuti pendekatan ini:

  • Periksa apakah Anda memiliki NotReady pod di dalamnya DaemonSet.

  • Jika tidak, Anda dapat memperbarui DaemonSet template dengan aman dan RollingUpdate strategi akan memastikan peluncuran bertahap.

  • Jika ya, Anda harus terlebih dahulu memperbarui Anda DaemonSet untuk menggunakan OnDelete strategi.

updateStrategy:
  type: OnDelete
  • Selanjutnya, perbarui DaemonSet template Anda dengan perubahan yang diperlukan.

  • Setelah pembaruan ini, Anda dapat menghapus pod lama DaemonSet dengan mengeluarkan permintaan hapus pod dengan kecepatan terkontrol. Anda dapat menggunakan skrip bash ini sebagai contoh di mana namanya fluentd-elasticsearch di namespace kube-system: DaemonSet

#!/bin/bash

daemonset_pods=$(kubectl get --raw "/api/v1/namespaces/kube-system/pods?labelSelector=name%3Dfluentd-elasticsearch" | jq -r '.items | .[].metadata.name')

for pod in ${daemonset_pods[@]}; do
   echo "Deleting pod $pod"
   kubectl delete pod $pod -n kube-system
   sleep 5
done
  • Akhirnya, Anda dapat memperbarui DaemonSet kembali ke RollingUpdate strategi sebelumnya.