쿠버네티스 CertManager 인증서 만료 이슈 해결하기

hbjs97·2025년 4월 26일
post-thumbnail

최근 쿠버네티스 환경에서 운영 중인 Harbor의 SSL 인증서가 만료되어 접속이 불가능한 문제가 발생했다. 생각보다 흔히 겪을 수 있는 문제지만, 이번에는 Traefik이 별도의 VM에서 TCP passthrough로 동작하며 Kubernetes 내부 Harbor가 직접 SSL 인증서를 제공하는 형태였기에 조금 헤맸다. 과정을 차근차근 정리해 본다.

문제상황

Harbor에 접속하려고 보니 다음과 같은 SSL 경고가 발생했다.

net::ERR_CERT_DATE_INVALID
Expires on: 2025. 4. 26.
Current date: 2025. 4. 26.

간단히 말해, Harbor가 사용하는 SSL 인증서가 오늘 날짜로 만료된 것이었다.

시도한 접근 방법

일반적으로 SSL 인증서가 만료된 경우에는 인증서를 재발급받아야 하는 것이 당연한 접근이다. 하지만 이번 상황에서는 cert-manager가 자동으로 SSL 인증서를 관리하도록 설정되어 있었기 때문에, 가장 먼저 cert-manager가 인증서를 정상적으로 갱신했는지 여부부터 확인했다.

helm 차트로 배포한 cert-manager는 일반적으로 인증서를 자동으로 갱신하는 기능을 제공한다. 하지만 온프레미스 물리 서버 전체가 내려가 복구 및 서버 이전 작업을 수행했던 적이 있어서, 이 과정에서 인증서 갱신 프로세스에 문제가 생겼을 가능성도 충분히 존재했다.

Harbor는 쿠버네티스 클러스터 내에서 운영 중이었고, cert-manager가 SSL 인증서를 자동으로 관리하고 있었다. DNS는 Cloudflare를 사용 중이었고, Proxy는 끈 상태로 Harbor 서비스에 직접 TCP로 연결된 Traefik을 통해 TLS passthrough로 요청을 전달하는 방식이었다.

우선 cert-manager의 인증서 상태를 확인했다.

kubectl get certificates -A

NAMESPACE   NAME                      	READY   SECRET                  AGE
harbor      harbor-***-***-cert			True    harbor-***-***-tls		150d

READY 상태가 True여서 인증서가 정상적인 상태로 보였다.
하지만 외부에서 실제 제공받는 인증서를 직접 확인해 보니, 여전히 예전(만료된) 인증서였다.

echo | openssl s_client -connect harbor.***.***:443 -servername harbor.***.*** 2>/dev/null | openssl x509 -noout -dates

notBefore=Jan 26 09:32:40 2025 GMT
notAfter=Apr 26 09:32:39 2025 GMT

cert-manager는 정상 상태였지만, 실제로 외부에 제공되는 인증서는 만료된 상태였다.

이 부분에서 아래 상항을 의심했다.

  • 서버 복구 및 이전 과정에서 cert-manager가 관리하는 인증서 데이터에 문제가 생겼을 가능성
  • 쿠버네티스 Secret이 갱신됐으나, 이를 실제 서비스가 로드하지 않은 상태일 가능성
  • 중간에서 TCP passthrough를 수행하는 Traefik이 문제일 가능성
  • 쿠버네티스 내부 Harbor 자체가 예전 인증서를 캐싱하고 있을 가능성

해결과정

Secret 강제 갱신 시도

우선 쿠버네티스 내부의 Secret을 삭제해서 cert-manager가 다시 인증서를 발급하도록 했다.

kubectl delete secret harbor-***-***-tls -n harbor

잠시 후 Secret은 정상적으로 재생성되었다.

외부 접속 확인

Secret이 재생성되었으나 여전히 외부 접속 시 이전 인증서가 제공됐다. Secret만 재생성된 것으로는 부족했다. Harbor 내부 Pod가 Secret을 다시 로드하지 못했을 가능성이 높아졌다.

Traefik VM 문제 여부 확인

Traefik 설정을 점검한 결과, Traefik은 인증서에 직접 관여하지 않고 TCP passthrough만 수행하고 있었다.

Traefik 설정 일부:

tcp:
  routers:
    harbor:
      entryPoints:
        - https
      rule: "HostSNI(`harbor.***.***`)"
      service: harbor
      tls:
        passthrough: true

즉, 이 과정에서 인증서는 오직 Harbor 서비스 내부에서만 처리했다.

Harbor의 nginx Pod 재시작

문제의 핵심은 Harbor의 nginx Pod가 예전 인증서를 메모리에 로드한 상태로 계속 운영 중인 것이었다. Pod를 재시작해 새로 갱신된 인증서를 로드하도록 했다.

kubectl rollout restart deployment -n harbor harbor-nginx

재시작 후 외부에서 인증서를 다시 체크해 봤다.

echo | openssl s_client -connect harbor.***.***:443 -servername harbor.***.*** 2>/dev/null | openssl x509 -noout -dates

notBefore=Apr 26 12:27:20 2025 GMT
notAfter=Jul 25 12:27:19 2025 GMT

이후 브라우저에서도 정상 접속이 가능해졌다.

정리

  • helm 차트로 배포된 cert-manager는 인증서를 자동 갱신하지만, 서버 복구나 클러스터 이전과 같은 큰 변화 이후에는 인증서 상태를 꼭 점검해야 한다.
  • 쿠버네티스에서 인증서 문제가 생겼을 때, Secret 상태만으로 판단하면 안 된다.
  • 애플리케이션(특히 nginx 같은 SSL 처리 서비스)은 Secret이 변경되어도 자동으로 다시 로드하지 않는다.
  • Traefik과 같이 TCP passthrough를 하는 Proxy는 인증서 갱신 문제와 직접적인 관련이 없다.
  • 반드시 변경된 인증서를 서비스가 인식할 수 있게 Pod 재시작을 수행해야 한다.

0개의 댓글