Harbor를 Kubernetes(Helm)에 운영하면서 정리한 설정·트러블슈팅입니다. 기준 chart는 공식 goharbor/harbor-helm입니다. (Bitnami chart는 유료화되어 공식 chart로 이전이 필요하며, Bitnami 전용 키는 아래에서 공식 대응을 함께 표기합니다.)
Secret을 values 평문 대신 외부 주입으로
S3 access key, OIDC client secret 등을 values.yaml에 평문으로 넣어 Git에 올리는 것은 피해야 합니다. 또한 OIDC를 UI에서 수동 설정하면 재배포 시 client secret이 날아가 로그인이 깨지는 문제가 있습니다. → Secret만 미리 정의하고 External Secrets Operator(ESO) 등으로 생성한 뒤 existingSecret으로 참조합니다.
Registry Secret
공식 chart도 registry.existingSecret(REGISTRY_HTTP_SECRET)과 동일한 S3 키를 씁니다. 시크릿 데이터:
data:
REGISTRY_HTPASSWD: *** # bcrypt 해시
REGISTRY_HTTP_SECRET: ***
REGISTRY_STORAGE_S3_ACCESSKEY: ***
REGISTRY_STORAGE_S3_SECRETKEY: ***Warning
REGISTRY_HTPASSWD는 bcrypt 해시여야 합니다:htpasswd -nbBC10 $username $password- credential 정보 간 불일치가 있으면 안 됩니다. Harbor 문서가 명시하며, 어기면 로봇 계정 로그인 불가 등 인증 오류가 납니다.
OIDC 연동
공식 harbor-helm에는 OIDC를 넣는 values 블록이 없습니다. Harbor의 auth_mode는 Helm values가 아니라 **런타임 시스템 설정(DB 저장)**이기 때문입니다. (Bitnami는 core.configOverwriteJsonSecret로 제공했음.) 주입 경로는 둘:
| 방법 | 설명 | 적합 |
|---|---|---|
| A. 배포 후 UI/API | Configuration 화면/API로 auth_mode=oidc_auth + provider 정보 설정 | 표준·수동 |
B. CONFIG_OVERWRITE_JSON env | core 컨테이너 환경변수로 시작 시 주입 (Harbor 2.3+) | GitOps·재현 가능 |
Warning
- B를 쓰면 UI/CLI에서 설정 변경 불가 — 이후 변경은 env 갱신 + 컨테이너 재시작으로만.
auth_mode는 DB에 admin 외 로컬 유저가 없을 때만 OIDC로 전환 가능. 초기 세팅 시점에 넣을 것.
주입할 JSON(= CONFIG_OVERWRITE_JSON 내용, provider 무관). client secret은 위처럼 외부 Secret으로 관리:
{
"auth_mode": "oidc_auth",
"primary_auth_mode": false,
"oidc_name": "<표시 이름>",
"oidc_endpoint": "https://<provider-issuer-url>",
"oidc_client_id": "<client-id>",
"oidc_client_secret": "<client-secret>",
"oidc_scope": "openid,profile,email,offline_access"
}primary_auth_mode:true면 로그인 화면에서 OIDC 우선. DB 로그인과 충돌 우려 시false.oidc_scope:openid필수, refresh token 필요 시offline_access포함.
Provider별 차이
방식은 동일하고 oidc_endpoint와 scope/claim만 provider에 맞게 교체합니다. Harbor가 .well-known/openid-configuration으로 나머지를 자동 검색하므로 issuer URL만 정확하면 됩니다.
| Provider | oidc_endpoint 예 | 비고 |
|---|---|---|
| Microsoft Entra ID | https://login.microsoftonline.com/{TENANT_ID}/v2.0 | refresh token 위해 offline_access |
https://accounts.google.com | ||
| Keycloak | https://<host>/realms/<realm> | |
| Okta / Auth0 / Dex | 각 issuer URL | group 매핑 시 oidc_groups_claim 추가 |
Job service update strategy
Job service는 주기적으로 계속 실행되며 PVC를 점유합니다. 기본 RollingUpdate면 교체 중 하나의 PVC에 신·구 Pod가 동시에 붙어 Multi-attach 에러가 납니다 (RWO 볼륨 일반 함정). Recreate로 막습니다:
jobservice:
updateStrategy:
type: RecreateTroubleshooting
로봇 계정 로그인 실패
원인이 둘로 나뉩니다.
- Credential 불일치 / bcrypt — 위 Registry Secret 경고 참조.
REGISTRY_HTPASSWD가 bcrypt가 아니거나 credential 간 불일치면 로봇 계정 로그인이 막힙니다. - 사용자명의
$특수문자 — 로봇 계정명에는$가 포함됩니다(예:robot$project+dev-cluster). shell/매니페스트에서 이스케이프되지 않으면 Secret 생성·인증이 실패합니다. 작은따옴표로 감싸거나 이스케이프:
kubectl create secret docker-registry harbor-registry-secret \
--docker-server=<HARBOR-URL> \
--docker-username='robot$project+dev-cluster' \
--docker-password=<ROBOT-TOKEN> \
--docker-email=<EMAIL> \
-n default관리자 계정 로그인 불가
Postgres 데이터 정합성 문제 등으로 admin 포함 로그인이 안 되는 경우, Postgres에 직접 접근해 관리자 계정을 초기화할 수 있습니다(goharbor/harbor#8778 comment).