Kaj je Docker: kratek izlet v zgodovino in osnovne abstrakcije

Začetek 10. avgusta v Slurmu Video tečaj Docker, v katerem ga analiziramo v celoti – od osnovnih abstrakcij do omrežnih parametrov.

V tem članku bomo govorili o zgodovini Dockerja in njegovih glavnih abstrakcijah: Image, Cli, Dockerfile. Predavanje je namenjeno začetnikom, zato izkušenim uporabnikom verjetno ne bo zanimivo. Ne bo krvi, slepiča ali globoke potopitve. Same osnove.

Kaj je Docker: kratek izlet v zgodovino in osnovne abstrakcije

Kaj je Docker

Poglejmo definicijo Dockerja iz Wikipedije.

Docker je programska oprema za avtomatizacijo uvajanja in upravljanja aplikacij v kontejnerskih okoljih.

Iz te definicije ni nič jasno. Še posebej ni jasno, kaj pomeni "v okoljih, ki podpirajo kontejnerizacijo". Če želite izvedeti, se vrnimo v preteklost. Začnimo z obdobjem, ki ga običajno imenujem »doba monolita«.

Monolitna doba

Monolitno obdobje je zgodnje 2000-ih, ko so bile vse aplikacije monolitne, s kupom odvisnosti. Razvoj je trajal dolgo. Hkrati pa strežnikov ni bilo veliko, vse smo poznali po imenu in jih spremljali. Obstaja tako smešna primerjava:

Hišni ljubljenčki so domače živali. V monolitni dobi smo naše strežnike obravnavali kot hišne ljubljenčke, negovane in negovane ter odpihovale delce prahu. Za boljše upravljanje virov pa smo uporabili virtualizacijo: vzeli smo strežnik in ga razrezali na več virtualnih strojev ter s tem zagotovili izolacijo okolja.

Virtualizacijski sistemi, ki temeljijo na hipervizorjih

Verjetno je že vsak slišal za virtualizacijske sisteme: VMware, VirtualBox, Hyper-V, Qemu KVM itd. Omogočajo izolacijo aplikacij in upravljanje virov, vendar imajo tudi slabosti. Za virtualizacijo potrebujete hipervizor. In hipervizor je strošek vira. In sam virtualni stroj je običajno cel kolos - težka slika, ki vsebuje operacijski sistem, Nginx, Apache in morda MySQL. Slika je velika in virtualni stroj je nepriročen za uporabo. Posledično je lahko delo z virtualnimi stroji počasno. Da bi rešili to težavo, so bili ustvarjeni virtualizacijski sistemi na ravni jedra.

Virtualizacijski sistemi na ravni jedra

Virtualizacijo na ravni jedra podpirajo sistemi OpenVZ, Systemd-nspawn, LXC. Osupljiv primer takšne virtualizacije je LXC (Linux Containers).

LXC je virtualizacijski sistem na ravni operacijskega sistema za izvajanje več izoliranih primerkov operacijskega sistema Linux na enem vozlišču. LXC ne uporablja virtualnih strojev, ampak ustvari virtualno okolje z lastnim procesnim prostorom in omrežnim skladom.

V bistvu LXC ustvarja vsebnike. Kakšna je razlika med virtualnimi stroji in vsebniki?

Kaj je Docker: kratek izlet v zgodovino in osnovne abstrakcije

Vsebnik ni primeren za izolacijo procesov: v virtualizacijskih sistemih na ravni jedra so najdene ranljivosti, ki jim omogočajo, da pobegnejo iz vsebnika na gostitelja. Zato, če morate nekaj izolirati, je bolje uporabiti virtualni stroj.

Razlike med virtualizacijo in kontejnerizacijo so vidne na diagramu.
Obstajajo hipervizorji strojne opreme, hipervizorji na vrhu OS in vsebniki.

Kaj je Docker: kratek izlet v zgodovino in osnovne abstrakcije

Strojni hipervizorji so kul, če res želite nekaj izolirati. Ker je možna izolacija na ravni pomnilniških strani in procesorjev.

Obstajajo hipervizorji kot program in obstajajo vsebniki, o katerih bomo še govorili. Sistemi za kontejnerizacijo nimajo hipervizorja, vendar obstaja Container Engine, ki ustvarja in upravlja kontejnerje. Ta stvar je lažja, zato je zaradi dela z jedrom manj stroškov ali pa jih sploh ni.

Kaj se uporablja za kontejnerizacijo na ravni jedra

Glavne tehnologije, ki vam omogočajo ustvarjanje vsebnika, izoliranega od drugih procesov, so imenski prostori in nadzorne skupine.

Imenski prostori: PID, Networking, Mount in User. Teh je več, vendar se bomo zaradi lažjega razumevanja osredotočili na te.

Imenski prostor PID omejuje procese. Ko na primer ustvarimo imenski prostor PID in tja postavimo proces, ta postane s PID 1. Običajno je v sistemih PID 1 systemd ali init. V skladu s tem, ko proces postavimo v nov imenski prostor, prejme tudi PID 1.

Omrežni imenski prostor vam omogoča, da omejite/izolirate omrežje in vanj postavite lastne vmesnike. Pripenjanje je omejitev datotečnega sistema. Uporabnik—omejitev uporabnikov.

Nadzorne skupine: Pomnilnik, CPE, IOPS, Omrežje - skupaj približno 12 nastavitev. Drugače jih imenujemo tudi C-skupine (»C-skupine«).

Nadzorne skupine upravljajo vire za vsebnik. Preko kontrolnih skupin lahko rečemo, da vsebnik ne sme porabiti več kot določeno količino virov.

Za polno delovanje kontejnerizacije se uporabljajo dodatne tehnologije: zmogljivosti, kopiranje ob pisanju in druge.

Zmogljivosti so, ko procesu povemo, kaj lahko in česa ne. Na ravni jedra so to preprosto bitne slike s številnimi parametri. Uporabnik root ima na primer polne pravice in lahko naredi vse. Časovni strežnik lahko spremeni sistemski čas: ima zmožnosti na Time Capsule in to je to. S privilegiji lahko prilagodljivo nastavite omejitve za procese in se s tem zaščitite.

Sistem Copy-on-write nam omogoča delo s slikami Docker in njihovo učinkovitejšo uporabo.

Docker ima trenutno težave z združljivostjo s Cgroups v2, zato se ta članek osredotoča posebej na Cgroups v1.

A vrnimo se k zgodovini.

Ko so se virtualizacijski sistemi pojavili na ravni jedra, so se začeli aktivno uporabljati. Režija na hipervizorju je izginila, nekaj težav pa je ostalo:

  • velike slike: v isti OpenVZ potisnejo operacijski sistem, knjižnice, kup različnega programja, na koncu pa slika vseeno izpade kar velika;
  • Normalnega standarda za pakiranje in dostavo ni, zato ostaja problem odvisnosti. Obstajajo situacije, ko dva dela kode uporabljata isto knjižnico, vendar z različnimi različicami. Med njima lahko pride do konflikta.

Za rešitev vseh teh težav je prišlo naslednje obdobje.

Obdobje zabojnikov

Ko je nastopila doba zabojnikov, se je filozofija dela z njimi spremenila:

  • En proces - ena posoda.
  • Vse odvisnosti, ki jih proces potrebuje, dostavimo v njegov vsebnik. To zahteva rezanje monolitov v mikrostoritve.
  • Manjša ko je slika, bolje je – manj je možnih ranljivosti, hitreje se pojavi itd.
  • Primeri postanejo minljivi.

Se spomnite, kaj sem rekel o hišnih ljubljenčkih proti govedu? Prej so bili primerki kot domače živali, zdaj pa so postali kot govedo. Prej je bil monolit - ena aplikacija. Zdaj je 100 mikrostoritev, 100 vsebnikov. Nekateri vsebniki imajo lahko 2-3 replike. Za nas postane manj pomembno, da nadzorujemo vsako posodo. Bolj pomembna nam je razpoložljivost same storitve: kaj ta nabor vsebnikov počne. To spreminja pristope k spremljanju.

V letih 2014–2015 je cvetel Docker – tehnologija, o kateri bomo zdaj govorili.

Docker je spremenil filozofijo in standardiziral embalažo aplikacij. Z uporabo Dockerja lahko zapakiramo aplikacijo, jo pošljemo v repozitorij, prenesemo od tam in razmestimo.

Vse, kar potrebujemo, damo v vsebnik Docker, tako da je problem odvisnosti rešen. Docker zagotavlja ponovljivost. Mislim, da se je veliko ljudi srečalo z neponovljivostjo: vse ti dela, potisneš v proizvodnjo, tam pa preneha delovati. Z Dockerjem ta težava izgine. Če se vaš vsebnik Docker zažene in naredi, kar mora, potem se bo z veliko verjetnostjo začel v produkciji in tam naredil enako.

Digresija o režijskih stroških

Vedno so spori glede režijskih stroškov. Nekateri verjamejo, da Docker ne nosi dodatne obremenitve, saj uporablja jedro Linuxa in vse njegove procese, potrebne za kontejnerizacijo. Na primer, "če rečete, da je Docker prevelik, potem je jedro Linuxa preveliko."

Po drugi strani pa, če greste globlje, je v Dockerju res več stvari, za katere lahko rečemo, da so prevelike.

Prvi je imenski prostor PID. Ko proces postavimo v imenski prostor, mu dodelimo PID 1. Hkrati ima ta proces še en PID, ki se nahaja na imenskem prostoru gostitelja, izven vsebnika. Na primer, zagnali smo Nginx v vsebniku, postal je PID 1 (glavni proces). In na gostitelju ima PID 12623. In težko je reči, koliko režijskih stroškov je to.

Druga stvar so Cgroups. Vzemimo Cgroups po pomnilniku, to je zmožnost omejitve pomnilnika vsebnika. Ko je omogočeno, se aktivirajo števci in obračunavanje pomnilnika: jedro mora razumeti, koliko strani je bilo dodeljenih in koliko jih je še prostih za ta vsebnik. To so morda dodatni stroški, vendar nisem videl nobenih natančnih študij o tem, kako to vpliva na uspešnost. In sam nisem opazil, da je aplikacija, ki se izvaja v Dockerju, nenadoma močno izgubila zmogljivost.

In še ena opomba glede delovanja. Nekateri parametri jedra se prenesejo iz gostitelja v vsebnik. Zlasti nekateri omrežni parametri. Torej, če želite zagnati nekaj visoko zmogljivega v Dockerju, na primer nekaj, kar bo aktivno uporabljalo omrežje, potem morate prilagoditi vsaj te parametre. Nekaj ​​nf_conntrack, na primer.

O konceptu Docker

Docker je sestavljen iz več komponent:

  1. Docker Daemon je isti Container Engine; izstreljuje kontejnerje.
  2. Docker CII je pripomoček za upravljanje Dockerja.
  3. Dockerfile - navodila za izdelavo slike.
  4. Slika — slika, iz katere se zvije vsebnik.
  5. Zabojnik.
  6. Docker register je repozitorij slik.

Shematično je videti nekako takole:

Kaj je Docker: kratek izlet v zgodovino in osnovne abstrakcije

Demon Docker deluje na Docker_host in zaganja vsebnike. Obstaja odjemalec, ki pošilja ukaze: sestavite sliko, prenesite sliko, zaženite vsebnik. Docker daemon gre v register in jih izvede. Odjemalec Docker lahko dostopa tako lokalno (do vtičnice Unix) kot prek TCP z oddaljenega gostitelja.

Pojdimo skozi vsako komponento.

Docker demon - to je strežniški del, deluje na gostiteljskem stroju: prenaša slike in zaganja vsebnike iz njih, ustvarja mrežo med vsebniki, zbira dnevnike. Ko rečemo "ustvari podobo", demon počne tudi to.

Docker CLI — Odjemalski del Dockerja, konzolni pripomoček za delo z demonom. Ponavljam, lahko deluje ne samo lokalno, ampak tudi prek omrežja.

Osnovni ukazi:

docker ps - pokaži vsebnike, ki se trenutno izvajajo na gostitelju Docker.
docker slike - prikaži slike, prenesene lokalno.
docker search <> - iskanje slike v registru.
docker pull <> - prenesite sliko iz registra na stroj.
docker build < > - zberi sliko.
docker run <> - zagon vsebnika.
docker rm <> - odstranite vsebnik.
docker logs <> - vsebniški dnevniki
docker start/stop/restart <> - delo z vsebnikom

Če obvladate te ukaze in ste prepričani v njihovo uporabo, se smatrajte za 70-odstotnega strokovnjaka Dockerja na ravni uporabnika.

Dockerfile - navodila za izdelavo slike. Skoraj vsak ukaz z navodili je nova plast. Poglejmo si primer.

Kaj je Docker: kratek izlet v zgodovino in osnovne abstrakcije

Tako izgleda datoteka Dockerfile: ukazi na levi, argumenti na desni. Vsak ukaz, ki je tukaj (in na splošno zapisan v datoteki Docker), ustvari novo plast v sliki.

Tudi če pogledate levo stran, lahko približno razumete, kaj se dogaja. Pravimo: "ustvarite mapo za nas" - to je ena plast. »Naredi mapo delujočo« je druga plast in tako naprej. Večplastna torta olajša življenje. Če ustvarim drugo datoteko Dockerfile in spremenim nekaj v zadnji vrstici - zaženem nekaj drugega kot "python" "main.py" ali namestim odvisnosti iz druge datoteke - bodo prejšnje plasti ponovno uporabljene kot predpomnilnik.

Image - to je kontejnerska embalaža, kontejnerji se izstrelijo iz slike. Če na Docker pogledamo z vidika upravitelja paketov (kot če bi delali s paketi deb ali rpm), potem je image v bistvu paket rpm. Z yum install lahko namestimo aplikacijo, jo izbrišemo, poiščemo v repozitoriju in prenesemo. Tukaj je približno enako: vsebniki so zagnani iz slike, shranjeni so v registru Docker (podobno kot yum, v repozitoriju), vsaka slika pa ima zgoščeno vrednost SHA-256, ime in oznako.

Slika je zgrajena v skladu z navodili iz datoteke Docker. Vsako navodilo iz datoteke Dockerfile ustvari novo plast. Plasti se lahko ponovno uporabijo.

Docker register je skladišče slik Docker. Podobno kot OS ima Docker javni standardni register - dockerhub. Lahko pa zgradite svoje lastno skladišče, svoj lasten register Docker.

Posoda - kaj se sproži iz slike. Zgradili smo sliko po navodilih iz datoteke Dockerfile, nato pa jo zaženemo iz te slike. Ta vsebnik je izoliran od drugih vsebnikov in mora vsebovati vse, kar je potrebno za delovanje aplikacije. V tem primeru en vsebnik - en proces. Zgodi se, da morate narediti dva procesa, vendar je to nekoliko v nasprotju z ideologijo Docker.

Zahteva "en vsebnik, en proces" je povezana z imenskim prostorom PID. Ko se proces s PID 1 zažene v imenskem prostoru, če nenadoma umre, umre tudi celoten vsebnik. Če se tam izvajata dva procesa: eden je živ in drugi mrtev, bo vsebnik še vedno živel. Toda to je vprašanje najboljših praks, o njih bomo govorili v drugih materialih.

Če želite podrobneje preučiti značilnosti in celoten program tečaja, sledite povezavi: “Video tečaj Docker".

Avtor: Marcel Ibraev, certificirani skrbnik Kubernetes, inženir v Southbridgeu, govorec in razvijalec tečajev Slurm.

Vir: www.habr.com

Dodaj komentar