Werf'te konteyner görsellerinin “akıllı” temizlenmesi sorunu ve çözümü

Werf'te konteyner görsellerinin “akıllı” temizlenmesi sorunu ve çözümü

Makalede, Kubernetes'e sunulan bulut tabanlı uygulamalara yönelik modern CI/CD ardışık düzenlerinin gerçekliklerinde konteyner kayıtlarında (Docker Registry ve analogları) biriken görüntülerin temizlenmesiyle ilgili sorunlar tartışılıyor. Görüntülerin alaka düzeyine ilişkin ana kriterler ve temizliğin otomatikleştirilmesi, yerden tasarruf edilmesi ve ekiplerin ihtiyaçlarının karşılanması konusunda ortaya çıkan zorluklar verilmektedir. Son olarak belirli bir Açık Kaynak projesi örneğini kullanarak size bu zorlukların nasıl aşılabileceğini anlatacağız.

Giriş

Bir kapsayıcı kaydındaki görüntülerin sayısı hızla artabilir, daha fazla depolama alanı kaplayabilir ve dolayısıyla maliyeti önemli ölçüde artırabilir. Kayıt defterinde kaplanan alanın kabul edilebilir büyümesini kontrol etmek, sınırlamak veya sürdürmek için aşağıdakiler kabul edilir:

  1. resimler için sabit sayıda etiket kullanın;
  2. görüntüleri bir şekilde temizleyin.


İlk sınırlama bazen küçük takımlar için kabul edilebilir. Geliştiricilerin yeterli sayıda kalıcı etiketi varsa (latest, main, test, boris vb.), kayıt defterinin boyutu artmayacak ve uzun süre onu temizlemeyi düşünmenize gerek kalmayacak. Sonuçta, ilgisiz tüm görüntüler silinir ve temizlik için hiçbir iş kalmaz (her şey sıradan bir çöp toplayıcı tarafından yapılır).

Ancak bu yaklaşım, geliştirmeyi büyük ölçüde sınırlandırır ve modern CI/CD projelerine nadiren uygulanabilir. Gelişimin ayrılmaz bir parçası otomasyonBu, yeni işlevleri çok daha hızlı bir şekilde test etmenize, dağıtmanıza ve kullanıcılara sunmanıza olanak tanır. Örneğin, tüm projelerimizde her taahhütte otomatik olarak bir CI kanalı oluşturulur. İçinde görüntü birleştirilir, test edilir, hata ayıklama ve kalan kontroller için çeşitli Kubernetes devrelerine sunulur ve her şey yolundaysa değişiklikler son kullanıcıya ulaşır. Ve bu artık roket bilimi değil, birçokları için günlük bir olaydır - büyük olasılıkla sizin için, bu makaleyi okuduğunuza göre.

Hataların düzeltilmesi ve yeni işlevsellik geliştirilmesi paralel olarak gerçekleştirildiğinden ve sürümler günde birkaç kez gerçekleştirilebildiğinden, geliştirme sürecine önemli sayıda taahhütün eşlik ettiği açıktır, bu da şu anlama gelir: kayıt defterinde çok sayıda resim. Sonuç olarak, kayıt defterinin etkin temizliğinin organize edilmesi sorunu ortaya çıkıyor, yani. alakasız görsellerin kaldırılması.

Peki bir görselin alakalı olup olmadığını nasıl belirlersiniz?

Resmin alaka düzeyine ilişkin kriterler

Vakaların büyük çoğunluğunda ana kriterler şöyle olacaktır:

1. Bunlardan ilki (en barizi ve en kritik olanı), şu anda Kubernetes'te kullanılıyor. Bu görüntülerin kaldırılması, üretimde önemli kesinti maliyetlerine neden olabilir (örneğin, görüntülerin çoğaltılması için gerekli olabilir) veya ekibin döngülerden herhangi birinde hata ayıklama çabalarını boşa çıkarabilir. (Bu nedenle özel bir etkinlik bile yaptık. Prometheus ihracatçısı, herhangi bir Kubernetes kümesinde bu tür görüntülerin bulunmadığını izler.)

2. İkincisi (daha az belirgindir ancak aynı zamanda çok önemlidir ve yine istismarla ilgilidir) - görüntüler Ciddi sorunların tespiti durumunda geri alma için gerekli mevcut sürümde. Örneğin Helm durumunda bunlar, sürümün kayıtlı sürümlerinde kullanılan görsellerdir. (Bu arada, Helm'de varsayılan olarak sınır 256 revizyondur, ancak herhangi birinin gerçekten kaydetmeye ihtiyaç duyması pek olası değildir. bu çok sayıda sürüm?..) Sonuçta, özellikle sürümleri daha sonra kullanabilmek için saklıyoruz, ör. Gerekirse onlara “geri dönün”.

3. Üçüncü - geliştirici ihtiyaçları: Mevcut çalışmaları ile ilgili tüm görseller. Örneğin, bir PR düşünüyorsak, son işleme ve örneğin önceki işleme karşılık gelen bir görüntü bırakmak mantıklıdır: bu şekilde geliştirici herhangi bir göreve hızlı bir şekilde geri dönebilir ve en son değişikliklerle çalışabilir.

4. Dördüncüsü - görseller uygulamamızın sürümlerine karşılık geliryani nihai üründür: v1.0.0, 20.04.01/XNUMX/XNUMX, Sierra, vb.

Not: Burada tanımlanan kriterler, farklı şirketlerden düzinelerce geliştirme ekibiyle etkileşimde bulunulan deneyimlere dayanarak formüle edilmiştir. Ancak elbette geliştirme süreçlerindeki spesifikasyonlara ve kullanılan altyapıya (örneğin Kubernetes kullanılmıyor) bağlı olarak bu kriterler farklılık gösterebilir.

Uygunluk ve mevcut çözümler

Konteyner kayıtlarına sahip popüler hizmetler, kural olarak, kendi görüntü temizleme politikalarını sunar: bunlarda, bir etiketin kayıt defterinden kaldırılma koşullarını tanımlayabilirsiniz. Ancak bu koşullar adlar, oluşturulma zamanı ve etiket sayısı* gibi parametrelerle sınırlıdır.

* Belirli kapsayıcı kayıt defteri uygulamalarına bağlıdır. Şu çözümlerin olanaklarını değerlendirdik: Eylül 2020 itibarıyla Azure CR, Docker Hub, ECR, GCR, GitHub Paketleri, GitLab Container Registry, Harbour Registry, JFrog Artifactory, Quay.io.

Bu parametre seti dördüncü kriteri karşılamak için, yani versiyonlara karşılık gelen görüntüleri seçmek için oldukça yeterlidir. Bununla birlikte, diğer tüm kriterler için, beklentilere ve finansal yeteneklere bağlı olarak bir tür uzlaşmacı çözüm (daha sert veya tersine daha yumuşak bir politika) seçilmelidir.

Örneğin, geliştiricilerin ihtiyaçlarıyla ilgili olan üçüncü kriter, ekipler içindeki süreçlerin düzenlenmesiyle çözülebilir: görsellerin özel olarak adlandırılması, özel izin listelerinin tutulması ve dahili anlaşmalar. Ancak sonuçta yine de otomatikleştirilmesi gerekiyor. Ve eğer hazır çözümlerin yetenekleri yeterli değilse, kendi başınıza bir şeyler yapmalısınız.

İlk iki kriterde de durum benzer: harici bir sistemden - uygulamaların dağıtıldığı sistemden (bizim durumumuzda Kubernetes) veri almadan bunlar karşılanamaz.

Git'teki iş akışının çizimi

Diyelim ki Git'te şöyle bir şey üzerinde çalışıyorsunuz:

Werf'te konteyner görsellerinin “akıllı” temizlenmesi sorunu ve çözümü

Diyagramdaki başlıklı simge, herhangi bir kullanıcı (son kullanıcılar, test uzmanları, yöneticiler vb.) için Kubernetes'te halihazırda dağıtılan veya geliştiriciler tarafından hata ayıklama ve benzer amaçlarla kullanılan konteyner görüntülerini gösterir.

Temizleme politikaları yalnızca görsellerin saklanmasına (silinmesine değil) izin veriyorsa ne olur? verilen etiket adlarına göre?

Werf'te konteyner görsellerinin “akıllı” temizlenmesi sorunu ve çözümü

Açıkçası böyle bir senaryo kimseyi memnun etmeyecektir.

Politikalar görsellerin silinmemesine izin verirse ne değişecek? belirli bir zaman aralığına/son taahhüt sayısına göre?

Werf'te konteyner görsellerinin “akıllı” temizlenmesi sorunu ve çözümü

Sonuç çok daha iyi hale geldi, ancak hala ideal olmaktan uzak. Sonuçta, hataları ayıklamak için hala kayıt defterindeki (veya hatta K8'lerde konuşlandırılmış) görüntülere ihtiyaç duyan geliştiricilerimiz var...

Mevcut pazar durumunu özetlemek gerekirse: Konteyner kayıtlarında mevcut olan işlevler, temizlik sırasında yeterli esneklik sunmamaktadır ve bunun temel nedeni, dış dünyayla etkileşim kurmanın hiçbir yolu yok. Böyle bir esnekliğe ihtiyaç duyan ekiplerin, Docker Registry API'sini (veya ilgili uygulamanın yerel API'sini) kullanarak "dışarıdan" görüntü silme işlemini bağımsız olarak uygulamaya zorlandığı ortaya çıktı.

Ancak farklı kayıtlar kullanan farklı ekipler için görüntü temizlemeyi otomatikleştirecek evrensel bir çözüm arıyorduk...

Evrensel görüntü temizlemeye giden yolumuz

Bu ihtiyaç nereden geliyor? Gerçek şu ki, biz ayrı bir geliştirici grubu değiliz; bunların çoğuna aynı anda hizmet veren ve CI/CD sorunlarını kapsamlı bir şekilde çözmeye yardımcı olan bir ekibiz. Ve bunun için ana teknik araç Açık Kaynak yardımcı programıdır. Werf. Özelliği, tek bir işlevi yerine getirmemesi, ancak montajdan dağıtıma kadar her aşamada sürekli teslimat süreçlerine eşlik etmesidir.

Görüntüleri kayıt defterine yayınlamak* (oluşturulduktan hemen sonra) bu tür bir yardımcı programın belirgin bir işlevidir. Görüntüler saklanmak üzere oraya yerleştirildiğinden, depolama alanınız sınırsız değilse, sonraki temizliklerinden siz sorumlu olmanız gerekir. Belirtilen tüm kriterleri karşılayarak bu konuda nasıl başarıya ulaştığımız daha ayrıntılı olarak tartışılacaktır.

* Kayıtların kendileri farklı olsa da (Docker Registry, GitLab Container Registry, Harbor vb.) kullanıcıları aynı sorunlarla karşı karşıyadır. Bizim durumumuzda evrensel çözüm, kayıt defterinin uygulanmasına bağlı değildir, çünkü kayıtların dışında çalışır ve herkese aynı davranışı sunar.

Her ne kadar örnek uygulama olarak werf kullanıyor olsak da, kullanılan yaklaşımların benzer zorluklarla karşılaşan diğer ekiplere faydalı olacağını umuyoruz.

Bu yüzden meşguldük dış konteyner kayıtlarında zaten yerleşik olan yetenekler yerine, görüntüleri temizlemeye yönelik bir mekanizmanın uygulanması. İlk adım, etiketlerin sayısı ve oluşturulma zamanına (yukarıda bahsedildiği gibi) ilişkin aynı temel politikaları oluşturmak için Docker Kayıt API'sini kullanmaktı. Onlara eklendi Dağıtılan altyapıda kullanılan görselleri temel alan izin verilenler listesiyani Kubernet'ler. İkincisi için, dağıtılan tüm kaynakları yinelemek ve değerlerin bir listesini almak için Kubernetes API'sini kullanmak yeterliydi. image.

Bu önemsiz çözüm, en kritik sorunu (1 numaralı kriter) çözdü, ancak temizleme mekanizmasını iyileştirme yolculuğumuzun yalnızca başlangıcıydı. Bir sonraki ve çok daha ilginç adım ise karardı yayınlanan görselleri Git geçmişiyle ilişkilendirin.

Etiketleme şemaları

Başlangıç ​​olarak, son görüntünün temizlik için gerekli bilgileri saklaması gereken bir yaklaşım seçtik ve süreci etiketleme şemaları üzerine kurduk. Bir görseli yayınlarken kullanıcı belirli bir etiketleme seçeneğini seçti (git-branch, git-commit veya git-tag) ve karşılık gelen değeri kullandık. CI sistemlerinde bu değerler ortam değişkenlerine göre otomatik olarak ayarlandı. Aslında son görüntü belirli bir Git ilkeliyle ilişkilendirildi, temizlik için gerekli verilerin etiketlerde saklanması.

Bu yaklaşım Git'in tek gerçek kaynak olarak kullanılmasına izin veren bir dizi politikayla sonuçlandı:

  • Git'te bir şube/etiket silinirken kayıt defterindeki ilgili görseller otomatik olarak siliniyordu.
  • Git etiketleri ve taahhütleriyle ilişkili görsellerin sayısı, seçilen şemada kullanılan etiketlerin sayısına ve ilgili taahhüdün oluşturulduğu zamana göre kontrol edilebilir.

Sonuç olarak ortaya çıkan uygulama ihtiyaçlarımızı karşıladı ancak kısa süre sonra bizi yeni bir zorluk bekliyordu. Gerçek şu ki Git temellerini temel alan etiketleme şemalarını kullanırken bir takım eksikliklerle karşılaştık. (Açıklamaları bu makalenin kapsamı dışında olduğundan herkes ayrıntılara aşina olabilir. burada.) Bu nedenle etiketleme konusunda daha verimli bir yaklaşıma (içerik tabanlı etiketleme) geçmeye karar verdikten sonra görüntü temizleme uygulamasını yeniden düşünmek zorunda kaldık.

Yeni algoritma

Neden? İçerik tabanlı etiketlemeyle her etiket Git'te birden fazla işlemi karşılayabilir. Görüntüleri temizlerken artık varsayamazsınız sadece yeni etiketin kayıt defterine eklendiği taahhütten.

Yeni temizleme algoritması için etiketleme şemalarından uzaklaşılıp, meta-görüntü süreci, her biri aşağıdakileri depolar:

  • yayının gerçekleştirildiği taahhüt (resmin kapsayıcı kayıt defterinde eklenmiş, değiştirilmiş veya aynı kalması önemli değildir);
  • ve birleştirilmiş görüntüye karşılık gelen dahili tanımlayıcımız.

Başka bir deyişle, sağlandı yayınlanan etiketleri Git'teki taahhütlere bağlama.

Son konfigürasyon ve genel algoritma

Temizlemeyi yapılandırırken kullanıcılar artık mevcut görüntüleri seçen politikalara erişebilir. Bu tür politikaların her biri tanımlanır:

  • birçok referans, yani Tarama sırasında kullanılan Git etiketleri veya Git dalları;
  • ve setteki her referans için aranan görsellerin sınırı.

Örneklemek gerekirse, varsayılan politika yapılandırması şu şekilde görünmeye başladı:

cleanup:
  keepPolicies:
  - references:
      tag: /.*/
      limit:
        last: 10
  - references:
      branch: /.*/
      limit:
        last: 10
        in: 168h
        operator: And
    imagesPerReference:
      last: 2
      in: 168h
      operator: And
  - references:  
      branch: /^(main|staging|production)$/
    imagesPerReference:
      last: 10

Bu yapılandırma aşağıdaki kurallara uyan üç politika içerir:

  1. Son 10 Git etiketi için görüntüyü kaydedin (etiket oluşturma tarihine göre).
  2. Geçen hafta etkinliği olan 2'dan fazla konu başlığı için, geçen hafta yayınlanmış en fazla 10 görseli kaydetmeyin.
  3. Şubeler için 10 görsel kaydedin main, staging и production.

Nihai algoritma aşağıdaki adımlara indirgenir:

  • Konteyner kayıt defterinden bildirimler alınıyor.
  • Kubernetes'te kullanılan görseller hariç tutuluyor çünkü Bunları zaten K8s API'sini yoklayarak önceden seçtik.
  • Git geçmişini tarama ve belirtilen politikalara göre görüntüleri hariç tutma.
  • Kalan resimler kaldırılıyor.

Çizimimize dönecek olursak, werf'te olan şey budur:

Werf'te konteyner görsellerinin “akıllı” temizlenmesi sorunu ve çözümü

Bununla birlikte, werf kullanmasanız bile, gelişmiş görüntü temizlemeye benzer bir yaklaşım - şu veya bu uygulamada (görüntü etiketlemede tercih edilen yaklaşıma göre) - diğer sistemlere/yardımcı programlara uygulanabilir. Bunu yapmak için, ortaya çıkan sorunları hatırlamanız ve yığınınızda, çözümlerini mümkün olduğunca sorunsuz bir şekilde entegre etmenize olanak tanıyan fırsatları bulmanız yeterlidir. Umarız kat ettiğimiz yol, özel durumunuza yeni ayrıntılar ve düşüncelerle bakmanıza yardımcı olur.

Sonuç

  • Er ya da geç çoğu ekip kayıt defteri taşması sorunuyla karşılaşır.
  • Çözüm ararken öncelikle görselin alaka düzeyine ilişkin kriterleri belirlemek gerekir.
  • Popüler konteyner kayıt hizmetleri tarafından sunulan araçlar, "dış dünyayı", yani Kubernetes'te kullanılan görüntüleri ve ekibin iş akışlarının özelliklerini hesaba katmayan çok basit bir temizleme düzenlemenize olanak tanır.
  • Esnek ve verimli bir algoritmanın CI/CD süreçlerini anlaması ve yalnızca Docker görüntü verileriyle çalışmaması gerekir.

PS

Blogumuzda da okuyun:

Kaynak: habr.com

Yorum ekle