Dobro razmislite prije upotrebe Docker-in-Docker za CI ili testno okruženje

Dobro razmislite prije upotrebe Docker-in-Docker za CI ili testno okruženje

Docker-in-Docker je virtualizirano okruženje Docker demona koje radi unutar samog spremnika za izradu slika spremnika. Glavna svrha stvaranja Docker-in-Docker bila je pomoć u razvoju samog Dockera. Mnogi ga ljudi koriste za pokretanje Jenkins CI. To se u početku čini normalnim, ali onda se pojavljuju problemi koji se mogu izbjeći instaliranjem Dockera u Jenkinsov CI spremnik. Ovaj vam članak govori kako to učiniti. Ako vas zanima konačno rješenje bez detalja, samo pročitajte zadnji dio članka, “Rješavanje problema”.

Dobro razmislite prije upotrebe Docker-in-Docker za CI ili testno okruženje

Docker-in-Docker: "Dobro"

Prije više od dvije godine stavio sam u Docker zastava – privilegiran i napisao prva verzija dind. Cilj je bio pomoći glavnom timu da brže razvije Docker. Prije Docker-in-Docker-a, tipični razvojni ciklus izgledao je ovako:

  • hackity hack;
  • izgraditi;
  • zaustavljanje pokrenutog Docker demona;
  • pokretanje novog Docker demona;
  • ispitivanja;
  • ponovite ciklus.

Ako ste htjeli napraviti prekrasan sklop koji se može reproducirati (to jest, u spremniku), onda je postalo zamršenije:

  • hackity hack;
  • provjerite radi li radna verzija Dockera;
  • izgraditi novi Docker sa starim Dockerom;
  • zaustavi Docker demona;
  • pokrenuti novi Docker demon;
  • test;
  • zaustaviti novog Docker demona;
  • ponoviti.

S pojavom Docker-in-Docker, proces je postao jednostavniji:

  • hackity hack;
  • montaža + lansiranje u jednoj fazi;
  • ponovite ciklus.

Nije li puno bolje ovako?

Dobro razmislite prije upotrebe Docker-in-Docker za CI ili testno okruženje

Docker-in-Docker: "Loše"

Međutim, suprotno uvriježenom mišljenju, Docker-in-Docker nisu 100% zvijezde, poniji i jednorozi. Ono što želim reći jest da postoji nekoliko problema kojih programer mora biti svjestan.

Jedan od njih odnosi se na LSM-ove (Linux sigurnosne module) kao što su AppArmor i SELinux: prilikom pokretanja spremnika, "unutarnji Docker" može pokušati primijeniti sigurnosne profile koji će biti u sukobu ili zbuniti "vanjski Docker". Ovo je najteži problem za riješiti kada se pokušava spojiti izvorna implementacija oznake –privileged. Moje promjene su radile i svi testovi bi prošli na mom Debian stroju i Ubuntu testnim VM-ovima, ali bi se srušili i spali na stroju Michaela Crosbyja (imao je Fedoru, koliko se sjećam). Ne mogu se sjetiti točnog uzroka problema, ali možda je to zato što je Mike mudar tip koji radi sa SELINUX=enforce (koristio sam AppArmor) i moje promjene nisu uzele u obzir SELinux profile.

Docker-in-Docker: "Zlo"

Drugi problem je s Docker drajverima za pohranu. Kada pokrenete Docker-in-Docker, vanjski Docker radi na vrhu redovnog datotečnog sustava (EXT4, BTRFS ili što god imate), a interni Docker radi na vrhu sustava za kopiranje na pisanje (AUFS, BTRFS, Device Mapper , itd.), ovisno o tome što je konfigurirano za korištenje vanjskog Dockera). To stvara mnoge kombinacije koje neće funkcionirati. Na primjer, nećete moći pokrenuti AUFS povrh AUFS-a.

Ako pokrenete BTRFS povrh BTRFS-a, isprva bi trebao raditi, ali kada postoje ugniježđene podvolume, brisanje nadređenog podvolumena neće uspjeti. Modul Device Mapper nema prostor imena, pa ako ga više instanci Dockera pokreće na istom računalu, svi će moći vidjeti (i utjecati) na slike jedni na drugima i na uređajima za sigurnosno kopiranje spremnika. To je loše.

Postoje zaobilazna rješenja za rješavanje mnogih od ovih problema. Na primjer, ako želite koristiti AUFS u internom Dockeru, samo pretvorite mapu /var/lib/docker u volumen i sve će biti u redu. Docker je dodao neke osnovne prostore imena ciljnim imenima Device Mappera tako da ako se na istom računalu izvodi više Docker poziva, oni neće stati jedni na druge.

Međutim, takvo postavljanje nije nimalo jednostavno, kao što se može vidjeti iz ovih članci u dind repozitoriju na GitHubu.

Docker-in-Docker: Postaje gore

Što je s predmemorijom izrade? Ovo također može biti prilično teško. Ljudi me često pitaju "ako koristim Docker-in-Docker, kako mogu koristiti slike hostirane na mom hostu umjesto da sve povučem natrag u svoj interni Docker"?

Neki poduzetni ljudi pokušali su vezati /var/lib/docker s hosta na Docker-in-Docker spremnik. Ponekad dijele /var/lib/docker s više spremnika.

Dobro razmislite prije upotrebe Docker-in-Docker za CI ili testno okruženje
Želite li oštetiti svoje podatke? Jer upravo to će oštetiti vaše podatke!

Docker demon je jasno dizajniran da ima ekskluzivan pristup /var/lib/docker. Ništa drugo ne smije "dirati, bockati ili bockati" bilo koju Docker datoteku koja se nalazi u ovoj mapi.

Zašto je to tako? Jer ovo je rezultat jedne od najtežih lekcija naučenih tijekom razvoja dotClouda. DotCloud spremnik je radio tako da je više procesa istovremeno pristupalo /var/lib/dotcloud. Lukavi trikovi poput atomske zamjene datoteka (umjesto uređivanja na licu mjesta), dodavanja koda sa savjetodavnim i obaveznim zaključavanjima i drugi eksperimenti sa sigurnim sustavima kao što su SQLite i BDB nisu uvijek funkcionirali. Kad smo redizajnirali naš spremnik, koji je na kraju postao Docker, jedna od glavnih dizajnerskih odluka bila je konsolidacija svih operacija spremnika pod jednim demonom kako bismo uklonili sve besmislice o istovremenosti.

Nemojte me krivo shvatiti: sasvim je moguće napraviti nešto dobro, pouzdano i brzo što uključuje više procesa i modernu paralelnu kontrolu. Ali mislimo da je jednostavnije i lakše pisati i održavati kod koristeći Docker kao jedinog igrača.

To znači da ako dijelite direktorij /var/lib/docker između više instanci Dockera, imat ćete problema. Naravno, to može funkcionirati, posebno u ranim fazama testiranja. "Slušaj, mama, mogu pokrenuti ubuntu kao docker!" Ali pokušajte nešto složenije, poput izvlačenja iste slike iz dvije različite instance, i vidjet ćete kako svijet gori.

To znači da ako vaš CI sustav izvodi izgradnju i ponovnu izgradnju, svaki put kada ponovno pokrenete svoj Docker-in-Docker spremnik, riskirate ispuštanje nuklearne bombe u njegovu predmemoriju. Ovo uopće nije cool!

Rješenje

Vratimo se korak unatrag. Trebate li stvarno Docker-in-Docker ili samo želite imati mogućnost pokretanja Dockera i izgradnje i pokretanja spremnika i slika iz vašeg CI sustava dok je sam CI sustav u spremniku?

Kladim se da većina ljudi želi potonju opciju, što znači da žele CI sustav poput Jenkinsa koji bi mogao pokretati spremnike. A najlakši način da to učinite je da jednostavno umetnete Docker utičnicu u svoj CI spremnik i povežete je s zastavom -v.

Jednostavno rečeno, kada pokrenete svoj CI spremnik (Jenkins ili neki drugi), umjesto hakiranja nečega uz Docker-in-Docker, pokrenite ga linijom:

docker run -v /var/run/docker.sock:/var/run/docker.sock ...

Ovaj će spremnik sada imati pristup Docker utičnici i stoga će moći pokretati spremnike. Osim što će umjesto pokretanja "podređenih" spremnika pokrenuti "srodne" spremnike.

Pokušajte ovo koristeći službenu docker sliku (koja sadrži Docker binarnu datoteku):

docker run -v /var/run/docker.sock:/var/run/docker.sock 
           -ti docker

Izgleda i radi kao Docker-in-Docker, ali nije Docker-in-Docker: kada ovaj spremnik stvori dodatne spremnike, oni će se stvoriti u Dockeru najviše razine. Nećete iskusiti nuspojave ugniježđivanja, a predmemorija sklopa dijelit će se u više poziva.

Napomena: prethodne verzije ovog članka savjetovale su povezivanje binarne datoteke Docker s glavnog računala na spremnik. Ovo je sada postalo nepouzdano jer Docker mehanizam više ne pokriva statične ili gotovo statične biblioteke.

Dakle, ako želite koristiti Docker iz Jenkins CI, imate 2 opcije:
instaliranje Docker CLI-a korištenjem osnovnog sustava za pakiranje slika (tj. ako je vaša slika temeljena na Debianu, koristite .deb pakete), korištenjem Docker API-ja.

Neki oglasi 🙂

Hvala što ste ostali s nama. Sviđaju li vam se naši članci? Želite li vidjeti više zanimljivog sadržaja? Podržite nas narudžbom ili preporukom prijateljima, cloud VPS za programere od 4.99 USD, jedinstveni analog poslužitelja početne razine, koji smo izmislili za vas: Cijela istina o VPS (KVM) E5-2697 v3 (6 jezgri) 10GB DDR4 480GB SSD 1Gbps od 19 USD ili kako podijeliti poslužitelj? (dostupno s RAID1 i RAID10, do 24 jezgre i do 40 GB DDR4).

Dell R730xd 2 puta jeftiniji u Equinix Tier IV podatkovnom centru u Amsterdamu? Samo ovdje 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TV od 199 USD u Nizozemskoj! Dell R420 - 2x E5-2430 2.2 Ghz 6C 128 GB DDR3 2x960 GB SSD 1 Gbps 100 TB - od 99 USD! Pročitaj o Kako izgraditi infrastrukturu corp. klase uz korištenje Dell R730xd E5-2650 v4 servera vrijednih 9000 eura za lipu?

Izvor: www.habr.com

Dodajte komentar