Harbor 설치 가이드
1. 개요
본 문서는 gitops 저장소의 /harbor 디렉터리 구조를 기반으로 Harbor 이미지 레지스트리를 설치하는 전체 과정을 안내합니다. Kustomize를 사용하여 환경별 설정을 관리하고, Makefile을 이용한 배포 자동화 방법을 다룹니다.
2. 사전 요구사항
- Kubernetes 클러스터: v1.30 이상
- 로컬 도구: kubectl, kustomize, helm 설치 완료
- 인증서:
cert-manager를 통한 TLS 인증서 발급 및 네임스페이스 간 복제 구성 준비 - DNS 등록: harbor.cnapcloud.com
- Keycloak Client 설정: harbor client 생성
3. 디렉터리 구조 및 역할
Makefile:apply,delete,preview등 배포 자동화 스크립트.kustomize/base/: 모든 환경에 공통으로 적용될 리소스 및 원본 Helm Chart.kustomize/overlays/dev/:dev환경을 위한 설정.helm/values.yaml:dev환경에 특화된 Harbor 설정 (도메인, Ingress, 스토리지, 인증 등).
4. 설치 단계 (기본 설치)
4.1. values.yaml 커스터마이징
kustomize/overlays/dev/helm/values.yaml 파일을 열어 Harbor의 기본 설정을 수정합니다. (OIDC 설정은 이 단계에서 제외합니다.)
4.1.1. 도메인 및 Ingress 설정
expose:
type: ingress
tls:
enabled: true
certSource: secret
secret:
secretName: cnapcloud.com-tls # cert-manager가 생성한 TLS Secret 이름
ingress:
hosts:
core: harbor.cnapcloud.com # Harbor에 접속할 도메인
notary: notary.harbor.cnapcloud.com
ingressClassName: nginx
4.1.2. 관리자 비밀번호 설정
Harbor UI에 로그인할 admin 계정의 초기 비밀번호를 설정합니다.
harborAdminPassword: <your-secure-password>
보안 경고: 이 값을 직접 입력하는 대신, Kubernetes Secret을 생성하고
existingSecret옵션을 사용하는 것을 강력히 권장합니다.
4.1.3. 스토리지 설정
persistence:
enabled: true
resourcePolicy: "keep"
persistentVolumeClaim:
registry:
storageClass: <your-storage-class>
size: 50Gi
# ... 기타 컴포넌트 스토리지 설정
S3 스토리지 사용 예제
S3와 같은 오브젝트 스토리지를 이미지 저장소로 사용할 수 있습니다. 그러나 Registry 컨테이너는 로컬 디스크를 사용하여 임시 작업을 수행하므로 PVC도 필요합니다. 다음은 AWS S3를 사용하는 예제입니다:
persistence:
enabled: true
persistentVolumeClaim:
registry:
storageClass: <your-storage-class>
size: 5Gi # 최소 용량 권장
# ... 기타 컴포넌트 스토리지 설정
imageChartStorage:
type: s3
s3:
region: us-west-1
bucket: my-harbor-bucket
accesskey: <your-access-key>
secretkey: <your-secret-key>
regionendpoint: https://s3.us-west-1.amazonaws.com
encrypt: false
secure: true
v4auth: true
chunksize: 5242880
참고: S3를 사용할 경우에도 Registry PVC는 필요합니다. Registry는 로컬 디스크를 사용하여 업로드 중 임시 layer, pull/push 중 staging 파일, 내부 작업 디렉터리 (/var/lib/registry), atomic write 처리를 수행합니다. 이러한 작업은 S3로 대체할 수 없습니다. PVC 용량은 최소 5GB를 권장합니다. accesskey와 secretkey는 Kubernetes Secret으로 관리하는 것을 권장합니다.
4.2. 배포 프로세스 (Makefile 활용)
Step 1: Namespace 생성
kubectl create namespace harbor || true
Step 2: 배포 미리보기 (권장)
make preview DEPLOY_ENV=dev
Step 3: 배포 실행
make apply DEPLOY_ENV=dev
5. 설치 후 검증 (기본 설치)
- 리소스 상태 확인:
kubectl get pods,svc,ingress,pvc -n harbor- 모든 Pod이
Running상태이고, PVC가Bound상태인지 확인합니다.
- 모든 Pod이
- 웹 UI 접속: 브라우저에서
https://harbor.cnapcloud.com에 접속합니다. - 관리자 로그인:
admin계정과values.yaml에서 설정한 비밀번호로 로그인이 되는지 확인합니다.
6. 설치 후 구성: Keycloak OIDC 연동 (SSO)
Harbor 기본 설치가 완료된 후, SSO를 위해 Harbor UI에서 Keycloak 연동을 설정합니다.
6.1. Keycloak에서 OIDC 클라이언트 생성
- Keycloak 관리 콘솔에 접속하여 원하는 Realm을 선택합니다.
- Clients 메뉴로 이동하여 Create client를 클릭합니다.
- 다음 정보를 입력하여 클라이언트를 생성합니다.
- Client ID:
harbor - Name:
Harbor - Client authentication:
On - Valid redirect URIs:
https://harbor.cnapcloud.com/c/oidc/callback
- Client ID:
- 생성된 클라이언트의 Credentials 탭으로 이동하여 Client secret을 복사합니다.
6.2. Harbor UI에서 OIDC 설정
- Harbor UI(
https://harbor.cnapcloud.com)에admin계정으로 로그인합니다. - 왼쪽 메뉴에서 Configuration으로 이동한 후 Authentication 탭을 선택합니다.
- Auth Mode를
OIDC로 변경합니다. - 다음과 같이 Keycloak OIDC 제공자 정보를 입력합니다.
- OIDC Provider Name:
Keycloak(또는 원하는 이름) - OIDC Provider Endpoint:
https://keycloak.cnapcloud.com/realms/cnap - OIDC Client ID:
harbor - OIDC Client Secret:
6.1단계에서 복사한 Client Secret - OIDC Scope:
openid,profile,email,groups - Group Claim Name:
groups - Verify Certificate: 체크 활성화 (인증서가 유효한 경우)
- OIDC Provider Name:
- TEST OIDC SERVER 버튼을 클릭하여 연결을 테스트합니다.
- 테스트가 성공하면 SAVE 버튼을 눌러 설정을 저장합니다.
6.3. OIDC 로그인 검증
- Harbor UI에서 로그아웃한 후 다시 로그인 페이지에 접속합니다.
- 로그인 화면에 “LOGIN VIA OIDC PROVIDER” 버튼이 나타나는지 확인합니다.
- 버튼을 클릭하여 Keycloak 로그인 페이지로 이동하는지, 그리고 로그인 후 Harbor로 정상적으로 리디렉션되는지 확인합니다.
6.4. OIDC 그룹을 이용한 권한 관리
OIDC를 통해 로그인한 사용자는 Keycloak의 그룹 멤버십을 기반으로 Harbor 프로젝트에 대한 권한을 자동으로 부여받을 수 있습니다.
6.4.1. 최초 로그인 및 사용자 등록
- OIDC 사용자가 Harbor에 처음 로그인할 때, Harbor에서 사용할 사용자 이름을 등록하라는 메시지가 표시됩니다.
- 이때 입력하는 사용자 이름은 Harbor 데이터베이스에 이미 존재하지 않는 고유한 이름이어야 합니다.
6.4.2. 프로젝트 멤버로 OIDC 그룹 추가
- Harbor UI에서 권한을 부여할 프로젝트를 선택합니다.
- Members 탭으로 이동하여 + ADD MEMBER 버튼을 클릭합니다.
- Add OIDC group 탭을 선택합니다.
- Group Name에 Keycloak Realm에 정의된 그룹의 이름을 정확하게 입력합니다.
- Role 드롭다운에서 해당 그룹에 부여할 역할(예:
Project Admin,Maintainer,Developer)을 선택합니다. - ADD 버튼을 클릭합니다.
이제 해당 Keycloak 그룹에 속한 사용자가 OIDC로 로그인하면, 자동으로 지정된 프로젝트의 멤버가 되며 해당 역할을 부여받습니다.
6.4.3. 그룹 확인
- Administration > Groups 메뉴로 이동하면, 프로젝트에 추가된 OIDC 그룹이
OIDC타입으로 자동 등록된 것을 확인할 수 있습니다.
7. 이미지 빌드 및 등록
Harbor가 정상적으로 설치되고 OIDC 연동까지 완료되었다면, 샘플 이미지를 빌드하여 Harbor에 Push하는 과정을 통해 최종 검증을 수행합니다.
7.1. Dockerfile 생성
간단한 “Hello World"를 출력하는 웹서버 이미지를 생성합니다. 로컬에 Dockerfile이라는 이름의 파일을 생성하고 다음 내용을 추가합니다.
FROM nginx:alpine
COPY . /usr/share/nginx/html
RUN echo "Hello World from Harbor!" > /usr/share/nginx/html/index.html
7.2. 이미지 관리
터미널에서 다음 명령어를 순서대로 실행합니다.
1. 이미지 빌드
docker build -t helloworld:v1.0 .
2. Harbor 레지스트리 로그인
# harbor.cnapcloud.com: Harbor 도메인
# <username>: Keycloak 사용자 ID
docker login harbor.cnapcloud.com -u <username>
- OIDC를 통해 로그인하므로, Keycloak 사용자 ID와 비밀번호를 입력합니다.
3. 이미지 태그 지정
Harbor 프로젝트 경로에 맞게 이미지 태그를 변경합니다. library는 Harbor의 기본 프로젝트 이름입니다.
docker tag helloworld:v1.0 harbor.cnapcloud.com/library/helloworld:v1.0
4. 이미지 Push
docker push harbor.cnapcloud.com/library/helloworld:v1.0
7.3. Harbor UI에서 이미지 확인
- Harbor UI에 접속하여
library프로젝트로 이동합니다. helloworld리포지토리가 생성되고v1.0태그의 이미지가 정상적으로 Push되었는지 확인합니다.
8. Helm Chart 관리
Harbor는 OCI(OCI Image Format) 호환 레지스트리로 Helm Chart를 저장하고 관리할 수 있습니다. 이를 통해 Harbor를 Helm Chart 레지스트리로 활용할 수 있습니다.
8.1. Helm Chart를 Harbor에 Push (등록)
Chart 패키징: 로컬에서 Helm Chart를 패키징합니다.
helm package ./jenkins # 예: jenkins Chart 디렉터리jenkins-5.8.110.tgz파일이 생성됩니다.
Harbor 로그인: Harbor 레지스트리에 로그인합니다.
helm registry login harbor.cnapcloud.com -u <username><username>: Harbor 사용자 ID (OIDC 로그인 시 Keycloak 사용자 ID)
Chart Push: 패키징된 Chart를 Harbor에 Push합니다.
helm push jenkins-5.8.110.tgz oci://harbor.cnapcloud.com/library/helm- 출력 예시:
Pushed: harbor.cnapcloud.com/library/helm/jenkins:5.8.110 Digest: sha256:77c1bc7aed2ce44af4ae3cf2d3c4477d900f470a4ba82efb75f15632747d9440 library/helm은 프로젝트 경로입니다. 필요에 따라 변경하세요.
- 출력 예시:
8.2. Helm Chart를 Harbor에서 Pull
Harbor에 저장된 Helm Chart를 다운로드합니다.
helm pull oci://harbor.cnapcloud.com/library/helm/jenkins \
--version 5.8.110 \
--destination .
--version: 특정 버전을 지정 (생략 시 최신 버전)--destination: 다운로드 경로 (기본: 현재 디렉터리)
9. 문제 해결 (Troubleshooting)
- Pod Pending 상태: PVC가
Bound되지 않았거나 리소스(CPU/Memory)가 부족할 수 있습니다.kubectl describe pod <pod-name> -n harbor로 이벤트를 확인하세요. - Ingress 접속 불가: Ingress 컨트롤러 로그와
cert-manager가 TLS Secret을 정상적으로 생성했는지 확인하세요. - OIDC 로그인 실패: Harbor Core Pod의 로그(
kubectl logs -n harbor <harbor-core-pod>)에서 OIDC 관련 오류 메시지를 확인하세요. - Docker Push 실패:
x509: certificate signed by unknown authority: Docker 데몬이 Harbor의 TLS 인증서를 신뢰하지 못하는 경우입니다. 시스템에 Harbor의 CA 인증서를 등록해야 합니다.denied: requested access to the resource is denied: 로그인한 사용자가 해당 프로젝트에 대한 Push 권한이 없는 경우입니다.6.4단계를 참고하여 사용자에게 적절한 역할을 부여하세요.