Նախքան Docker-in-Docker-ը CI-ի կամ թեստային միջավայրի համար օգտագործելը, ուշադիր մտածեք

Նախքան Docker-in-Docker-ը CI-ի կամ թեստային միջավայրի համար օգտագործելը, ուշադիր մտածեք

Docker-in-Docker-ը վիրտուալացված Docker daemon միջավայր է, որն աշխատում է հենց կոնտեյների ներսում՝ կոնտեյների պատկերներ ստեղծելու համար: Docker-in-Docker-ի ստեղծման հիմնական նպատակն էր օգնել Docker-ի զարգացմանը: Շատ մարդիկ օգտագործում են այն Jenkins CI-ն գործարկելու համար: Սա սկզբում նորմալ է թվում, բայց հետո խնդիրներ են առաջանում, որոնցից կարելի է խուսափել՝ տեղադրելով Docker-ը Jenkins CI կոնտեյներով: Այս հոդվածը պատմում է ձեզ, թե ինչպես դա անել: Եթե ​​ձեզ հետաքրքրում է վերջնական լուծումն առանց մանրամասների, պարզապես կարդացեք հոդվածի վերջին բաժինը՝ «Խնդրի լուծում»:

Նախքան Docker-in-Docker-ը CI-ի կամ թեստային միջավայրի համար օգտագործելը, ուշադիր մտածեք

Docker-in-Docker: «Լավ»

Ավելի քան երկու տարի առաջ ես դրեցի Docker-ը դրոշ – արտոնյալ է և գրել dind-ի առաջին տարբերակը. Նպատակն էր օգնել հիմնական թիմին ավելի արագ զարգացնել Docker-ը: Նախքան Docker-in-Docker-ը, զարգացման բնորոշ ցիկլը այսպիսի տեսք ուներ.

  • hackity hack;
  • կառուցել;
  • դադարեցնել վազող Docker daemon-ը;
  • նոր Docker daemon-ի գործարկում;
  • թեստավորում;
  • կրկնել ցիկլը:

Եթե ​​ցանկանում էիք պատրաստել գեղեցիկ, վերարտադրվող հավաքույթ (այսինքն՝ տարայի մեջ), ապա այն ավելի բարդ դարձավ.

  • hackity hack;
  • համոզվեք, որ աշխատում է Docker-ի աշխատանքային տարբերակը.
  • կառուցել նոր Docker հին Docker-ով;
  • դադարեցնել Docker daemon;
  • սկսել նոր Docker daemon;
  • փորձարկում;
  • դադարեցնել նոր Docker daemon;
  • կրկնել.

Docker-in-Docker-ի գալուստով գործընթացն ավելի պարզ է դարձել.

  • hackity hack;
  • հավաքում + մեկնարկը մեկ փուլով;
  • կրկնել ցիկլը:

Այսպես շատ ավելի լավ չէ՞:

Նախքան Docker-in-Docker-ը CI-ի կամ թեստային միջավայրի համար օգտագործելը, ուշադիր մտածեք

Docker-in-Docker: «Վատ»

Այնուամենայնիվ, հակառակ տարածված կարծիքի, Docker-in-Docker-ը 100% աստղեր, պոնիներ և միաեղջյուրներ չեն: Ես նկատի ունեմ այն, որ կան մի քանի խնդիրներ, որոնց մասին պետք է տեղյակ լինի մշակողը:

Դրանցից մեկը վերաբերում է LSM-ներին (Linux անվտանգության մոդուլներին), ինչպիսիք են AppArmor-ը և SELinux-ը. կոնտեյներ աշխատելիս «ներքին Docker»-ը կարող է փորձել կիրառել անվտանգության պրոֆիլներ, որոնք հակասում են կամ շփոթեցնում «արտաքին Docker»-ը: Սա ամենադժվար խնդիրն է լուծել, երբ փորձում ենք միավորել –արտոնյալ դրոշի սկզբնական իրականացումը: Իմ փոփոխություններն աշխատեցին, և բոլոր թեստերը կփոխանցվեին իմ Debian մեքենայի և Ubuntu փորձարկման VM-ների վրա, բայց դրանք կխափանվեին և կվառվեին Մայքլ Քրոսբիի մեքենայի վրա (նա ուներ Fedora, ինչպես հիշում եմ): Ես չեմ կարող հիշել խնդրի ճշգրիտ պատճառը, բայց դա կարող է լինել այն պատճառով, որ Մայքը իմաստուն տղա է, ով աշխատում է SELINUX=enforce-ով (ես օգտագործել եմ AppArmor-ը), և իմ փոփոխությունները հաշվի չեն առել SELinux պրոֆիլները:

Docker-in-Docker: «Չար»

Երկրորդ խնդիրը կապված է Docker պահեստավորման դրայվերների հետ: Երբ դուք գործարկում եք Docker-in-Docker, արտաքին Docker-ն աշխատում է սովորական ֆայլային համակարգի վերևում (EXT4, BTRFS կամ ինչ ունեք), իսկ ներքին Docker-ն աշխատում է պատճենահանման վրա գրելու համակարգի վրա (AUFS, BTRFS, Device Mapper): և այլն): , կախված նրանից, թե ինչ է կազմաձևված արտաքին Docker-ն օգտագործելու համար): Սա ստեղծում է բազմաթիվ համակցություններ, որոնք չեն աշխատի: Օրինակ, դուք չեք կարողանա գործարկել AUFS-ը AUFS-ի վրա:

Եթե ​​դուք գործարկում եք BTRFS-ը BTRFS-ի վերևում, այն սկզբում պետք է աշխատի, բայց երբ կան ներդիր ենթածավալներ, մայր ենթածավալը ջնջելը չի ​​հաջողվի: Device Mapper մոդուլը չունի անվանատարածք, այնպես որ, եթե Docker-ի մի քանի օրինակներ այն գործարկեն միևնույն մեքենայի վրա, նրանք բոլորը կկարողանան տեսնել (և ազդել) պատկերները միմյանց և կոնտեյների պահեստային սարքերի վրա: Սա վատ է:

Այս խնդիրներից շատերը լուծելու համար կան լուծումներ: Օրինակ, եթե ցանկանում եք օգտագործել AUFS-ը ներքին Docker-ում, պարզապես վերածեք /var/lib/docker թղթապանակը ծավալի, և դուք լավ կլինեք: Docker-ը մի քանի բազային անունների տարածքներ է ավելացրել Device Mapper-ի թիրախային անուններին, որպեսզի եթե Docker-ի մի քանի զանգեր միևնույն մեքենայի վրա են, դրանք միմյանց վրա չենթարկվի:

Այնուամենայնիվ, նման կարգավորումը ամենևին էլ պարզ չէ, ինչպես երևում է դրանցից Հոդվածներ GitHub-ի dind պահոցում:

Docker-in-Docker. Այն վատանում է

Ինչ վերաբերում է կառուցման քեշին: Սա նույնպես կարող է բավականին դժվար լինել: Մարդիկ հաճախ ինձ հարցնում են. «եթե ես գործարկում եմ Docker-in-Docker-ը, ինչպե՞ս կարող եմ օգտագործել իմ հոսթի վրա տեղադրված պատկերները՝ ամեն ինչ ետ քաշելու իմ ներքին Docker-ում»:

Որոշ նախաձեռնող մարդիկ փորձել են կապել /var/lib/docker-ը հյուրընկալողից Docker-in-Docker կոնտեյների հետ: Երբեմն նրանք կիսում են /var/lib/docker-ը բազմաթիվ կոնտեյներների հետ:

Նախքան Docker-in-Docker-ը CI-ի կամ թեստային միջավայրի համար օգտագործելը, ուշադիր մտածեք
Ցանկանու՞մ եք փչացնել ձեր տվյալները: Քանի որ սա հենց այն է, ինչը կվնասի ձեր տվյալները:

Docker daemon-ը հստակ նախագծված էր բացառիկ մուտք ունենալու համար /var/lib/docker: Ուրիշ ոչինչ չպետք է «դիպչի, խփի կամ առաջացնի» Docker ֆայլերը, որոնք գտնվում են այս թղթապանակում:

Ինչո՞ւ է սա այդպես։ Քանի որ սա dotCloud-ի մշակման ընթացքում քաղված ամենադժվար դասերից մեկի արդյունքն է: DotCloud բեռնարկղային շարժիչն աշխատում էր մի քանի պրոցեսներով, որոնք միաժամանակ մուտք էին գործում /var/lib/dotcloud: Խորամանկ հնարքները, ինչպիսիք են ատոմային ֆայլի փոխարինումը (տեղում խմբագրելու փոխարեն), խորհրդատվական և պարտադիր կողպեքներով ծածկագրելը և այլ փորձեր անվտանգ համակարգերով, ինչպիսիք են SQLite-ը և BDB-ն, միշտ չէ, որ աշխատում էին: Երբ մենք վերանախագծում էինք մեր կոնտեյներային շարժիչը, որն ի վերջո դարձավ Docker, դիզայնի մեծ որոշումներից մեկն այն էր, որ կոնտեյներների բոլոր գործառնությունները համախմբվեն մեկ դեյմոնի ներքո՝ վերացնելու համաժամանակյա բոլոր անհեթեթությունները:

Ինձ սխալ չհասկանաք. լիովին հնարավոր է լավ, հուսալի և արագ ինչ-որ բան պատրաստել, որը ներառում է բազմաթիվ գործընթացներ և ժամանակակից զուգահեռ վերահսկողություն: Բայց մենք կարծում ենք, որ ավելի պարզ և հեշտ է գրել և պահպանել կոդը՝ օգտագործելով Docker-ը որպես միակ խաղացող:

Սա նշանակում է, որ եթե դուք կիսում եք /var/lib/docker գրացուցակը Docker-ի մի քանի օրինակների միջև, դուք խնդիրներ կունենաք: Իհարկե, դա կարող է աշխատել, հատկապես թեստավորման վաղ փուլերում: «Լսիր, մայրիկ, ես կարող եմ Ubuntu-ն գործարկել որպես դոկեր»: Բայց փորձեք ինչ-որ ավելի բարդ բան, օրինակ՝ նույն պատկերը երկու տարբեր օրինակներից հանելը, և կտեսնեք, որ աշխարհը այրվում է:

Սա նշանակում է, որ եթե ձեր CI համակարգը կառուցում և վերակառուցում է, ամեն անգամ, երբ դուք վերագործարկում եք ձեր Docker-in-Docker կոնտեյները, դուք վտանգում եք միջուկ գցել դրա քեշը: Սա ամենևին էլ թույն չէ:

Լուծումը

Եկեք մի քայլ հետ գնանք։ Ձեզ իսկապես անհրաժեշտ է Docker-in-Docker-ը, թե՞ պարզապես ցանկանում եք, որ կարողանաք գործարկել Docker-ը և կառուցել և գործարկել կոնտեյներներ և պատկերներ ձեր CI համակարգից, մինչ այդ CI համակարգը ինքնին գտնվում է կոնտեյների մեջ:

Գրազ եմ գալիս, որ մարդկանց մեծամասնությունը ցանկանում է վերջին տարբերակը, այսինքն՝ նրանք ցանկանում են, որ Ջենկինսի նման CI համակարգը կարողանա բեռնարկղեր վարել: Եվ դա անելու ամենահեշտ ձևը պարզապես Docker վարդակից տեղադրելն է ձեր CI կոնտեյների մեջ և այն կապել -v դրոշի հետ:

Պարզ ասած, երբ գործարկում եք ձեր CI կոնտեյները (Ջենկինս կամ այլ), Docker-in-Docker-ի հետ մեկտեղ ինչ-որ բան կոտրելու փոխարեն, սկսեք այն տողով.

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

Այս կոնտեյները այժմ մուտք կունենա Docker վարդակից և, հետևաբար, կկարողանա գործարկել բեռնարկղերը: Միայն թե «մանկական» կոնտեյներներ գործարկելու փոխարեն այն կգործարկի «եղբայր կամ եղբայր» կոնտեյներներ։

Փորձեք սա՝ օգտագործելով պաշտոնական դոկերի պատկերը (որը պարունակում է Docker երկուական):

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

Այն արտաքինից և աշխատում է Docker-in-Docker-ի նման, բայց դա Docker-in-Docker չէ. երբ այս կոնտեյները ստեղծի լրացուցիչ կոնտեյներներ, դրանք կստեղծվեն վերին մակարդակի Docker-ում: Դուք չեք զգա բնադրման կողմնակի ազդեցությունները, և հավաքման քեշը կհամօգտագործվի բազմաթիվ զանգերի ընթացքում:

Նշում. Այս հոդվածի նախորդ տարբերակները խորհուրդ էին տալիս միացնել Docker երկուականը հոսթից դեպի կոնտեյներ: Սա այժմ դարձել է անհուսալի, քանի որ Docker շարժիչն այլևս չի ընդգրկում ստատիկ կամ գրեթե ստատիկ գրադարանները:

Այսպիսով, եթե ցանկանում եք օգտագործել Docker-ը Jenkins CI-ից, ունեք 2 տարբերակ.
Docker CLI-ի տեղադրում պատկերների փաթեթավորման հիմնական համակարգի միջոցով (այսինքն, եթե ձեր պատկերը հիմնված է Debian-ի վրա, օգտագործեք .deb փաթեթներ), օգտագործելով Docker API-ն:

Մի քանի գովազդ 🙂

Շնորհակալություն մեզ հետ մնալու համար: Ձեզ դուր են գալիս մեր հոդվածները: Ցանկանու՞մ եք տեսնել ավելի հետաքրքիր բովանդակություն: Աջակցեք մեզ՝ պատվիրելով կամ խորհուրդ տալով ընկերներին, ամպային VPS մշակողների համար $4.99-ից, մուտքի մակարդակի սերվերների եզակի անալոգ, որը հորինվել է մեր կողմից ձեզ համար. Ամբողջ ճշմարտությունը VPS (KVM) E5-2697 v3 (6 Cores) 10GB DDR4 480GB SSD 1Gbps 19 դոլարից կամ ինչպես կիսել սերվերը: (հասանելի է RAID1 և RAID10-ով, մինչև 24 միջուկով և մինչև 40 ԳԲ DDR4):

Dell R730xd 2 անգամ ավելի էժան Ամստերդամի Equinix Tier IV տվյալների կենտրոնում: Միայն այստեղ 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 հեռուստացույց $199-ից Նիդեռլանդներում! Dell R420 - 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - $99-ից: Կարդացեք մասին Ինչպես կառուցել ենթակառուցվածքի կորպ. դաս՝ 730 եվրո արժողությամբ Dell R5xd E2650-4 v9000 սերվերների օգտագործմամբ մեկ կոպեկի համար:

Source: www.habr.com

Добавить комментарий