Private Cloud에 Kubernets를 구성하는 경우, Cert Manager로 공인 인증서를 자동 발급받는데는 제약이 발생합니다.
이에, 이 글에서는 acme.sh를 사용하여 Gabia DNS에 _acme-challenge TXT 레코드를 수동으로 등록하고,
DNS-01 방식으로 Let’s Encrypt TLS 인증서를 발급하는 방법을 단계별로 안내합니다.
발급한 인증서를 Kubernetes Ingress에 적용하고 Secret 생성, 갱신까지 포함한 실무 가이드입니다.
1. 준비 사항
- 도메인:
jenkins.cnapcloud.com - Kubernetes 네임스페이스:
cicd - 서비스 이름:
jenkins(Ingress가 연결할 서비스) - acme.sh 설치: 로컬 또는 CI/CD 환경
- DNS 접근: DNS TXT 레코드를 수동으로 추가할 수 있어야 함
참고: 여기서는 Let’s Encrypt와 ZeroSSL 모두 사용 가능하며, 예시는 Let’s Encrypt 기준입니다.
2. acme.sh 설치 및 계정등록
acme.sh GitHub 저장소를 clone합니다.
# acme.sh GitHub 저장소 clone
git clone https://github.com/acmesh-official/acme.sh.git
cd acme.sh
# 설치 (선택적)
./acme.sh --install
계정 정보와 thumbprint 확인합니다.
./acme.sh --register-account -m your-email@example.com
echo $ACCOUNT_THUMBPRINT
3. TLS 인증서 발급 (DNS-01, 수동)
3-1. 인증서 발급 명령
./acme.sh --issue \
-d jenkins.cnapcloud.com \
--dns dns_manual \
--server letsencrypt
3-2. 수동 DNS 설정 안내
발급 과정에서 아래와 같은 안내가 나옵니다:
Add the following TXT record:
Domain: '_acme-challenge.jenkins.cnapcloud.com'
TXT value: 'PWuQ**************NkhYUlHYY'
Gabia DNS 관리 페이지에 접속하여 도메인을 선택하여 위에 출력된 정보를 가지고 TXT 레코드를 추가합니다.
- DNS 공급자 콘솔에서 TXT 레코드를 추가
_acme-challenge.jenkins.cnapcloud.com을 이름으로 사용- 위 TXT 값을 그대로 입력

DNS에 TXT record가 정상적으로 등록되었는지 확인합니다.
dig TXT _acme-challenge.jenkins.cnapcloud.com +short
다시 위 인증서 발급 명령을 수행하여 인증서를 발급받습니다.
4. Kubernetes TLS Secret 생성
발급된 인증서는 ~/.acme.sh/jenkins.cnapcloud.com_ecc에 파일로 보관됩니다.
~/.acme.sh/jenkins.cnapcloud.com_ecc/jenkins.cnapcloud.com.cer # 인증서
~/.acme.sh/jenkins.cnapcloud.com_ecc/jenkins.cnapcloud.com.key # 키
~/.acme.sh/jenkins.cnapcloud.com_ecc/fullchain.cer # 체인 포함 전체
위에 발급된 인증서 파일을 가지고 Kubernetes Secret 명령을 사용하여 jenkins-tls 파일을 생성합니다.
kubectl -n cicd create secret tls jenkins-tls \
--cert=~/.acme.sh/jenkins.cnapcloud.com_ecc/fullchain.cer \
--key=~/.acme.sh/jenkins.cnapcloud.com_ecc/jenkins.cnapcloud.com.key
jenkins-tls 파일이 정상적으로 생성되었는지 확입니다.
kubectl -n cicd get secret jenkins-tls
5. Ingress 리소스 설정
위에서 생성한 jenkins-tls를 사용하여 Ingress 파일을 생성합니다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: jenkins
namespace: cicd
spec:
rules:
- host: jenkins.cnapcloud.com
http:
paths:
- path: /
pathType: ImplementationSpecific
backend:
service:
name: jenkins
port:
number: 8080
tls:
- hosts:
- jenkins.cnapcloud.com
secretName: jenkins-tls
이 Ingress를 클러스터에 배포합니다.
kubectl -n cicd apply -f jenkins-ingress.yaml
Ingress가 올바르게 TLS를 적용했는지 확인합니다.
kubectl -n cicd describe ingress jenkins
브라우저 또는 curl로 도메인에 접속하여 정상적으로 인증서가 처리되는지 확인합니다.
curl -vk https://jenkins.cnapcloud.com
6. 갱신 자동화
수동 DNS 방식은 자동화에 제약이 있지만, acme.sh 자체는 cron을 통한 자동 갱신 기능을 제공합니다. 그러나 dns_manual 모드를 사용할 경우 인증서 갱신 시마다 TXT 레코드를 직접 다시 등록해야 하므로 운영 과정에서 상당한 번거로움이 발생합니다. Gabia는 공식적인 DNS API를 제공하지 않아 Cloudflare, Route53 등과 같은 DNS API를 제공하는 서비스로 도메인을 이전하여 자동화 방식을 적용할 수 있습니다.
# 기본 갱신
~/.acme.sh/acme.sh --renew -d jenkins.cnapcloud.com --force
인증서 갱신 후 다음과 같이 Secret 업데이트합니다.
kubectl -n cicd create secret tls jenkins-tls \
--cert=~/.acme.sh/jenkins.cnapcloud.com_ecc/fullchain.cer \
--key=~/.acme.sh/jenkins.cnapcloud.com_ecc/jenkins.cnapcloud.com.key \
--dry-run=client -o yaml | kubectl apply -f -
이렇게 하면 acme.sh를 이용한 DNS-01 인증서 발급 → Kubernetes TLS Secret 등록 → Ingress TLS 적용 과정이 체계적으로 정리됩니다.