인프라

[K8S] Harbor : LoadBalancer 및 TLS 설정

하루이2222 2025. 6. 17. 04:35

1. 배경: 왜 Ingress-Nginx와 MetalLB가 필요한가?

Kubernetes 클러스터에 Harbor와 같은 서비스를 배포하면, 기본적으로는 클러스터 내부에서만 접근 가능한 ClusterIP 타입으로 생성된다. 이를 외부에서 접근 가능하게 하려면 NodePort나 LoadBalancer 타입을 사용해야 한다.

  • NodePort의 한계: 클러스터의 모든 노드 IP와 특정 포트(예: 3xxxx)를 통해 접근해야 하므로, URL이 복잡해지고 노드 장애 시 IP를 변경해야 하는 불편함이 있다. 또한, 표준 웹 포트인 80/443을 직접 사용하기 어렵다.
  • LoadBalancer의 필요성: 클라우드 환경(AWS, GCP 등)에서는 LoadBalancer 타입을 지정하면 클라우드 제공업체가 외부 IP를 가진 로드밸런서를 자동으로 생성해준다. 하지만 Proxmox와 같은 Bare-metal 환경에서는 이 기능을 제공하는 주체가 없으므로, MetalLB와 같은 소프트웨어를 통해 이 기능을 직접 구현해야 한다.

따라서, 이 구성의 목표는 다음과 같다:

  1. MetalLB가 Bare-metal 클러스터에 LoadBalancer 기능을 제공한다.
  2. Ingress-Nginx 서비스 타입을 LoadBalancer로 변경하여, MetalLB로부터 고정된 외부 IP를 할당받는다.
  3. Ingress-Nginx가 외부의 모든 80/443 포트 트래픽을 수신하여, 설정된 도메인에 따라 Harbor 서비스로 라우팅한다.

2. Ingress-Nginx 서비스 타입을 LoadBalancer로 변경

먼저, 클러스터의 관문(Gateway) 역할을 수행할 Ingress-Nginx의 서비스 타입을 LoadBalancer로 변경하여 외부 IP를 할당받도록 설정했음.

기존에 NodePort 등으로 설치된 ingress-nginx의 설정을 helm upgrade 명령어를 통해 변경한다. --set 옵션으로 controller.service.type의 값을 LoadBalancer로 지정하면, Helm이 기존 차트의 설정을 동적으로 덮어쓴다.

Bash
 
# ingress-nginx 네임스페이스에 설치된 ingress-nginx 릴리스의 설정을 업그레이드한다.
# 컨트롤러 서비스의 타입을 LoadBalancer로 변경한다.
helm upgrade ingress-nginx ingress-nginx/ingress-nginx \
  --namespace ingress-nginx \
  --set controller.service.type=LoadBalancer

이 명령을 실행하면, ingress-nginx-controller 서비스는 Pending 상태에 있다가 잠시 후 MetalLB가 할당한 외부 IP(External IP)를 갖게 된다. 이제 이 IP의 80/443 포트로 들어오는 모든 트래픽은 Ingress-Nginx 컨트롤러로 전달된다.


3. Harbor Ingress 및 TLS 설정 구성

Ingress-Nginx가 외부 트래픽을 수신할 준비가 되었으므로, 이제 Harbor가 이 Ingress를 통해 서비스를 노출하도록 values.yaml 파일을 수정한다.

Harbor의 Helm 차트에서 expose 섹션은 외부 노출 방식을 정의하는 부분이다. type을 ingress로 설정하고 세부 사항을 아래와 같이 구성했음.

YAML
 
expose:
  # Harbor를 노출시키는 방식을 Ingress로 지정함.
  type: ingress
  ingress:
    # 이 Ingress 리소스를 처리할 Ingress Controller의 클래스 이름을 'nginx'로 지정함.
    className: nginx

    # Harbor에 접근할 도메인을 설정함.
    # nip.io는 별도의 DNS 설정 없이 IP 주소를 도메인처럼 사용하게 해주는 서비스임.
    hosts:
      core: harbor.192.168.0.110.nip.io

    # Ingress에 TLS(HTTPS) 설정을 활성화함.
    tls:
      enabled: true
      # TLS 인증서와 개인 키가 저장된 Kubernetes Secret의 이름을 지정함.
      # 이 Secret은 사전에 직접 생성해 두어야 함.
      secretName: harbor-ingress

  # Harbor의 API와 UI가 외부에서 인식하는 최종 URL을 명시함.
  # Docker CLI 등이 이 주소를 기준으로 로그인 및 이미지 푸시/풀을 시도하므로,
  # hosts.core에 설정된 도메인과 반드시 일치시켜야 함.
  externalURL: https://harbor.192.168.0.110.nip.io

핵심 설정 분석:

  • hosts.core: Ingress-Nginx가 어떤 호스트명(Host Header)으로 들어온 요청을 Harbor로 라우팅할지 결정하는 규칙이다.
  • tls.enabled 및 secretName: HTTPS 통신을 활성화하고, 사용할 인증서가 담긴 Secret을 지정한다. 이 설정을 통해 Ingress-Nginx는 해당 도메인으로 들어오는 트래픽을 SSL/TLS로 암호화한다.
  • externalURL: Harbor 운영에서 가장 중요한 설정 중 하나이다. Docker 클라이언트가 docker login harbor.192.168.0.110.nip.io 명령을 실행하면, Harbor는 내부적으로 이 externalURL 값을 참조하여 인증 토큰을 발급하고 통신한다. 만약 이 값이 실제 접속 도메인과 다를 경우, 인증은 성공하더라도 이미지 푸시/풀 과정에서 주소 불일치로 인해 실패하게 된다.

위와 같이 values.yaml 파일을 수정한 뒤 helm upgrade harbor ... 명령으로 적용하면, Ingress-Nginx는 harbor.192.168.0.110.nip.io 도메인으로 들어오는 모든 HTTPS 트래픽을 Harbor 서비스로 안전하게 전달하게 된다.