본문 바로가기
문서 목차
ORKESTRIX설치

컨테이너 이미지 레지스트리 (Harbor / Nexus)

보안 취약점 스캐닝 및 이미지 서명을 지원하는 기업 전용 컨테이너 이미지 레지스트리 를 구성합니다.

QUANTUM C&S

보안 취약점 스캐닝 및 이미지 서명을 지원하는 기업 전용 컨테이너 이미지 레지스트리를 구성합니다.

레지스트리 선택 (택 1)

A. Harbor (기본값)
qks_harbor_enabled: true — 취약점 스캐닝(Trivy)/이미지 서명(Cosign) 내장. 검증 완료.
B. Nexus
qks_nexus_enabled: true + qks_nexus_proxy_enabled: true — 범용 아티팩트 저장소(Docker/Maven/npm 등 다목적), Docker 레지스트리 기능만 사용. 검증 진행 중.

inventory/qks/group_vars/all/all-k8s.yaml에서 원하는 쪽을 활성화한 뒤, 아래 A/B 중 그 옵션에 해당하는 섹션만 읽고 진행하면 됩니다.

Nexus Repository OSS(무료판)는 취약점 스캐닝 · 이미지 서명 기능이 없습니다(Sonatype Nexus IQ 유료 제품의 기능). 체크리스트 문구는 Harbor 기준으로 작성된 것이며, Nexus는 "대안 컨테이너 레지스트리"로서만 검증된 것입니다.

A. Harbor

보안 취약점 스캐닝(Trivy) 및 이미지 서명(Cosign) 내장. 검증 완료.

설정값

inventory/qks/group_vars/all/all-k8s.yaml:

qks_harbor_enabled: true
qks_harbor_version: 1.19.2
qks_harbor_app_version: 2.15.2
qks_harbor_release: qks-harbor
qks_harbor_namespace: qks-harbor
qks_harbor_fqdn_core: "registry.{{ kube_default_domain }}"
qks_harbor_pass: "{{ kube_default_passwd }}"
qks_harbor_project: qks
qks_harbor_registry_storage_type: s3   # s3 / filesystem
qks_harbor_database_type: internal     # internal / external

실행

./install.sh ubuntu plays/qks-harbor.yaml

설치 흐름

./install.sh ubuntu plays/qks-harbor.yaml
  ├─ 1. 접속 도메인을 각 노드 /etc/hosts에 등록
  ├─ 2. Helm 저장소 등록 ('harbor')
  ├─ 3. (S3 스토리지 사용 시) 클러스터 CA 인증서를 Secret으로 생성 (caBundleSecretName)
  ├─ 4. Helm으로 Harbor 배포 (core+portal+registry+jobservice+database+redis+trivy)
  ├─ 5. (S3 스토리지 사용 시) registry/core 배포에 S3 엔드포인트 hostAlias 패치
  ├─ 6. Ingress에 Traefik 어노테이션 패치
  ├─ 7. (내장 DB 사용 시) DB Service를 NodePort로 패치
  └─ 8. 기본 프로젝트('qks') 생성

설치 확인

kubectl get pods -n <qks_harbor_namespace>

qks-harbor-core · qks-harbor-portal · qks-harbor-registry(2replica) · qks-harbor-jobservice · qks-harbor-database · qks-harbor-redis · qks-harbor-trivy 파드가 모두 Running이어야 합니다.

실제 동작 확인

웹 접속:

curl -k -s -o /dev/null -w "%{http_code}\n" https://<qks_harbor_fqdn_core>/

200이 나오면 정상입니다.

이미지 push (crane 등 OCI 표준 클라이언트 사용):

crane auth login <qks_harbor_fqdn_core> -u admin -p <qks_harbor_pass>
crane copy <원본 이미지> <qks_harbor_fqdn_core>/<qks_harbor_project>/<이미지명>:<태그>

push가 성공하면 정상입니다.

보안 취약점 스캐닝(Trivy):

curl -k -s -u "admin:<qks_harbor_pass>" -X POST \
  "https://<qks_harbor_fqdn_core>/api/v2.0/projects/<프로젝트>/repositories/<이미지명>/artifacts/<태그>/scan"
curl -k -s -u "admin:<qks_harbor_pass>" \
  "https://<qks_harbor_fqdn_core>/api/v2.0/projects/<프로젝트>/repositories/<이미지명>/artifacts/<태그>?with_scan_overview=true"

scan_overview의 scan_status가 Success이고 severity/summary에 실제 취약점 통계가 나오면 정상입니다.

이미지 서명(Cosign):

cosign generate-key-pair
cosign sign --key cosign.key <qks_harbor_fqdn_core>/<프로젝트>/<이미지명>@<digest>
cosign verify --key cosign.pub <qks_harbor_fqdn_core>/<프로젝트>/<이미지명>@<digest>
curl -k -s -u "admin:<qks_harbor_pass>" \
  "https://<qks_harbor_fqdn_core>/api/v2.0/projects/<프로젝트>/repositories/<이미지명>/artifacts/<태그>/accessories"

cosign verify가 서명 검증에 성공하고, accessories 조회 결과에 type: "signature.cosign" 항목이 있으면 정상입니다.


B. Nexus

Sonatype Nexus Repository — Docker 외에도 PyPI/npm(Raw)/APT/Conda/R 등 다양한 패키지 생태계를 하나의 저장소로 통합 관리할 수 있는 범용 아티팩트 저장소입니다. 이 문서는 체크리스트 요구사항인 Docker 레지스트리 기능 기준으로 검증합니다.

설정값

inventory/qks/group_vars/all/all-k8s.yaml:

qks_nexus_enabled: true
qks_nexus_proxy_enabled: true   # Docker 레지스트리(프록시/호스티드/그룹 레포) 기능 활성화 — 이게 꺼지면 UI만 뜨고 레지스트리 기능은 전혀 설정되지 않음
qks_nexus_version: 64.2.0       # Helm 차트 버전
qks_nexus_app_version: 3.96.3   # Nexus 앱(이미지 태그) 버전
qks_nexus_fqdn: "nexus.{{ kube_default_domain }}"
qks_nexus_push_fqdn: "push.{{ kube_default_domain }}"
qks_nexus_storage_type: s3      # s3 / filesystem
qks_nexus_storage_class: "{{ qks_block_storage_class_name }}"   # PVC용 StorageClass(보통 Ceph) — Nexus 자체 데이터 저장용이며 storage_type과 별개
Ceph 등 블록 스토리지가 없는 환경(예: 스토리지 단계를 건너뛴 테스트 클러스터)에서는 qks_nexus_storage_class를 Local Path 프로비저너(GS 2.5)의 StorageClass로 임시 지정할 수 있습니다. 이건 PVC가 바인딩될 StorageClass가 반드시 존재해야 하기 때문이며, 정상적인 배포에서는 별도 지정 없이 기본값(Ceph)이 그대로 사용됩니다.

실행

./install.sh ubuntu plays/qks-nexus.yaml

설치 흐름

./install.sh ubuntu plays/qks-nexus.yaml
  ├─ 1. 접속 도메인을 각 노드 /etc/hosts에 등록
  ├─ 2. Helm 저장소 등록 ('sonatype')
  ├─ 3. Helm으로 Nexus 배포
  └─ 4. (qks_nexus_proxy_enabled=true인 경우) 프록시 초기 설정
       ├─ Service에 Docker용 포트(8181=프록시, 8182=push용 호스티드) 추가
       ├─ 초기 admin 비밀번호 확인 후 관리 비밀번호로 변경
       ├─ EULA 동의, 익명 접속 활성화
       ├─ PyPI/R/Conda/APT/Raw 프록시 · 호스티드 · 그룹 레포 생성
       ├─ Docker 프록시(외부 레지스트리 미러)/호스티드(사내 이미지 push용)/그룹 레포 생성
       └─ DockerToken 인증 Realm 활성화

설치 확인

kubectl get pods -n <qks_nexus_namespace> -l app.kubernetes.io/name=nexus-repository-manager
kubectl get pvc -n <qks_nexus_namespace> | grep nexus

qks-nexus 파드가 Running, PVC가 Bound 상태여야 합니다.

실제 동작 확인

API 헬스체크:

NEXUS_IP=$(kubectl get svc qks-nexus -n <qks_nexus_namespace> -o jsonpath='{.spec.clusterIP}')
curl -su admin:<qks_nexus_admin_pass> http://$NEXUS_IP:8081/service/rest/v1/system/eula
curl -su admin:<qks_nexus_admin_pass> http://$NEXUS_IP:8081/service/rest/v1/security/anonymous
curl -su admin:<qks_nexus_admin_pass> http://$NEXUS_IP:8081/service/rest/v1/security/realms/active

"accepted":true(EULA), "enabled":true(익명 접속), 응답에 DockerToken이 포함(Realm)되면 정상입니다.

이미지 push/pull (Docker 호스티드 레포를 통해):

docker login <qks_nexus_push_fqdn> -u admin -p <qks_nexus_admin_pass>
docker tag <원본 이미지> <qks_nexus_push_fqdn>/<이미지명>:<태그>
docker push <qks_nexus_push_fqdn>/<이미지명>:<태그>
docker pull <qks_nexus_push_fqdn>/<이미지명>:<태그>

push/pull이 모두 성공하면 정상입니다.

다음 단계