컨테이너 레지스트리 저장소 축소

Tier: Free, Premium, Ultimate Offering: GitLab.com, Self-managed, GitLab Dedicated

컨테이너 레지스트리는 레지스트리 사용량을 관리하지 않으면 시간이 지남에 따라 크기가 커질 수 있습니다. 예를 들어, 대량의 이미지나 태그를 추가하는 경우:

  • 사용 가능한 태그나 이미지 목록을 검색하는 데 시간이 더 오래 걸립니다.
  • 서버의 많은 저장 공간을 차지합니다.

불필요한 이미지와 태그를 삭제하고 컨테이너 레지스트리 사용량을 자동으로 관리하려면 정리 정책을 설정하세요.

컨테이너 레지스트리 사용량 보기

Tier: Free, Premium, Ultimate Offering: GitLab.com

컨테이너 레지스트리의 저장소 사용량을 보려면:

  1. 왼쪽 사이드바에서 검색 또는 이동을 선택하고 프로젝트를 찾습니다.
  2. 설정 > 사용량 할당을 선택합니다.

자체관리형 인스턴스의 컨테이너 레지스트리 사용량을 볼 수는 없지만, 이에 대한 제안 사항이 epic 5521에 있습니다.

컨테이너 레지스트리 사용량 계산 방법

컨테이너 레지스트리에 저장된 이미지 레이어는 루트 네임스페이스 수준에서 중복 제외됩니다.

이미지는 다음과 같은 경우에만 한 번만 계산됩니다:

  • 동일한 이미지를 동일한 저장소에서 여러 번 태깅하는 경우.
  • 동일한 이미지를 동일한 루트 네임스페이스 내의 다른 저장소에 걸쳐 태깅하는 경우.

이미지 레이어는 다음과 같은 경우에만 한 번만 계산됩니다:

  • 동일한 이미지 레이어를 동일한 컨테이너 저장소, 프로젝트 또는 그룹에서 여러 이미지에 공유하는 경우.
  • 동일한 이미지 레이어를 다른 저장소에 공유하는 경우.

태그가 있는 이미지에서만 참조되는 레이어만 계산됩니다. 태그가 없는 이미지와 해당 레이어만 있는 경우, 그 레이어는 해당 기간 동안 참조되지 않으면 24시간 후에 자동으로 삭제됩니다.

이미지 레이어는 일반적으로 원본 (일반적으로 압축된) 형식으로 저장소 백엔드에 저장됩니다. 따라서 특정 이미지 레이어의 측정 크기는 해당하는 이미지 매니페스트에 표시된 크기와 일치해야 합니다.

네임스페이스 사용량은 태그가 푸시되거나 삭제된 후 몇 분 후에 새로 고침됩니다.

지연된 새로 고침

매우 큰 네임스페이스 (네임스페이스의 약 1%)의 실시간 정밀한 컨테이너 레지스트리 사용량을 계산하는 것은 불가능합니다. 이러한 네임스페이스의 유지보수자가 사용량을 볼 수 있게 하려면 지연된 대체 메커니즘이 있습니다. 자세한 내용은 epic 9413을 참조하세요.

Namespace의 사용량을 정밀하게 계산할 수 없는 경우, GitLab은 지연된 방법으로 전환합니다. 지연된 방법에서 표시된 사용량 크기는 네임스페이스의 모든 고유 이미지 레이어의 합계입니다. 태그가 푸시된 후 사용되지 않은 레이어가 삭제될 때 사용량이 업데이트됩니다. 네임스페이스 사용량이 충분히 줄어들면 정밀한 사용량 측정으로 자동 전환됩니다.

정밀한 사용량 측정 방법을 확인할 수 있는 위치는 UI에 없지만 이를 개선하도록 하는 issue 386468이 제안되었습니다.

정리 정책

  • GitLab 15.0에서 필요한 권한이 개발자에서 유지자로 변경됨.

정리 정책은 컨테이너 레지스트리에서 태그를 제거하는 예약 작업입니다. 정의된 프로젝트에서 정규식 패턴과 일치하는 태그가 제거됩니다. 기본 레이어와 이미지는 그대로 남습니다.

태그와 연관이 없는 기본 레이어와 이미지를 삭제하려면 관리자는 -m 스위치를 사용하여 garbage collection을 사용할 수 있습니다.

정리 정책 활성화

경고: 성능상의 이유로 GitLab.com의 프로젝트에서 컨테이너 이미지가 없는 경우, 활성화된 정리 정책이 자동으로 비활성화됩니다.

정리 정책 작동 방식

정리 정책은 컨테이너 레지스트리의 모든 태그를 수집하고 제거하고 싶은 태그만 남을 때까지 제외합니다.

정리 정책은 태그 이름을 기준으로 이미지를 찾습니다. 전체 경로 일치 지원은 이슈 281071에서 추적됩니다.

정리 정책은 다음과 같은 작업을 수행합니다:

  1. 지정된 저장소의 모든 태그를 목록으로 수집합니다.
  2. 이름이 latest인 태그를 제외합니다.
  3. name_regex (만료되는 태그)를 기준으로 평가하고 일치하지 않는 이름을 제외합니다.
  4. name_regex_keep 값 (보존할 태그)과 일치하는 태그를 제외합니다.
  5. 매니페스트가 없는 태그를 제외합니다.
  6. created_date를 기준으로 남은 태그를 정렬합니다.
  7. keep_n 값 (보유할 태그 수)을 기준으로 N개의 태그를 제외합니다.
  8. older_than 값 (만료 간격)보다 최신인 태그를 제외합니다.
  9. 리스트에서 남은 태그를 컨테이너 레지스트리에서 삭제합니다.

경고: GitLab.com에서 정리 정책 실행 시간은 제한됩니다. 정책 실행 후에도 일부 태그가 컨테이너 레지스트리에 남아 있을 수 있습니다. 정책이 다음에 실행되면 나머지 태그가 포함됩니다. 모든 태그를 삭제하기 위해 여러 번 실행될 수 있습니다.

경고: GitLab 자체 설치는 Docker Registry HTTP API V2 사양을 준수하는 타사 컨테이너 레지스트리를 지원합니다. 그러나 이 사양에는 태그 삭제 작업이 포함되지 않습니다. 그래서 GitLab은 타사 컨테이너 레지스트리와 상호작용할 때 태그를 삭제하는 우회 방법을 사용합니다. 자세한 내용은 이슈 15737을 참조하세요. 가능한 구현 변화로 인해 이 우회 방법이 모든 타사 레지스트리에서 동일한 예측 가능한 방식으로 작동하는 것은 보장되지 않습니다. GitLab 컨테이너 레지스트리를 사용하는 경우 이 우회 방법이 필요하지 않습니다. 그런 경우에는 정리 정책이 일관되고 예측 가능하게 작동할 것입니다.

예시 정리 정책 워크플로우

정리 정책의 유지 및 제거 규칙 간 상호작용은 복잡할 수 있습니다. 이러한 정리 정책 구성을 갖는 프로젝트의 경우 다음과 같은 예제가 있습니다.

  • 가장 최근 것 유지: 이미지 이름별로 1개의 태그를 유지합니다.
  • 일치하는 태그 유지: production-.*
  • 다음보다 오래된 태그 제거: 7일.
  • 일치하는 태그 제거: .*.

그리고 이러한 태그를 포함하는 컨테이너 저장소가 있습니다:

  • latest, 2시간 전에 발행됨.
  • production-v44, 3일 전에 발행됨.
  • production-v43, 6일 전에 발행됨.
  • production-v42, 11일 전에 발행됨.
  • dev-v44, 2일 전에 발행됨.
  • dev-v43, 5일 전에 발행됨.
  • dev-v42, 10일 전에 발행됨.
  • v44, 어제 발행됨.
  • v43, 12일 전에 발행됨.
  • v42, 20일 전에 발행됨.

이 예에서, 다음 정리 실행에서 삭제될 태그는 dev-v42, v43, v42입니다. 규칙 해석은 다음과 같습니다:

  1. 가장 먼저, 유지 규칙이 가장 높은 우선순위를 갖습니다. 태그는 어떠한 규칙과 일치할 때 유지되어야 합니다.
    • latest 태그는 항상 유지되기 때문에 유지되어야 합니다.
    • production-v44, production-v43, production-v42 태그는 일치하는 태그 유지 규칙과 일치하기 때문에 유지되어야 합니다.
    • v44 태그는 가장 최근이기 때문에 가장 최근 것 유지 규칙과 일치하여 유지되어야 합니다.
  2. 그 다음, 제거 규칙이 낮은 우선순위를 갖고, 모든 규칙이 일치할 때에만 태그가 삭제됩니다. 유지 규칙과 일치하지 않는 태그(dev-44, dev-v43, dev-v42, v43, v42)에 대해:
    • dev-44dev-43다음보다 오래된 태그 제거와 일치하지 않으므로 유지됩니다.
    • dev-v42, v43, 그리고 v42다음보다 오래된 태그 제거일치하는 태그 제거 규칙과 둘 다 일치하기 때문에 삭제될 수 있습니다.

정리 정책 만들기

UI에서 정리 정책을 만들 수 있습니다: 정리 정책 API 사용 또는 UI에서 만들 수 있습니다.

UI에서 정리 정책을 만들려면:

  1. 왼쪽 사이드바에서 검색 또는 이동을 선택하고 프로젝트를 찾습니다.
  2. 설정 > 패키지 및 레지스트리를 선택합니다.
  3. 정리 정책 섹션에서 정리 규칙 설정을 선택합니다.
  4. 다음과 같은 필드를 완성합니다:

    필드 설명
    토글 정책을 켜거나 끕니다.
    정리 실행 정책이 실행되는 빈도입니다.
    가장 최근 것 유지 이미지 당 항상 유지할 태그 수입니다.
    일치하는 태그 유지 보존될 태그를 결정하는 정규식 패턴입니다. latest 태그는 항상 보존됩니다. 모든 태그의 경우 .*을 사용합니다. 다른 정규식 예제는 정규식 패턴 예제를 참조하세요.
    다음보다 오래된 태그 제거 X일보다 오래된 태그만 제거합니다.
    일치하는 태그 제거 삭제할 태그를 결정하는 정규식 패턴입니다. 이 값은 비워둘 수 없습니다. 모든 태그의 경우 .*을 사용합니다. 다른 정규식 예제는 정규식 패턴 예제를 참조하세요.

    참고: 유지 및 제거 정규식 패턴은 자동으로 \A\Z 앵커로 둘러싸입니다. 따라서 이를 포함할 필요가 없습니다. 그러나 정규식 패턴을 선택하고 테스트할 때 이 사항을 고려하세요.

  5. 저장을 선택합니다.

정책은 선택한 예약 간격에 따라 실행됩니다.

참고: 정책을 편집하고 다시 저장을 선택하면 예약 간격이 재설정됩니다.

정규식 패턴 예제

UI 및 API에서 정리 정책을 사용할 때 정규식 패턴을 사용합니다.

GitLab은 정리 정책에서 정규 표현식으로 RE2 구문을 사용합니다.

사용할 수 있는 일부 정규식 패턴 예제는 다음과 같습니다:

  • 모든 태그 일치:

    .*
    

    이 패턴은 만료 정규식의 기본값입니다.

  • v로 시작하는 태그 일치:

    v.+
    
  • main이라는 태그만 일치:

    main
    
  • release로 시작하거나 release로 시작하는 태그 일치:

    release.*
    
  • v로 시작하거나 main이라는 태그 또는 release로 시작하는 태그 일치:

    (?:v.+|main|release.*)
    

소스 보존을 위한 정리 한도 설정

  • GitLab 15.0에서 container_registry_expiration_policies_throttling 기능 플래그 제거.

정리 정책은 백그라운드 프로세스로 실행됩니다. 이 프로세스는 복잡하며, 삭제할 태그의 수에 따라 프로세스가 완료되는 데 시간이 소요될 수 있습니다.

서버 리소스 고갈을 방지하려면 다음의 응용 프로그램 설정을 사용할 수 있습니다:

  • container_registry_expiration_policies_worker_capacity: 동시에 실행되는 최대 정리 작업자 수입니다. 이 값은 0 이상이어야 합니다. 백그라운드 작업자가 사용하는 리소스를 모니터링한 후, 낮은 수로 시작하여 증가시켜야 합니다. 모든 작업자를 제거하고 정리 정책을 실행하지 않으려면 이 값을 0으로 설정하세요. 기본값은 4입니다.
  • container_registry_delete_tags_service_timeout: 태그 일괄 삭제에 소요될 수 있는 최대 시간(초)입니다. 기본값은 250입니다.
  • container_registry_cleanup_tags_service_max_list_size: 단일 실행에서 삭제할 수 있는 최대 태그 수입니다. 추가 태그는 다른 실행에서 삭제해야 합니다. 올바르게 이미지가 삭제되었는지 확인한 후, 낮은 수로 시작하여 증가시켜야 합니다. 기본값은 200입니다.
  • container_registry_expiration_policies_caching: 정책 실행 중에 태그 작성 타임스탬프 캐싱을 활성화 또는 비활성화합니다. 캐시된 타임스탬프는 Redis에 저장됩니다. 기본적으로 활성화되어 있습니다.

자체 관리형 인스턴스의 경우, 이러한 설정을 Rails 콘솔에서 업데이트할 수 있습니다:

ApplicationSetting.last.update(container_registry_expiration_policies_worker_capacity: 3)

또한 관리자 영역에서 이러한 설정을 찾을 수 있습니다:

  1. 왼쪽 사이드바에서, 맨 아래에서 관리자를 선택합니다.
  2. 설정 > CI/CD를 선택합니다.
  3. 컨테이너 레지스트리를 확장합니다.

Cleanup policy API 사용하기

GitLab API를 사용하여 정리 정책을 설정, 업데이트 및 비활성화할 수 있습니다.

예시:

  • 모든 태그 선택, 이미지 당 최소 1개의 태그 유지, 14일보다 오래된 태그 정리, 매월 실행, main이름을 가진 이미지는 유지, 정책이 활성화됨:

    curl --fail-with-body --request PUT --header 'Content-Type: application/json;charset=UTF-8'
         --header "PRIVATE-TOKEN: <your_access_token>" \
         --data-binary '{"container_expiration_policy_attributes":{"cadence":"1month","enabled":true,"keep_n":1,"older_than":"14d","name_regex":".*","name_regex_keep":".*-main"}}' \
         "https://gitlab.example.com/api/v4/projects/2"
    

API를 사용할 때 cadence에 대한 유효한 값은:

  • 1d (매일)
  • 7d (매주)
  • 14d (2주마다)
  • 1month (매월)
  • 3month (분기별)

API를 사용할 때 keep_n (이미지 이름당 유지되는 태그 수)에 대한 유효한 값은:

  • 1
  • 5
  • 10
  • 25
  • 50
  • 100

API를 사용할 때 older_than (자동으로 제거되는 태그까지의 일 수)에 대한 유효한 값은:

  • 7d
  • 14d
  • 30d
  • 90d

더 많은 세부 정보는 API 설명서를 참조하세요: 프로젝트 API 편집하기.

외부 컨테이너 레지스트리 사용하기

외부 컨테이너 레지스트리를 사용하는 경우, 프로젝트에서 정리 정책을 실행하면 몇 가지 성능 문제가 발생할 수 있습니다. 프로젝트에서 수천 개의 태그를 제거하는 정책을 실행하는 경우, GitLab 백그라운드 작업에 지연이 발생하거나 완전히 실패할 수 있습니다.

추가적인 컨테이너 레지스트리 저장 공간 축소 옵션

프로젝트에서 사용하는 컨테이너 레지스트리 저장 공간을 줄이는 다른 옵션들은 다음과 같습니다:

  • GitLab UI를 사용하여 개별 이미지 태그 또는 모든 태그를 포함하는 저장소 전체를 삭제합니다.
  • API를 사용하여 개별 이미지 태그를 삭제합니다.
  • API를 사용하여 모든 태그를 포함하는 컨테이너 레지스트리 저장소 전체를 삭제합니다.
  • API를 사용하여 대량의 레지스트리 저장소 태그를 삭제합니다.

정리 정책 문제 해결

정리 정책을 업데이트하는 동안 오류가 발생했습니다.

이 오류 메시지가 표시되면 정규식 패턴이 유효한지 확인하세요.

Golang 스타일을 사용하여 regex101 regex tester로 테스트할 수 있습니다. 일반적인 정규식 패턴 예제를 확인하세요.

정리 정책이 어떤 태그도 삭제하지 않음

이에는 다양한 이유가 있을 수 있습니다:

  • GitLab Self-Managed 인스턴스를 사용하고 컨테이너 저장소에 1000개 이상의 태그가 있는 경우, 로그에서 error authorizing context: invalid token 오류가 발생할 수 있는 컨테이너 레지스트리 토큰 만료 문제가 발생할 수 있습니다.

    이를 해결하기 위해 두 가지 해결책이 있습니다:

    • 정리 정책에 제한 설정합니다. 이렇게 하면 시간 내에 정리가 실행되고 만료된 토큰 오류를 방지할 수 있습니다.

    • 컨테이너 레지스트리 인증 토큰의 만료 지연을 연장합니다. 기본값은 5분입니다. Rails 콘솔에서 ApplicationSetting.last.update(container_registry_token_expire_delay: <integer>)를 실행하여 사용자 정의 값을 설정할 수 있습니다. 여기서 <integer>은 원하는 분 수입니다. 참조로, GitLab.com에서 만료 지연은 15분으로 설정되어 있습니다. 이 값을 늘리면 권한 취소에 필요한 시간이 늘어납니다.

또는 삭제할 태그 목록을 생성하고 해당 목록을 사용하여 태그를 삭제할 수 있습니다. 목록을 작성하고 태그를 삭제하려면:

  1. 다음 셸 스크립트를 실행하세요. for 루프를 시작할 때 list_o_tags.out이 항상 다시 초기화되도록 하는 명령어입니다. 이 명령을 실행한 후 모든 태그 이름이 list_o_tags.out 파일에 기록됩니다.

    :::탭

    :::탭타이틀 Linux

    # 특정 컨테이너 저장소에 있는 모든 태그 목록 가져오기(페이징 고려)
    echo -n "" > list_o_tags.out; for i in {1..N}; do curl --fail-with-body --header 'PRIVATE-TOKEN: <PAT>' "https://gitlab.example.com/api/v4/projects/<Project_id>/registry/repositories/<container_repo_id>/tags?per_page=100&page=${i}" | jq '.[].name' | sed 's:^.\(.*\).$:\1:' >> list_o_tags.out; done
    

    Rails 콘솔에 액세스할 수 있다면 다음 명령을 입력하여 날짜별로 제한된 태그 목록을 검색할 수 있습니다.

    output = File.open( "/tmp/list_o_tags.out","w" )
    Project.find(<Project_id>).container_repositories.find(<container_repo_id>).tags.each do |tag|
      output << tag.name + "\n" if tag.created_at < 1.month.ago
    end;nil
    output.close
    

    이 명령어 세트는 1개월 전 이전에 생성된 모든 태그가 나열된 /tmp/list_o_tags.out 파일을 작성합니다.

  2. list_o_tags.out 파일에서 유지하고 싶은 태그를 제거하세요. 예를 들어, 파일을 분석하고 태그를 제거할 수 있습니다.

    :::탭타이틀 macOS

    # 파일에서 `latest` 태그 제거
    sed -i .bak '/latest/d' list_o_tags.out
    
    # 파일에서 처음 N개의 태그 제거
    sed -i .bak '1,Nd' list_o_tags.out
    
    # 파일에서 `Av`로 시작하는 태그 제거
    sed -i .bak '/^Av/d' list_o_tags.out
    
    # 파일에서 `_v3`로 끝나는 태그 제거
    sed -i .bak '/_v3$/d' list_o_tags.out
    

    :::

  3. list_o_tags.out 파일이 올바르게 삭제해야 할 태그만 포함하도록 확인하세요.

  4. list_o_tags.out 파일에 있는 태그를 삭제하기 위해 다음 셸 스크립트를 실행하세요:

    # list_o_tags.out을 반복하여 태그를 하나씩 삭제
    while read -r LINE || [[ -n $LINE ]]; do echo ${LINE}; curl --fail-with-body --request DELETE --header 'PRIVATE-TOKEN: <PAT>' "https://gitlab.example.com/api/v4/projects/<Project_id>/registry/repositories/<container_repo_id>/tags/${LINE}"; sleep 0.1; echo; done < list_o_tags.out > delete.logs