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

Tier: Free, Premium, Ultimate Offering: Self-managed

registry sub-chart는 쿠버네티스 상의 완전한 클라우드 네이티브 GitLab 배포를 위해 레지스트리 구성 요소를 제공합니다. 이 서브 차트는 upstream chart를 기반으로 하며 GitLab Container Registry를 포함하고 있습니다.

이 차트는 3가지 주요 부분으로 구성됩니다:

모든 구성은 /etc/docker/registry/config.yml 변수를 Deployment에 제공하고 ConfigMap으로부터 파생된 값을 사용하여 Registry 구성 문서에 따라 처리됩니다. ConfigMap은 upstream 기본값을 재정의하지만 이를 기반으로 합니다. 자세한 내용은 아래를 확인하세요:

디자인 선택 사항

이 차트에서는 간단한 인스턴스 확장을 허용하면서 롤링 업데이트를 가능하게 하기 위해 쿠버네티스 Deployment를 배포 방법으로 선택했습니다.

이 차트는 두 가지 필수 시크릿과 하나의 선택적인 시크릿을 사용합니다:

필수

  • global.registry.certificate.secret: 연관된 GitLab 인스턴스에서 제공된 인증 토큰을 확인하기 위한 공용 인증서 번들을 포함하는 전역 시크릿입니다. 문서에서 GitLab을 인증 엔드포인트로 사용하는 방법을 확인하세요.
  • global.registry.httpSecret.secret: 레지스트리 파드 간의 공유 비밀을 포함할 전역 시크릿입니다.

선택적

  • profiling.stackdriver.credentials.secret: Stackdriver 프로파일링이 활성화되어 있고 명시적 서비스 계정 자격 증명을 제공해야 하는 경우, 이 시크릿의 값 (기본적으로 credentials 키)은 GCP 서비스 계정 JSON 자격 증명입니다. GKE를 사용하고 있고 Workload Identity를 사용하여 워크로드에 서비스 계정을 제공하는 경우 (권장되는 방법은 아니지만)이 시크릿이 필요하지 않으며 제공해서는 안 됩니다. 어느 경우든지 서비스 계정에는 roles/cloudprofiler.agent 역할 또는 해당 수동 권한이 필요합니다.

구성

아래에서 구성의 모든 주요 부분을 설명하겠습니다. 부모 차트에서 구성할 때 이 값들은 다음과 같을 것입니다:

registry:
  enabled:
  maintenance:
    readonly:
      enabled: false
    uploadpurging:
      enabled: true
      age: 168h
      interval: 24h
      dryrun: false
  image:
    tag: 'v3.90.0-gitlab'
    pullPolicy: IfNotPresent
  annotations:
  service:
    type: ClusterIP
    name: registry
  httpSecret:
    secret:
    key:
  authEndpoint:
  tokenIssuer:
  certificate:
    secret: gitlab-registry
    key: registry-auth.crt
  deployment:
    terminationGracePeriodSeconds: 30
  draintimeout: '0'
  hpa:
    minReplicas: 2
    maxReplicas: 10
    cpu:
      targetAverageUtilization: 75
    behavior:
      scaleDown:
        stabilizationWindowSeconds: 300
  storage:
    secret:
    key: storage
    extraKey:
  validation:
    disabled: true
    manifests:
      referencelimit: 0
      payloadsizelimit: 0
      urls:
        allow: []
        deny: []
  notifications: {}
  tolerations: []
  ingress:
    enabled: false
    tls:
      enabled: true
      secretName: redis
    annotations:
    configureCertmanager:
    proxyReadTimeout:
    proxyBodySize:
    proxyBuffering:
  networkpolicy:
    enabled: false
    egress:
      enabled: false
      rules: []
    ingress:
      enabled: false
      rules: []
  tls:
    enabled: false
    secretName:
    verify: true
    caSecretName:

이 차트를 독립적으로 배포하려면 최상위 수준에서 registry를 제거하세요.

## 설치 매개변수

| 매개변수                                   | 기본값                                                              | 설명 |
|-------------------------------------------|----------------------------------------------------------------------|---------|
| `annotations`                             |                                                                      | Pod 주석 |
| `podLabels`                               |                                                                      | 보충 Pod 라벨. 선택기에는 사용되지 않습니다. |
| `common.labels`                           |                                                                      | 이 차트에 의해 생성된 모든 오브젝트에 적용되는 보충 라벨 |
| `authAutoRedirect`                        | `true`                                                               | 인증 자동 리디렉션 (Windows 클라이언트가 작동하려면 true여야 함) |
| `authEndpoint`                            | `global.hosts.gitlab.name`                                           | 인증 엔드포인트 (호스트 및 포트만 해당) |
| `certificate.secret`                      | `gitlab-registry`                                                    | JWT 인증서 |
| `debug.addr.port`                         | `5001`                                                               | 디버그 포트  |
| `debug.tls.enabled`                       | `false`                                                              | 레지스트리 디버그 포트용 TLS 활성화. liveness 및 readiness 프로브 및 (활성화된 경우) 메트릭 엔드포인트에 영향을 미침 |
| `debug.tls.secretName`                    |                                                                      | 쿠버네티스 TLS 시크릿의 이름. `debug.tls.enabled=true`이고 설정되지 않은 경우 디버그 TLS 구성은 레지스트리의 TLS 인증서로 기본 설정됨 |
| `debug.prometheus.enabled`                | `false`                                                              | **폐기됨** `metrics.enabled` 사용 |
| `debug.prometheus.path`                   | `""`                                                                 | **폐기됨** `metrics.path` 사용 |
| `metrics.enabled`                         | `false`                                                              | 스크래핑 가능한 메트릭 엔드포인트 여부 |
| `metrics.path`                            | `/metrics`                                                           | 메트릭 엔드포인트 경로 |
| `metrics.serviceMonitor.enabled`          | `false`                                                              | Prometheus Operator가 메트릭 스크래핑을 관리하도록 ServiceMonitor를 만들어야 하는지 여부. 이 기능이 활성화되면 `prometheus.io` 스크래핑 어노테이션이 제거됨을 참고 |
| `metrics.serviceMonitor.additionalLabels` | `{}`                                                                 | ServiceMonitor에 추가할 라벨 |
| `metrics.serviceMonitor.endpointConfig`   | `{}`                                                                 | ServiceMonitor에 대한 추가 엔드포인트 구성 |
| `deployment.terminationGracePeriodSeconds`| `30`                                                                | Pod가 원활하게 종료되기 위한 선택적 시간 (초) |
| `deployment.strategy`                     | `{}`                                                                 | 배포에 의해 사용되는 업데이트 전략 구성 가능 |
| `draintimeout`                            | `'0'`                                                               | SIGTERM 신호 수신 후 HTTP 연결을 비우기 위해 기다릴 시간(예: `'10s'`) |
| `relativeurls`                            | `false`                                                              | 레지스트리가 Location 헤더에서 상대 URL을 반환하도록 활성화 |
| `enabled`                                 | `true`                                                               | 레지스트리 플래그 활성화 |
| `hpa.behavior`                            | `{scaleDown: {stabilizationWindowSeconds: 300 }}`                    | 업-스케일링 동작 사양 (autoscaling/v2beta2 이상 필요) |
| `hpa.customMetrics`                       | `[]`                                                                 | 원하는 복제본 수를 계산하는 데 사용하는 사용자 정의 메트릭 사양 (기본 설정된 `targetAverageUtilization`의 평균 CPU 사용률 사용을 무시함) |
| `hpa.cpu.targetType`                      | `Utilization`                                                        | 오토 스케일링 CPU 대상 유형, `Utilization` 또는 `AverageValue` 중 하나여야 함 |
| `hpa.cpu.targetAverageValue`              |                                                                      | 오토 스케일링 CPU 대상 값 설정 |
| `hpa.cpu.targetAverageUtilization`        | `75`                                                                 | 오토 스케일링 CPU 대상 활용도 설정 |
| `hpa.memory.targetType`                   |                                                                      | 오토 스케일링 메모리 대상 유형, `Utilization` 또는 `AverageValue` 중 하나여야 함 |
| `hpa.memory.targetAverageValue`           |                                                                      | 오토 슼일링 메모리 대상 값 설정 |
| `hpa.memory.targetAverageUtilization`     |                                                                      | 오토 스케일링 메모리 대상 활용도 설정 |
| `hpa.minReplicas`                         | `2`                                                                  | 최소 복제본 수 |
| `hpa.maxReplicas`                         | `10`                                                                 | 최대 복제본 수 |
| `httpSecret`                              |                                                                      | HTTPS 시크릿 |
| `extraEnvFrom`                            |                                                                      | 노출할 다른 데이터 소스에서 추가 환경 변수 목록 |
| `image.pullPolicy`                        |                                                                      | 레지스트리 이미지용 풀 정책 |
| `image.pullSecrets`                       |                                                                      | 이미지 저장소에 사용할 시크릿 |
| `image.repository`                        | `registry.gitlab.com/gitlab-org/build/cng/gitlab-container-registry` | 레지스트리 이미지 |
| `image.tag`                               | `v3.90.0-gitlab`                                                     | 사용할 이미지 버전 |
| `init.image.repository`                   |                                                                      | initContainer 이미지 |
| `init.image.tag`                          |                                                                      | initContainer 이미지 태그 |
| `init.containerSecurityContext`           |                                                                      | initContainer 컨테이너별 [securityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.25/#securitycontext-v1-core) 재정의 |
| `keda.enabled`                            | `false`                                                              | [KEDA](https://keda.sh/)`ScaledObjects` 대신 `HorizontalPodAutoscalers` 사용 |
| `keda.pollingInterval`                    | `30`                                                                 | 각 트리거를 확인하는 간격 |
| `keda.cooldownPeriod`                     | `300`                                                                | 마지막 트리거가 활성화된 후 리소스를 0으로 다시 축소하기 전 대기해야 하는 기간 |
| `keda.minReplicaCount`                    |                                                                      | KEDA가 리소스를 축소할 최소 복제본 수. `hpa.minReplicas`로 기본 설정됨 |
| `keda.maxReplicaCount`                    |                                                                      | KEDA가 리소스를 확장할 최대 복제본 수. `hpa.maxReplicas`로 기본 설정됨 |
| `keda.fallback`                           |                                                                      | KEDA 후행 구성. 자세한 내용은 [문서](https://keda.sh/docs/2.10/concepts/scaling-deployments/#fallback) 참고 |
| `keda.hpaName`                            |                                                                      | KEDA가 만들 HPA 리소스의 이름. 기본값은 `keda-hpa-{scaled-object-name}` |
| `keda.restoreToOriginalReplicaCount`      |                                                                      | `ScaledObject` 삭제 후 대상 리소스를 원래 복제본 수로 축소해야 하는지 여부 지정 |
| `keda.behavior`                           |                                                                      | 업-스케일링 및 다운-스케일링 동작 사양. 기본값은 `hpa.behavior`로 설정됨 |
| `keda.triggers`                           |                                                                      | 대상 리소스의 스케일링을 활성화할 트리거 목록. 기본값은 `hpa.cpu``hpa.memory`에서 계산된 트리거로 설정됨 |
| `log`                                     | `{level: info, fields: {service: registry}}`                         | 로깅 옵션 구성 |
| `minio.bucket`                            | `global.registry.bucket`                                             | 레거시 레지스트리 버킷 이름 |
| `maintenance.readonly.enabled`            | `false`                                                              | 레지스트리의 읽기 전용 모드 활성화 |
| `maintenance.uploadpurging.enabled`       | `true`                                                               | 업로드 퍼징 활성화 |
| `maintenance.uploadpurging.age`           | `168h`                                                               | 지정된 나이 이상의 업로드를 삭제하는 빈도 |
| `maintenance.uploadpurging.interval`      | `24h`                                                                | 업로드 퍼징이 수행되는 빈도 |
| `maintenance.uploadpurging.dryrun`        | `false`                                                              | 삭제하지 않고 제거될 업로드만 나열 |
| `priorityClassName`                       |                                                                      | 파드에 할당된 [우선순위 클래스](https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/) |
| `reporting.sentry.enabled`                | `false`                                                              | Sentry를 사용한 레포팅 활성화 |
| `reporting.sentry.dsn`                    |                                                                      | Sentry DSN (데이터 소스 이름) |
| `reporting.sentry.environment`            |                                                                      | Sentry [환경](https://docs.sentry.io/product/sentry-basics/concepts/environments/) |
| `profiling.stackdriver.enabled`           | `false`                                                              | Stackdriver를 사용한 지속적인 프로파일링 활성화 |
| `profiling.stackdriver.credentials.secret`| `gitlab-registry-profiling-creds`                                    | 자격 증명이 저장된 시크릿 이름 |
| `profiling.stackdriver.credentials.key`   | `credentials`                                                        | 자격 증명이 저장된 시크릿 키 |
| `profiling.stackdriver.service`           | `RELEASE-registry` (템플릿화된 서비스 이름)                       | 프로파일을 기록할 Stackdriver 서비스 이름 |
| `profiling.stackdriver.projectid`         | 실행 중인 GCP 프로젝트                                                | 프로파일을 보고할 GCP 프로젝트 |
| `database.enabled`                        | `false`                                                              | 메타데이터 데이터베이스 활성화. 실험적인 기능이며 프로덕션 환경에서 사용해서는 안 됨 |
| `database.host`                           | `global.psql.host`                                                   | 데이터베이스 서버 호스트명 |
| `database.port`                           | `global.psql.port`                                                   | 데이터베이스 서버 포트 |
| `database.user`                           |                                                                      | 데이터베이스 사용자 이름 |
| `database.password.secret`                | `RELEASE-registry-database-password`                                 | 데이터베이스 비밀번호가 저장된 시크릿 이름 |
| `database.password.key`                   | `password`                                                           | 데이터베이스 비밀번호가 저장된 시크릿 키 |
| `database.name`                           |                                                                      | 데이터베이스 이름 |
| `database.sslmode`                        |                                                                      | SSL 모드. `disable`, `allow`, `prefer`, `require`, `verify-ca` 또는 `verify-full` 중 하나일 수 있음 |
| `database.ssl.secret`                     | `global.psql.ssl.secret`                                             | 클라이언트 인증서, 키 및 인증 기관을 포함하는 시크릿. 기본적으로 기본 PostgreSQL SSL 시크릿으로 설정됨 |
| `database.ssl.clientCertificate`          | `global.psql.ssl.clientCertificate`                                  | 클라이언트 인증서 참조하는 시크릿 내부 키 |
| `database.ssl.clientKey`                  | `global.psql.ssl.clientKey`                                          | 클라이언트 키 참조하는 시크릿 내부 키 |
| `database.ssl.serverCA`                   | `global.psql.ssl.serverCA`                                           | 인증 기관 (CA)를 참조하는 시크릿 내부 키 |
| `database.connecttimeout`                 | `0`                                                                  | 연결을 대기할 최대 시간. 0이나 지정되지 않으면 무제한 대기 |
| `database.draintimeout`                   | `0`                                                                  | 종료 시 모든 연결을 비우기 위해 대기할 최대 시간. 0이나 지정되지 않으면 무제한 대기 |
| `database.preparedstatements`             | `false`                                                              | 준비된 문장 활성화. PgBouncer 호환성을 위해 기본적으로 비활성화됨 |
| `database.primary`                        | `false`                                                              | 기본 데이터베이스 서버 대상. `host`가 지정되지 않으면 `database.migrations` 실행을 위해 대상 데이터베이스 서버의 FQDN을 지정함 |
| `database.pool.maxidle`                   | `0`                                                                  | 유휴 연결 풀의 최대 연결 수. `maxopen``maxidle`보다 작으면 `maxidle``maxopen` 제한에 맞게 감소함. 0이나 지정되지 않으면 유휴 연결 없음 |
| `database.pool.maxopen`                   | `0`                                                                  | 데이터베이스에 대한 최대 오픈 연결 수. `maxopen``maxidle`보다 작으면 `maxidle``maxopen` 제한에 맞게 감소함. 0이나 지정되지 않으면 무제한 오픈 연결 |
| `database.pool.maxlifetime`               | `0`                                                                  | 연결을 재사용할 수 있는 최대 시간. 만료된 연결은 재사용되기 전에 나태하게 종료됨. 0이나 지정되지 않으면 무제한 재사용 |
| `database.pool.maxidletime`               | `0`                                                                  | 연결이 유휴 상태일 수 있는 최대 시간. 만료된 연결은 나태하게 종료됨. 0이나 지정되지 않으면 무제한 기간 |
| `database.migrations.enabled`             | `true`                                                               | 차트 초기 배포 및 업그레이드 시 자동으로 마이그레이션 실행하는 작업 활성화. 레지스트리 팟 내에서도 수동으로 마이그레이션 실행할 수 있음 |
| `database.migrations.activeDeadlineSeconds`| `3600`                                                              | 마이그레이션 작업에 대한 [activeDeadlineSeconds](https://kubernetes.io/docs/concepts/workloads/controllers/job/#job-termination-and-cleanup) 설정 |
| `database.migrations.backoffLimit`        | `6`                                                                  | 마이그레이션 작업에 대한 [backoffLimit](https://kubernetes.io/docs/concepts/workloads/controllers/job/#job-termination-and-cleanup) 설정 |
| `gc.disabled`                             | `true`                                                               | 온라인 GC 워커를 비활성화하는 경우 true |
| `gc.maxbackoff`                           | `24h`                                                                | 오류 발생 시 작업을 사이에 수면하기 위해 사용하는 최대 지수 백오프 지속 시간. 작업할 작업이 없거나 `gc.noidlebackoff``true`인 경우에도 적용됨. 비고: 항상 최대값은 아니며 최대값에 최대 33%의 임의의 흔들림 요소가 추가됨 |
| `gc.noidlebackoff`                        | `false`                                                              | 작업할 작업이 없을 때 사이를 꺾기 위한 지수 백오프 비활성화하는 경우 true |
| `gc.transactiontimeout`                   | `10s`                                                                | 각 워커 실행에 대한 데이터베이스 트랜잭션 시간 제한. 각 워커는 시작 시 데이터베이스 트랜잭션을 시작함. 이 시간 제한 초과로 인해 중단됨을 피하려면 작업 실행이 중지됨 |
| `gc.blobs.disabled`                       | `false`                                                              | 블롭 GC 워커를 비활성화하는 경우 true |
| `gc.blobs.interval`                       | `5s`                                                                 | 각 워커 실행 사이의 초기 대기 간격 |
| `gc.blobs.storagetimeout`                 | `5s`                                                                

## 차트 구성 예시

### pullSecrets

`pullSecrets`를 사용하면 포드에서 이미지를 가져오기 위해 개인 레지스트리에 인증할 수 있습니다.

개인 레지스트리 및 그들의 인증 방법에 대한 추가적인 세부 정보는 [Kubernetes documentation](https://kubernetes.io/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod)에서 찾을 수 있습니다.

아래는 `pullSecrets`의 사용 예시입니다:

```yaml
image:
  repository: my.registry.repository
  tag: latest
  pullPolicy: Always
  pullSecrets:
  - name: my-secret-name
  - name: my-secondary-secret-name

tolerations

tolerations을 사용하면 오염된 워커 노드에 포드를 예약할 수 있습니다.

아래는 tolerations의 사용 예시입니다:

tolerations:
- key: "node_label"
  operator: "Equal"
  value: "true"
  effect: "NoSchedule"
- key: "node_label"
  operator: "Equal"
  value: "true"
  effect: "NoExecute"

annotations

annotations를 사용하면 레지스트리 포드에 주석을 추가할 수 있습니다.

아래는 annotations의 사용 예시입니다:

annotations:
  kubernetes.io/example-annotation: annotation-value

서브 차트 활성화

우리가 선택한 분할된 서브 차트를 구현하는 방식은, 특정 배포에서 원하지 않는 구성 요소를 비활성화하는 기능을 포함합니다. 이를 위해, 결정해야 할 첫 번째 설정은 enabled입니다.

기본적으로, 레지스트리는 기본적으로 활성화되어 있습니다. 비활성화하려면 enabled: false로 설정하면 됩니다.

image 구성

이 섹션에서는 이 서브 차트의 Deployment에서 사용되는 컨테이너 이미지의 설정을 상세히 설명합니다. 레지스트리 및 pullPolicy 버전을 변경할 수 있습니다.

기본 설정:

  • tag: 'v3.90.0-gitlab'
  • pullPolicy: 'IfNotPresent'

service 구성

이 섹션에서는 Service의 이름과 유형을 제어합니다. 이러한 설정은 values.yaml에서 제공됩니다.

기본적으로, 서비스는 다음과 같이 구성됩니다:

이름 유형 기본값 설명
name 문자열 registry 서비스의 이름을 구성합니다
type 문자열 ClusterIP 서비스의 유형을 구성합니다
externalPort 정수 5000 서비스에서 노출된 포트
internalPort 정수 5000 포드가 서비스에서 요청을 수락하는 데 사용하는 포트
clusterIP 문자열 null 필요에 맞게 사용자 정의 클러스터 IP를 구성합니다
loadBalancerIP 문자열 null 필요에 맞게 사용자 정의 로드 밸런서 IP 주소를 구성합니다

ingress 구성

이 섹션에서는 레지스트리 Ingress를 제어합니다.

이름 유형 기본값 설명
apiVersion 문자열   apiVersion 필드에 사용할 값
annotations 문자열   이 필드는 Kubernetes Ingress에 대한 표준 annotations와 정확히 일치합니다.
configureCertmanager 부울   Ingress 주석 cert-manager.io/issueracme.cert-manager.io/http01-edit-in-place를 전환합니다. 자세한 정보는 GitLab Pages를 위한 TLS 요구 사항를 참조하십시오.
enabled 부울 false 해당 서비스에 대한 Ingress 객체를 생성할지 여부를 제어하는 설정입니다. false로 설정하면 global.ingress.enabled 설정이 사용됩니다.
tls.enabled 부울 true false로 설정하면 레지스트리 서브차트의 TLS를 비활성화합니다. 이 설정은 주로 Ingress 컨트롤러 앞에서 TLS를 사용할 수 없는 경우에 유용합니다.
tls.secretName 문자열   레지스트리 URL에 대한 유효한 인증서 및 키를 포함하는 Kubernetes TLS Secret의 이름입니다. 설정되지 않은 경우, global.ingress.tls.secretName이 대신 사용됩니다. 기본적으로 설정되지 않습니다.

TLS 구성

컨테이너 레지스트리는 nginx-ingress를 포함한 다른 구성 요소와의 통신을 보호하는 TLS를 지원합니다.

TLS를 구성하려면 사전 조건은 다음과 같습니다:

  • TLS 인증서에는 레지스트리 서비스 호스트 이름(예: RELEASE-registry.default.svc)이 Common Name (CN) 또는 Subject Alternate Name (SAN)에 포함되어 있어야 합니다.
  • TLS 인증서 생성 후:
    • Kubernetes TLS Secret를 생성합니다.
    • TLS 인증서의 CA 인증서만을 포함하는 다른 Secret을 생성하고 ca.crt 키로만 구성합니다.

TLS를 활성화하려면:

  1. registry.tls.enabledtrue로 설정합니다.
  2. global.hosts.registry.protocolhttps로 설정합니다.
  3. Secret 이름을 registry.tls.secretNameglobal.certificates.customCAs에 전달합니다.

registry.tls.verifytrue인 경우 CA 인증서 Secret 이름을 registry.tls.caSecretName에 전달해야 합니다. 이것은 자체 서명된 인증서 및 사용자 정의 인증기관에 필요합니다. 이 Secret은 레지스트리의 TLS 인증서를 확인하기 위해 NGINX에서 사용됩니다.

예시:

global:
  certificates:
    customCAs:
    - secret: registry-tls-ca
  hosts:
    registry:
      protocol: https

registry:
  tls:
    enabled: true
    secretName: registry-tls
    verify: true
    caSecretName: registry-tls-ca

디버그 포트를 위한 TLS 구성

레지스트리 디버그 포트도 TLS를 지원합니다. 디버그 포트는 Kubernetes liveness 및 readiness 확인에 사용되며 (활성화된 경우) Prometheus의 /metrics 엔드포인트를 노출하는 데 사용됩니다.

TLS는 registry.debug.tls.enabledtrue로 설정하여 활성화할 수 있습니다. 디버그 포트의 TLS 구성에 전용 Secret을 지정할 수 있으며, 그때는 registry.debug.tls.secretName에 제공하면 되며, 제공되지 않은 경우 디버그 구성은 레지스트리의 일반 TLS 구성과 공유할 것입니다.

프로메테우스가 https를 사용하여 /metrics/ 엔드포인트를 수집하려면 인증서의 CommonName 속성이나 SubjectAlternativeName 항목에 대한 추가 구성이 필요합니다. 해당 요구 사항은
프로메테우스가 TLS로 활성화된 엔드포인트를 수집하도록 구성을 참조하십시오.

networkpolicy 구성

이 섹션은 레지스트리의 NetworkPolicy를 제어합니다. 이 구성은 선택 사항이며, 레지스트리의 egress 및 Ingress를 특정 엔드포인트로 제한하는 데 사용됩니다.

Name Type Default Description
enabled Boolean false 이 설정은 레지스트리의 NetworkPolicy를 활성화합니다.
ingress.enabled Boolean false true로 설정하면 Ingress 네트워크 정책이 활성화됩니다. 이렇게 하면 규칙이 지정되지 않은 경우 Ingress 연결이 차단됩니다.
ingress.rules Array [] Ingress 정책에 대한 규칙에 대해서는 https://kubernetes.io/docs/concepts/services-networking/network-policies/#the-networkpolicy-resource 및 아래 예시를 참조하십시오.
egress.enabled Boolean false true로 설정하면 Egress 네트워크 정책이 활성화됩니다. 이렇게 하면 규칙이 지정되지 않은 경우 Egress 연결이 차단됩니다.
egress.rules Array [] Egress 정책에 대한 규칙에 대해서는 https://kubernetes.io/docs/concepts/services-networking/network-policies/#the-networkpolicy-resource 및 아래 예시를 참조하십시오.

모든 내부 엔드포인트로의 연결 방지를 위한 정책 예제

레지스트리 서비스는 일반적으로 객체 저장소로의 egress 연결, Docker 클라이언트로부터의 Ingress 연결 및 DNS 조회를 위해 kube-dns를 필요로 합니다. 이는 레지스트리 서비스에 다음과 같은 네트워크 제한사항을 추가합니다:

  • 지역 네트워크에 대한 모든 egress 요청은 10.0.0.0/8의 53 포트가 허용됩니다 (kubeDNS를 위해).
  • 다른 10.0.0.0/8의 지역 네트워크로의 egress 요청은 제한됩니다.
  • 10.0.0.0/8 외부의 egress 요청은 허용됩니다.

레지스트리 서비스는 외부 객체 저장소에 있는 이미지를 위해 공개 인터넷에 대한 외부 연결성이 필요합니다.

networkpolicy:
  enabled: true
  egress:
    enabled: true
    # 다음 규칙은 로컬 네트워크를 제외한 모든 외부 엔드포인트로의 트래픽을 허용합니다.
    # (DNS 요청을 제외한) 로컬 네트워크로의 egress 트래픽을 허용합니다
    rules:
      - to:
        - ipBlock:
            cidr: 10.0.0.0/8
        ports:
        - port: 53
          protocol: UDP
      - to:
        - ipBlock:
            cidr: 0.0.0.0/0
            except:
            - 10.0.0.0/8

KEDA 구성

keda 섹션은 일반 HorizontalPodAutoscalers 대신에 KEDA ScaledObjects를 설치하는 것을 가능하게 합니다.
이 구성은 선택적이며 필요에 따라 사용할 수 있으며 사용자 지정 또는 외부 지표에 기반한 자동 스케일링이 필요할 때 사용할 수 있습니다.

대부분의 설정은 해당되는 경우 hpa 섹션에 설정된 값으로 기본값으로 설정됩니다.

다음이 참이면 CPU 및 메모리 트리거는 자동으로 추가됩니다. 이는 triggers가 설정되지 않을 때, 해당하는 request.cpu.request 또는 request.memory.request 설정도 0이 아닌 값으로 설정되어 있는 경우입니다.

  • triggers가 설정되지 않음.
  • 해당하는 request.cpu.request 또는 request.memory.request 설정도 0이 아닌 값으로 설정되어 있음.

트리거가 설정되지 않으면 ScaledObject가 생성되지 않습니다.

더 많은 정보를 보려면 KEDA 문서를 참조하세요.

이름 유형 기본값 설명
enabled 부울 false KEDA ScaledObjects 대신 HorizontalPodAutoscalers 사용
pollingInterval 정수 30 각 트리거를 확인하는 간격
cooldownPeriod 정수 300 스케일링 된 리소스를 다시 0으로 축소하기 전에 마지막 트리거가 활성화된 후 대기해야 하는 기간
minReplicaCount 정수   KEDA가 리소스를 축소할 최소 레플리카 수, 기본값은 hpa.minReplicas로 설정됨
maxReplicaCount 정수   KEDA가 리소스를 확장할 최대 레플리카 수, 기본값은 hpa.maxReplicas로 설정됨
fallback   KEDA 후행 설정, 문서 참조
hpaName 문자열   KEDA가 생성할 HPA 리소스의 이름, 기본값은 keda-hpa-{scaled-object-name}로 설정됨
restoreToOriginalReplicaCount 부울   ScaledObject가 삭제된 후 대상 리소스를 원래의 레플리카 수로 축소해야 하는지 여부를 지정
behavior   업-스케일링 및 다운-스케일링 동작에 대한 사양, 기본값은 hpa.behavior로 설정됨
triggers 배열   대상 리소스의 스케일링을 활성화하기 위한 트리거 목록, 기본값은 hpa.cpuhpa.memory에서 계산된 트리거 목록으로 설정됨

내부 엔드포인트로의 연결 방지를 위한 예제 정책

레지스트리 서비스는 일반적으로 객체 스토리지에 대한 아웃바운드 연결, Docker 클라이언트로부터의 인바운드 연결 및 DNS 조회를 위해 kube-dns를 필요로 합니다. 이는 레지스트리 서비스에 다음과 같은 네트워크 제한을 추가합니다:

  • 10.0.0.0/8 포트 53의 로컬 네트워크로의 아웃바운드 요청은 모두 허용됩니다 (kubeDNS를 위한)
  • 다른 10.0.0.0/8로의 로컬 네트워크 아웃바운드 요청은 제한됩니다
  • 10.0.0.0/8 외부로의 아웃바운드 요청은 모두 허용됩니다

레지스트리 서비스는 외부 객체 스토리지의 이미지를 위해 공개 인터넷으로의 아웃바운드 연결이 필요합니다

networkpolicy:
  enabled: true
  egress:
    enabled: true
    # 다음 규칙은 로컬 네트워크 이외 모든 외부 엔드포인트로의 트래픽을 허용하나
    # 로컬 네트워크(단, DNS 요청은 예외)로의 트래픽은 금지함
    rules:
      - to:
        - ipBlock:
            cidr: 10.0.0.0/8
        ports:
        - port: 53
          protocol: UDP
      - to:
        - ipBlock:
            cidr: 0.0.0.0/0
            except:
            - 10.0.0.0/8

레지스트리 구성 정의

이 차트의 다음 속성은 기본 레지스트리 컨테이너의 구성과 관련이 있습니다. GitLab과의 통합을 위해 가장 중요한 값만 노출됩니다. 이 통합에서 Docker Distributionauth.token.x 설정을 사용하여 레지스트리로의 JWT 인증 토큰을 통제합니다.

httpSecret

httpSecret 필드는 secretkey 두 항목을 포함하는 맵입니다.

이 항목이 참조하는 키 내용은 레지스트리http.secret 값에 상응합니다. 이 값은 암호학적으로 생성된 랜덤한 문자열로 채워져야 합니다.

수동으로 이 시크릿을 생성하려면:

kubectl create secret generic gitlab-registry-httpsecret --from-literal=secret=strongrandomstring

알림 비밀

알림 비밀은 다양한 방법으로 GitLab 애플리케이션에 다시 호출하는 데 사용됩니다. 주요 사이트 간에 Container Registry 데이터를 동기화하는 데 도움을 주는 Geo와 같은 경우입니다.

shared-secrets 기능이 활성화되면 notificationSecret 비밀 객체가 자동으로 생성됩니다.

이 비밀을 수동으로 만들려면:

kubectl create secret generic gitlab-registry-notification --from-literal=secret=[\"strongrandomstring\"]

그런 다음 다음을 설정하십시오.

global:
  # 자체 비밀을 제공하려면
  registry:
    notificationSecret:
        secret: gitlab-registry-notification
        key: secret

  # Geo를 활용하고 컨테이너 레지스트리를 동기화하려는 경우
  # 이것은 주 사이트 구성에서만 정의하십시오.
  geo:
    registry:
      replication:
        enabled: true
        primaryApiUrl: <기본 레지스트리의 URL>

secret 값이 위에서 만든 비밀 이름으로 설정되었는지 확인하십시오.

Redis 캐시 비밀

global.redis.auth.enabledtrue로 설정된 경우 Redis 캐시 비밀이 사용됩니다.

shared-secrets 기능이 활성화되면 제공되지 않은 경우 gitlab-redis-secret 비밀 객체가 자동으로 생성됩니다.

이 비밀을 수동으로 만들려면 Redis 암호 지침을 참조하십시오.

authEndpoint

authEndpoint 필드는 레지스트리가 인증될 GitLab 인스턴스의 URL을 제공하는 문자열입니다.

값은 프로토콜 및 호스트 이름만 포함해야 합니다. 차트 템플릿은 필요한 요청 경로를 자동으로 추가합니다. 결과 값은 컨테이너 내부의 auth.token.realm에 채워질 것입니다. 예: authEndpoint: "https://gitlab.example.com"

기본적으로 이 필드는 글로벌 설정에서 설정된 GitLab 호스트 이름 구성으로 채워집니다.

certificate

certificate 필드는 secretkey 두 항목을 포함하는 맵입니다.

secret는 GitLab 인스턴스에서 생성된 토큰을 확인하는 데 사용되는 인증서 번들을 포함하는 Kubernetes Secret의 이름을 포함하는 문자열입니다.

keysecret 내의 key의 이름으로, 레지스트리 컨테이너 내에서 auth.token.rootcertbundle로 제공될 인증서 번들을 포함하는 것입니다.

기본 예제:

certificate:
  secret: gitlab-registry
  key: registry-auth.crt

준비 및 살아있음 프로브

기본적으로 /debug/health 포트 5001에서 준비 및 살아있음 프로브가 구성되어 있습니다.

validation

validation 필드는 레지스트리에서 도커 이미지 유효성 검증 프로세스를 제어하는 맵입니다. 이미지 유효성 검사가 활성화된 경우, 레지스트리는 외부 레이어가 있는 Windows 이미지를 거부합니다. manifests.urls.allow 필드가 해당 레이어 URL을 허용하도록 명시적으로 설정되지 않는 한입니다.

이 섹션의 값이 변경되더라도 이미지 유효성 검증은 매니페스트 푸시 중에만 발생하므로 레지스트리에 이미 존재하는 이미지에는 영향을 미치지 않습니다.

이미지 유효성 검증은 기본적으로 비활성화되어 있습니다.

이미지 유효성 검증을 활성화하려면 명시적으로 registry.validation.disabled: false를 설정해야 합니다.

manifests

manifests 필드를 사용하여 매니페스트에 특정한 유효성 검사 정책을 구성할 수 있습니다.

urls 섹션에는 allowdeny 필드가 포함되어 있습니다. 유효성 검사를 통과하는 URL을 포함하는 매니페스트 레이어에 대해, 해당 레이어는 allow 필드의 정규 표현 중 하나와 일치해야 하고, deny 필드의 정규 표현과 일치하지 않아야 합니다.

이름 유형 기본값 설명
referencelimit Int 0 단일 매니페스트가 가질 수 있는 참조(레이어, 이미지 구성 및 기타 매니페스트 포함)의 최대 수. 0으로 설정하면(기본값) 이 유효성 검증이 비활성화됩니다.
payloadsizelimit Int 0 매니페스트 페이로드의 최대 데이터 크기(바이트). 0으로 설정하면(기본값) 이 유효성 검증이 비활성화됩니다.
urls.allow Array [] 매니페스트 레이어의 URL을 활성화하는 정규 표현 목록입니다. 비어 있으면(기본값) 모든 URL을 포함하는 레이어가 거부됩니다.
urls.deny Array [] 매니페스트 레이어의 URL을 제한하는 정규 표현 목록입니다. 비어 있으면(기본값) urls.allow 목록을 통과한 URL을 포함하는 레이어가 거부되지 않습니다.

알림

notifications 필드는 레지스트리 알림을 구성하는 데 사용됩니다. 기본 값은 비어 있는 해시입니다.

이름 유형 기본값 설명
endpoints Array [] 각 항목이 endpoint에 해당하는 항목의 목록입니다.
events 해시 {} 이벤트 알림에서 제공된 정보

다음과 같이 예제 설정은 다음과 같을 것입니다.

notifications:
  endpoints:
    - name: FooListener
      url: https://foolistener.com/event
      timeout: 500ms
      threshold: 10
      backoff: 1s
    - name: BarListener
      url: https://barlistener.com/event
      timeout: 100ms
      threshold: 3
      backoff: 1s
  events:
    includereferences: true

hpa

hpa 필드는 레지스트리 인스턴스의 수를 제어하는 객체로, 세트의 일부로 생성됩니다. 이는 기본적으로 minReplicas 값이 2, maxReplicas 값이 10으로 설정되어 있으며, cpu.targetAverageUtilization이 75%로 구성되어 있습니다.

storage

storage:
  secret:
  key: config
  extraKey:

storage 필드는 Kubernetes Secret 및 관련 키에 대한 참조입니다. 이 시크릿의 내용은 레지스트리 구성: storage에서 직접 가져옵니다. 자세한 내용은 해당 문서를 참조하십시오.

AWS S3 및 Google GCS 드라이버에 대한 예제는 examples/objectstorage에서 찾을 수 있습니다.

S3의 경우, 올바른 레지스트리 스토리지 권한을 제공해야 합니다. 스토리지 구성에 대한 자세한 내용은 관리 문서의 컨테이너 레지스트리 스토리지 드라이버를 참조하십시오.

storage 블록의 내용을 시크릿에 넣고, 다음을 storage 맵의 항목으로 제공하십시오:

  • secret: YAML 블록을 보관하는 Kubernetes Secret의 이름.
  • key: 시크릿에서 사용할 키의 이름. 기본값은 config입니다.
  • extraKey: (선택사항) 컨테이너 내의 /etc/docker/registry/storage/${extraKey}에 마운트될 추가 키의 이름입니다. 이는 gcs 드라이버의 keyfile을 제공하는 데 사용할 수 있습니다.
# S3 사용 예시
kubectl create secret generic registry-storage \
    --from-file=config=registry-storage.yaml

# JSON 키를 사용한 GCS 사용 예시
# - 참고: `registry.storage.extraKey=gcs.json`
kubectl create secret generic registry-storage \
    --from-file=config=registry-storage.yaml \
    --from-file=gcs.json=example-project-382839-gcs-bucket.json

스토리지 드라이버에 대한 리디렉션을 비활성화하여 모든 트래픽이 다른 백엔드로 리디렉션되지 않고 레지스트리 서비스로 흐르도록 하려면:

storage:
  secret: example-secret
  key: config
  redirect:
    disable: true

filesystem 드라이버를 사용하는 경우:

  • 이 데이터에 대한 지속적인 볼륨을 제공해야 합니다.
  • hpa.minReplicas1로 설정해야 합니다.
  • hpa.maxReplicas1로 설정해야 합니다.

탄력성과 간편함을 위해 s3, gcs, azure 또는 기타 호환되는 객체 스토리지를 활용하는 것이 권장됩니다.

참고: 사용자가 지정하지 않은 경우 차트는 이 구성에 delete.enabled: true를 자동으로 채웁니다. 이는 MinIO의 기본 사용과 Linux 패키지의 기본 동작을 유지하기 위해입니다. 사용자가 제공하는 값이 이 기본값을 덮어씁니다.

middleware.storage

middleware.storage의 구성은 상위 규칙을 따릅니다.

구성은 상당히 일반적이며 유사한 패턴을 따릅니다:

middleware:
  # https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs/configuration.md#middleware 참조
  storage:
    - name: cloudfront
      options:
        baseurl: https://abcdefghijklmn.cloudfront.net/
        # `privatekey`는 `privatekey` 시크릿의 내용이 자동으로 채워집니다.
        privatekeySecret:
          secret: cloudfront-secret-name
          # "key" 값은 PEM 스토리지의 파일 이름을 생성하는 데 사용됩니다:
          #   /etc/docker/registry/middleware.storage/<index>/<key>
          key: private-key-ABC.pem
        keypairid: ABCEDFGHIJKLMNOPQRST

위 코드에서 options.privatekeySecret은 PEM 파일 내용에 해당하는 generic Kubernetes 시크릿의 내용입니다:

kubectl create secret generic cloudfront-secret-name --type=kubernetes.io/ssh-auth --from-file=private-key-ABC.pem=pk-ABCEDFGHIJKLMNOPQRST.pem

상위에서 사용된 privatekey는 차트가 시크릿에서 자동으로 채우며, 사용자가 지정한 경우 무시됩니다.

keypairid 변형

다양한 공급업체는 동일한 구조를 위한 다른 필드 이름을 사용합니다:

Vendor 필드 이름
Google CDN keyname
CloudFront keypairid

참고: 현재는 middleware.storage 섹션의 구성만 지원됩니다.

디버그

디버그 포트는 기본적으로 활성화되며 라이브/준비 여부 프로브에 사용됩니다. 추가로, 프로메테우스 메트릭은 metrics 값을 통해 활성화할 수 있습니다.

debug:
  addr:
    port: 5001

metrics:
  enabled: true

헬스

health 속성은 선택 사항이며 스토리지 드라이버의 백엔드 스토리지에 대한 주기적인 헬스 체크에 대한 환경 설정을 포함합니다. 더 많은 세부 정보는 Docker의 구성 문서에서 확인하세요.

health:
  storagedriver:
    enabled: false
    interval: 10s
    threshold: 3

보고

reporting 속성은 선택 사항으로 보고를 활성화합니다.

reporting:
  sentry:
    enabled: true
    dsn: 'https://<key>@sentry.io/<project>'
    environment: 'production'

프로파일링

profiling 속성은 선택 사항으로 지속적인 프로파일링을 활성화합니다.

profiling:
  stackdriver:
    enabled: true
    credentials:
      secret: gitlab-registry-profiling-creds
      key: credentials
    service: gitlab-registry

데이터베이스

세부 정보: 상태: Beta

database 속성은 선택 사항으로 메타데이터 데이터베이스를 활성화합니다.

이것은 베타 기능입니다. 이 기능을 활성화하기 전에 해당 기능에 대한 피드백 이슈와 관련 문서를 확인하세요.

참고: 이 기능은 PostgreSQL 12 이상이 필요합니다.

database:
  enabled: true
  host: registry.db.example.com
  port: 5432
  user: registry
  password:
    secret: gitlab-postgresql-password
    key: postgresql-registry-password
  dbname: registry
  sslmode: verify-full
  ssl:
    secret: gitlab-registry-postgresql-ssl
    clientKey: client-key.pem
    clientCertificate: client-cert.pem
    serverCA: server-ca.pem
  connecttimeout: 5s
  draintimeout: 2m
  preparedstatements: false
  primary: 'primary.record.fqdn'
  pool:
    maxidle: 25
    maxopen: 25
    maxlifetime: 5m
    maxidletime: 5m
  migrations:
    enabled: true
    activeDeadlineSeconds: 3600
    backoffLimit: 6

데이터베이스 관리

데이터베이스를 생성하는 방법에 대한 자세한 내용은 컨테이너 레지스트리 메타데이터 데이터베이스 페이지를 참조하세요.

gc 속성

gc 속성은 온라인 가비지 수집 옵션을 제공합니다.

참고: 온라인 가비지 수집은 16.4 버전부터의 베타 기능입니다. 이 기능을 활성화하기 전에 해당 기능에 대한 피드백 이슈와 관련 문서를 확인하세요.

온라인 가비지 수집은 메타데이터 데이터베이스의 활성화가 필요합니다. 데이터베이스를 사용할 때 온라인 가비지 수집을 사용해야 하지만 유지 보수 및 디버깅을 위해 일시적으로 온라인 가비지 수집을 비활성화할 수 있습니다.

gc:
  disabled: false
  maxbackoff: 24h
  noidlebackoff: false
  transactiontimeout: 10s
  reviewafter: 24h
  manifests:
    disabled: false
    interval: 5s
  blobs:
    disabled: false
    interval: 5s
    storagetimeout: 5s

Redis 캐시

참고: Redis 캐시는 16.4 버전 이후의 베타 기능입니다. 이 기능을 활성화하기 전에 해당 기능에 대한 피드백 이슈와 관련 문서를 확인하세요.

redis.cache 속성은 선택 사항으로 Redis 캐시에 관한 옵션을 제공합니다. 레지스트리에서 redis.cache를 사용하려면 메타데이터 데이터베이스를 활성화해야 합니다.

예시:

redis:
  cache:
    enabled: true
    host: localhost
    port: 16379
    password:
      secret: gitlab-redis-secret
      key: redis-password
    db: 0
    dialtimeout: 10ms
    readtimeout: 10ms
    writetimeout: 10ms
    tls:
      enabled: true
      insecure: true
    pool:
      size: 10
      maxlifetime: 1h
      idletimeout: 300s

Sentinels

redis.cacheglobal.redis.sentinels 구성을 사용할 수 있습니다. 로컬 값이 제공되고 전역 값보다 우선시됩니다. 예를 들면:

redis:
  cache:
    enabled: true
    host: redis.example.com
    sentinels:
      - host: sentinel1.example.com
        port: 16379
      - host: sentinel2.example.com
        port: 16379

가비지 수집

Docker 레지스트리는 시간이 지남에 따라 불필요한 데이터가 축적되어 가비지 수집을 사용하여 해제할 수 있습니다. 현재(지금)은이 차트를 사용하여 가비지 수집을 자동으로 실행하거나 예약하는 방법이 없습니다.

경고: 온라인 가비지 수집을 메타데이터 데이터베이스(#database)와 함께 사용해야 합니다. 메타데이터 데이터베이스에 수동으로 가비지 수집을 사용하면 데이터 손실이 발생합니다. 온라인 가비지 수집은 수동으로 가비지 수집을 실행할 필요를 완전히 제거합니다.

수동 가비지 수집

수동 가비지 수집에는 레지스트리가 먼저 읽기 전용 모드 여야합니다. Helm을 사용하여 이미 GitLab 차트를 설치했고mygitlab이름을 지정하고gitlabns네임 스페이스에 설치했다고 가정해 봅시다. 다음은 실제 구성에 따라 아래 명령어의 값들을 대체하세요.

# https://github.com/helm/helm/issues/2948 때문에 --reuse-values에 의존할 수 없기 때문에(helm이 이슈가 올 때까지 여기에있다.) 현재의 구성을 가져오겠습니다.
helm get values mygitlab > mygitlab.yml
# Helm 설치를 업그레이드하고 레지스트리를 읽기 전용으로 구성합니다.
# --wait 매개 변수는 모든 리소스가 준비 상태에 있을 때까지 기다리도록하여 안전하게 계속할 수 있습니다.
helm upgrade mygitlab gitlab/gitlab -f mygitlab.yml --set registry.maintenance.readonly.enabled=true --wait
# 우리의 레지스트리는 현재 r/o 모드입니다. 따라서 레지스트리 Pod 중 하나의 이름을 얻어야 합니다.
# 아래의 '<registry-pod>' placeholder를 그 값으로 대체하세요.
# 이 값을 Windows' cmd.exe에서 사용하는 경우 단일 인용 부호를 이중 인용 부호로 변경하세요 (' -> ")
kubectl get pods -n gitlabns -l app=registry -o jsonpath='{.items[0].metadata.name}'
# 실제 가비지 수집 실행. 실제로 '-m' 매개 변수를 원할 경우 레지스트리 메뉴얼을 확인하세요.
kubectl exec -n gitlabns <registry-pod> -- /bin/registry garbage-collect -m /etc/docker/registry/config.yml
# 레지스트리를 원래 상태로 재설정합니다.
helm upgrade mygitlab gitlab/gitlab -f mygitlab.yml --wait
# 모든 작업이 완료되었습니다 :)

컨테이너 레지스트리에 대한 관리 명령 실행

관리 명령은 registry 바이너리 및 필요한 구성이 모두 사용 가능한 레지스트리 Pod에서만 실행할 수 있습니다. Issue #2629는 도구 상자 Pod에서 이 기능을 제공하는 방법에 대해 논의하기 위한 것입니다.

관리 명령을 실행하려면:

  1. 레지스트리 Pod에 연결합니다.

    kubectl exec -it <registry-pod> -- bash
    
  2. 레지스트리 Pod 내부에 들어간 후에registry 바이너리는 ‘PATH’에 사용 가능하고 직접 사용할 수 있습니다. 구성 파일은/etc/docker/registry/config.yml에서 사용할 수 있습니다. 다음 예는 데이터베이스 마이그레이션 상태를 확인합니다.

    registry database migrate status /etc/docker/registry/config.yml
    

자세한 내용 및 다른 사용 가능한 명령어에 대해서는 관련 문서를 참조하세요: