Mình đã dọn 250GiB Azure container registry (ACR) thành 10Gib đón Noel

Hoàn cảnh lịch sử

Công ty mình đang dùng Azure Registry (ACR) để lưu trữ container image. Mọi chuyện tưởng chừng đơn giản vì mọi thứ đã có Azure lo, mình không cần lo lắng gì cả. Tuy nhiên một ngày đẹp trời, sau 1 phút nhẹ nhàng đi lòng vòng xem xét thì mình phát hiện team mình đã xài hơn 200GiB storage. OMG…Có cái gì đó sai sai đang diễn ra…

ACR 250GiB to 10GiB – Before clean up

Việc đầu tiên mình cần làm là tìm ra vấn đề nằm ở chỗ nào. Một công cụ thống kê được lượng lưu trữ mà mình đã tiêu tốn trên từng repository. Thật là thất vọng khi mà Azure lại không cung cấp 1 cái tính năng cơ bản như thế này. Chỉ có thể nhờ tool trên github để giải quyết. Kết quả cho ra team mình không xài nhiều storage như vậy, đâu đó khoản 20GiB thôi. Đã mất một buổi chiều vì cái thứ này, đời em lại đi về bế tắc.

Nguyên nhân

Sau 1 đêm mình là đi lòng vòng, gác đầu lên trán mà nghĩ xem chuyện gì đang xảy ra. Và rồi..chính là nó..Dangling images, Untagged Manifest. Một chuyện mà mình không biết và là nguyên nhân nỗi đau đó chính là:

Mỗi lần chúng ta push image lên ACR với cùng tag thì Azure không xóa image cũ đi.

Giải thích kiểu nông dân ở chỗ này một chút là thế này, giả sử bạn build một cái image docker là kikigaugau:stable , rồi push lên azure, thì azure sẽ lưu image kikigaugau với tag stable mình tạm gọi là version 1. Sau đó bạn build lại cái image này với cùng tag đó rồi push lên azure lần nữa, lúc này image sẽ có nội dung mới là version 2. version 1 và version 2 cùng name nhưng có nội dung khác nhau. Mình cứ tưởng là khi mình push version 2 lên thì azure phải xóa version 1 cũ đi nhưng sự thật là nó không làm như vậy. Azure giữ lại những version 1 này và chúng nó là những Untagged Manifest. Team mình mỗi lần build docker đều dùng 1 tag, cứ build xong là push image lên cung tag, đơn giản vậy đó. Việc này kéo dài hơn 1 năm, nên trên azure có có một bầy image không tên, không tag bơi đi bơi lại trong đó. Điều này có vẻ azure rất thích, còn mình thì méo mỏ với nó.

Thế là mình đã tạo một schedule job để dọn dẹp Untagged Manifest. Kết quả vượt ngoài mong đợi, bạn có thể xem hình bên dưới  là kết quá mình đã đạt được.

ACR 250GiB to 10GiB – After clean up

Vâng thưa các bạn, thật là nhẹ người..cảm giác này ai có hiểu.

PS. Nếu ai đang bị giống mình thì xin báo trước là cái document của azure chỉ cách xóa Untagged không chuẩn lắm [hicc].

Cách giải quyết vấn đề (cập nhật 1/2/2021)

Mình xin viết bổ sung cách mà mình đã giải quyết chuyện này, vì một số bạn ping mình nên chia sẽ luôn, anh em đỡ google cho khỏe. Theo mình thì cần làm 2 việc đó là cần 1 tool để xem từng repo mình tiêu hao bao nhiêu không gian lưu trữ và một tool để dọn rác giúp mình.

Tool xem thông tin repo.

Dù rằng Azure vẫn luôn khoe là support tốt cho doanh nghiệp, tuy nhiên cái tính năng xem mỗi repo xài hết nhiêu lại chưa từng tồn tại trên Azure portal (API thì có mà phải code nhẹ). Mình có tìm được một lib trên github, dù rằng tool này chắc do chán đời nên đã không còn phát triển sản phẩm từ khá lâu (4-5 năm rồi).

https://github.com/mkuchin/docker-registry-web

Do là đồ cổ nên xài nguyên si không chạy đâu nhé, bạn nào lười lười thì copy cái dưới cho khỏe!

docker run --rm -it -p 8888:8080 --name registry-web  \
           -e REGISTRY_URL=https://<your_registry>.azurecr.io/v2 \
           -e CATALINA_OPTS="-Dhttps.protocols=TLSv1.1,TLSv1.2" \
           -e REGISTRY_BASIC_AUTH="<base64_encode(username:password)>" \
           -e REGISTRY_NAME=<your_registry>.azurecr.io hyper/docker-registry-web
Tạo Azure Registry Task để dọn rác.

Cái này anh em có thể tham khảo trên Azure docs cách xóa Untagged Manifest tại link phía dưới.

https://learn.microsoft.com/en-us/azure/container-registry/container-registry-auto-purge

Lưu ý:
Tuy nhiên cái docs này khá rỏm vì làm theo nó có ngày nó xóa luôn mấy cái image có tags. Ăn hành ráng chịu nhé!

Cách hoạt động sơ sơ là nó sẽ tạo ra 1 cái Schedule Task chạy định kỳ theo anh em quy định. Mình chọn chạy vào T3 hàng tuần, đối với mình cái này là ngày tương đối ổn hơn là thứ 6 deploy thần thánh hay là thứ 2 gì đó.

Cụ thể là cái filter này có gì đó sai sai 'samples/devimage1:.*', vì nó dùng .* nên nó match luôn máy cái tagged manifest luôn. (Không biết người viết cái doc này có test không nữa). Cái issue này có report trên github rồi, và có cách fix tạm là dùng ^$ thay vì .*.  

Code mẫu cho anh em lười lười đi search nè!

az acr task create --name cleanweb --schedule="* * * * *" --cmd "acr purge \
    --filter='web/api-gateway:^$' \
    --filter='web/couchdb:^$' \
    --filter='web/database:^$' \
    --filter='web/dundas:^$' \
    --filter='web/migration:^$' \
    --filter='web/fpm:^$' \
    --filter='web/nginx:^$' \
    --filter='web/service:^$' \
    --ago 365d --untagged --dry-run"  \
    --registry <your_registry> --subscription="<subscription_id>" --timeout 3600 --context /dev/null

Năm mới vui vẻ và quyết thắng nhé!