Bài toán dọn dẹp container image “thông minh” và giải pháp trong werf

Bài toán dọn dẹp container image “thông minh” và giải pháp trong werf

Bài viết thảo luận về các vấn đề làm sạch hình ảnh tích lũy trong các cơ quan đăng ký vùng chứa (Docker Register và các phần tương tự của nó) trong thực tế của các quy trình CI/CD hiện đại cho các ứng dụng gốc trên đám mây được phân phối tới Kubernetes. Các tiêu chí chính về mức độ liên quan của hình ảnh và những khó khăn dẫn đến việc tự động hóa việc dọn dẹp, tiết kiệm không gian và đáp ứng nhu cầu của các nhóm được đưa ra. Cuối cùng, bằng cách sử dụng ví dụ về một dự án Nguồn mở cụ thể, chúng tôi sẽ cho bạn biết cách khắc phục những khó khăn này.

Giới thiệu

Số lượng hình ảnh trong sổ đăng ký vùng chứa có thể tăng nhanh, chiếm nhiều dung lượng lưu trữ hơn và do đó làm tăng đáng kể chi phí của nó. Để kiểm soát, hạn chế hoặc duy trì sự tăng trưởng có thể chấp nhận được của không gian bị chiếm dụng trong sổ đăng ký, nó được chấp nhận:

  1. sử dụng số lượng thẻ cố định cho hình ảnh;
  2. làm sạch hình ảnh theo một cách nào đó.


Hạn chế đầu tiên đôi khi có thể chấp nhận được đối với các đội nhỏ. Nếu nhà phát triển có đủ thẻ vĩnh viễn (latest, main, test, boris v.v.), sổ đăng ký sẽ không tăng kích thước và trong một thời gian dài bạn sẽ không phải nghĩ đến việc dọn dẹp nó. Rốt cuộc, tất cả các hình ảnh không liên quan đều bị xóa và đơn giản là không còn công việc gì để dọn dẹp (mọi thứ đều do người thu gom rác thông thường thực hiện).

Tuy nhiên, cách tiếp cận này hạn chế rất nhiều sự phát triển và hiếm khi áp dụng được cho các dự án CI/CD hiện đại. Một phần không thể thiếu của sự phát triển là tự động hóa, cho phép bạn thử nghiệm, triển khai và cung cấp chức năng mới cho người dùng nhanh hơn nhiều. Ví dụ: trong tất cả các dự án của chúng tôi, quy trình CI được tạo tự động với mỗi lần xác nhận. Trong đó, image được lắp ráp, thử nghiệm, triển khai tới các mạch Kubernetes khác nhau để gỡ lỗi và kiểm tra các phần còn lại, và nếu tất cả đều ổn, những thay đổi sẽ đến tay người dùng cuối. Và đây không còn là khoa học tên lửa nữa mà là chuyện xảy ra hàng ngày đối với nhiều người - rất có thể đối với bạn, vì bạn đang đọc bài viết này.

Vì việc sửa lỗi và phát triển chức năng mới được thực hiện song song và việc phát hành có thể được thực hiện nhiều lần trong ngày nên rõ ràng là quá trình phát triển đi kèm với một số lượng đáng kể các cam kết, điều đó có nghĩa là một số lượng lớn hình ảnh trong sổ đăng ký. Do đó, nảy sinh vấn đề tổ chức dọn dẹp sổ đăng ký hiệu quả, tức là. loại bỏ những hình ảnh không liên quan.

Nhưng làm thế nào để bạn xác định liệu một hình ảnh có liên quan hay không?

Tiêu chí về mức độ liên quan của hình ảnh

Trong phần lớn các trường hợp, tiêu chí chính sẽ là:

1. Điều đầu tiên (rõ ràng nhất và quan trọng nhất) là những hình ảnh hiện đang được sử dụng trong Kubernetes. Việc xóa những hình ảnh này có thể dẫn đến chi phí đáng kể cho thời gian ngừng sản xuất (ví dụ: hình ảnh có thể được yêu cầu để sao chép) hoặc cản trở nỗ lực gỡ lỗi của nhóm trên bất kỳ vòng lặp nào. (Vì lý do này chúng tôi thậm chí còn thực hiện một chương trình đặc biệt Nhà xuất khẩu Prometheus, theo dõi sự vắng mặt của những hình ảnh như vậy trong bất kỳ cụm Kubernetes nào.)

2. Thứ hai (ít rõ ràng hơn, nhưng cũng rất quan trọng và lại liên quan đến sự bóc lột) - những hình ảnh cần thiết để khôi phục trong trường hợp phát hiện sự cố nghiêm trọng trong phiên bản hiện tại. Ví dụ: trong trường hợp của Helm, đây là những hình ảnh được sử dụng trong các phiên bản đã lưu của bản phát hành. (Nhân tiện, theo mặc định trong Helm, giới hạn là 256 bản sửa đổi, nhưng khó có ai thực sự cần lưu như vậy một số lượng lớn các phiên bản?..) Rốt cuộc, chúng tôi đặc biệt lưu trữ các phiên bản để có thể sử dụng chúng sau này, tức là. “quay lại” với họ nếu cần thiết.

3. Thứ ba - nhu cầu của nhà phát triển: Tất cả các hình ảnh có liên quan đến công việc hiện tại của họ. Ví dụ: nếu chúng ta đang xem xét một PR, thì sẽ hợp lý nếu để lại một hình ảnh tương ứng với lần xác nhận cuối cùng và, chẳng hạn như lần cam kết trước đó: bằng cách này, nhà phát triển có thể nhanh chóng quay lại bất kỳ tác vụ nào và làm việc với những thay đổi mới nhất.

4. Thứ tư - những hình ảnh tương ứng với các phiên bản ứng dụng của chúng tôi, I E. là sản phẩm cuối cùng: v1.0.0, 20.04.01/XNUMX/XNUMX, sierra, v.v.

Lưu ý: Các tiêu chí được xác định ở đây được xây dựng dựa trên kinh nghiệm tương tác với hàng chục nhóm phát triển từ các công ty khác nhau. Tuy nhiên, tất nhiên, tùy thuộc vào chi tiết cụ thể trong quá trình phát triển và cơ sở hạ tầng được sử dụng (ví dụ: Kubernetes không được sử dụng), các tiêu chí này có thể khác nhau.

Tính đủ điều kiện và các giải pháp hiện có

Theo quy định, các dịch vụ phổ biến có cơ quan đăng ký vùng chứa cung cấp các chính sách dọn dẹp hình ảnh của riêng họ: trong đó bạn có thể xác định các điều kiện để xóa thẻ khỏi sổ đăng ký. Tuy nhiên, những điều kiện này bị giới hạn bởi các tham số như tên, thời gian tạo và số lượng thẻ*.

* Phụ thuộc vào việc triển khai đăng ký vùng chứa cụ thể. Chúng tôi đã xem xét khả năng của các giải pháp sau: Azure CR, Docker Hub, ECR, GCR, Gói GitHub, Cơ quan đăng ký vùng chứa GitLab, Cơ quan đăng ký bến cảng, JFrog Artifactory, Quay.io - kể từ tháng 2020 năm XNUMX.

Bộ tham số này khá đủ để đáp ứng tiêu chí thứ tư - tức là chọn hình ảnh tương ứng với các phiên bản. Tuy nhiên, đối với tất cả các tiêu chí khác, người ta phải chọn một số loại giải pháp thỏa hiệp (chính sách cứng rắn hơn hoặc ngược lại, khoan dung hơn) - tùy thuộc vào kỳ vọng và khả năng tài chính.

Ví dụ: tiêu chí thứ ba - liên quan đến nhu cầu của nhà phát triển - có thể được giải quyết bằng cách tổ chức các quy trình trong nhóm: đặt tên cụ thể cho hình ảnh, duy trì danh sách cho phép đặc biệt và thỏa thuận nội bộ. Nhưng cuối cùng nó vẫn cần được tự động hóa. Và nếu khả năng của các giải pháp làm sẵn là không đủ, bạn phải tự mình làm điều gì đó.

Tình huống với hai tiêu chí đầu tiên cũng tương tự nhau: chúng không thể hài lòng nếu không nhận được dữ liệu từ hệ thống bên ngoài - hệ thống nơi các ứng dụng được triển khai (trong trường hợp của chúng tôi là Kubernetes).

Minh họa quy trình làm việc trong Git

Giả sử bạn đang làm việc như thế này trong Git:

Bài toán dọn dẹp container image “thông minh” và giải pháp trong werf

Biểu tượng có phần đầu trong sơ đồ biểu thị hình ảnh vùng chứa hiện được triển khai trong Kubernetes cho bất kỳ người dùng nào (người dùng cuối, người kiểm tra, người quản lý, v.v.) hoặc được các nhà phát triển sử dụng để gỡ lỗi và cho các mục đích tương tự.

Điều gì xảy ra nếu chính sách dọn dẹp chỉ cho phép giữ lại hình ảnh (không bị xóa) theo tên thẻ đã cho?

Bài toán dọn dẹp container image “thông minh” và giải pháp trong werf

Rõ ràng, một kịch bản như vậy sẽ không làm hài lòng bất cứ ai.

Điều gì sẽ thay đổi nếu chính sách cho phép không xóa hình ảnh? theo một khoảng thời gian nhất định/số lần xác nhận cuối cùng?

Bài toán dọn dẹp container image “thông minh” và giải pháp trong werf

Kết quả đã trở nên tốt hơn nhiều, nhưng vẫn còn xa lý tưởng. Suy cho cùng, chúng tôi vẫn có những nhà phát triển cần hình ảnh trong sổ đăng ký (hoặc thậm chí được triển khai trong K8) để gỡ lỗi...

Tóm tắt tình hình thị trường hiện tại: các chức năng có sẵn trong cơ quan đăng ký container không cung cấp đủ tính linh hoạt khi làm sạch và lý do chính cho điều này là không có cách nào để tương tác với thế giới bên ngoài. Hóa ra các nhóm yêu cầu tính linh hoạt như vậy buộc phải thực hiện xóa hình ảnh một cách độc lập “từ bên ngoài”, bằng cách sử dụng API đăng ký Docker (hoặc API gốc của quá trình triển khai tương ứng).

Tuy nhiên, chúng tôi đang tìm kiếm một giải pháp phổ quát có thể tự động hóa việc dọn dẹp hình ảnh cho các nhóm khác nhau bằng cách sử dụng các cơ quan đăng ký khác nhau...

Con đường của chúng tôi để làm sạch hình ảnh phổ quát

Nhu cầu này đến từ đâu? Thực tế là chúng tôi không phải là một nhóm các nhà phát triển riêng biệt mà là một nhóm phục vụ nhiều người trong số họ cùng một lúc, giúp giải quyết toàn diện các vấn đề về CI/CD. Và công cụ kỹ thuật chính cho việc này là tiện ích Nguồn mở người sói. Điểm đặc biệt của nó là nó không thực hiện một chức năng duy nhất mà đi kèm với các quá trình phân phối liên tục ở tất cả các giai đoạn: từ lắp ráp đến triển khai.

Xuất bản hình ảnh lên sổ đăng ký* (ngay sau khi chúng được tạo) là một chức năng rõ ràng của một tiện ích như vậy. Và vì hình ảnh được đặt ở đó để lưu trữ, nên - nếu dung lượng lưu trữ của bạn không phải là vô hạn - bạn cần phải chịu trách nhiệm về việc làm sạch chúng sau này. Làm thế nào chúng tôi đạt được thành công trong việc này, đáp ứng tất cả các tiêu chí đã chỉ định, sẽ được thảo luận thêm.

* Mặc dù bản thân các cơ quan đăng ký có thể khác nhau (Docker Cơ quan đăng ký, Cơ quan đăng ký vùng chứa GitLab, Cảng, v.v.), người dùng của các cơ quan đăng ký này đều gặp phải các vấn đề tương tự. Giải pháp phổ quát trong trường hợp của chúng tôi không phụ thuộc vào việc triển khai sổ đăng ký, bởi vì tự chạy bên ngoài cơ quan đăng ký và đưa ra hành vi giống nhau cho mọi người.

Mặc dù chúng tôi đang sử dụng werf làm ví dụ triển khai nhưng chúng tôi hy vọng rằng các phương pháp được sử dụng sẽ hữu ích cho các nhóm khác đang gặp phải những khó khăn tương tự.

Vì thế chúng tôi bận rộn bên ngoài triển khai cơ chế làm sạch hình ảnh - thay vì những khả năng đã được tích hợp sẵn trong sổ đăng ký cho vùng chứa. Bước đầu tiên là sử dụng API đăng ký Docker để tạo các chính sách nguyên thủy tương tự về số lượng thẻ và thời gian tạo chúng (đã đề cập ở trên). Đã thêm vào họ danh sách cho phép dựa trên hình ảnh được sử dụng trong cơ sở hạ tầng được triển khai, I E. Kubernetes. Đối với trường hợp thứ hai, chỉ cần sử dụng API Kubernetes để lặp qua tất cả các tài nguyên đã triển khai và nhận danh sách các giá trị là đủ image.

Giải pháp tầm thường này đã giải quyết được vấn đề quan trọng nhất (tiêu chí số 1), nhưng chỉ là bước khởi đầu trong hành trình cải tiến cơ chế làm sạch của chúng tôi. Bước tiếp theo - và thú vị hơn nhiều - là quyết định liên kết hình ảnh được xuất bản với lịch sử Git.

Đề án gắn thẻ

Để bắt đầu, chúng tôi đã chọn một phương pháp trong đó hình ảnh cuối cùng sẽ lưu trữ thông tin cần thiết để làm sạch và xây dựng quy trình dựa trên sơ đồ gắn thẻ. Khi xuất bản một hình ảnh, người dùng đã chọn tùy chọn gắn thẻ cụ thể (git-branch, git-commit hoặc git-tag) và sử dụng giá trị tương ứng. Trong hệ thống CI, các giá trị này được đặt tự động dựa trên các biến môi trường. Trong thực tế hình ảnh cuối cùng được liên kết với một nguyên hàm Git cụ thể, lưu trữ dữ liệu cần thiết để làm sạch trong nhãn.

Cách tiếp cận này dẫn đến một bộ chính sách cho phép sử dụng Git làm nguồn sự thật duy nhất:

  • Khi xóa một nhánh/thẻ trong Git, các hình ảnh liên quan trong sổ đăng ký sẽ tự động bị xóa.
  • Số lượng hình ảnh được liên kết với thẻ Git và các cam kết có thể được kiểm soát bởi số lượng thẻ được sử dụng trong lược đồ đã chọn và thời gian mà cam kết liên quan được tạo.

Nhìn chung, kết quả triển khai đã đáp ứng được nhu cầu của chúng tôi, nhưng một thách thức mới sẽ sớm chờ đợi chúng tôi. Thực tế là khi sử dụng các lược đồ gắn thẻ dựa trên nguyên hàm Git, chúng tôi đã gặp phải một số thiếu sót. (Vì mô tả của chúng nằm ngoài phạm vi của bài viết này nên mọi người có thể tự làm quen với các chi tiết đây.) Do đó, khi quyết định chuyển sang phương pháp gắn thẻ hiệu quả hơn (gắn thẻ dựa trên nội dung), chúng tôi đã phải xem xét lại việc thực hiện làm sạch hình ảnh.

Thuật toán mới

Tại sao? Với tính năng gắn thẻ dựa trên nội dung, mỗi thẻ có thể đáp ứng nhiều cam kết trong Git. Khi làm sạch hình ảnh, bạn không còn có thể giả định chỉ từ cam kết nơi thẻ mới được thêm vào sổ đăng ký.

Đối với thuật toán làm sạch mới, người ta đã quyết định loại bỏ các sơ đồ gắn thẻ và xây dựng quá trình siêu hình ảnh, mỗi cái lưu trữ một loạt:

  • cam kết mà việc xuất bản đã được thực hiện (không quan trọng hình ảnh đã được thêm, thay đổi hay giữ nguyên trong sổ đăng ký vùng chứa);
  • và mã định danh nội bộ của chúng tôi tương ứng với hình ảnh được lắp ráp.

Nói cách khác, nó đã được cung cấp liên kết các thẻ đã xuất bản với các xác nhận trong Git.

Cấu hình cuối cùng và thuật toán chung

Khi định cấu hình dọn dẹp, người dùng hiện có quyền truy cập vào các chính sách chọn hình ảnh hiện tại. Mỗi chính sách như vậy được xác định:

  • nhiều tài liệu tham khảo, tức là Thẻ Git hoặc nhánh Git được sử dụng trong quá trình quét;
  • và giới hạn hình ảnh được tìm kiếm cho mỗi tham chiếu từ bộ này.

Để minh họa, đây là hình thức cấu hình chính sách mặc định:

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

Cấu hình này chứa ba chính sách tuân thủ các quy tắc sau:

  1. Lưu hình ảnh cho 10 thẻ Git cuối cùng (theo ngày tạo thẻ).
  2. Lưu không quá 2 hình ảnh được xuất bản vào tuần trước cho không quá 10 chủ đề có hoạt động trong tuần trước.
  3. Lưu 10 hình ảnh cho chi nhánh main, staging и production.

Thuật toán cuối cùng thực hiện theo các bước sau:

  • Truy xuất bảng kê khai từ sổ đăng ký vùng chứa.
  • Không bao gồm hình ảnh được sử dụng trong Kubernetes, vì Chúng tôi đã chọn trước chúng bằng cách thăm dò API K8s.
  • Quét lịch sử Git và loại trừ hình ảnh dựa trên các chính sách được chỉ định.
  • Xóa các hình ảnh còn lại.

Quay trở lại hình minh họa của chúng tôi, đây là những gì xảy ra với werf:

Bài toán dọn dẹp container image “thông minh” và giải pháp trong werf

Tuy nhiên, ngay cả khi bạn không sử dụng werf, một cách tiếp cận tương tự để làm sạch hình ảnh nâng cao - theo cách triển khai này hay cách triển khai khác (theo cách tiếp cận ưa thích để gắn thẻ hình ảnh) - có thể được áp dụng cho các hệ thống/tiện ích khác. Để làm được điều này, chỉ cần ghi nhớ các vấn đề phát sinh và tìm những cơ hội đó trong ngăn xếp của bạn để cho phép bạn tích hợp giải pháp của chúng một cách suôn sẻ nhất có thể. Chúng tôi hy vọng rằng con đường chúng tôi đã đi sẽ giúp bạn nhìn nhận trường hợp cụ thể của mình bằng những chi tiết và suy nghĩ mới.

Kết luận

  • Sớm hay muộn, hầu hết các nhóm đều gặp phải vấn đề tràn sổ đăng ký.
  • Khi tìm kiếm giải pháp, trước tiên cần xác định tiêu chí về mức độ phù hợp của hình ảnh.
  • Các công cụ được cung cấp bởi các dịch vụ đăng ký vùng chứa phổ biến cho phép bạn tổ chức việc dọn dẹp rất đơn giản mà không tính đến “thế giới bên ngoài”: các hình ảnh được sử dụng trong Kubernetes và các đặc thù trong quy trình làm việc của nhóm.
  • Thuật toán linh hoạt và hiệu quả phải có hiểu biết về các quy trình CI/CD và hoạt động không chỉ với dữ liệu hình ảnh Docker.

PS

Đọc thêm trên blog của chúng tôi:

Nguồn: www.habr.com

Thêm một lời nhận xét