CI veya test ortamı için Docker-in-Docker'ı kullanmadan önce dikkatlice düşünün

CI veya test ortamı için Docker-in-Docker'ı kullanmadan önce dikkatlice düşünün

Docker-in-Docker, konteyner görüntüleri oluşturmak için konteynerin içinde çalışan sanallaştırılmış bir Docker arka plan programı ortamıdır. Docker-in-Docker'ı yaratmanın asıl amacı Docker'ın kendisini geliştirmeye yardımcı olmaktı. Birçok kişi bunu Jenkins CI'yi çalıştırmak için kullanıyor. Bu ilk başta normal görünebilir, ancak daha sonra Docker'ı bir Jenkins CI konteynerine kurarak önlenebilecek sorunlar ortaya çıkar. Bu makalede bunun nasıl yapılacağı anlatılmaktadır. Ayrıntılara girmeden nihai çözüm ilginizi çekiyorsa makalenin son bölümü olan “Sorunu Çözmek” bölümünü okumanız yeterli.

CI veya test ortamı için Docker-in-Docker'ı kullanmadan önce dikkatlice düşünün

Docker'da Docker: "İyi"

İki yıldan fazla bir süre önce Docker'ı kullanmaya başladım bayrak –ayrıcalıklı ve yazdı dind'in ilk versiyonu. Amaç, çekirdek ekibin Docker'ı daha hızlı geliştirmesine yardımcı olmaktı. Docker-in-Docker'dan önce tipik geliştirme döngüsü şuna benziyordu:

  • hack hack;
  • inşa etmek;
  • çalışan bir Docker arka plan programının durdurulması;
  • yeni bir Docker arka plan programının başlatılması;
  • test edilmesi;
  • döngüyü tekrarlayın.

Güzel, tekrarlanabilir bir montaj (yani bir kapta) yapmak istiyorsanız, o zaman daha karmaşık hale geldi:

  • hack hack;
  • Docker'ın çalışan bir sürümünün çalıştığından emin olun;
  • eski Docker ile yeni Docker oluşturun;
  • Docker arka plan programını durdurun;
  • yeni bir Docker arka plan programı başlatın;
  • Ölçek;
  • yeni Docker arka plan programını durdurun;
  • tekrar et.

Docker-in-Docker'ın ortaya çıkışıyla süreç daha basit hale geldi:

  • hack hack;
  • tek aşamada montaj + lansman;
  • döngüyü tekrarlayın.

Bu şekilde çok daha iyi değil mi?

CI veya test ortamı için Docker-in-Docker'ı kullanmadan önce dikkatlice düşünün

Docker'da Docker: "Kötü"

Ancak popüler inanışın aksine Docker-in-Docker %100 yıldızlar, midilliler ve tek boynuzlu atlar değildir. Demek istediğim, bir geliştiricinin bilmesi gereken birkaç konu var.

Bunlardan biri, AppArmor ve SELinux gibi LSM'lerle (Linux güvenlik modülleri) ilgilidir: bir konteyner çalıştırırken, "dahili Docker", "harici Docker"la çakışacak veya kafasını karıştıracak güvenlik profilleri uygulamaya çalışabilir. Bu –ayrıcalıklı bayrağın orijinal uygulamasını birleştirmeye çalışırken çözülmesi en zor sorundur. Değişikliklerim işe yaradı ve tüm testler Debian makinemde ve Ubuntu test VM'lerinde başarılı oldu, ancak Michael Crosby'nin makinesinde çöküp yanıyordu (hatırladığım kadarıyla Fedora'sı vardı). Sorunun tam nedenini hatırlayamıyorum, ancak bunun nedeni Mike'ın SELINUX=enforce (AppArmor kullandım) ile çalışan bilge bir adam olması ve değişikliklerimin SELinux profillerini hesaba katmaması olabilir.

Docker-in-Docker: "Kötü"

İkinci sorun Docker depolama sürücüleriyle ilgilidir. Docker-in-Docker'ı çalıştırdığınızda, harici Docker normal bir dosya sisteminin (EXT4, BTRFS veya sahip olduğunuz her şey) üzerinde çalışır ve dahili Docker, yazma üzerine kopyalama sisteminin (AUFS, BTRFS, Device Mapper) üzerinde çalışır. , vb.). , harici Docker'ı kullanacak şekilde neyin yapılandırıldığına bağlı olarak). Bu, işe yaramayacak birçok kombinasyon yaratır. Örneğin, AUFS'yi AUFS'nin üzerinde çalıştıramazsınız.

BTRFS'yi BTRFS'nin üzerinde çalıştırırsanız, ilk başta çalışması gerekir, ancak iç içe geçmiş alt hacimler olduğunda üst alt hacmin silinmesi başarısız olur. Cihaz Eşleyici modülünün ad alanı yoktur; bu nedenle, aynı makinede birden fazla Docker örneği çalıştırıyorsa, bunların tümü birbirlerinin ve konteyner yedekleme cihazlarının üzerindeki görüntüleri görebilir (ve etkileyebilir). Bu kötü.

Bu sorunların çoğunu çözecek geçici çözümler vardır. Örneğin, dahili Docker'da AUFS kullanmak istiyorsanız, /var/lib/docker klasörünü bir birime dönüştürmeniz yeterli; sorun olmayacak. Docker, Cihaz Eşleyici hedef adlarına bazı temel ad alanları ekledi; böylece aynı makinede birden fazla Docker çağrısı çalışıyorsa, bunlar birbirinin üzerine basmayacak.

Ancak bu kurulum, bunlardan da anlaşılacağı üzere hiç de basit değildir. makaleler GitHub'daki dind deposunda.

Docker-in-Docker: Daha da kötüye gidiyor

Yapı önbelleği ne olacak? Bu aynı zamanda oldukça zor olabilir. İnsanlar bana sıklıkla şunu soruyor: "Docker-in-Docker'ı çalıştırıyorsam, her şeyi dahili Docker'ıma geri çekmek yerine ana makinemde barındırılan görüntüleri nasıl kullanabilirim?"

Bazı girişimci kişiler /var/lib/docker'ı ana bilgisayardan Docker-in-Docker kapsayıcısına bağlamayı denediler. Bazen /var/lib/docker'ı birden fazla kapsayıcıyla paylaşırlar.

CI veya test ortamı için Docker-in-Docker'ı kullanmadan önce dikkatlice düşünün
Verilerinizi bozmak mı istiyorsunuz? Çünkü verilerinize zarar verecek olan da tam olarak budur!

Docker arka plan programı açıkça /var/lib/docker'a özel erişime sahip olacak şekilde tasarlandı. Bu klasörde bulunan Docker dosyalarına başka hiçbir şey "dokunmamalı, dürtmemeli veya dürtmemelidir".

Bu neden böyle? Çünkü bu, dotCloud'u geliştirirken öğrenilen en zor derslerden birinin sonucudur. dotCloud konteyner motoru, /var/lib/dotcloud'a aynı anda erişen birden fazla işlemle çalışıyordu. Atomik dosya değiştirme (yerinde düzenleme yerine), kodu tavsiye niteliğinde ve zorunlu kilitlerle doldurma gibi kurnaz hileler ve SQLite ve BDB gibi güvenli sistemlerle yapılan diğer deneyler her zaman işe yaramadı. Sonunda Docker haline gelen konteyner motorumuzu yeniden tasarlarken, en büyük tasarım kararlarından biri, tüm eşzamanlılık saçmalıklarını ortadan kaldırmak için tüm konteyner operasyonlarını tek bir arka plan programı altında birleştirmekti.

Beni yanlış anlamayın: birden fazla süreç ve modern paralel kontrol içeren iyi, güvenilir ve hızlı bir şey yapmak tamamen mümkündür. Ancak tek oynatıcı olarak Docker'ı kullanarak kod yazmanın ve sürdürmenin daha basit ve kolay olduğunu düşünüyoruz.

Bu, /var/lib/docker dizinini birden fazla Docker örneği arasında paylaşırsanız sorun yaşayacağınız anlamına gelir. Elbette bu, özellikle testin ilk aşamalarında işe yarayabilir. "Dinle anne, ubuntu'yu liman işçisi olarak çalıştırabilirim!" Ancak aynı görüntüyü iki farklı örnekten almak gibi daha karmaşık bir şey deneyin; dünyanın yandığını göreceksiniz.

Bu, CI sisteminiz oluşturma ve yeniden oluşturma işlemleri gerçekleştirirse, Docker-in-Docker konteynerinizi her yeniden başlattığınızda, önbelleğine bir nükleer bomba bırakma riskiyle karşı karşıya kalacağınız anlamına gelir. Bu hiç hoş değil!

Çözelti

Bir adım geriye gidelim. Gerçekten Docker-in-Docker'a ihtiyacınız var mı, yoksa CI sistemi bir konteynerin içindeyken sadece Docker'ı çalıştırabilmek ve CI sisteminizden konteynerler ve görüntüler oluşturup çalıştırmak mı istiyorsunuz?

Eminim çoğu insan ikinci seçeneği istiyor, yani Jenkins gibi bir CI sisteminin konteynerleri çalıştırabilmesini istiyorlar. Bunu yapmanın en kolay yolu ise CI konteynerinize bir Docker soketi yerleştirmek ve bunu -v bayrağıyla ilişkilendirmektir.

Basitçe söylemek gerekirse, CI konteynerinizi (Jenkins veya diğer) çalıştırdığınızda, Docker-in-Docker ile birlikte bir şeyi hacklemek yerine şu satırla başlayın:

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

Bu konteyner artık Docker soketine erişebilecek ve dolayısıyla konteynerleri çalıştırabilecek. Bunun dışında "alt" kapsayıcıları çalıştırmak yerine "kardeş" kapsayıcıları başlatacaktır.

Bunu resmi docker görüntüsünü (Docker ikili dosyasını içeren) kullanarak deneyin:

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

Docker-in-Docker gibi görünür ve çalışır, ancak Docker-in-Docker değildir: Bu kapsayıcı ek kapsayıcılar oluşturduğunda, bunlar üst düzey Docker'da oluşturulacaktır. İç içe yerleştirmenin yan etkilerini yaşamazsınız ve derleme önbelleği birden fazla çağrı arasında paylaşılır.

Not: Bu makalenin önceki sürümlerinde Docker ikili dosyasının ana bilgisayardan kapsayıcıya bağlanması önerildi. Docker motoru artık statik veya statike yakın kitaplıkları kapsamadığından bu artık güvenilmez hale geldi.

Yani Jenkins CI'dan Docker'ı kullanmak istiyorsanız 2 seçeneğiniz var:
Docker API'sini kullanarak temel görüntü paketleme sistemini kullanarak Docker CLI'yi yükleme (ör. görüntünüz Debian'ı temel alıyorsa .deb paketlerini kullanın).

Bazı reklamlar 🙂

Bizimle kaldığın için teşekkürler. Yazılarımızı beğeniyor musunuz? Daha ilginç içerik görmek ister misiniz? Sipariş vererek veya arkadaşlarınıza tavsiye ederek bize destek olun, Geliştiriciler için bulut VPS'si 4.99 ABD dolarından başlayan fiyatlarla, sizin için bizim tarafımızdan icat edilen benzersiz bir giriş seviyesi sunucu analoğu: 5$'dan başlayan fiyatlarla VPS (KVM) E2697-3 v6 (10 Çekirdek) 4GB DDR480 1GB SSD 19Gbps hakkındaki tüm gerçekler veya bir sunucu nasıl paylaşılır? (RAID1 ve RAID10, 24 adede kadar çekirdek ve 40 GB'a kadar DDR4 ile mevcuttur).

Amsterdam'daki Equinix Tier IV veri merkezinde Dell R730xd 2 kat daha mı ucuz? Sadece burada 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TV 199$'dan Hollanda'da! Dell R420 - 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - 99$'dan! Hakkında oku Altyapı şirketi nasıl kurulur? Bir kuruş için 730 Euro değerinde Dell R5xd E2650-4 v9000 sunucuların kullanımı ile sınıf?

Kaynak: habr.com

Yorum ekle