Kubernetes v1.37 ба etcd RangeStream: Том хэмжээний кластерын санах ойн хямралыг шийдсэн нь
Томоохон хэмжээний Kubernetes кластер хариуцан ажилладаг DevOps, Platform болон Site Reliability инженерүүдийн хувьд хамгийн хүнд сорилтуудын нэг нь kube-apiserver болон etcd-ийн санах ойн гэнэтийн үсрэлт (memory spike) байдаг. Хэдэн зуун мянган Pod, ConfigMap бүхий орчинд API сервер дахин ачаалах (restart) эсвэл холболт тасрах үед RAM дүүрч, санамсаргүй OOMKilled (Out Of Memory) алдаа гарч кластер бүхэлдээ доголдох эрсдэл үүсдэг.
Энэхүү олон жил үргэлжилсэн системийн гацааг шийдвэрлэхээр Kubernetes-ийн инженерийн баг саяхан танилцуулсан Kubernetes v1.37 ("Garhwal") хувилбарт etcd RangeStream функцийг Beta шатанд дэвшүүлж, албан ёсоор өргөн туршилтад оруулснаа зарлалаа.
Энэхүү нийтлэлээр уг шинэчлэлт чухам ямар асуудлыг хэрхэн шийдсэн, архитектурын хувьд ямар өөрчлөлт орсон талаар нарийвчлан авч үзье.
Асуудлын үндэс: Watch Cache болон etcd-ийн асар том "уншилт"
Kubernetes API сервер нь гаднаас ирж буй олон мянган GET, LIST, WATCH хүсэлт бүрийг etcd рүү шууд дамжуулахгүй байх үүрэгтэй санах ойн Watch Cache ашигладаг. Ингэснээр etcd-ийн ачааллыг хамгаалж, унших хүсэлтийг маш хурдан хариулдаг билээ.
Гэвч энд нэг суурь асуудал байсаар ирсэн:
- Cache Warming (Кэш бэлтгэх үе): API сервер анх асах эсвэл
etcd-тэй үүссэн холболт тасарч дахин сэргэх үед тухайн ресурсийн (ялангуяа Pod-уудын) нийт өгөгдлийгetcd-ээс бүрэн эхээр нь уншиж санах ойн кэшээ дүүргэх шаардлага үүсдэг. - Unary Range RPC-ийн хязгаарлалт: Хуучин архитектурт
etcd-ийн үндсэнRangeдуудлага нь асар том өгөгдлийг цуглуулахдаа тухайн түлхүүр-утгуудын жагсаалт, Protobuf сериалчлал, gRPC илгээх буфер зэргийг бүгдийг нь санах ойд нэг зэрэг үүсгэж байж клиент рүү нэг багцаар илгээдэг байв. - Хоёр талын санах ойн үсрэлт: API сервер ч мөн адил тэрхүү гигант өгөгдлийн багцыг хүлээн аваад санах ойдоо бүхлээр нь байршуулж байж задалдаг тул хоёр талд зэрэг хэдэн арван гигабайт RAM-ийн "пик" үүсдэг. Үүнээс үүдэн Control Plane-ийн node-үүд OOM болж унах нь энгийн үзэгдэл байв.
Хуудсаар хуваах (Pagination) яагаад хангалтгүй байсан бэ?
Өмнө нь инженерийн баг энэ асуудлыг limit тохируулан хуудсаар (paginated read) унших зарчмаар багасгах гэж оролдсон. Гэвч энэ нь хоёр том сул талтай байлаа:
- Объектын бодит хэмжээг тооцдоггүй: Хуудаслалт нь түлхүүрийн (key) тоонд тулгуурладаг тул 500 ширхэг энгийн Pod байх, эсвэл дотроо асар олон annotation, environment хувьсагч агуулсан 500 аварга Pod байх хоёр санах ойд тэс өөр нөлөө үзүүлнэ. Үүнээс болж санах ойн хэрэглээг урьдчилан тааварлах боломжгүй хэвээр үлдсэн.
- Нэмэлт Round-Trip болон олон дахин буферлэлт: Хуудас бүрийн хооронд шинэ хүсэлт илгээгдэх тул сүлжээний хоцролт (latency) үүсч, хуудас бүрийн хувьд
etcdдээр буферлэлт давтагддаг сул талтай байв.
Шийдэл: etcd v3.7 болон RangeStream хэрхэн ажилладаг вэ?
Энэхүү гацааг арилгахын тулд etcd v3.7 хувилбарт RangeStream хэмээх шинэ server-streaming RPC нэвтэрсэн бөгөөд Kubernetes v1.37 нь үүнийг өөрийн Watch Cache-д бүрэн холбож Beta болголоо.
1. Байтаар хязгаарлагдсан урсгал (Byte-bounded Chunks)
Бүх өгөгдлийг санах ойд нэг дор цуглуулж нэг бүхэл блок болгон илгээхийн оронд RangeStream нь үр дүнг бодит байтын хэмжээгээр тооцсон жижиг блокуудад хуваан тасралтгүй урсгалаар (stream) илгээдэг.
2. Шуурхай чөлөөлөлт (Incremental Processing & GC)
API сервер өгөгдлийн блокийг хүлээн авмагцаа тэр дор нь тайлж (decode хийж) кэш рүүгээ бичээд, тухайн сүлжээний багцыг санах ойноос тэр дор нь чөлөөлдөг (Garbage Collector-т өгдөг). Үр дүнд нь 500,000 Pod-ийн мэдээллийг татаж байсан ч API серверийн санах ойд зөвхөн одоо боловсруулагдаж буй жижиг блок л түр орших бөгөөд санах ойн оргил ачаалал эрс буурна.
3. ConcurrentWatchObjectDecode-тэй хосолсон нь
Kubernetes v1.37-д мөн анхдагчаар идэвхжсэн зэрэгцээ декодчилолын механизмтэй (Concurrent Object Decode) хоршсоноор, дамжин ирж буй өгөгдлийг олон CPU цөм дээр зэрэг боловсруулдаг болсон. Туршилтын үр дүнгээр том хэмжээний кластерт Watch Cache анхлан бэлтгэгдэх хугацаа 40%-аас 55% хүртэл богиноссон байна.
Платформ багуудад авчрах бодит давуу талууд
Энэхүү сайжруулалт нь өдөр тутмын хөгжүүлэлт болон дэд бүтцийн менежментэд дараах шууд өгөөжийг өгнө:
- Урьдчилан таамаглахуйц санах ойн зарцуулалт:
kube-apiserver-ийн RAM хэрэглээнд гэнэтийн хэдэн арван гигабайтын савлагаа үүсэхгүй тул Control Plane-ийн Node-үүдэд нөөц хуваарилах (Resource Request/Limit) тооцоолол илүү оновчтой, хэмнэлттэй болно. - Control Plane Failover-ийн найдвартай байдал: Аль нэг API серверийн instance унах эсвэл шинэчлэгдэх үед бусад амьд үлдсэн серверийн ачаалал snawball эффект үүсгэн бүхлээрээ унах (cascading failure) эрсдэл эрс багасна.
- AI болон Big Data кластерын өргөжилт: Орчин үед мянга мянган параллель pod үүсгэдэг AI сургалтын болон өгөгдөл боловсруулалтын орчинд Kubernetes-ийн кластер өргөжих (scalability) боломж дараагийн түвшинд гарлаа.
Хэрхэн ашиглах вэ?
Kubernetes v1.37 хувилбарт энэхүү боломж нь EtcdRangeStream feature gate-ийн ард Beta шатанд орсон.
Ашиглахад тавигдах гол шаардлага:
- Кластерын үндсэн өгөгдлийн сан etcd v3.7 эсвэл түүнээс дээш хувилбар байх шаардлагатай.
kube-apiserver-ийн эхлүүлэх тохиргоонд--feature-gates=EtcdRangeStream=trueгэж зааж өгөх боломжтой (дэмжигдсэн орчинд анхдагчаар асна).
Хэрэв танай баг enterprise түвшний том хэмжээний кластер удирддаг бол Kubernetes v1.37 болон etcd v3.7-ийн шинэчлэлтийг stage орчиндоо туршиж үзэхийг зөвлөж байна.
Эх сурвалж: Kubernetes Official Blog: Kubernetes v1.37: etcd RangeStream Cuts Memory Use on Large List Reads
Сэтгэгдэл
Ачаалж байна...