paint-brush
A Kubernetes optimalizálása a nagy Docker-képekhezáltal@kksudo
Új történelem

A Kubernetes optimalizálása a nagy Docker-képekhez

által Kazakov Kirill10m2024/09/30
Read on Terminal Reader

Túl hosszú; Olvasni

🚀 Kubernetes varázslók, belefáradtál abba, hogy órákat kell várnod, amíg a csomópontok felmelegednek? Képzelje el, hogy ezt az időt másodpercekre csökkenti! Ez a játékot megváltoztató cikk bemutatja, hogyan lehet felturbózni a Kubernetes telepítési folyamatát, még hatalmas 3 GB-os képek és 1000 pod esetén is. Fedezze fel a titkos szószt, amely a fürt teljesítményét lomháról szuperszonikusra változtatja. Ne hagyja, hogy a lassú bemelegítés visszatartson – tanulja meg, hogyan forradalmasíthatja Kubernetes munkafolyamatát még ma!
featured image - A Kubernetes optimalizálása a nagy Docker-képekhez
Kazakov Kirill HackerNoon profile picture
0-item

A probléma rövid áttekintése

Egy nap, a k8s-fürt tervezett frissítése során felfedeztük, hogy szinte az összes POD-unk (1000-ből körülbelül 500) az új csomópontokon nem tudott elindulni, és a percek gyorsan órákká váltak. Aktívan keressük a kiváltó okot, de három óra elteltével a PODS-ek még mindig ContainerCreating állapotban voltak.


A Kubernetes megragadt a ContainerCreating-nél

Szerencsére ez nem a prod környezet volt, és a karbantartási időszakot a hétvégére ütemezték. Volt időnk nyomás nélkül kivizsgálni a kérdést.

Hol kezdje a kiváltó ok keresését? Szeretne többet megtudni az általunk talált megoldásról? Kapcsold be és élvezd!

További részletek a problémáról

A probléma az volt, hogy nagyszámú docker-képünk volt, amelyeket egyszerre kellett lehúzni és elindítani a fürt minden csomópontján. Ennek az az oka, hogy az egy csomóponton végzett többszöri, egyidejű dokkolókép-letöltés magas lemezkihasználáshoz és meghosszabbított hidegindítási időhöz vezethet.


A CD-feldolgozás időnként akár 3 órát is igénybe vesz a képek előhívásához. Ezúttal azonban ez teljesen elakadt, mert az EKS frissítés során (inline, amikor a fürt összes csomópontját cseréljük) túl magas volt a PODS mennyisége.


  • Minden alkalmazásunk a k8s-ban él ( EKS alapú). A DEV env költségeinek megtakarítása érdekében spot példányokat használunk.

  • A csomópontokhoz az AmazonLinux2 képet használjuk.

  • A fejlesztői környezetben számos szolgáltatási ág (FB) található, amelyeket folyamatosan telepítünk Kubernetes-fürtünkre. Minden FB-nek megvannak a saját alkalmazáskészletei, és minden alkalmazásnak megvannak a saját függőségei (egy képen belül).

  • Projektünkben közel 200 alkalmazás, és ez a szám növekszik. Mindegyik alkalmazás a 7 ~2 GB méretű docker alapkép egyikét használja. Az archivált kép maximális teljes mérete (az ECR -ben) körülbelül 3 GB.

  • Az összes képet az Amazon Elastic Container Registry (ECR) tárolja.

  • A csomópontokhoz az alapértelmezett gp3 EBS kötettípust használjuk.


Problémák

  • Meghosszabbított hidegindítási idő: Egy új képsor új indítása több mint 1 órát is igénybe vehet, különösen akkor, ha több képet húznak egyszerre egy csomóponton.

  • ErrImagePull hibák: Gyakori ErrImagePull vagy beragad a ContainerCreating állapotoknál, ami a képlehívással kapcsolatos problémákra utal.

  • Magas lemezkihasználás: A lemezkihasználtság 100% közelében marad a képletöltési folyamat során, elsősorban a kibontáshoz szükséges intenzív lemez I/O miatt (pl. „unpigz”).

  • System DaemonSet problémák: Egyes rendszer DaemonSets (például aws-node vagy ebs-csi-node ) "nem kész" állapotba került a lemeznyomás miatt, ami befolyásolja a csomópont készenlétét.

  • Nincs képgyorsítótár a csomópontokon: Mivel spot példányokat használunk, nem használhatjuk a helyi lemezt a képek gyorsítótárazására.


Ez sok elakadt központi telepítést eredményez a szolgáltatási ágakon, különösen azért, mert a különböző FB-k eltérő alapképkészletekkel rendelkeznek.

Gyors vizsgálat után azt találtuk, hogy a fő probléma az unpigz folyamat által a csomópontokra nehezedő lemeznyomás volt. Ez a folyamat felelős a docker képek kicsomagolásáért. A gp3 EBS kötettípus alapbeállításait nem változtattuk meg, mert esetünkben nem megfelelőek.


Gyorsjavítás a fürt helyreállításához

Első lépésként úgy döntöttünk, hogy csökkentjük a POD-ok számát a csomópontokon.

  1. Az új csomópontokat „Cordon” állapotba helyezzük
  2. Távolítson el minden elakadt PODS-t a lemeznyomás csökkentése érdekében
  3. Futtassa egyenként a POD-okat a csomópontok bemelegítéséhez
  4. Ezt követően a felmelegedett csomópontokat normál állapotba ("unCordon") mozgatjuk.
  5. Az összes beragadt állapotú csomópont eltávolítva
  6. Az összes PODS sikeresen elkezdte használni a Docker kép-gyorsítótárat


Eredeti CI/CD dizájn

A megoldás fő ötlete az, hogy a CD-folyamat megkezdése előtt felmelegítsük a csomópontokat a docker image (JS függőségi réteg) legnagyobb részével, amely az összes alkalmazásunk gyökérképeként használható. Legalább 7 fajta gyökérképünk van a JS-függőségekkel, amelyek az alkalmazás típusához kapcsolódnak. Tehát elemezzük az eredeti CI/CD dizájnt.


CI/CD folyamatunkban 3 pillérünk van: Eredeti CI/CD pipeline

Eredeti CI/CD csővezeték:

  1. Az Init it lépésben: előkészítjük a környezetet/változókat, meghatározzuk az újraépítendő képek halmazát, stb...

  2. Az Build lépésben: megépítjük a képeket, és eltoljuk őket az ECR-hez

  3. A Deploy lépésnél: telepítjük a képeket a k8s-ba (frissítési telepítések stb.)


További részletek az eredeti CICD dizájnról:

  • Szolgáltatási fiókjaink (FB) a main ágból kiágaztak. A CI folyamatban mindig elemezzük az FB-ben módosított képkészletet, és újraépítjük azokat. A main ág mindig stabil, a definíció szerint mindig az alapképek legfrissebb verziójának kell lennie.
  • Külön építjük fel a JS-függőségek docker-képeit (minden környezethez), és továbbítjuk az ECR-hez, hogy újra felhasználhassuk gyökér (alap) képként a Dockerfile-ban. Körülbelül 5–10 típusú JS-függőségi dokkolókép áll rendelkezésünkre.
  • Az FB a k8s fürtbe kerül a külön névtérbe, de az FB közös csomópontjaiba. Az FB-n ~200 alkalmazás lehet, a képméret akár 3 GB is lehet.
  • Rendelkezünk a fürt automatikus skálázó rendszerével, amely a terhelés vagy a függőben lévő PODS-ek alapján skálázza a fürt csomópontjait a megfelelő nodeSelectorral és toleranciával.
  • A csomópontokhoz a spot példányokat használjuk.

A bemelegítési folyamat végrehajtása

A bemelegítési folyamatnak vannak követelményei.

Kötelező:

  1. Problémamegoldás : Megoldja és megoldja ContainerCreating problémákat.
  2. Továbbfejlesztett teljesítmény : Jelentősen csökkenti az indítási időt az előmelegített alapképek (JS-függőségek) használatával.

Örülök, hogy vannak fejlesztések:

  1. Rugalmasság : Lehetővé teszi a csomópont típusának és élettartamának egyszerű megváltoztatását (pl. magas SLA vagy hosszabb élettartam).
  2. Átlátszóság : Világos mérőszámokat biztosít a használatról és a teljesítményről.
  3. Költséghatékonyság : Költséget takarít meg a VNG azonnali törlésével, miután a kapcsolódó szolgáltatási ágat törölték.
  4. Izoláció : Ez a megközelítés biztosítja, hogy más környezeteket ne érintsen.

Megoldás

A követelmények és megszorítások elemzése után úgy döntöttünk, hogy egy bemelegítő folyamatot hajtunk végre, amely előmelegíti a csomópontokat az alap JS gyorsítótár-képekkel. Ez a folyamat a CD-folyamat megkezdése előtt indul el, biztosítva, hogy a csomópontok készen álljanak az FB telepítésére, és maximális esélyünk legyen a gyorsítótár eléréséhez.


Ezt a fejlesztést nagy lépésekre bontjuk:

  1. Hozza létre a csomópontok készletét (virtuális csomópontcsoport) minden egyes FB-nként

  2. Adjon hozzá alapképeket az új csomópontok felhő-init parancsfájljához

  3. Adjon hozzá egy telepítés előtti lépést a DaemonSet futtatásához az initContainers szakaszsal, hogy a CD-folyamat megkezdése előtt letöltse a szükséges dokkolóképeket a csomópontokra.


Egy frissített CI/CD folyamat így néz ki: Frissített CI/CD folyamat


Frissített CI/CD folyamat:

  1. Init lépés
    1.1. (új lépés) Telepítés megkezdése : Ha ez az FB első indítása, akkor hozzon létre egy új személyes csomópont-példánykészletet (a mi fogalmaink szerint ez Virtual Node Group vagy VNG), és töltse le az összes JS alapképet (5–10 kép). ) a főágról. Elég jogos megtenni, mert elágaztuk a FB-t a főfiókból. Fontos szempont, hogy ez nem blokkoló művelet.
  2. Építési lépés
  3. Telepítés előtti lépés Töltse le a frissen elkészített JS-alapképeket az adott FB-címkével az ECR-ből.
    3.1.(új lépés) Fontos tudnivalók : Ez egy blokkoló művelet, mert csökkenteni kell a lemeznyomást. Egyesével letöltjük az alapképeket minden kapcsolódó csomóponthoz.
    Btw, köszönjük az „ init deploy” lépést, már megvannak az alap docker image-ek a főágból, vagyis nagy esélyünk van arra, hogy az első indításkor elérjük a gyorsítótárat.
  4. ** Telepítés
    ** Ebben a lépésben nincs változás. De az előző lépésnek köszönhetően már minden nehéz docker képrétegünk van a szükséges csomópontokon.

Init telepítési lépés

Hozzon létre egy új csomópontkészletet minden egyes FB-hez API-híváson keresztül (a harmadik fél automatikus skálázó rendszeréhez) a CI-folyamatból.


Megoldott problémák:

  1. Izoláció : Minden FB-nek saját csomópontkészlete van, biztosítva, hogy a környezetet ne befolyásolják más FB-k.

  2. Rugalmasság : Könnyen megváltoztathatjuk a csomópont típusát és élettartamát.

  3. Költséghatékonyság : Az FB törlése után azonnal törölhetjük a csomópontokat.

  4. Átlátszóság : Könnyen nyomon követhetjük a csomópontok használatát és teljesítményét (minden csomóponton van egy FB-hez kapcsolódó tag).

  5. A spot példányok hatékony használata : A spot példány már előre definiált alapképekkel indul, vagyis a spot csomópont indulása után már ott vannak az alapképek a csomóponton (a fő ágból).


Töltse le az összes JS-alapképet a fő ágból az új csomópontokba cloud-init parancsfájl segítségével.


Amíg a képek letöltése folyamatban van a háttérben, a CD-folyamat gond nélkül folytathatja az új képek létrehozását. Sőt, ebből a csoportból a következő csomópontok (amelyeket az automatikus skálázási rendszer hoz létre) a frissített cloud-init adatokkal jönnek létre, amelyek már rendelkeznek utasításokkal a képek letöltéséhez az indítás előtt.


Megoldott problémák:

  1. Problémamegoldás : A lemeznyomás megszűnt, mert frissítettük a cloud-init szkriptet az alapképek letöltésének hozzáadásával a fő ágból. Ez lehetővé teszi, hogy az FB első indításakor elérjük a gyorsítótárat.

  2. A helyszíni példányok hatékony használata : A helyszíni példány frissített cloud-init adatokkal indul. Ez azt jelenti, hogy a spot csomópont indulása után már ott vannak az alapképek a csomóponton (a fő ágból).

  3. Továbbfejlesztett teljesítmény : A CD-folyamat gond nélkül folytathatja az új lemezképek létrehozását.


Ez a művelet körülbelül 17 másodpercet (API-hívást) adott a CI/CD folyamatunkhoz.

Ennek a műveletnek csak az első alkalommal van értelme, amikor elindítjuk az FB-t. Legközelebb a már meglévő csomópontokra telepítjük alkalmazásainkat, amelyek már rendelkeznek az előző telepítéskor szállított alapképekkel.

Telepítés előtti lépés

Erre a lépésre azért van szükségünk, mert az FB képek eltérnek a fő ágképektől. A CD-folyamat megkezdése előtt le kell töltenünk az FB alapképeket a csomópontokra. Ez segít csökkenteni a hosszabb hidegindítási időket és a magas lemezkihasználást, amely akkor fordulhat elő, ha több nehéz képet egyszerre húznak ki.


A bevezetés előtti lépés céljai

  1. Lemeznyomás megelőzése : A docker legnehezebb képeinek szekvenciális letöltése. Az init-deploy lépés után már megvannak az alapképek a csomópontokon, ami azt jelenti, hogy nagy esélyünk van a találati gyorsítótárra.

  2. A telepítési hatékonyság javítása : Győződjön meg róla, hogy a csomópontok előmelegítve vannak az alapvető docker-képekkel, ami gyorsabb (szinte azonnali) POD-indítási időt eredményez.

  3. Stabilitás növelése : Csökkentse az ErrImagePull / ContainerCreating hibák előfordulásának esélyét, és biztosítsa, hogy a rendszerdémonkészletek „kész” állapotban maradjanak.


Ebben a lépésben 10–15 percet adunk a CD-folyamathoz.

Telepítés előtti lépés részletei:

  • A CD-n létrehozunk egy DaemonSet-et az initContainers szekcióval.
  • Az initContainers szakasz a fő tároló elindulása előtt lefut, biztosítva, hogy a szükséges képek letöltésre kerüljenek a fő tároló indulása előtt.
  • A CD-n folyamatosan ellenőrizzük a daemonSet állapotát. Ha a daemonSet „kész” állapotban van, akkor folytatjuk a telepítést. Ellenkező esetben megvárjuk, amíg a daemonSet készen áll.

Összehasonlítás

Az eredeti és frissített lépések összehasonlítása az előmelegítési folyamattal.

Lépés

Init telepítési lépés

Telepítés előtti lépés

Telepítés

Teljes idő

Diff

Előmelegítés nélkül

0

0

11h 21s

11h 21s

0

Előmelegítéssel

8 másodperc

58 másodperc

25 másodperc

1h 31s

-9m 50s


A lényeg, hogy a „Deploy” idő megváltozott (az első alkalmazás parancstól a podok futási állapotáig) 11 perc 21 másodpercről 25 másodpercre. A teljes idő 11 óra 21 másodpercről 1 óra 31 másodpercre változott.

Fontos szempont, hogy ha nincsenek alapképek a fő ágból, akkor a „Deploy” ideje megegyezik az eredeti időponttal, vagy kicsit több. De mindenesetre megoldottuk a lemeznyomással és a hidegindítási idővel kapcsolatos problémát.


Következtetés A húzási idő

A ContainerCreating fő problémáját a bemelegítési folyamat megoldotta. Előnyként jelentősen csökkentettük a POD-ok hidegindítási idejét.
A lemeznyomás megszűnt, mert már megvannak az alapképek a csomópontokon. A rendszer démonSets „kész” és „egészséges” állapotban van (mivel nincs lemeznyomás), és nem találkoztunk ezzel a problémával kapcsolatos ErrImagePull hibával.


Lehetséges megoldások és linkek


PS: Szeretnék köszönetet mondani a Justt nagyszerű technikai csapatának ( https://www.linkedin.com/company/justt-ai ) fáradhatatlan munkájukért és igazán kreatív hozzáállásukért minden problémához, amellyel szembesülnek. vel. Különösen Ronny Sharaby-nak, a kiváló vezetőnek, aki felelős a csapat által végzett nagyszerű munkáért. Alig várom, hogy egyre több nagyszerű példát láthassak arra vonatkozóan, hogy az Ön kreativitása hogyan hat a Justt termékre.