GitLab 컨테이너 레지스트리 관리
GitLab v19.5Offering: GitLab Self-Managed
요약
차세대 컨테이너 레지스트리로 GitLab Self-Managed 인스턴스를 업그레이드할 수 있습니다. GitLab 컨테이너 레지스트리를 사용하면 모든 프로젝트가 Docker 이미지를 저장할 자체 공간을 가질 수 있습니다.
차세대 컨테이너 레지스트리로 GitLab Self-Managed 인스턴스를 업그레이드할 수 있습니다. 이 업그레이드된 레지스트리는 온라인 가비지 컬렉션을 지원하며, 성능과 안정성이 크게 개선되었습니다.
GitLab 컨테이너 레지스트리를 사용하면 모든 프로젝트가 Docker 이미지를 저장할 자체 공간을 가질 수 있습니다.
Distribution Registry에 대한 자세한 내용은 다음을 참고합니다.
이 문서는 관리자 가이드입니다. GitLab 컨테이너 레지스트리 사용 방법은 사용자 문서를 참고합니다.
컨테이너 레지스트리 활성화#
컨테이너 레지스트리를 활성화하는 과정은 사용하는 설치 유형에 따라 다릅니다.
Linux 패키지 설치#
Linux 패키지로 GitLab을 설치한 경우 컨테이너 레지스트리는 기본적으로 사용할 수 있을 수도, 없을 수도 있습니다.
내장 Let's Encrypt 통합을 사용하는 경우 컨테이너 레지스트리가 자동으로 활성화되며 GitLab 도메인의 5050 포트에서 사용할 수 있습니다.
그렇지 않으면 컨테이너 레지스트리는 활성화되지 않습니다. 활성화하려면 다음 중 하나를 수행합니다.
- GitLab 도메인에 대해 구성합니다.
- 다른 도메인에 대해 구성합니다.
컨테이너 레지스트리는 기본적으로 HTTPS에서 작동합니다. HTTP를 사용할 수도 있지만 권장하지 않으며 이 문서의 범위를 벗어납니다.
Helm Charts 설치#
Helm Charts 설치는 Helm Charts 문서의 컨테이너 레지스트리 사용을 참고합니다.
자체 컴파일 설치#
GitLab을 직접 컴파일하여 설치한 경우 다음을 수행합니다.
- 설치하는 GitLab 버전에 해당하는 이미지를 사용해
레지스트리를 배포해야 합니다
(예:
registry.gitlab.com/gitlab-org/build/cng/gitlab-container-registry:v3.15.0-gitlab). - 설치가 완료된 후 레지스트리를 활성화하려면
gitlab.yml에서 레지스트리 설정을 구성해야 합니다. lib/support/nginx/registry-ssl의 NGINX 샘플 구성 파일을 사용하고host,port, TLS 인증서 경로에 맞게 편집합니다.
gitlab.yml의 내용은 다음과 같습니다.
registry:
enabled: true
host: <registry.gitlab.example.com>
port: <5005>
api_url: <http://localhost:5000/>
key: <config/registry.key>
path: <shared/registry>
issuer: <gitlab-issuer>
각 항목의 의미는 다음과 같습니다.
| 매개변수 | 설명 |
|---|---|
enabled |
true 또는 false. GitLab에서 레지스트리를 활성화합니다. 기본값은 false입니다. |
host |
레지스트리가 실행되며 사용자가 사용할 수 있는 호스트 URL입니다. |
port |
외부 레지스트리 도메인이 수신 대기하는 포트입니다. |
api_url |
레지스트리가 노출되는 내부 API URL입니다. 기본값은 http://localhost:5000입니다. 외부 Docker 레지스트리를 설정하는 경우가 아니면 변경하지 않습니다. |
key |
레지스트리의 rootcertbundle과 쌍을 이루는 개인 키 위치입니다. |
path |
레지스트리의 rootdirectory에 지정한 것과 같은 디렉터리여야 합니다. 이 경로는 GitLab 사용자, 웹 서버 사용자, 레지스트리 사용자가 읽을 수 있어야 합니다. |
issuer |
레지스트리의 issuer에 구성한 값과 같아야 합니다. |
소스에서 GitLab을 설치하면 레지스트리 init 파일이 함께 제공되지 않습니다. 따라서 레지스트리 설정을 수정해도 GitLab을 다시 시작하더라도 레지스트리는 다시 시작되지 않습니다. 이를 수행하는 방법은 업스트림 문서를 참고합니다.
최소한 레지스트리 구성에서
서비스를 container_registry로,
영역(realm)을 https://gitlab.example.com/jwt/auth로 설정했는지 확인합니다.
auth:
token:
realm: <https://gitlab.example.com/jwt/auth>
service: container_registry
issuer: gitlab-issuer
rootcertbundle: /root/certs/certbundle
auth를 설정하지 않으면 사용자가 인증 없이 Docker 이미지를 가져올 수 있습니다.
컨테이너 레지스트리 도메인 구성#
레지스트리의 외부 도메인은 다음 두 가지 방법 중 하나로 구성할 수 있습니다.
- 기존 GitLab 도메인을 사용합니다. 레지스트리는 특정 포트에서 수신 대기하며 GitLab의 TLS 인증서를 재사용합니다.
- 완전히 별도의 도메인을 사용합니다. 해당 도메인용 새 TLS 인증서가 필요합니다.
컨테이너 레지스트리에는 TLS 인증서가 필요하므로 비용이 고려 사항이 될 수 있습니다.
컨테이너 레지스트리를 처음 구성하기 전에 이 점을 고려합니다.
기존 GitLab 도메인에서 컨테이너 레지스트리 구성#
컨테이너 레지스트리가 기존 GitLab 도메인을 사용하도록 구성된 경우 컨테이너 레지스트리를 특정 포트에 노출할 수 있습니다. 이렇게 하면 기존 GitLab TLS 인증서를 재사용할 수 있습니다.
GitLab 도메인이 https://gitlab.example.com이고 외부에 공개하는 포트가 5050인 경우
컨테이너 레지스트리를 구성하는 방법은 다음과 같습니다.
- Linux 패키지 설치를 사용하는 경우
gitlab.rb를 편집합니다. - 자체 컴파일 설치를 사용하는 경우
gitlab.yml을 편집합니다.
레지스트리가 수신 대기하는 포트(기본값 5000)와 다른 포트를 선택해야 합니다.
그렇지 않으면 충돌이 발생합니다.
호스트 및 컨테이너 방화벽 규칙은 gitlab_rails['registry_port'](기본값 5000)에
나열된 포트가 아니라 registry_external_url 줄에 나열된 포트를 통해
트래픽이 들어오도록 구성해야 합니다.
-
/etc/gitlab/gitlab.rb에 레지스트리 URL과 GitLab에서 사용하는 기존 TLS 인증서 및 키의 경로가 포함되어야 합니다.registry_external_url '<https://gitlab.example.com:5050>'registry_external_url은 기존 GitLab URL에서 HTTPS로 수신 대기하지만 포트는 다릅니다.TLS 인증서가
/etc/gitlab/ssl/gitlab.example.com.crt에 없거나 키가/etc/gitlab/ssl/gitlab.example.com.key에 없는 경우 아래 줄의 주석을 해제합니다.registry_nginx['ssl_certificate'] = "</path/to/certificate.pem>" registry_nginx['ssl_certificate_key'] = "</path/to/certificate.key>" -
파일을 저장하고 GitLab을 재구성하여 변경 사항을 적용합니다.
-
다음 명령으로 검증합니다.
openssl s_client -showcerts -servername gitlab.example.com -connect gitlab.example.com:5050 > cacert.pem
인증서 공급자가 CA 번들 인증서를 제공하는 경우 TLS 인증서 파일에 덧붙입니다.
관리자가 컨테이너 레지스트리를 5678 같은 임의의 포트에서 수신 대기하게 하려는 경우가 있습니다.
그러나 레지스트리와 애플리케이션 서버가 포트 80과 443에서만 수신 대기하는
AWS 애플리케이션 로드 밸런서 뒤에 있을 수 있습니다. 관리자는 registry_external_url에서
포트 번호를 제거하여 HTTP 또는 HTTPS를 가정하게 할 수 있습니다. 그런 다음 로드
밸런서에서 레지스트리로 가는 포트 80 또는 443을 임의의 포트로 매핑하는 규칙을 적용합니다.
사용자가 컨테이너 레지스트리의 docker login 예시에 의존하는 경우 이 점이 중요합니다. 다음은 예시입니다.
registry_external_url '<https://registry-gitlab.example.com>'
registry_nginx['redirect_http_to_https'] = true
registry_nginx['listen_port'] = 5678
-
/home/git/gitlab/config/gitlab.yml을 열고registry항목을 찾아 다음 설정으로 구성합니다.registry: enabled: true host: <gitlab.example.com> port: 5050 -
파일을 저장하고 GitLab을 다시 시작하여 변경 사항을 적용합니다.
-
NGINX에서도 관련 변경 사항(도메인, 포트, TLS 인증서 경로)을 적용합니다.
이제 사용자는 다음 명령으로 GitLab 자격 증명을 사용해 컨테이너 레지스트리에 로그인할 수 있습니다.
docker login <gitlab.example.com:5050>
자체 도메인에서 컨테이너 레지스트리 구성#
레지스트리가 자체 도메인을 사용하도록 구성하는 경우 해당 도메인(예: registry.example.com)에
대한 TLS 인증서가 필요합니다. 기존 GitLab 도메인의
하위 도메인에서 호스팅하는 경우
와일드카드 인증서가 필요할 수 있습니다. 예를 들어 *.gitlab.example.com은
registry.gitlab.example.com과 일치하는 와일드카드이며 *.example.com과는 별개입니다.
수동으로 생성한 SSL 인증서(여기에서 설명)뿐만 아니라 Let's Encrypt에서 자동으로 생성한 인증서도 Linux 패키지 설치에서 지원됩니다.
컨테이너 레지스트리를 https://registry.gitlab.example.com에서
접근할 수 있게 하려는 경우를 가정합니다.
-
TLS 인증서와 키를
/etc/gitlab/ssl/<registry.gitlab.example.com>.crt및/etc/gitlab/ssl/<registry.gitlab.example.com>.key에 두고 올바른 권한이 설정되어 있는지 확인합니다.chmod 600 /etc/gitlab/ssl/<registry.gitlab.example.com>.* -
TLS 인증서를 배치한 후
/etc/gitlab/gitlab.rb를 다음과 같이 편집합니다.registry_external_url '<https://registry.gitlab.example.com>'registry_external_url은 HTTPS에서 수신 대기합니다. -
파일을 저장하고 GitLab을 재구성하여 변경 사항을 적용합니다.
와일드카드 인증서가 있는 경우 URL과 함께
인증서 경로를 지정해야 하며, 이 경우 /etc/gitlab/gitlab.rb는
다음과 같습니다.
registry_nginx['ssl_certificate'] = "/etc/gitlab/ssl/certificate.pem"
registry_nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/certificate.key"
-
/home/git/gitlab/config/gitlab.yml을 열고registry항목을 찾아 다음 설정으로 구성합니다.registry: enabled: true host: <registry.gitlab.example.com> -
파일을 저장하고 GitLab을 다시 시작하여 변경 사항을 적용합니다.
-
NGINX에서도 관련 변경 사항(도메인, 포트, TLS 인증서 경로)을 적용합니다.
이제 사용자는 GitLab 자격 증명을 사용해 컨테이너 레지스트리에 로그인할 수 있습니다.
docker login <registry.gitlab.example.com>
자체 서명 인증서 구성#
컨테이너 레지스트리에서 자체 서명 인증서를 사용하려면 Docker 데몬이 자체 서명 인증서를 신뢰하도록 구성해야 합니다.
-
Docker 데몬이 자체 서명 인증서를 사용하도록 지시합니다. 이 단계는 운영 체제에 따라 다릅니다.
-
GitLab Runner
config.toml파일에서 Docker 데몬을 마운트하고privileged = false로 설정합니다.[runners.docker] image = "ruby:2.6" privileged = false volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]privileged = true로 설정하면 Docker 데몬보다 우선합니다. -
Docker를 다시 시작합니다.
컨테이너 레지스트리 사이트 전체 비활성화#
다음 단계에 따라 레지스트리를 비활성화해도 기존 Docker 이미지는 제거되지 않습니다. Docker 이미지 제거는 레지스트리 애플리케이션 자체에서 처리합니다.
-
/etc/gitlab/gitlab.rb를 열고registry['enable']을false로 설정합니다.registry['enable'] = false -
파일을 저장하고 GitLab을 재구성하여 변경 사항을 적용합니다.
-
/home/git/gitlab/config/gitlab.yml을 열고registry항목을 찾아enabled를false로 설정합니다.registry: enabled: false -
파일을 저장하고 GitLab을 다시 시작하여 변경 사항을 적용합니다.
새 프로젝트에 대해 컨테이너 레지스트리 사이트 전체 비활성화#
컨테이너 레지스트리가 활성화되어 있으면 모든 새 프로젝트에서 사용할 수 있습니다. 이 기능을 비활성화하고 프로젝트 소유자가 직접 컨테이너 레지스트리를 활성화하게 하려면 아래 단계를 따릅니다.
-
/etc/gitlab/gitlab.rb를 편집하고 다음 줄을 추가합니다.gitlab_rails['gitlab_default_projects_features_container_registry'] = false -
파일을 저장하고 GitLab을 재구성하여 변경 사항을 적용합니다.
-
/home/git/gitlab/config/gitlab.yml을 열고default_projects_features항목을 찾아container_registry가false로 설정되도록 구성합니다.## Default project features settings default_projects_features: issues: true merge_requests: true wiki: true snippets: false builds: true container_registry: false -
파일을 저장하고 GitLab을 다시 시작하여 변경 사항을 적용합니다.
토큰 유효 기간 늘리기#
GitLab에서 컨테이너 레지스트리 토큰은 5분마다 만료됩니다. 토큰 유효 기간을 늘리려면 다음을 수행합니다.
- 오른쪽 위 모서리에서 Admin을 선택합니다.
- 왼쪽 사이드바에서 Settings > CI/CD를 선택합니다.
- Container Registry를 확장합니다.
- **Authorization token duration (minutes)**의 값을 업데이트합니다.
- Save changes를 선택합니다.
컨테이너 레지스트리 기능 플래그#
컨테이너 레지스트리 기능 플래그는 컨테이너 레지스트리의 실험적 또는 과도기적 기능을 제어하는 환경 변수 토글입니다.
GitLab 애플리케이션 기능 플래그와 달리 컨테이너 레지스트리 기능 플래그는 다음과 같은 특징이 있습니다.
- 레지스트리 전용 환경 변수를 통해 관리됩니다.
- 컨테이너 레지스트리 코드베이스에서 정의됩니다.
- 변경하려면 레지스트리를 다시 구성해야 합니다.
컨테이너 레지스트리 기능 플래그 구성#
다음 표는 활성 상태인 컨테이너 레지스트리 기능 플래그를 나열합니다.
| 기능 플래그 | 설명 | 마일스톤 | 기본 상태 | 제거 마일스톤 |
|---|---|---|---|---|
REGISTRY_FF_ONGOING_RENAME_CHECK |
이름 변경 작업이 진행 중인 프로젝트가 있는지 Redis에서 확인합니다. | 16.2 | Disabled | |
REGISTRY_FF_DYNAMIC_MEDIA_TYPES |
런타임 중에 새 미디어 유형을 생성할 수 있도록 허용합니다. | 17.1 | Disabled | |
REGISTRY_FF_BBM |
비동기 배치 백그라운드 마이그레이션 프로세스를 제어합니다. | 17.2 | Disabled | |
REGISTRY_FF_ENFORCE_LOCKFILES |
데이터베이스 또는 레거시 메타데이터 스토리지에 대한 잠금 파일 검사를 활성화합니다. | GitLab 17.6에서 도입되었습니다. | GitLab 18.9에서 GitLab Self-Managed에 활성화되었습니다. | GitLab 18.10에서 제거되었습니다. |
컨테이너 레지스트리 기능 플래그를 구성하려면 사용하는 플랫폼에 맞는 지침을 따릅니다.
/etc/gitlab/gitlab.rb에서 기능 플래그를 구성합니다.
registry['env'] = {
'' => 'true' # or 'false' to disable
}
그런 다음 컨테이너 레지스트리를 재구성합니다.
sudo gitlab-ctl reconfigure
sudo gitlab-ctl restart registry
values.yaml에서 기능 플래그를 구성합니다.
registry:
extraEnv:
: "true" # or "false" to disable
그런 다음 values.yaml을 업그레이드합니다.
helm upgrade gitlab gitlab/gitlab -f values.yaml
Docker Compose에서 환경 변수를 직접 설정하면 작동하지 않습니다.
gitlab.rb를 통해 구성해야 합니다.
Docker 또는 Docker Compose의 경우 gitlab.rb를 생성하거나 편집합니다.
registry['env'] = {
'' => 'true'
}
이 구성을 Docker Compose 설정에 마운트하고 시작 시 GitLab이 재구성되도록 합니다.
컨테이너 레지스트리 스토리지 구성#
컨테이너 레지스트리가 저장한 파일이나 오브젝트를 직접 수정하지 않습니다. 레지스트리가 이 항목을 쓰거나 삭제하는 경우 외의 모든 작업은 인스턴스 전체의 데이터 일관성 문제와 불안정성을 일으킬 수 있으며, 복구가 불가능할 수도 있습니다.
스토리지 드라이버를 구성하여 컨테이너 레지스트리가 다양한 스토리지 백엔드를 사용하도록 구성할 수 있습니다. 기본적으로 GitLab 컨테이너 레지스트리는 파일 시스템 드라이버 구성을 사용하도록 설정되어 있습니다.
이를 지원하는 스토리지 백엔드에서는 오브젝트 버전 관리를 사용하여 버킷에 저장된 모든 오브젝트의 이전(non-current) 버전을 보존, 조회, 복원할 수 있습니다. 다만 이로 인해 스토리지 사용량과 비용이 늘어날 수 있습니다. 레지스트리의 동작 방식상 이미지 업로드는 먼저 임시 경로에 저장된 후 최종 위치로 전송됩니다. S3와 GCS를 포함한 오브젝트 스토리지 백엔드에서는 이 전송이 복사 후 삭제 방식으로 이루어집니다. 오브젝트 버전 관리를 활성화하면 삭제된 이러한 임시 업로드 아티팩트가 이전 버전으로 유지되어 스토리지 버킷 크기가 늘어납니다. 이전 버전이 일정 시간 후 삭제되도록 스토리지 공급자에서 오브젝트 수명 주기 정책을 구성해야 합니다.
지원되는 드라이버는 다음과 같습니다.
| 드라이버 | 설명 |
|---|---|
filesystem |
로컬 파일 시스템의 경로를 사용합니다 |
azure |
Microsoft Azure Blob Storage |
gcs |
Google Cloud Storage |
s3 |
Amazon Simple Storage Service. 스토리지 버킷을 올바른 S3 권한 범위로 구성해야 합니다. |
대부분의 S3 호환 서비스는 컨테이너 레지스트리와 함께 작동하지만, 지원은 AWS S3에 대해서만 보장합니다. 서드파티 S3 구현의 정확성을 확인할 수 없으므로 문제를 디버깅할 수는 있지만, AWS S3 버킷에서 재현되는 문제가 아니면 레지스트리를 패치할 수 없습니다.
파일 시스템 사용#
이미지를 파일 시스템에 저장하려면 컨테이너 레지스트리의 스토리지 경로를 변경할 수 있습니다. 아래 단계를 따릅니다.
이 경로에는 다음 사용자가 접근할 수 있습니다.
- 컨테이너 레지스트리 데몬을 실행하는 사용자
- GitLab을 실행하는 사용자
모든 GitLab, 레지스트리, 웹 서버 사용자가 이 디렉터리에 접근할 수 있어야 합니다.
Linux 패키지 설치에서 이미지가 저장되는 기본 위치는
/var/opt/gitlab/gitlab-rails/shared/registry입니다. 변경하려면 다음을 수행합니다.
-
/etc/gitlab/gitlab.rb를 편집합니다.gitlab_rails['registry_path'] = "</path/to/registry/storage>" -
파일을 저장하고 GitLab을 재구성하여 변경 사항을 적용합니다.
자체 컴파일 설치에서 이미지가 저장되는 기본 위치는
/home/git/gitlab/shared/registry입니다. 변경하려면 다음을 수행합니다.
-
/home/git/gitlab/config/gitlab.yml을 열고registry항목을 찾아path설정을 변경합니다.registry: path: shared/registry -
파일을 저장하고 GitLab을 다시 시작하여 변경 사항을 적용합니다.
오브젝트 스토리지 사용#
컨테이너 레지스트리 이미지를 로컬 파일 시스템 대신 오브젝트 스토리지에 저장하려면 지원되는 스토리지 드라이버 중 하나를 구성할 수 있습니다.
자세한 내용은 오브젝트 스토리지를 참고합니다.
GitLab은 파일 시스템에 저장되지 않은 Docker 이미지를 백업하지 않습니다. 필요한 경우 오브젝트 스토리지 공급자에서 백업을 활성화합니다.
Linux 패키지 설치용 오브젝트 스토리지 구성#
컨테이너 레지스트리용 오브젝트 스토리지를 구성하려면 다음을 수행합니다.
- 사용하려는 스토리지 드라이버를 선택합니다.
/etc/gitlab/gitlab.rb를 적절한 구성으로 편집합니다.- 파일을 저장하고 GitLab을 재구성하여 변경 사항을 적용합니다.
S3 스토리지 드라이버는 Amazon S3 또는 모든 S3 호환 오브젝트 스토리지 서비스와 통합됩니다.
s3_v2 드라이버(베타)는 AWS SDK v2를 사용하며 인증에 Signature Version 4만 지원합니다.
이 드라이버는 성능과 안정성을 개선하면서 AWS 인증 요구 사항과의 호환성을 보장합니다.
이전 서명 방식에 대한 지원은 더 이상 사용되지 않습니다(deprecated). 자세한 내용은 에픽 16272를 참고합니다.
각 드라이버의 전체 구성 매개변수 목록은 s3_v1과 s3_v2를 참고합니다.
S3 스토리지 드라이버를 구성하려면 /etc/gitlab/gitlab.rb 파일에 다음 구성 중 하나를 추가합니다.
# Deprecated: Will be removed in GitLab 19.0
registry['storage'] = {
's3' => {
'accesskey' => '<s3-access-key>',
'secretkey' => '<s3-secret-key-for-access-key>',
'bucket' => '<your-s3-bucket>',
'region' => '<your-s3-region>',
'regionendpoint' => '<your-s3-regionendpoint>'
}
}
또는
# Beta: s3_v2 driver
registry['storage'] = {
's3_v2' => {
'accesskey' => '<s3-access-key>',
'secretkey' => '<s3-secret-key-for-access-key>',
'bucket' => '<your-s3-bucket>',
'region' => '<your-s3-region>',
'regionendpoint' => '<your-s3-regionendpoint>'
}
}
보안을 강화하려면 accesskey와 secretkey 매개변수를 포함하지 않고 정적 자격 증명 대신 IAM 역할을 사용할 수 있습니다.
스토리지 비용 증가를 방지하려면 S3 버킷에 미완료 멀티파트 업로드를 삭제하는 수명 주기 정책을 구성합니다. 컨테이너 레지스트리는 이를 자동으로 정리하지 않습니다. 미완료 멀티파트 업로드에 대한 3일 만료 정책은 대부분의 사용 패턴에 적합합니다.
일부 S3 호환 서비스에서 s3_v2 드라이버를 사용할 때는 AWS 체크섬을 비활성화하기 위해 checksum_disabled 매개변수를 추가해야 할 수 있습니다.
registry['storage'] = {
's3_v2' => {
'accesskey' => '<s3-access-key>',
'secretkey' => '<s3-secret-key-for-access-key>',
'bucket' => '<your-s3-bucket>',
'region' => '<your-s3-region>',
'regionendpoint' => '<your-s3-regionendpoint>',
'checksum_disabled' => true
}
}
S3 VPC 엔드포인트의 경우 다음과 같이 구성합니다.
registry['storage'] = {
's3_v2' => { # Beta driver
'accesskey' => '<s3-access-key>',
'secretkey' => '<s3-secret-key-for-access-key>',
'bucket' => '<your-s3-bucket>',
'region' => '<your-s3-region>',
'regionendpoint' => '<your-s3-vpc-endpoint>',
'pathstyle' => false
}
}
S3 구성 매개변수는 다음과 같습니다.
<your-s3-bucket>: 기존 버킷의 이름입니다. 하위 디렉터리를 포함할 수 없습니다.regionendpoint: S3 호환 서비스 또는 AWS S3 VPC 엔드포인트를 사용하는 경우에만 필요합니다.pathstyle: URL 형식을 제어합니다.host/bucket_name/object(대부분의 S3 호환 서비스)는true로,bucket_name.host/object(AWS S3)는false로 설정합니다.
AWS S3에서 s3_v2 드라이버는 구성된 region에 대한 S3 엔드포인트를 확인합니다.
따라서 클라이언트가 블롭을 다운로드하기 위해 따라가는 사전 서명된 URL은 전역 s3.amazonaws.com 호스트 이름 대신
s3.us-east-1.amazonaws.com 같은 리전별 호스트 이름을 사용할 수 있습니다.
프록시, 방화벽 또는 보안 웹 게이트웨이가 컨테이너 이미지 클라이언트의 아웃바운드 트래픽을 필터링하는 경우
해당 장치의 허용 목록에 버킷 리전의 리전별 호스트 이름을 추가합니다.
s3.amazonaws.com만 포함된 허용 목록은 이미지 가져오기가 403 Forbidden 응답과 함께 실패하게 만듭니다.
사전 서명된 URL이 직접 관리하는 호스트 이름을 가리키게 하려면 regionendpoint를 S3 VPC 엔드포인트
또는 다른 고정 엔드포인트로 설정합니다.
S3 API의 503 오류를 방지하려면 maxrequestspersecond 매개변수를 추가하여 연결에 속도 제한을 설정합니다.
registry['storage'] = {
's3' => {
'accesskey' => '<s3-access-key>',
'secretkey' => '<s3-secret-key-for-access-key>',
'bucket' => '<your-s3-bucket>',
'region' => '<your-s3-region>',
'regionendpoint' => '<your-s3-regionendpoint>',
'maxrequestspersecond' => 100
}
}
Azure 스토리지 드라이버는 Microsoft Azure Blob Storage와 통합됩니다.
레거시 Azure 스토리지 드라이버는 GitLab 17.10에서 사용 중단되었으며 GitLab 19.0에서 제거될 예정입니다.
대신 azure_v2 드라이버(베타)를 사용합니다. 이 드라이버는 성능과 안정성이 개선되었고 최신 인증 방법을 제공합니다. 이는 호환성이 깨지는 변경이지만, 새 드라이버는 대부분의 구성에서 원활하게 전환되도록 폭넓게 테스트되었습니다.
프로덕션에 배포하기 전에 비프로덕션 환경에서 새 드라이버를 테스트하여 사용자 환경과 사용 패턴에 고유한 예외 상황을 파악하고 해결해야 합니다.
문제나 의견은 이슈 525855를 통해 알려 주시기 바랍니다.
각 드라이버의 전체 구성 매개변수 목록은 azure_v1과 azure_v2를 참고합니다.
Azure 스토리지 드라이버를 구성하려면 /etc/gitlab/gitlab.rb 파일에 다음 구성 중 하나를 추가합니다.
# Deprecated: Will be removed in GitLab 19.0
registry['storage'] = {
'azure' => {
'accountname' => '<your_storage_account_name>',
'accountkey' => '<base64_encoded_account_key>',
'container' => '<container_name>'
}
}
또는
# Beta: azure_v2 driver
registry['storage'] = {
'azure_v2' => {
'credentials_type' => '<client_secret>',
'tenant_id' => '<your_tenant_id>',
'client_id' => '<your_client_id>',
'secret' => '<your_secret>',
'container' => '<your_container>',
'accountname' => '<your_account_name>'
}
}
기본적으로 Azure 스토리지 드라이버는 core.windows.net realm을 사용합니다. Azure 섹션에서 realm에 다른 값을 설정할 수 있습니다(예: Azure Government Cloud는 core.usgovcloudapi.net).
GCS 스토리지 드라이버는 Google Cloud Storage와 통합됩니다.
registry['storage'] = {
'gcs' => {
'bucket' => '<your_bucket_name>',
'keyfile' => '<path/to/keyfile>',
# If you have the bucket shared with other apps beyond the registry, uncomment the following:
# 'rootdirectory' => '/gcs/object/name/prefix'
}
}
GitLab은 사용 가능한 모든 매개변수를 지원합니다.
자체 컴파일 설치#
스토리지 드라이버 구성은 Docker 레지스트리를 배포할 때 만든 레지스트리 구성 YAML 파일에서 수행합니다.
s3 스토리지 드라이버 예시는 다음과 같습니다.
storage:
s3:
accesskey: '<s3-access-key>' # Not needed if IAM role used
secretkey: '<s3-secret-key-for-access-key>' # Not needed if IAM role used
bucket: '<your-s3-bucket>'
region: '<your-s3-region>'
regionendpoint: '<your-s3-regionendpoint>'
cache:
blobdescriptor: inmemory
delete:
enabled: true
<your-s3-bucket>은 존재하는 버킷의 이름이어야 하며 하위 디렉터리를 포함할 수 없습니다.
다운타임 없이 오브젝트 스토리지로 마이그레이션#
AWS DataSync를 사용하여
레지스트리 데이터를 S3 버킷으로 또는 S3 버킷 간에 복사하면 버킷에 잘못된 메타데이터 오브젝트가 생성됩니다.
자세한 내용은 이름이 비어 있는 태그를 참고합니다.
S3 버킷으로 또는 버킷 간에 데이터를 이동하려면 AWS CLI sync 작업을 권장합니다.
컨테이너 레지스트리를 중지하지 않고 스토리지를 마이그레이션하려면 컨테이너 레지스트리를 읽기 전용 모드로 설정합니다. 대규모 인스턴스에서는 컨테이너 레지스트리를 한동안 읽기 전용 모드로 유지해야 할 수 있습니다. 이 기간 동안에는 컨테이너 레지스트리에서 가져오기(pull)는 할 수 있지만 푸시(push)는 할 수 없습니다.
-
선택 사항입니다. 마이그레이션할 데이터 양을 줄이려면 다운타임 없이 가비지 컬렉션 도구를 실행합니다.
-
이 예시는
awsCLI를 사용합니다. CLI를 이전에 구성하지 않았다면sudo aws configure를 실행하여 자격 증명을 구성해야 합니다. 관리자가 아닌 사용자는 컨테이너 레지스트리 폴더에 접근하지 못할 가능성이 높으므로sudo를 사용해야 합니다. 자격 증명 구성을 확인하려면ls를 실행하여 모든 버킷을 나열합니다.sudo aws --endpoint-url <https://your-object-storage-backend.com> s3 lsAWS를 백엔드로 사용하는 경우
--endpoint-url은 필요하지 않습니다. -
초기 데이터를 S3 버킷에 복사합니다. 예를 들어
awsCLI의cp또는sync명령을 사용합니다.docker폴더가 버킷 내부의 최상위 폴더로 유지되도록 합니다.sudo aws --endpoint-url <https://your-object-storage-backend.com> s3 sync registry s3://mybucket[!note] 데이터가 많은 경우 병렬 동기화 작업을 실행하여 성능을 개선할 수 있습니다.
-
최종 데이터 동기화를 수행하려면 컨테이너 레지스트리를
read-only모드로 전환하고 GitLab을 재구성합니다. -
초기 데이터 로드 이후의 모든 변경 사항을 S3 버킷에 동기화하고, 대상 버킷에는 있지만 소스에는 없는 파일을 삭제합니다.
sudo aws --endpoint-url <https://your-object-storage-backend.com> s3 sync registry s3://mybucket --delete --dryrun명령이 예상대로 동작하는지 확인한 후
--dryrun플래그를 제거하고 명령을 실행합니다.[!warning]
--delete플래그는 대상에는 있지만 소스에는 없는 파일을 삭제합니다. 소스와 대상을 바꾸면 레지스트리의 모든 데이터가 삭제됩니다. -
모든 컨테이너 레지스트리 파일이 오브젝트 스토리지에 업로드되었는지 다음 두 명령이 반환하는 파일 수로 확인합니다.
sudo find registry -type f | wc -lsudo aws --endpoint-url <https://your-object-storage-backend.com> s3 ls s3://<mybucket> --recursive | wc -l이 명령들의 출력은
_uploads디렉터리와 그 하위 디렉터리의 콘텐츠를 제외하고 일치해야 합니다. -
레지스트리가 S3 버킷을 스토리지로 사용하도록 구성합니다.
-
변경 사항을 적용하려면 레지스트리를 다시
read-write모드로 설정하고 GitLab을 재구성합니다.
Azure 오브젝트 스토리지로 이동#
registry['storage'] = {
'azure' => {
'accountname' => '<your_storage_account_name>',
'accountkey' => '<base64_encoded_account_key>',
'container' => '<container_name>',
'trimlegacyrootprefix' => true
}
}
storage:
azure:
accountname: <your_storage_account_name>
accountkey: <base64_encoded_account_key>
container: <container_name>
trimlegacyrootprefix: true
기본적으로 Azure 스토리지 드라이버는 core.windows.net realm을 사용합니다. azure 섹션에서 realm에 다른 값을 설정할 수 있습니다(예: Azure Government Cloud는 core.usgovcloudapi.net).
스토리지 드라이버 리디렉션 비활성화#
기본적으로 원격 백엔드로 구성된 레지스트리에 접근하는 사용자는 스토리지 드라이버의 기본 백엔드로 리디렉션됩니다. 예를 들어 레지스트리를 s3 스토리지 드라이버로 구성하면 GitLab 서버의 부하를 줄이기 위해 요청이 원격 S3 버킷으로 리디렉션됩니다.
그러나 일반적으로 공개 서버에 접근할 수 없는 내부 호스트가 사용하는 레지스트리에서는 이 동작이 바람직하지 않습니다. 리디렉션을 비활성화하고 프록시 다운로드를 사용하려면 다음과 같이 disable 플래그를 true로 설정합니다. 이렇게 하면 모든 트래픽이 항상 레지스트리 서비스를 거칩니다. 스토리지 백엔드가 공개적으로 접근 가능하지 않아 공격 표면이 줄어 보안이 향상되지만, 모든 트래픽이 서비스를 통해 전달되므로 성능은 나빠집니다.
-
/etc/gitlab/gitlab.rb를 편집합니다.registry['storage'] = { 's3' => { 'accesskey' => '<s3_access_key>', 'secretkey' => '<s3_secret_key_for_access_key>', 'bucket' => '<your_s3_bucket>', 'region' => '<your_s3_region>', 'regionendpoint' => '<your_s3_regionendpoint>' }, 'redirect' => { 'disable' => true } } -
파일을 저장하고 GitLab을 재구성하여 변경 사항을 적용합니다.
-
레지스트리 구성 YAML 파일에
redirect플래그를 추가합니다.storage: s3: accesskey: '<s3_access_key>' secretkey: '<s3_secret_key_for_access_key>' bucket: '<your_s3_bucket>' region: '<your_s3_region>' regionendpoint: '<your_s3_regionendpoint>' redirect: disable: true cache: blobdescriptor: inmemory delete: enabled: true -
파일을 저장하고 GitLab을 다시 시작하여 변경 사항을 적용합니다.
암호화된 S3 버킷#
SSE-S3 또는 SSE-KMS 암호화가 기본으로 활성화된 S3 버킷에는 AWS KMS를 사용한 서버 측 암호화를 사용할 수 있습니다. 고객 마스터 키(CMK)와 SSE-C 암호화는 모든 요청에 암호화 키를 함께 보내야 하므로 지원되지 않습니다.
SSE-S3의 경우 레지스트리 설정에서 encrypt 옵션을 활성화해야 합니다. 방법은 GitLab을
설치한 방식에 따라 다릅니다. 사용하는 설치 방식에 맞는 지침을 따릅니다.
-
/etc/gitlab/gitlab.rb를 편집합니다.registry['storage'] = { 's3' => { 'accesskey' => '<s3_access_key>', 'secretkey' => '<s3_secret_key_for_access_key>', 'bucket' => '<your_s3_bucket>', 'region' => '<your_s3_region>', 'regionendpoint' => '<your_s3_regionendpoint>', 'encrypt' => true } } -
파일을 저장하고 GitLab을 재구성하여 변경 사항을 적용합니다.
-
레지스트리 구성 YAML 파일을 편집합니다.
storage: s3: accesskey: '<s3_access_key>' secretkey: '<s3_secret_key_for_access_key>' bucket: '<your_s3_bucket>' region: '<your_s3_region>' regionendpoint: '<your_s3_regionendpoint>' encrypt: true -
파일을 저장하고 GitLab을 다시 시작하여 변경 사항을 적용합니다.
스토리지 제한#
스토리지 제한이 없으므로 사용자는 임의의 크기의 Docker 이미지를 무한히 업로드할 수 있습니다. 이 설정은 향후 릴리스에서 구성할 수 있게 될 예정입니다.
레지스트리 내부 포트 변경#
레지스트리 서버는 기본적으로 localhost의 5000 포트에서 수신 대기하며,
이 주소가 레지스트리 서버가 연결을 수락해야 하는 주소입니다.
아래 예시에서는 레지스트리 포트를 5010으로 설정합니다.
-
/etc/gitlab/gitlab.rb를 열고registry['registry_http_addr']를 설정합니다.registry['registry_http_addr'] = "localhost:5010" -
파일을 저장하고 GitLab을 재구성하여 변경 사항을 적용합니다.
-
레지스트리 서버의 구성 파일을 열고
http:addr값을 편집합니다.http: addr: localhost:5010 -
파일을 저장하고 레지스트리 서버를 다시 시작합니다.
프로젝트별 컨테이너 레지스트리 비활성화#
GitLab 인스턴스에서 레지스트리가 활성화되어 있지만 프로젝트에 필요하지 않은 경우 프로젝트 설정에서 비활성화할 수 있습니다.
GitLab을 인증 엔드포인트로 사용하는 외부 컨테이너 레지스트리#
GitLab에서 서드파티 컨테이너 레지스트리를 사용하는 것은 사용 중단되었으며 더 이상 지원되지 않습니다. GitLab 컨테이너 레지스트리 대신 서드파티 컨테이너 레지스트리를 사용해야 한다면 피드백 이슈 958에 사용 사례를 알려 주시기 바랍니다.
외부 컨테이너 레지스트리를 사용하면 컨테이너 레지스트리와 관련된 일부 기능을 사용할 수 없거나 본질적인 위험이 있을 수 있습니다.
통합이 작동하려면 외부 레지스트리가 GitLab에 인증하기 위해 JSON Web Token을 사용하도록 구성되어야 합니다. 외부 레지스트리의 런타임 구성에 다음 항목이 있어야 합니다.
auth:
token:
realm: https://<gitlab.example.com>/jwt/auth
service: container_registry
issuer: gitlab-issuer
rootcertbundle: /root/certs/certbundle
이 항목이 없으면 레지스트리 로그인이 GitLab에 인증할 수 없습니다.
또한 GitLab은 프로젝트 계층 구조 아래의
중첩된 이미지 이름을
인식하지 못합니다. 예를 들어
registry.example.com/group/project/image-name:tag 또는
registry.example.com/group/project/my/image-name:tag는 인식하지 못하고
registry.example.com/group/project:tag만 인식합니다.
Linux 패키지 설치#
외부 컨테이너 레지스트리와 함께 GitLab을 인증 엔드포인트로 사용할 수 있습니다.
-
/etc/gitlab/gitlab.rb를 열고 필요한 구성을 설정합니다.gitlab_rails['registry_enabled'] = true gitlab_rails['registry_api_url'] = "https://<external_registry_host>:5000" gitlab_rails['registry_issuer'] = "gitlab-issuer"gitlab_rails['registry_enabled'] = true는 GitLab 컨테이너 레지스트리 기능과 인증 엔드포인트를 활성화하는 데 필요합니다. 이 설정을 활성화해도 GitLab에 번들로 포함된 컨테이너 레지스트리 서비스는 시작되지 않습니다.gitlab_rails['registry_api_url'] = "http://<external_registry_host>:5000"은 레지스트리가 설치된 호스트와 일치하도록 변경해야 합니다. 외부 레지스트리가 TLS를 사용하도록 구성된 경우https도 지정해야 합니다.
-
GitLab과 외부 컨테이너 레지스트리가 안전하게 통신하려면 인증서-키 쌍이 필요합니다. 인증서-키 쌍을 생성하고, 외부 컨테이너 레지스트리에는 공개 인증서(
rootcertbundle)를, GitLab에는 개인 키를 구성합니다. 이를 위해/etc/gitlab/gitlab.rb에 다음을 추가합니다.# registry['internal_key'] should contain the contents of the custom key # file. Line breaks in the key file should be marked using `\n` character # Example: registry['internal_key'] = "---BEGIN RSA PRIVATE KEY---\nMIIEpQIBAA\n" # Optionally define a custom file for a Linux package installation to write the contents # of registry['internal_key'] to. gitlab_rails['registry_key_path'] = "/custom/path/to/registry-key.key"재구성을 실행할 때마다
registry_key_path에 지정된 파일이internal_key에 지정된 내용으로 채워집니다. 파일을 지정하지 않으면 Linux 패키지 설치는 기본값으로/var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key를 사용하고 이 파일을 채웁니다. -
GitLab Container Registry 페이지에 표시되는 컨테이너 레지스트리 URL을 변경하려면 다음 구성을 설정합니다.
gitlab_rails['registry_host'] = "<registry.gitlab.example.com>" gitlab_rails['registry_port'] = "5005" -
파일을 저장하고 GitLab을 재구성하여 변경 사항을 적용합니다.
자체 컴파일 설치#
-
/home/git/gitlab/config/gitlab.yml을 열고registry아래의 구성 설정을 편집합니다.## Container registry registry: enabled: true host: "<registry.gitlab.example.com>" port: "5005" api_url: "https://<external_registry_host>:5000" path: /var/lib/registry key: </path/to/keyfile> issuer: gitlab-issuer이 매개변수의 의미는 컨테이너 레지스트리 활성화를 참고합니다.
-
파일을 저장하고 GitLab을 다시 시작하여 변경 사항을 적용합니다.
컨테이너 레지스트리 알림 구성#
레지스트리에서 발생하는 이벤트에 대한 응답으로 웹훅 알림을 보내도록 컨테이너 레지스트리를 구성할 수 있습니다.
컨테이너 레지스트리 알림 구성 옵션에 대한 자세한 내용은 Docker Registry 알림 문서를 참고합니다.
threshold 매개변수는 GitLab 17.0에서 사용 중단되었지만
하위 호환성을 보장하기 위해 계속 사용할 수 있습니다. 이 매개변수는 향후 마일스톤에서 제거될 예정일 수 있습니다.
대신 maxretries를 사용합니다. 레지스트리는 기존 threshold 구성을 구성된 backoff 기간에 따라 동등한 maxretries
값으로 자동 변환하고, 변환된 값을 보여 주는 사용 중단 경고를 로그에 출력합니다.
기존 구성은 계속 작동하지만 자동 변환을 피하려면 maxretries를 설정해야 합니다.
컨테이너 레지스트리에 여러 엔드포인트를 구성할 수 있습니다.
Linux 패키지 설치에서 알림 엔드포인트를 구성하려면 다음을 수행합니다.
-
/etc/gitlab/gitlab.rb를 편집합니다.registry['notifications'] = [ { 'name' => '<test_endpoint>', 'url' => 'https://<gitlab.example.com>/api/v4/container_registry_event/events', 'timeout' => '500ms', 'threshold' => 5, # DEPRECATED: use `maxretries` instead. 'maxretries' => 5, 'backoff' => '1s', 'headers' => { "Authorization" => [""] } } ] gitlab_rails['registry_notification_secret'] = '' # Must match the auth token in registry['notifications'][!note]
을 문자로 시작하는 대소문자를 구분하는 영숫자 문자열로 바꿉니다.< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c 32 | sed "s/^[0-9]*//"; echo로 생성할 수 있습니다. -
파일을 저장하고 GitLab을 재구성하여 변경 사항을 적용합니다.
알림 엔드포인트 구성은 Docker 레지스트리를 배포할 때 만든 레지스트리 구성 YAML 파일에서 수행합니다.
예시:
notifications:
endpoints:
- name: <alistener>
disabled: false
url: https://<my.listener.com>/event
headers: <http.Header>
timeout: 500
threshold: 5 # DEPRECATED: use `maxretries` instead.
maxretries: 5
backoff: 1000
정리 정책 실행#
사전 요구 사항:
- 컨테이너 레지스트리가 Sidekiq과 다른 노드에서 실행되는 분산 아키텍처를 사용하는 경우 외부 Sidekiq 사용 시 컨테이너 레지스트리 구성의 단계를 따릅니다.
정리 정책을 생성한 후 즉시 실행하여 컨테이너 레지스트리 스토리지 공간을 줄일 수 있습니다. 예약된 정리를 기다릴 필요가 없습니다.
특정 프로젝트가 사용하는 컨테이너 레지스트리 디스크 공간을 줄이기 위해 관리자는 다음을 수행할 수 있습니다.
- 프로젝트별 디스크 공간 사용량을 확인하여 정리가 필요한 프로젝트를 파악합니다.
- GitLab Rails 콘솔을 사용해 정리 정책을 실행하여 이미지 태그를 제거합니다.
- 가비지 컬렉션을 실행하여 참조되지 않는 레이어와 태그가 없는 매니페스트를 제거합니다.
프로젝트별 레지스트리 디스크 공간 사용량#
각 프로젝트가 사용하는 디스크 공간을 확인하려면 GitLab Rails 콘솔에서 다음을 실행합니다.
projects_and_size = [["project_id", "creator_id", "registry_size_bytes", "project path"]]
# You need to specify the projects that you want to look through. You can get these in any manner.
projects = Project.last(100)
registry_metadata_database = ContainerRegistry::GitlabApiClient.supports_gitlab_api?
if registry_metadata_database
projects.each do |project|
size = project.container_repositories_size
if size > 0
projects_and_size << [project.project_id, project.creator&.id, size, project.full_path]
end
end
else
projects.each do |project|
project_layers = {}
project.container_repositories.each do |repository|
repository.tags.each do |tag|
tag.layers.each do |layer|
project_layers[layer.digest] ||= layer.size
end
end
end
total_size = project_layers.values.compact.sum
if total_size > 0
projects_and_size << [project.project_id, project.creator&.id, total_size, project.full_path]
end
end
end
# print it as comma separated output
projects_and_size.each do |ps|
puts "%s,%s,%s,%s" % ps
end
이 스크립트는 컨테이너 이미지 레이어를 기준으로 크기를 계산합니다. 레이어는 여러 프로젝트에서 공유될 수 있으므로 결과는 근삿값이지만 프로젝트 간 상대적인 디스크 사용량을 파악하는 데 좋은 지표가 됩니다.
정리 정책을 실행하여 이미지 태그를 제거하려면 GitLab Rails 콘솔에서 다음 명령을 실행합니다.
# Numeric ID of the project whose container registry should be cleaned up
P = <project_id>
# Numeric ID of a user with Developer, Maintainer, or Owner role for the project
U = <user_id>
# Get required details / objects
user = User.find_by_id(U)
project = Project.find_by_id(P)
policy = ContainerExpirationPolicy.find_by(project_id: P)
# Loop through each container repository
project.container_repositories.find_each do |repo|
puts repo.attributes
# Start the tag cleanup
puts Projects::ContainerRepository::CleanupTagsService.new(container_repository: repo, current_user: user, params: policy.attributes.except("created_at", "updated_at")).execute
end
일정에 따라 정리를 실행할 수도 있습니다.
인스턴스 전체의 모든 프로젝트에 정리 정책을 활성화하려면 컨테이너 레지스트리가 있지만 정리 정책이 비활성화된 모든 프로젝트를 찾아야 합니다.
# Find all projects where Container registry is enabled, and cleanup policies disabled
projects = Project.find_by_sql ("SELECT * FROM projects WHERE id IN (SELECT project_id FROM container_expiration_policies WHERE enabled=false AND id IN (SELECT project_id FROM container_repositories))")
# Loop through each project
projects.each do |p|
# Print project IDs and project full names
puts "#{p.id},#{p.full_name}"
end
컨테이너 레지스트리 메타데이터 데이터베이스#
히스토리
- GitLab 17.3에서 정식 출시되었습니다.
메타데이터 데이터베이스는 온라인 가비지 컬렉션을 포함한 많은 새 레지스트리 기능을 가능하게 하며 많은 레지스트리 작업의 효율을 높입니다. 자세한 내용은 컨테이너 레지스트리 메타데이터 데이터베이스 페이지를 참고합니다.
컨테이너 레지스트리 가비지 컬렉션#
사전 요구 사항:
- Linux 패키지 또는 GitLab Helm 차트를 사용하여 GitLab을 설치해야 합니다.
Amazon S3 Lifecycle 같은 오브젝트 스토리지 공급자의 보존 정책이 오브젝트가 올바르게 삭제되는 것을 방해할 수 있습니다.
컨테이너 레지스트리는 상당한 스토리지 공간을 사용할 수 있으며 스토리지 사용량을 줄이려는 경우가 있습니다. 나열된 옵션 중 태그 삭제가 가장 효과적입니다. 그러나 태그를 삭제하는 것만으로는 이미지 레이어가 삭제되지 않습니다. 기반 이미지 매니페스트에서 태그만 사라질 뿐입니다.
공간을 더 효과적으로 확보하기 위해 컨테이너 레지스트리에는 참조되지 않는 레이어와 (선택적으로) 태그가 없는 매니페스트를 삭제할 수 있는 가비지 컬렉터가 있습니다.
GitLab Geo를 사용하는 경우 Geo 사이트의 가비지 컬렉션을 참고합니다.
가비지 컬렉터를 시작하려면 다음 gitlab-ctl 명령을 실행합니다.
sudo gitlab-ctl registry-garbage-collect
가비지 컬렉션을 수행하는 데 걸리는 시간은 컨테이너 레지스트리 데이터 크기에 비례합니다.
registry-garbage-collect 명령은 가비지 컬렉션 전에 컨테이너 레지스트리를 종료하고
가비지 컬렉션이 완료된 후에만 다시 시작합니다. 다운타임을 피하려면
컨테이너 레지스트리를 수동으로 읽기 전용 모드로 설정하고 gitlab-ctl을 우회할 수 있습니다.
이 명령은 레거시 메타데이터를 사용하는 경우에만 진행됩니다. 컨테이너 레지스트리 메타데이터 데이터베이스가 활성화된 경우에는 진행되지 않습니다.
콘텐츠 주소 지정 레이어 이해#
먼저 이미지를 빌드하는 다음 예시를 생각해 봅니다.
# This builds an image with content of sha256:<111111...>
docker build -t <my.registry.com>/<my.group>/<my.project>:latest .
docker push <my.registry.com>/<my.group>/<my.project>:latest
이제 latest를 새 버전으로 덮어씁니다.
# This builds an image with content of sha256:<222222...>
docker build -t <my.registry.com>/<my.group>/<my.project>:latest .
docker push <my.registry.com>/<my.group>/<my.project>:latest
이제 latest 태그는 sha256:<222222...>의 매니페스트를 가리킵니다.
레지스트리의 아키텍처상 이 데이터는 latest 태그로는 더 이상 직접 접근할 수 없지만,
<my.registry.com>/<my.group>/<my.project>@sha256:<111111...> 이미지를 가져올 때는
여전히 접근할 수 있습니다.
참조되지 않는 레이어 제거#
이미지 레이어는 컨테이너 레지스트리 스토리지의 대부분을 차지합니다. 어떤 이미지 매니페스트도 참조하지 않는 레이어는 참조되지 않는 레이어로 간주됩니다. 참조되지 않는 레이어는 컨테이너 레지스트리 가비지 컬렉터의 기본 대상입니다.
구성 파일의 기본 위치를 변경하지 않았다면 다음을 실행합니다.
sudo gitlab-ctl registry-garbage-collect
컨테이너 레지스트리 config.yml의 위치를 변경했다면 다음과 같이 실행합니다.
sudo gitlab-ctl registry-garbage-collect /path/to/config.yml
태그가 없는 모든 매니페스트와 참조되지 않는 레이어를 제거하여 추가 공간을 확보할 수도 있습니다.
태그가 없는 매니페스트와 참조되지 않는 레이어 제거#
기본적으로 컨테이너 레지스트리 가비지 컬렉터는 태그가 없는 이미지를 무시하며, 사용자는 다이제스트로 태그가 없는 이미지를 계속 가져올 수 있습니다. 사용자는 나중에 이미지를 다시 태그하여 GitLab UI와 API에서 다시 보이게 할 수도 있습니다.
태그가 없는 이미지와 해당 이미지만 참조하는 레이어가 필요하지 않다면
모두 삭제할 수 있습니다. registry-garbage-collect 명령에 -m 플래그를 사용합니다.
sudo gitlab-ctl registry-garbage-collect -m
태그가 없는 이미지를 삭제해도 될지 확실하지 않다면 진행하기 전에 레지스트리 데이터를 백업합니다.
다운타임 없이 가비지 컬렉션 수행#
컨테이너 레지스트리를 온라인으로 유지한 채 가비지 컬렉션을 수행하려면 레지스트리를
읽기 전용 모드로 전환하고 기본 제공 gitlab-ctl registry-garbage-collect 명령을 우회합니다.
컨테이너 레지스트리가 읽기 전용 모드일 때는 이미지를 가져올 수는 있지만 푸시할 수는 없습니다. 가비지 컬렉션이 진행되는 내내 컨테이너 레지스트리는 읽기 전용 상태로 유지되어야 합니다.
기본적으로 레지스트리 스토리지 경로는
/var/opt/gitlab/gitlab-rails/shared/registry입니다.
읽기 전용 모드를 활성화하려면 다음을 수행합니다.
-
/etc/gitlab/gitlab.rb에서 읽기 전용 모드를 지정합니다.registry['storage'] = { 'filesystem' => { 'rootdirectory' => "<your_registry_storage_path>" }, 'maintenance' => { 'readonly' => { 'enabled' => true } } } -
저장하고 GitLab을 재구성합니다.
sudo gitlab-ctl reconfigure이 명령은 컨테이너 레지스트리를 읽기 전용 모드로 설정합니다.
-
다음으로 가비지 컬렉션 명령 중 하나를 실행합니다.
# Remove unreferenced layers sudo /opt/gitlab/embedded/bin/registry garbage-collect /var/opt/gitlab/registry/config.yml # Remove untagged manifests and unreferenced layers sudo /opt/gitlab/embedded/bin/registry garbage-collect -m /var/opt/gitlab/registry/config.yml이 명령은 가비지 컬렉션을 시작합니다. 완료까지 걸리는 시간은 레지스트리 데이터 크기에 비례합니다.
-
완료되면
/etc/gitlab/gitlab.rb에서 다시 읽기/쓰기 모드로 변경합니다.registry['storage'] = { 'filesystem' => { 'rootdirectory' => "<your_registry_storage_path>" }, 'maintenance' => { 'readonly' => { 'enabled' => false } } } -
저장하고 GitLab을 재구성합니다.
sudo gitlab-ctl reconfigure
일정에 따라 가비지 컬렉션 실행#
레지스트리의 가비지 컬렉션은 레지스트리를 사용하지 않는 시간에 매주 정기적으로 실행하는 것이 이상적입니다. 가장 간단한 방법은 일주일에 한 번 주기적으로 실행되는 새 crontab 작업을 추가하는 것입니다.
/etc/cron.d/registry-garbage-collect 아래에 파일을 생성합니다.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# Run every Sunday at 04:05am
5 4 * * 0 root gitlab-ctl registry-garbage-collect
태그가 없는 매니페스트와 참조되지 않는 레이어를 제거하려면 -m 플래그를 추가할 수 있습니다.
가비지 컬렉션 중지#
가비지 컬렉션을 중지할 가능성이 있다면 다운타임 없이 가비지 컬렉션 수행에 설명된 대로 가비지 컬렉션을 수동으로 실행해야 합니다. 그런 다음 Control+C를 눌러 가비지 컬렉션을 중지할 수 있습니다.
그렇지 않고 gitlab-ctl을 중단하면 레지스트리 서비스가 중지된 상태로 남을 수 있습니다.
이 경우 gitlab-ctl 명령이 레지스트리 서비스를 다시 시작할 수 있도록 시스템에서
가비지 컬렉션 프로세스 자체를 찾아야 합니다.
또한 프로세스의 마크 단계에서는 진행 상황이나 결과를 저장할 방법이 없습니다. 블롭 삭제가 시작된 이후에야 영구적인 작업이 이루어집니다.
지속적인 무중단 가비지 컬렉션#
메타데이터 데이터베이스로 마이그레이션하면 일정을 예약하거나 읽기 전용 모드를 요구하지 않고 백그라운드에서 가비지 컬렉션을 실행할 수 있습니다.
구성 요소별 확장#
이 섹션에서는 레지스트리 트래픽이 증가할 때 구성 요소별로 발생할 수 있는 성능 병목 지점을 설명합니다. 각 하위 섹션은 대략 작은 레지스트리 워크로드에서 큰 레지스트리 워크로드 순으로 도움이 되는 권장 사항 순서로 배열되어 있습니다. 레지스트리는 참조 아키텍처에 포함되어 있지 않으며, 사용자 수나 초당 요청 수를 기준으로 한 확장 가이드도 없습니다.
데이터베이스#
- 별도의 데이터베이스로 이동: 데이터베이스 부하가 증가하면 레지스트리 메타데이터 데이터베이스를 별도의 물리 데이터베이스로 옮겨 수직으로 확장합니다. 별도의 데이터베이스를 사용하면 레지스트리 데이터베이스에 사용할 수 있는 리소스를 늘리고 레지스트리가 만드는 트래픽을 격리할 수 있습니다.
- HA PostgreSQL 서드파티 솔루션으로 이동: Praefect와 마찬가지로 신뢰할 수 있는 공급자나 솔루션으로 이동하면 HA를 사용할 수 있으며 멀티 노드 레지스트리 배포에 적합합니다. 레지스트리는 네이티브 Postgres 파티셔닝, 트리거, 함수를 많이 사용하므로 이를 지원하는 공급자를 선택해야 합니다.
레지스트리 서버#
- 별도의 노드로 이동: 별도의 노드는 컨테이너 레지스트리 서버 프로세스에서 사용할 수 있는 리소스를 늘리기 위해 수직으로 확장하는 방법 중 하나입니다.
- 로드 밸런서 뒤에서 여러 레지스트리 노드 실행: 레지스트리는 대형 노드 하나로도 많은 트래픽을 처리할 수 있지만, 일반적으로 레지스트리는 여러 배포로 수평 확장하도록 설계되었습니다. 더 작은 노드를 여러 개 구성하면 자동 확장 같은 기법도 사용할 수 있습니다.
Redis 캐시#
Redis 캐시를 활성화하면 성능이 향상될 뿐만 아니라 리포지터리 이름 변경 같은 기능도 사용할 수 있습니다.
- Redis Server: 단일 Redis 인스턴스가 지원되며 Redis 캐시의 이점을 얻는 가장 간단한 방법입니다.
- Redis Sentinel: Redis Sentinel도 지원되며 캐시를 HA로 구성할 수 있습니다.
- Redis Cluster: 배포 규모가 커지면 추가 확장을 위해 Redis Cluster를 사용할 수도 있습니다.
스토리지#
- 로컬 파일 시스템: 로컬 파일 시스템은 기본값이며 성능이 비교적 좋지만 멀티 노드 배포나 대량의 레지스트리 데이터에는 적합하지 않습니다.
- 오브젝트 스토리지: 오브젝트 스토리지를 사용하면 더 많은 양의 레지스트리 데이터를 현실적으로 저장할 수 있습니다. 오브젝트 스토리지는 멀티 노드 레지스트리 배포에도 적합합니다.
온라인 가비지 컬렉션#
- 기본값 조정: 온라인 가비지 컬렉션이 검토 큐를 안정적으로 비우지 못하면
gc구성 섹션 아래manifests와blobs섹션의interval설정을 조정할 수 있습니다. 기본값은5s이며 밀리초 단위로도 구성할 수 있습니다. 예를 들어500ms입니다. - 레지스트리 서버와 함께 수평 확장: 레지스트리 애플리케이션을 멀티 노드 배포로 수평 확장하는 경우 온라인 가비지 컬렉션은 구성을 변경하지 않아도 자동으로 확장됩니다.
별도의 노드에서 GitLab과 레지스트리 구성(Linux 패키지 설치)#
기본적으로 GitLab 패키지는 두 서비스가 같은 노드에서 실행된다고 가정합니다. 별도의 노드에서 실행하려면 별도의 구성이 필요합니다.
구성 옵션#
다음 구성 옵션은 각 노드의 /etc/gitlab/gitlab.rb에 설정해야 합니다.
레지스트리 노드 설정#
| 옵션 | 설명 |
|---|---|
registry['registry_http_addr'] |
레지스트리가 수신 대기하는 네트워크 주소와 포트입니다. 웹 서버 또는 로드 밸런서에서 접근할 수 있어야 합니다. 기본값: 프로그래밍 방식으로 설정. |
registry['token_realm'] |
인증 엔드포인트 URL이며, 일반적으로 GitLab 인스턴스 URL입니다. 사용자가 접근할 수 있어야 합니다. 기본값: 프로그래밍 방식으로 설정. |
registry['http_secret'] |
클라이언트 측 변조를 방지하는 데 사용하는 보안 토큰입니다. 임의의 문자열로 생성됩니다. |
registry['internal_key'] |
토큰 서명 키이며, 레지스트리 서버에서 생성되지만 GitLab에서 사용합니다. 기본값: 자동 생성. |
registry['internal_certificate'] |
토큰 서명용 인증서입니다. 기본값: 자동 생성. |
registry['rootcertbundle'] |
internal_certificate가 저장되는 파일 경로입니다. 기본값: 프로그래밍 방식으로 설정. |
registry['health_storagedriver_enabled'] |
스토리지 드라이버의 상태 모니터링을 활성화합니다. 기본값: 프로그래밍 방식으로 설정. |
gitlab_rails['registry_key_path'] |
internal_key가 저장되는 파일 경로입니다. 기본값: 프로그래밍 방식으로 설정. |
gitlab_rails['registry_issuer'] |
토큰 발급자 이름입니다. 레지스트리와 GitLab 구성에서 일치해야 합니다. 기본값: 프로그래밍 방식으로 설정. |
GitLab 노드 설정#
| 옵션 | 설명 |
|---|---|
gitlab_rails['registry_enabled'] |
GitLab 레지스트리 API 통합을 활성화합니다. true로 설정해야 합니다. |
gitlab_rails['registry_api_url'] |
GitLab이 사용하는 내부 레지스트리 URL입니다(사용자에게 표시되지 않음). 스킴을 포함한 registry['registry_http_addr']를 사용합니다. 기본값: 프로그래밍 방식으로 설정. |
gitlab_rails['registry_host'] |
스킴을 제외한 공개 레지스트리 호스트 이름입니다(예: registry.gitlab.example). 이 주소는 사용자에게 표시됩니다. |
gitlab_rails['registry_port'] |
사용자에게 표시되는 공개 레지스트리 포트 번호입니다. |
gitlab_rails['registry_issuer'] |
레지스트리 구성과 일치해야 하는 토큰 발급자 이름입니다. |
gitlab_rails['registry_key_path'] |
레지스트리가 사용하는 인증서 키의 파일 경로입니다. |
gitlab_rails['internal_key'] |
GitLab이 사용하는 토큰 서명 키의 내용입니다. |
노드 설정#
GitLab과 컨테이너 레지스트리를 별도의 노드에 구성하려면 다음을 수행합니다.
-
레지스트리 노드에서
/etc/gitlab/gitlab.rb를 다음 설정으로 편집합니다.# Registry server details # - IP address: 10.30.227.194 # - Domain: registry.example.com # Disable unneeded services gitlab_workhorse['enable'] = false puma['enable'] = false sidekiq['enable'] = false postgresql['enable'] = false redis['enable'] = false gitlab_kas['enable'] = false gitaly['enable'] = false nginx['enable'] = false # Configure registry settings registry['enable'] = true registry['registry_http_addr'] = '0.0.0.0:5000' registry['token_realm'] = 'https://<gitlab.example.com>' registry['http_secret'] = '<6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b>' # Configure GitLab Rails settings gitlab_rails['registry_issuer'] = 'omnibus-gitlab-issuer' gitlab_rails['registry_key_path'] = '/etc/gitlab/gitlab-registry.key' -
GitLab 노드에서
/etc/gitlab/gitlab.rb를 다음 설정으로 편집합니다.# GitLab server details # - IP address: 10.30.227.149 # - Domain: gitlab.example.com # Configure GitLab URL external_url 'https://<gitlab.example.com>' # Configure registry settings gitlab_rails['registry_enabled'] = true gitlab_rails['registry_api_url'] = '<http://10.30.227.194:5000>' gitlab_rails['registry_host'] = '<registry.example.com>' gitlab_rails['registry_port'] = 5000 gitlab_rails['registry_issuer'] = 'omnibus-gitlab-issuer' gitlab_rails['registry_key_path'] = '/etc/gitlab/gitlab-registry.key' -
두 노드 간에
/etc/gitlab/gitlab-secrets.json파일을 동기화합니다.- GitLab 노드의 파일을 레지스트리 노드로 복사합니다.
- 파일 권한이 올바른지 확인합니다.
- 두 노드에서
sudo gitlab-ctl reconfigure를 실행합니다.
컨테이너 레지스트리 아키텍처#
사용자는 컨테이너 레지스트리에 자신의 Docker 이미지를 저장할 수 있습니다. 레지스트리는 클라이언트와 직접 맞닿아 있으므로 웹 서버 또는 로드 밸런서(LB)에 직접 노출됩니다.
소스 코드 보기
%%{init: { "fontFamily": "GitLab Sans" }}%%
flowchart LR
accTitle: Container registry authentication flow
accDescr: Shows how users authenticate with the container registry with GitLab API to push and pull Docker images
A[User] --->|1: Docker loginon port 443| C{Frontend loadbalancer}
C --->|2: connection attemptwithout token fails| D[Container registry]
C --->|5: connect with token succeeds| D[Container registry]
C --->|3: Dockerrequests token| E[API frontend]
E --->|4:API returnssigned token| C
linkStyle 1 stroke-width:4px,stroke:red
linkStyle 2 stroke-width:4px,stroke:green</code></pre></details></div>
인증 흐름은 다음 단계로 이루어집니다.
- 사용자가 클라이언트에서
docker login registry.gitlab.example을 실행합니다. 이 요청은 443 포트의 웹 서버(또는 LB)에 도달합니다.
- 웹 서버가 레지스트리 백엔드 풀(기본값 5000 포트)에 연결합니다. 사용자에게 유효한 토큰이 없으므로 레지스트리는
401 Unauthorized HTTP 코드와 토큰을 받을 URL을 반환합니다. 이 URL은 레지스트리 구성의 token_realm 설정으로 정의되며 GitLab API를 가리킵니다.
- Docker 클라이언트가 GitLab API에 연결하여 토큰을 받습니다.
- API가 레지스트리 키로 토큰에 서명하고 Docker 클라이언트에 전송합니다.
- Docker 클라이언트가 API에서 받은 토큰으로 다시 로그인합니다. 이제 인증된 클라이언트는 Docker 이미지를 푸시하고 가져올 수 있습니다.
참조: https://distribution.github.io/distribution/spec/auth/token/
GitLab과 컨테이너 레지스트리 간 통신#
컨테이너 레지스트리는 내부적으로 사용자를 인증할 수 없으므로 GitLab을 통해 자격 증명을 검증합니다.
레지스트리와 GitLab 간 연결은
TLS로 암호화됩니다.
GitLab은 개인 키로 토큰에 서명하고, 레지스트리는 인증서가 제공하는 공개 키로
서명을 검증합니다.
기본적으로 모든 설치에서 자체 서명 인증서 키 쌍이 생성됩니다.
레지스트리 구성의 internal_key 설정을 사용하여 이 동작을 재정의할 수 있습니다.
통신 흐름은 다음 단계로 이루어집니다.
- GitLab은 레지스트리의 개인 키를 사용해 레지스트리와 상호 작용합니다. 레지스트리
요청을 보낼 때 유효 기간이 짧고(10분) 네임스페이스로 제한된 토큰이 생성되며
개인 키로 서명됩니다.
- 레지스트리는 서명이 구성에 지정된 레지스트리 인증서와
일치하는지 확인하고 작업을 허용합니다.
- GitLab은 Sidekiq을 통해 백그라운드 job을 처리하며, Sidekiq도 레지스트리와 상호 작용합니다.
이러한 job은 레지스트리와 직접 통신하여 이미지 삭제를 처리합니다.
서드파티 레지스트리에서 마이그레이션#
GitLab에서 외부 컨테이너 레지스트리를 사용하는 것은 사용 중단되었으며 더 이상 지원되지 않습니다.
통합은 비활성화되지 않았지만 문제 디버깅과 수정에 대한 지원은
더 이상 제공되지 않습니다. 또한 이 통합은 더 이상 개발되지 않으며
새 기능이 추가되지도 않습니다. GitLab은 향후 릴리스에서 이 통합을 제거할 수 있습니다. GitLab 컨테이너 레지스트리로 마이그레이션합니다.
이 섹션에는 관리자가 서드파티 레지스트리에서 GitLab 컨테이너 레지스트리로 마이그레이션하는 방법에 대한 안내가 있습니다.
사용 중인 서드파티 컨테이너 레지스트리가 여기에 나열되어 있지 않다면
피드백 이슈에 사용 사례를 설명할 수 있습니다.
아래에 제공된 모든 지침은 먼저 테스트 환경에서 시도해야 합니다.
프로덕션에 적용하기 전에 모든 것이 예상대로 계속 작동하는지 확인합니다.
Docker Distribution Registry#
Docker Distribution Registry는 CNCF에 기증되었으며
현재는 Distribution Registry로 알려져 있습니다.
이 레지스트리는 GitLab 컨테이너 레지스트리의 기반이 되는 오픈 소스 구현입니다.
GitLab 컨테이너 레지스트리는 지원되는 모든 스토리지 백엔드를 포함하여 Distribution Registry가 제공하는
기본 기능과 호환됩니다. GitLab 컨테이너 레지스트리로 마이그레이션하려면
이 페이지의 지침을 따르고 Distribution Registry와 같은 스토리지 백엔드를 사용하면 됩니다.
GitLab 컨테이너 레지스트리는 Distribution Registry에 사용 중인 구성을 그대로 받아들일 수 있어야 합니다.
컨테이너 이미지 삭제 최대 재시도 횟수#
히스토리
- GitLab 17.5에서
set_delete_failed_container_repository라는 기능 플래그와 함께 도입되었습니다. 기본적으로 비활성화되어 있습니다.
- GitLab 17.6에서 정식 출시되었습니다. 기능 플래그
set_delete_failed_container_repository가 제거되었습니다.
컨테이너 이미지를 삭제할 때 오류가 발생할 수 있으므로 오류가 일시적인 문제가 아닌지 확인하기 위해
삭제를 재시도합니다. 삭제는 최대 10번 재시도되며 재시도 사이에 백오프 지연이 적용됩니다.
이 지연은 일시적인 오류가 해결될 시간을 재시도 사이에 더 확보해 줍니다.
최대 재시도 횟수를 설정하면 재시도 사이에 해결되지 않은
지속적인 오류가 있는지 감지하는 데에도 도움이 됩니다. 삭제가 최대 재시도 횟수만큼 실패하면
컨테이너 리포지터리의 status가 delete_failed로 설정됩니다. 이 상태에서는
리포지터리가 더 이상 삭제를 재시도하지 않습니다.
delete_failed 상태인 컨테이너 리포지터리를 조사하고
문제를 해결해야 합니다. 문제가 해결된 후에는 이미지 삭제가 다시 시작될 수 있도록 리포지터리 상태를
delete_scheduled로 되돌릴 수 있습니다. 리포지터리 상태를 업데이트하려면
Rails 콘솔에서 다음을 실행합니다.
container_repository = ContainerRepository.find(<id>)
container_repository.update(status: 'delete_scheduled')