Kio estas Docker: mallonga ekskurso en historion kaj bazajn abstraktaĵojn

Komenciĝis la 10-an de aŭgusto en Slurm Videokurso de Docker, en kiu ni analizas ĝin tute - de bazaj abstraktaĵoj ĝis retaj parametroj.

En ĉi tiu artikolo ni parolos pri la historio de Docker kaj ĝiaj ĉefaj abstraktaĵoj: Image, Cli, Dockerfile. La prelego estas destinita por komencantoj, do ĝi verŝajne ne interesos spertajn uzantojn. Ne estos sango, apendico aŭ profunda mergo. La tre bazoj.

Kio estas Docker: mallonga ekskurso en historion kaj bazajn abstraktaĵojn

Kio estas Docker

Ni rigardu la difinon de Docker el Vikipedio.

Docker estas programaro por aŭtomatigi la deplojon kaj administradon de aplikoj en konteneritaj medioj.

Nenio klaras el ĉi tiu difino. Estas precipe neklare kio signifas "en medioj kiuj subtenas kontenerigon". Por ekscii, ni reiru en la tempo. Ni komencu kun la epoko, kiun mi konvencie nomas la "Monolitika Epoko".

Monolita epoko

La monolita epoko estas la fruaj 2000-aj jaroj, kiam ĉiuj aplikoj estis monolitaj, kun amaso da dependecoj. Evoluo daŭris longan tempon. Samtempe, ne estis multaj serviloj; ni ĉiuj konis ilin laŭnome kaj kontrolis ilin. Estas tia amuza komparo:

Dorlotbestoj estas hejmaj bestoj. En la monolita epoko, ni traktis niajn servilojn kiel dorlotbestojn, flegitajn kaj ŝatatajn, forblovante polverojn. Kaj por pli bona administrado de rimedoj, ni uzis virtualigon: ni prenis servilon kaj tranĉis ĝin en plurajn virtualajn maŝinojn, tiel certigante izolitecon de la medio.

Hypervisor-bazitaj virtualigsistemoj

Ĉiuj verŝajne aŭdis pri virtualigosistemoj: VMware, VirtualBox, Hyper-V, Qemu KVM, ktp. Ili provizas aplikaĵizolon kaj administradon de rimedoj, sed ili ankaŭ havas malavantaĝojn. Por fari virtualigon, vi bezonas hiperviziilon. Kaj la hiperviziero estas rimedo supre. Kaj la virtuala maŝino mem estas kutime tuta koloso - peza bildo enhavanta operaciumon, Nginx, Apache, kaj eble MySQL. La bildo estas granda kaj la virtuala maŝino estas maloportuna funkcii. Kiel rezulto, labori kun virtualaj maŝinoj povas esti malrapida. Por solvi ĉi tiun problemon, virtualigsistemoj estis kreitaj sur la kernnivelo.

Kernel-nivelaj virtualigsistemoj

Kernel-nivela virtualigo estas subtenata de OpenVZ, Systemd-nspawn, LXC-sistemoj. Frapa ekzemplo de tia virtualigo estas LXC (Linuksaj Ujoj).

LXC estas operaciumo-nivela virtualiga sistemo por prizorgi plurajn izolitajn kazojn de la Linukso operaciumo sur ununura nodo. LXC ne uzas virtualajn maŝinojn, sed kreas virtualan medion kun sia propra procezspaco kaj retstako.

Esence LXC kreas ujojn. Kio estas la diferenco inter virtualaj maŝinoj kaj ujoj?

Kio estas Docker: mallonga ekskurso en historion kaj bazajn abstraktaĵojn

La ujo ne taŭgas por izoli procezojn: vundeblecoj troviĝas en virtualigsistemoj ĉe la kernnivelo, kiuj permesas al ili eskapi de la ujo al la gastiganto. Tial, se vi bezonas izoli ion, estas pli bone uzi virtualan maŝinon.

La diferencoj inter virtualigo kaj kontenerigo povas esti viditaj en la diagramo.
Estas aparataj hiperviziiloj, hiperviziiloj supre de la OS kaj ujoj.

Kio estas Docker: mallonga ekskurso en historion kaj bazajn abstraktaĵojn

Aparataj hiperviziiloj estas bonegaj se vi vere volas izoli ion. Ĉar eblas izoli je la nivelo de memorpaĝoj kaj procesoroj.

Estas hiperviziiloj kiel programo, kaj estas ujoj, kaj ni parolos pri ili plu. Kontenigsistemoj ne havas hiperviziilon, sed ekzistas Container Engine kiu kreas kaj administras ujojn. Ĉi tiu afero estas pli malpeza, do pro laboro kun la kerno estas malpli superkompeto aŭ tute nenio.

Kio estas uzata por kontenerigo ĉe la kernnivelo

La ĉefaj teknologioj, kiuj permesas vin krei ujon izolitan de aliaj procezoj, estas Nomspacoj kaj Kontrolgrupoj.

Nomspacoj: PID, Reto, Monto kaj Uzanto. Estas pli, sed por facileco de kompreno ni koncentriĝos pri ĉi tiuj.

PID Nomspaco limigas procezojn. Kiam, ekzemple, ni kreas PID Nomspacon kaj metas procezon tie, ĝi fariĝas kun PID 1. Kutime en sistemoj PID 1 estas systemd aŭ init. Sekve, kiam ni metas procezon en novan nomspacon, ĝi ankaŭ ricevas PID 1.

Reta Nomspaco permesas vin limigi/izoli la reton kaj meti viajn proprajn interfacojn enen. Monto estas dosiersistemo limigo. Uzanto - limigo al uzantoj.

Kontrolgrupoj: Memoro, CPU, IOPS, Reto - ĉirkaŭ 12 agordoj entute. Alie ili ankaŭ nomiĝas C-grupoj ("C-grupoj").

Kontrolgrupoj administras rimedojn por ujo. Per Kontrolgrupoj ni povas diri, ke la ujo ne devus konsumi pli ol certan kvanton da rimedoj.

Por ke kontenerigo plene funkciu, aldonaj teknologioj estas uzataj: Kapabloj, Kopio-sur-skribi kaj aliaj.

Kapabloj estas kiam ni diras al procezo kion ĝi povas kaj ne povas fari. Je la kernnivelo, ĉi tiuj estas simple bitmapoj kun multaj parametroj. Ekzemple, la radika uzanto havas plenajn privilegiojn kaj povas fari ĉion. La temposervilo povas ŝanĝi la sisteman tempon: ĝi havas kapablojn sur la Tempokapsulo, kaj jen ĝi. Uzante privilegiojn, vi povas flekseble agordi limigojn por procezoj, kaj tiel protekti vin.

La sistemo Copy-on-write permesas al ni labori kun Docker-bildoj kaj uzi ilin pli efike.

Docker nuntempe havas kongruajn problemojn kun Cgroups v2, do ĉi tiu artikolo temigas specife Cgroups v1.

Sed ni revenu al la historio.

Kiam virtualigaj sistemoj aperis ĉe la kernnivelo, ili komencis esti aktive uzataj. La supre sur la hiperviziero malaperis, sed kelkaj problemoj restis:

  • grandaj bildoj: ili puŝas operaciumon, bibliotekojn, amason da malsamaj programoj en la saman OpenVZ, kaj finfine la bildo ankoraŭ montriĝas sufiĉe granda;
  • Ne ekzistas normala normo por pakado kaj livero, do la problemo de dependecoj restas. Estas situacioj kiam du pecoj de kodo uzas la saman bibliotekon, sed kun malsamaj versioj. Eble estas konflikto inter ili.

Por solvi ĉiujn ĉi tiujn problemojn, venis la sekva epoko.

Uja epoko

Kiam la Erao de Ujoj alvenis, la filozofio labori kun ili ŝanĝiĝis:

  • Unu procezo - unu ujo.
  • Ni liveras ĉiujn dependecojn, kiujn la procezo bezonas al sia ujo. Ĉi tio postulas tranĉi monolitojn en mikroservojn.
  • Ju pli malgranda estas la bildo, des pli bone - estas malpli da eblaj vundeblecoj, ĝi ruliĝas pli rapide, ktp.
  • Kazoj fariĝas efemeraj.

Memoru, kion mi diris pri dorlotbestoj kontraŭ brutaro? Antaŭe, ekzemploj estis kiel hejmaj bestoj, sed nun ili fariĝis kiel brutaro. Antaŭe, estis monolito - unu aplikaĵo. Nun temas pri 100 mikroservoj, 100 ujoj. Iuj ujoj povas havi 2-3 kopiojn. Fariĝas malpli grave por ni kontroli ĉiun ujon. Kio pli gravas por ni estas la havebleco de la servo mem: kion faras ĉi tiu aro de ujoj. Ĉi tio ŝanĝas alirojn al monitorado.

En 2014-2015, Docker prosperis - la teknologio pri kiu ni parolos nun.

Docker ŝanĝis la filozofion kaj normigis aplikaĵpakadon. Uzante Docker, ni povas paki aplikaĵon, sendi ĝin al deponejo, elŝuti ĝin de tie kaj disfaldi ĝin.

Ni metas ĉion, kion ni bezonas en la Docker-ujon, do la dependeca problemo estas solvita. Docker garantias reprodukteblecon. Mi pensas, ke multaj homoj renkontis neprodukteblecon: ĉio funkcias por vi, vi puŝas ĝin al produktado, kaj tie ĝi ĉesas funkcii. Kun Docker ĉi tiu problemo malaperas. Se via Docker-ujo komenciĝas kaj faras tion, kion ĝi bezonas fari, tiam kun alta probableco ĝi komencos en produktado kaj faros la samon tie.

Devastiĝo pri supre

Ĉiam estas disputoj pri superkostoj. Iuj homoj kredas, ke Docker ne portas plian ŝarĝon, ĉar ĝi uzas la Linuksan kernon kaj ĉiujn ĝiajn procezojn necesajn por kontenerigo. Kiel, "se vi diras, ke Docker estas superkapa, tiam la Linukso-kerno estas supre."

Aliflanke, se vi iras pli profunden, estas ja pluraj aferoj en Docker, kiuj, kun streĉado, povas diri, ke ili estas supre.

La unua estas PID-nomspaco. Kiam ni metas procezon en nomspacon, ĝi estas asignita PID 1. Samtempe, ĉi tiu procezo havas alian PID, kiu situas sur la gastiga nomspaco, ekster la ujo. Ekzemple, ni lanĉis Nginx en ujo, ĝi fariĝis PID 1 (majstra procezo). Kaj sur la gastiganto ĝi havas PID 12623. Kaj estas malfacile diri kiom da superkosto ĝi estas.

La dua afero estas Cgrupoj. Ni prenu C-grupojn per memoro, tio estas, la kapablon limigi la memoron de ujo. Kiam ĝi estas ebligita, nombriloj kaj memorkontado estas aktivigitaj: la kerno bezonas kompreni kiom da paĝoj estis asignitaj kaj kiom da ankoraŭ estas liberaj por ĉi tiu ujo. Ĉi tio eble estas supera kosto, sed mi ne vidis precizajn studojn pri kiel ĝi influas rendimenton. Kaj mi mem ne rimarkis, ke la aplikaĵo funkcianta en Docker subite spertis akran perdon de rendimento.

Kaj unu plia noto pri agado. Kelkaj kernaj parametroj estas transdonitaj de la gastiganto al la ujo. Aparte, iuj retaj parametroj. Sekve, se vi volas ruli ion alt-efikan en Docker, ekzemple, ion, kio aktive uzos la reton, tiam vi almenaŭ devas ĝustigi ĉi tiujn parametrojn. Iu nf_conntrack, ekzemple.

Pri la Docker-koncepto

Docker konsistas el pluraj komponentoj:

  1. Docker Daemon estas la sama Container Engine; lanĉas ujojn.
  2. Docker CII estas Docker-administra ilo.
  3. Dockerfile - instrukcioj pri kiel konstrui bildon.
  4. Bildo - la bildo el kiu la ujo estas rulita.
  5. Ujo.
  6. Docker-registro estas bilddeponejo.

Skeme ĝi aspektas kiel ĉi tio:

Kio estas Docker: mallonga ekskurso en historion kaj bazajn abstraktaĵojn

Docker-demono funkcias per Docker_host kaj lanĉas ujojn. Estas Kliento, kiu sendas komandojn: konstruu la bildon, elŝutu la bildon, lanĉu la ujon. Docker-demono iras al la registro kaj efektivigas ilin. La Docker-kliento povas aliri kaj loke (al Unikso-soko) kaj per TCP de fora gastiganto.

Ni trarigardu ĉiun komponanton.

Docker-demono - ĉi tio estas la servila parto, ĝi funkcias en la gastiga maŝino: elŝutas bildojn kaj lanĉas ujojn el ili, kreas reton inter ujoj, kolektas protokolojn. Kiam ni diras "krei bildon", la demono ankaŭ faras tion.

Docker CLI — Docker-klientoparto, konzola ilo por labori kun la demono. Mi ripetas, ĝi povas funkcii ne nur loke, sed ankaŭ tra la reto.

Bazaj komandoj:

docker ps - montru ujojn, kiuj nuntempe funkcias sur la Docker-gastiganto.
docker-bildoj - montru bildojn elŝutitajn loke.
docker search <> - serĉu bildon en la registro.
docker pull <> - elŝutu bildon de la registro al la maŝino.
docker konstruo < > - kolektu la bildon.
docker run <> - lanĉi la ujon.
docker rm <> - forigu la ujon.
docker protokoloj <> - uj protokoloj
docker start/stop/restart <> - laborante kun la ujo

Se vi regas ĉi tiujn komandojn kaj certas uzi ilin, konsideru vin 70% scipova pri Docker ĉe la uzantnivelo.

dockerfile - instrukcioj por krei bildon. Preskaŭ ĉiu instrukcia komando estas nova tavolo. Ni rigardu ekzemplon.

Kio estas Docker: mallonga ekskurso en historion kaj bazajn abstraktaĵojn

Jen kiel aspektas la Dockerfile: komandoj maldekstre, argumentoj dekstre. Ĉiu komando kiu estas ĉi tie (kaj ĝenerale skribita en la Dockerfile) kreas novan tavolon en Bildo.

Eĉ rigardante la maldekstran flankon, vi povas proksimume kompreni kio okazas. Ni diras: "kreu dosierujon por ni" - ĉi tio estas unu tavolo. "Faru la dosierujon" estas alia tavolo, ktp. Tavola kuko faciligas la vivon. Se mi kreas alian Dockerfile kaj ŝanĝas ion en la lasta linio - mi rulas ion alian ol "python" "main.py", aŭ instalas dependecojn de alia dosiero - tiam la antaŭaj tavoloj estos reuzitaj kiel kaŝmemoro.

bildo - ĉi tio estas ujo-pakaĵo; ujoj estas lanĉitaj de la bildo. Se ni rigardas Docker el la vidpunkto de pakaĵmanaĝero (kvazaŭ ni laborus kun deb aŭ rpm-pakaĵoj), tiam bildo estas esence rpm-pakaĵo. Per yum install ni povas instali la aplikaĵon, forigi ĝin, trovi ĝin en la deponejo kaj elŝuti ĝin. Ĉi tie temas pri la sama: ujoj estas lanĉitaj de la bildo, ili estas konservitaj en la Docker-registro (simila al yum, en deponejo), kaj ĉiu bildo havas SHA-256-haŝiŝon, nomon kaj etikedon.

Bildo estas konstruita laŭ la instrukcioj de la Dockerfile. Ĉiu instrukcio de la Dockerfile kreas novan tavolon. Tavoloj povas esti reuzitaj.

Docker-registro estas Docker-bilddeponejo. Simile al la OS, Docker havas publikan norman registron - dockerhub. Sed vi povas konstrui vian propran deponejon, vian propran Docker-registron.

ujo - kio estas lanĉita de la bildo. Ni konstruis bildon laŭ la instrukcioj de la Dockerfile, tiam ni lanĉas ĝin de ĉi tiu bildo. Ĉi tiu ujo estas izolita de aliaj ujoj kaj devas enhavi ĉion necesan por ke la aplikaĵo funkciu. En ĉi tiu kazo, unu ujo - unu procezo. Okazas, ke vi devas fari du procezojn, sed ĉi tio estas iom kontraŭa al la ideologio de Docker.

La postulo "unu ujo, unu procezo" rilatas al la PID Nomspaco. Kiam procezo kun PID 1 komenciĝas en Nomspaco, se ĝi subite mortas, tiam ankaŭ la tuta ujo mortas. Se du procezoj funkcias tie: unu estas viva kaj la alia estas morta, tiam la ujo daŭre vivos. Sed ĉi tio estas demando de Plej bonaj Praktikoj, pri ili ni parolos en aliaj materialoj.

Por studi la funkciojn kaj plenan programon de la kurso pli detale, bonvolu sekvi la ligilon: "Videokurso de Docker".

Aŭtoro: Marcel Ibraev, atestita administranto de Kubernetes, praktikanta inĝeniero ĉe Southbridge, parolanto kaj programisto de Slurm-kursoj.

fonto: www.habr.com

Aldoni komenton