Prioritas dan Kesetaraan API (API Priority and Fairness)
Kubernetes v1.18 [alpha]
Mengontrol perilaku server API dari Kubernetes pada situasi beban berlebih
merupakan tugas utama dari administrator klaster. kube-apiserver memiliki beberapa kontrol yang tersedia
(seperti opsi --max-request-inflight
dan --max-mutating-request-inflight
pada baris perintah atau command-line) untuk membatasi jumlah pekerjaan luar biasa yang akan
diterima, untuk mencegah banjirnya permintaan masuk dari beban berlebih
yang berpotensi untuk menghancurkan server API. Namun opsi ini tidak cukup untuk memastikan
bahwa permintaan yang paling penting dapat diteruskan pada saat kondisi lalu lintas (traffic) yang cukup tinggi.
Fitur Prioritas dan Kesetaraan API atau API Priority and Fairness (APF) adalah alternatif untuk meningkatkan batasan max-inflight seperti yang disebutkan di atas. APF mengklasifikasi dan mengisolasi permintaan dengan cara yang lebih halus. Fitur ini juga memperkenalkan jumlah antrian yang terbatas, sehingga tidak ada permintaan yang ditolak pada saat terjadi lonjakan permintaan dalam waktu yang sangat singkat. Permintaan dibebaskan dari antrian dengan menggunakan teknik antrian yang adil (fair queuing) sehingga, sebagai contoh, perilaku buruk dari satu controller tidak seharusnya mengakibatkan controller yang lain menderita (meskipun pada tingkat prioritas yang sama).
Perhatian: Permintaan yang diklasifikasikan sebagai "long running" - terutama watch - tidak mengikuti filter prioritas dan kesetaraan API. Dimana ini juga berlaku pada opsi--max-request-inflight
tanpa mengaktifkan APF.
Mengaktifkan prioritas dan kesetaraan API
Fitur APF dikontrol oleh sebuah gerbang fitur (feature gate)
dan fitur ini tidak diaktifkan secara bawaan. Silahkan lihat
gerbang fitur
untuk penjelasan umum tentang gerbang fitur dan bagaimana cara mengaktifkan dan menonaktifkannya.
Nama gerbang fitur untuk APF adalah "APIPriorityAndFairness".
Fitur ini melibatkan sebuah Grup API yang harus juga diaktifkan. Kamu bisa melakukan ini dengan
menambahkan opsi pada baris perintah berikut pada permintaan ke kube-apiserver
kamu:
kube-apiserver \
--feature-gates=APIPriorityAndFairness=true \
--runtime-config=flowcontrol.apiserver.k8s.io/v1alpha1=true \
# …dan opsi-opsi lainnya seperti biasa
Opsi pada baris perintah --enable-priority-and-fairness=false
akan menonaktifkan fitur
APF, bahkan ketika opsi yang lain telah mengaktifkannya.
Konsep
Ada beberapa fitur lainnya yang terlibat dalam fitur APF. Permintaan yang masuk diklasifikasikan berdasarkan atribut permintaan dengan menggunakan FlowSchema, dan diserahkan ke tingkat prioritas. Tingkat prioritas menambahkan tingkat isolasi dengan mempertahankan batas konkurensi yang terpisah, sehingga permintaan yang diserahkan ke tingkat prioritas yang berbeda tidak dapat membuat satu sama lain menderita. Dalam sebuah tingkat prioritas, algoritma fair-queuing mencegah permintaan dari flows yang berbeda akan memberikan penderitaan kepada yang lainnya, dan memperbolehkan permintaan untuk dimasukkan ke dalam antrian untuk mencegah pelonjakan lalu lintas yang akan menyebabkan gagalnya permintaan, walaupun pada saat beban rata-ratanya cukup rendah.
Tingkat prioritas (Priority Level)
Tanpa pengaktifan APF, keseluruhan konkurensi dalam
server API dibatasi oleh opsi pada kube-apiserver
--max-request-inflight
dan --max-mutating-request-inflight
. Dengan pengaktifan APF,
batas konkurensi yang ditentukan oleh opsi ini akan dijumlahkan dan kemudian jumlah tersebut dibagikan
untuk sekumpulan tingkat prioritas (priority level) yang dapat dikonfigurasi. Setiap permintaan masuk diserahkan
ke sebuah tingkat prioritas, dan setiap tingkat prioritas hanya akan meneruskan sebanyak mungkin
permintaan secara bersamaan sesuai dengan yang diijinkan dalam konfigurasi.
Konfigurasi bawaan, misalnya, sudah mencakup tingkat prioritas terpisah untuk permintaan dalam rangka pemilihan pemimpin (leader-election), permintaan dari controller bawaan, dan permintaan dari Pod. Hal ini berarti bahwa Pod yang berperilaku buruk, yang bisa membanjiri server API dengan permintaan, tidak akan mampu mencegah kesuksesan pemilihan pemimpin atau tindakan yang dilakukan oleh controller bawaan.
Antrian (Queuing)
Bahkan dalam sebuah tingkat prioritas mungkin akan ada sumber lalu lintas yang berbeda dalam jumlah besar. Dalam situasi beban berlebih, sangat penting untuk mencegah satu aliran permintaan dari penderitaan karena aliran yang lainnya (khususnya, dalam kasus yang relatif umum dari sebuah klien tunggal bermasalah (buggy) yang dapat membanjiri kube-apiserver dengan permintaan, klien bermasalah itu idealnya tidak memiliki banyak dampak yang bisa diukur terhadap klien yang lainnya). Hal ini ditangani dengan menggunakan algoritma fair-queuing untuk memproses permintaan yang diserahkan oleh tingkat prioritas yang sama. Setiap permintaan diserahkan ke sebuah flow, yang diidentifikasi berdasarkan nama FlowSchema yang sesuai, ditambah dengan flow distinguisher - yang bisa saja didasarkan pada pengguna yang meminta, sumber daya Namespace dari target, atau tidak sama sekali - dan sistem mencoba untuk memberikan bobot yang hampir sama untuk permintaan dalam flow yang berbeda dengan tingkat prioritas yang sama.
Setelah mengklasifikasikan permintaan ke dalam sebuah flow, fitur APF kemudian dapat menyerahkan permintaan ke dalam sebuah antrian. Penyerahan ini menggunakan teknik yang dikenal sebagai _shuffle sharding_, yang membuat penggunaan antrian yang relatif efisien untuk mengisolasi flow dengan intensitas rendah dari flow dengan intensitas tinggi.
Detail dari algoritma antrian dapat disesuaikan untuk setiap tingkat prioritas, dan memperbolehkan administrator untuk menukar (trade off) dengan penggunaan memori, kesetaraan (properti dimana flow yang independen akan membuat semua kemajuan ketika total dari lalu lintas sudah melebihi kapasitas), toleransi untuk lonjakan lalu lintas, dan penambahan latensi yang dihasilkan oleh antrian.
Permintaan yang dikecualikan (Exempt Request)
Beberapa permintaan dianggap cukup penting sehingga mereka tidak akan mengikuti salah satu batasan yang diberlakukan oleh fitur ini. Pengecualian ini untuk mencegah konfigurasi flow control yang tidak terkonfigurasi dengan baik sehingga tidak benar-benar menonaktifkan server API.
Bawaan (Default)
Fitur APF dikirimkan dengan konfigurasi yang disarankan dimana konfigurasi itu seharusnya cukup untuk bereksperimen; jika klaster kamu cenderung mengalami beban berat maka kamu harus mempertimbangkan konfigurasi apa yang akan bekerja paling baik. Kelompok konfigurasi yang disarankan untuk semua permintaan terbagi dalam lima prioritas kelas:
-
Tingkat prioritas
system
diperuntukkan bagi permintaan dari grupsystem:nodes
, mis. Kubelet, yang harus bisa menghubungi server API agar mendapatkan workload untuk dijadwalkan. -
Tingkat prioritas
leader-election
diperuntukkan bagi permintaan dalam pemilihan pemimpin (leader election) dari controller bawaan (khususnya, permintaan untukendpoint
,configmaps
, atauleases
yang berasal darisystem:kube-controller-manager
atau penggunasystem:kube-scheduler
dan akun Service di Namespacekube-system
). Hal ini penting untuk mengisolasi permintaan ini dari lalu lintas yang lain karena kegagalan dalam pemilihan pemimpin menyebabkan controller akan gagal dan memulai kembali (restart), yang pada akhirnya menyebabkan lalu lintas yang lebih mahal karena controller yang baru perlu menyinkronkan para informannya. -
Tingkat prioritas
workload-high
diperuntukkan bagi permintaan yang lain dari controller bawaan. -
Tingkat prioritas
workload-low
diperuntukkan bagi permintaan dari akun Service yang lain, yang biasanya mencakup semua permintaan dari controller yang bekerja didalam Pod. -
Tingkat prioritas
global-default
menangani semua lalu lintas lainnya, mis. perintah interaktifkubectl
yang dijalankan oleh pengguna yang tidak memiliki hak khusus.
Kemudian, ada dua PriorityLevelConfiguration dan dua FlowSchema yang telah dibangun dan tidak mungkin ditimpa ulang:
-
Tingkat prioritas khusus
exempt
diperuntukkan bagi permintaan yang tidak akan dikenakan flow control sama sekali: permintaan itu akan selalu diteruskan sesegera mungkin. FlowSchemaexempt
khusus mengklasifikasikan semua permintaan dari kelompoksystem:masters
ke dalam tingkat prioritas khusus ini. Kamu juga dapat menentukan FlowSchema lain yang mengarahkan permintaan lain ke tingkat prioritas ini juga, apabila permintaan tersebut sesuai. -
Tingkat prioritas khusus
catch-all
digunakan secara kombinasi dengan spesial FlowSchemacatch-all
untuk memastikan bahwa setiap permintaan mendapatkan proses klasifikasi. Biasanya kamu tidak harus bergantung pada konfigurasi catch-all ini, dan kamu seharusnya membuat FlowSchema catch-all dan PriorityLevelConfiguration kamu sendiri (atau gunakan konfigurasiglobal-default
yang sudah diinstal secara bawaan) secara benar. Untuk membantu menemukan kesalahan konfigurasi yang akan melewatkan beberapa klasifikasi permintaan, maka tingkat prioritascatch-all
hanya wajib mengijinkan satu konkurensi bersama dan tidak melakukan memasukkan permintaan dalam antrian, sehingga membuat lalu lintas yang secara relatif hanya sesuai dengan FlowSchemacatch-all
akan ditolak dengan kode kesalahan HTTP 429.
Sumber daya (Resource)
Flow control API melibatkan dua jenis sumber daya. PriorityLevelConfiguration yang menentukan kelas isolasi yang tersedia, bagian dari konkurensi anggaran yang tersedia yang masing-masing dapat menangani bagian tersebut, dan memperbolehkan untuk melakukan fine-tuning terhadap perilaku antrian. FlowSchema yang digunakan untuk mengklasifikasikan permintaan individu yang masuk, mencocokkan masing-masing dengan setiap PriorityLevelConfiguration.
PriorityLevelConfiguration
Sebuah PriorityLevelConfiguration merepresentasikan sebuah kelas isolasi tunggal. Setiap PriorityLevelConfiguration memiliki batas independensi dalam hal jumlah permintaan yang belum diselesaikan, dan batasan dalam hal jumlah permintaan yang mengantri.
Batas konkurensi untuk PriorityLevelConfiguration tidak disebutkan dalam
jumlah permintaan secara mutlak, melainkan dalam "concurrency shares." Total batas konkurensi
untuk server API didistribusikan di antara PriorityLevelConfiguration yang ada
secara proporsional dengan "concurrency shares" tersebut. Ini mengizinkan seorang
administrator klaster untuk meningkatkan atau menurunkan jumlah total lalu lintas ke sebuah
server dengan memulai kembali kube-apiserver
dengan nilai opsi
--max-request-inflight
(atau --max-mutating-request-inflight
) yang berbeda, dan semua
PriorityLevelConfiguration akan melihat konkurensi maksimum yang diizinkan kepadanya untuk menaikkan (atau
menurunkan) dalam fraksi yang sama.
Perhatian: Dengan fitur Prioritas dan Kesetaraan yang diaktifkan, batas total konkurensi untuk server diatur pada nilai penjumlahan dari--max-request-inflight
dan--max-mutating-request-inflight
. Tidak akan ada lagi perbedaan antara permintaan yang bermutasi dan permintaan yang tidak bermutasi; jika kamu ingin melayaninya secara terpisah untuk suatu sumber daya yang ada, maka perlu membuat FlowSchema terpisah yang sesuai dengan masing-masing kata kerja dari permintaan yang bermutasi dan yang tidak bermutasi tersebut.
Ketika jumlah permintaan masuk yang diserahkan kepada sebuah
PriorityLevelConfiguration melebihi dari tingkat konkurensi yang diizinkan,
bagian type
dari spesifikasinya menentukan apa yang akan terjadi pada permintaan selanjutnya.
Tipe Reject
berarti bahwa kelebihan lalu lintas akan segera ditolak
dengan kode kesalahan HTTP 429 (yang artinya terlalu banyak permintaan). Tipe Queue
berarti permintaan
di atas batas tersebut akan mengantri, dengan teknik sharding shuffle dan fair queuing yang digunakan
untuk menyelaraskan kemajuan antara flow permintaan.
Konfigurasi antrian memungkinkan mengatur algoritma fair queuing untuk sebuah tingkat prioritas. Detail algoritma dapat dibaca di proposal pembaharuan, namun secara singkat:
-
Meningkatkan
queue
(antrian) berarti mengurangi tingkat tabrakan antara flow yang berbeda, sehingga berakibat pada biaya untuk meningkatkan penggunaan memori. Nilai 1 di sini secara efektif menonaktifkan logika fair-queuing, tetapi masih mengizinkan permintaan untuk dimasukkan kedalam antrian. -
Meningkatkan
queueLengthLimit
berarti memperbolehkan lonjakan yang lebih besar dari lalu lintas untuk berkelanjutan tanpa menggagalkan permintaan apa pun, dengan konsekuensi akan meningkatkan latensi dan penggunaan memori. -
Mengubah
handSize
berarti memperbolehkan kamu untuk menyesuaikan probabilitas tabrakan antara flow yang berbeda dan keseluruhan konkurensi yang tersedia untuk satu flow tunggal dalam situasi beban berlebih.Catatan:HandSize
yang lebih besar membuat dua flow individual berpeluang kecil untuk bertabrakan (dan dimana flow yang satu bisa membuat flow yang lain menderita), tetapi akan lebih memungkinkan bahwa flow dalam jumlah kecil akan dapat mendominasi apiserver.HandSize
yang lebih besar juga berpotensi meningkatkan jumlah latensi yang diakibatkan oleh satu flow lalu lintas tunggal yang tinggi. Jumlah maksimum permintaan dalam antrian yang diijinkan dari sebuah flow tunggal adalahhandSize * queueLengthLimit
.
Berikut ini adalah tabel yang menunjukkan koleksi konfigurasi shuffle sharding yang menarik, dimana setiap probabilitas mouse (flow dengan intensitas rendah) yang diberikan akan dimampatkan oleh elephant (flow dengan intensitas tinggi) dalam sebuah koleksi ilustratif dari jumlah elephant yang berbeda. Silahkan lihat pada https://play.golang.org/p/Gi0PLgVHiUg, yang digunakan untuk menghitung nilai-nilai dalam tabel ini.
HandSize | Queues | 1 elephant | 4 elephants | 16 elephants |
---|---|---|---|---|
12 | 32 | 4.428838398950118e-09 | 0.11431348830099144 | 0.9935089607656024 |
10 | 32 | 1.550093439632541e-08 | 0.0626479840223545 | 0.9753101519027554 |
10 | 64 | 6.601827268370426e-12 | 0.00045571320990370776 | 0.49999929150089345 |
9 | 64 | 3.6310049976037345e-11 | 0.00045501212304112273 | 0.4282314876454858 |
8 | 64 | 2.25929199850899e-10 | 0.0004886697053040446 | 0.35935114681123076 |
8 | 128 | 6.994461389026097e-13 | 3.4055790161620863e-06 | 0.02746173137155063 |
7 | 128 | 1.0579122850901972e-11 | 6.960839379258192e-06 | 0.02406157386340147 |
7 | 256 | 7.597695465552631e-14 | 6.728547142019406e-08 | 0.0006709661542533682 |
6 | 256 | 2.7134626662687968e-12 | 2.9516464018476436e-07 | 0.0008895654642000348 |
6 | 512 | 4.116062922897309e-14 | 4.982983350480894e-09 | 2.26025764343413e-05 |
6 | 1024 | 6.337324016514285e-16 | 8.09060164312957e-11 | 4.517408062903668e-07 |
FlowSchema
FlowSchema mencocokkan beberapa permintaan yang masuk dan menetapkan permintaan ke dalam sebuah
tingkat prioritas. Setiap permintaan masuk diuji dengan setiap
FlowSchema secara bergiliran, dimulai dari yang terendah secara numerik ---
yang kita anggap sebagai yang tertinggi secara logis --- matchingPrecedence
dan
begitu seterusnya. FlowSchema yang cocok pertama kali akan menang.
Perhatian: Hanya FlowSchema yang pertama kali cocok untuk permintaan yang diberikan yang akan dianggap penting. Jika ada banyak FlowSchema yang cocok dengan sebuah permintaan masuk, maka akan ditetapkan berdasarkan salah satu yang mempunyaimatchingPrecedence
tertinggi. Jika ada beberapa FlowSchema dengan nilaimatchingPrecedence
yang sama dan cocok dengan permintaan yang sama juga, permintaan dengan leksikografisname
yang lebih kecil akan menang, tetapi akan lebih baik untuk tidak mengandalkan metode ini, dan sebaiknya perlu memastikan bahwa tidak ada dua FlowSchema yang memilikimatchingPrecedence
yang sama.
Sebuah FlowSchema dianggap cocok dengan sebuah permintaan yang diberikan jika setidaknya salah satu dari rules
nya
ada yang cocok. Sebuah aturan (rule) cocok jika setidaknya satu dari subject
dan
ada salah satu dari resourceRules
atau nonResourceRules
(tergantung dari apakah permintaan
yang masuk adalah untuk URL sumber daya atau non-sumber daya) yang cocok dengan permintaan tersebut.
Untuk bagian name
dalam subjek, dan bagian verbs
, apiGroups
, resources
,
namespaces
, dan nonResourceURLs
dalam aturan sumber daya dan non-sumber daya,
wildcard *
mungkin bisa ditetapkan untuk mencocokkan semua nilai pada bagian yang diberikan,
sehingga secara efektif menghapusnya dari pertimbangan.
Sebuah DistinguisherMethod.type
dari FlowSchema menentukan bagaimana permintaan
yang cocok dengan Skema itu akan dipisahkan menjadi flow. Nilai tipe itu bisa jadi ByUser
, dalam
hal ini satu pengguna yang meminta tidak akan bisa menghabiskan kapasitas dari pengguna lain,
atau bisa juga ByNamespace
, dalam hal ini permintaan sumber daya
di salah satu Namespace tidak akan bisa menyebabkan penderitaan bagi permintaan akan sumber daya
dalam kapasitas Namespace yang lain, atau bisa juga kosong (atau distinguisherMethod
dihilangkan seluruhnya), dalam hal ini semua permintaan yang cocok dengan FlowSchema ini akan
dianggap sebagai bagian dari sebuah flow tunggal. Pilihan yang tepat untuk FlowSchema yang diberikan
akan bergantung pada sumber daya dan lingkungan khusus kamu.
Diagnosis
Setiap respons HTTP dari server API dengan fitur prioritas dan kesetaraan
yang diaktifkan memiliki dua header tambahan: X-Kubernetes-PF-FlowSchema-UID
dan
X-Kubernetes-PF-PriorityLevel-UID
, yang mencatat skema flow yang cocok dengan permintaan
dan tingkat prioritas masing-masing. Name Objek API tidak termasuk dalam header ini jika pengguna peminta tidak
memiliki izin untuk melihatnya, jadi ketika melakukan debugging kamu dapat menggunakan perintah seperti ini
kubectl get flowschema -o custom-columns="uid:{metadata.uid},name:{metadata.name}"
kubectl get prioritylevelconfiguration -o custom-columns="uid:{metadata.uid},name:{metadata.name}"
untuk mendapatkan pemetaan UID ke names baik untuk FlowSchema maupun PriorityLevelConfiguration.
Observabilitas
Saat kamu mengaktifkan fitur Prioritas dan Kesetaraan API atau APF, kube-apiserver akan mengeluarkan metrik tambahan. Dengan memantau metrik ini dapat membantu kamu untuk menentukan apakah konfigurasi kamu tidak tepat dalam membatasi lalu lintas yang penting, atau menemukan beban kerja yang berperilaku buruk yang dapat membahayakan kesehatan dari sistem.
-
apiserver_flowcontrol_rejected_requests_total
menghitung permintaan yang ditolak, mengelompokkannya berdasarkan nama dari tingkat prioritas yang ditetapkan, nama FlowSchema yang ditetapkan, dan alasan penolakan tersebut. Alasan penolakan akan mengambil dari salah satu alasan-alasan berikut:queue-full
, yang mengindikasikan bahwa sudah terlalu banyak permintaan yang menunggu dalam antrian,concurrency-limit
, yang mengindikasikan bahwa PriorityLevelConfiguration telah dikonfigurasi untuk menolak, bukan untuk memasukan permintaan berlebih ke dalam antrian, atautime-out
, yang mengindikasikan bahwa permintaan masih dalam antrian ketika batas waktu antriannya telah berakhir.
-
apiserver_flowcontrol_dispatched_requests_total
menghitung permintaan yang sudah mulai dieksekusi, mengelompokkannya berdasarkan nama dari tingkat prioritas yang ditetapkan, dan nama dari FlowSchema yang ditetapkan. -
apiserver_flowcontrol_current_inqueue_requests
memberikan jumlah total sesaat secara instan dari permintaan dalam antrian (bukan yang dieksekusi), dan mengelompokkannya berdasarkan tingkat prioritas dan FlowSchema. -
apiserver_flowcontrol_current_executing_requests
memberikan jumlah total yang instan dari permintaan yang dieksekusi, dan mengelompokkannya berdasarkan tingkat prioritas dan FlowSchema. -
apiserver_flowcontrol_request_queue_length_after_enqueue
memberikan histogram dari panjang antrian untuk semua antrian yang ada, mengelompokkannya berdasarkan tingkat prioritas dan FlowSchema, berdasarkan pengambilan sampel oleh permintaan enqueued. Setiap permintaan yang mendapatkan antrian berkontribusi ke satu sampel dalam histogramnya, pelaporan panjang antrian dilakukan setelah permintaan yang mengantri tersebut ditambahkan. Perlu dicatat bahwa ini akan menghasilkan statistik yang berbeda dengan survei yang tidak bias.Catatan: Nilai asing atau tidak biasa dalam histogram akan berarti ada kemungkinan sebuah flow(misalnya, permintaan oleh satu pengguna atau untuk satu namespace, tergantung pada konfigurasinya) telah membanjiri server API, dan sedang dicekik. Sebaliknya, jika histogram dari satu tingkat prioritas menunjukkan bahwa semua antrian dalam prioritas level itu lebih panjang daripada level prioritas yang lainnya, mungkin akan sesuai untuk meningkatkan concurrency shares dari PriorityLevelConfiguration itu.
-
apiserver_flowcontrol_request_concurrency_limit
memberikan hasil perhitungan batas konkurensi (berdasarkan pada batas konkurensi total dari server API dan concurrency share dari PriorityLevelConfiguration) untuk setiap PriorityLevelConfiguration. -
apiserver_flowcontrol_request_wait_duration_seconds
memberikan histogram tentang bagaimana permintaan yang panjang dihabiskan dalam antrian, mengelompokkannya berdasarkan FlowSchema yang cocok dengan permintaan, tingkat prioritas yang ditetapkan, dan apakah permintaan tersebut berhasil dieksekusi atau tidak.Catatan: Karena setiap FlowSchema selalu memberikan permintaan untuk satuPriorityLevelConfiguration, kamu dapat menambahkan histogram untuk semua FlowSchema dalam satu tingkat prioritas untuk mendapatkan histogram yang efektif dari permintaan yang ditetapkan ke tingkat prioritas tersebut.
apiserver_flowcontrol_request_execution_seconds
memberikan histogram tentang bagaimana caranya permintaan yang panjang diambil untuk benar-benar dieksekusi, mengelompokkannya berdasarkan FlowSchema yang cocok dengan permintaan dan tingkat prioritas yang ditetapkan pada permintaan tersebut.
Selanjutnya
Untuk latar belakang informasi mengenai detail desain dari prioritas dan kesetaraan API, silahkan lihat proposal pembaharuan. Kamu juga dapat membuat saran dan permintaan akan fitur melalui SIG API Machinery.
Last modified August 20, 2021 at 2:27 AM PST : [id] Fixed link to API priority and fairness enhancement proposal (b3ecce8eb)
-