ingress nginx controller에 Let's encrypt 적용

2025. 8. 9. 13:52k8s

cert-manager 설치

helm repo add jetstack https://charts.jetstack.io
helm repo update
#helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --set installCRDs=true
helm upgrade --install cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --set installCRDs=true

# 확인
kubectl get pods -n cert-manager

ClusterIssuer 생성

# 스테이징용 (먼저 발급 테스트)
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
spec:
  acme:
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    email: {메일}  # ✅ Replace with your email
    privateKeySecretRef:
      name: letsencrypt-staging
    solvers:
      - http01:
          ingress:
            class: nginx
            ingressTemplate:
              metadata:
                annotations:
                  nginx.ingress.kubernetes.io/use-regex: "false"
---
# 실사용용 (테스트 성공 후 교체)
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: {메일}  # ✅ Replace with your email
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
      - http01:
          ingress:
            class: nginx
            ingressTemplate:
              metadata:
                annotations:
                  nginx.ingress.kubernetes.io/use-regex: "false"
                  
# 확인
# READUY가 true가 되어야 함
kubectl get clusterissuer -A

Ingress에 TLS 적용

# 처음 테스트 수행
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: hello
  namespace: nginx
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-staging
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - test.gift1000.co.kr
    secretName: test-gift1000-co-kr-tls
  rules:
  - host: test.gift1000.co.kr
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: hello-service
            port:
              number: 80
              
# 테스트 성공 후 교체
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: hello
  namespace: nginx
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - test.gift1000.co.kr
    secretName: test-gift1000-co-kr-tls
  rules:
  - host: test.gift1000.co.kr
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: hello-service
            port:
              number: 80

동작 확인

# Certificate 리소스 상태 확인
kubectl -n nginx get certificate
kubectl -n nginx describe certificate test-gift1000-co-kr-tls
-----------------------------------------
Spec:
...
  Issuer Ref:
    Group:      cert-manager.io
    Kind:       ClusterIssuer
    Name:       letsencrypt-prod  # 적용된 certificate
...
Status:
...
  Renewal Time:            2025-10-08T02:08:54Z # 갱신 시점
-----------------------------------------

# Order, Challenge 상태 확인
kubectl get order -A
kubectl describe order <order-name>
kubectl get challenge -A # 발급 완료되면 'No resources found'이 됨
kubectl describe challenge <challenge-name>

트러블슈팅

문제 원인 해결 방법

Challenge pending HTTP01 요청이 ingress로 도달하지 않음 DNS A 레코드 확인, 80포트 방화벽 개방, ingress rules 확인
Challenge invalid 응답이 ACME 서버에서 검증 실패 ingress annotation ingressClassName/class 일치 확인
Certificate False 발급 실패 kubectl describe certificate에서 이벤트 확인 후 ClusterIssuer/도메인/Ingress 설정 수정
Rate limit 발급 횟수 제한 스테이징 ClusterIssuer로 테스트 후 프로덕션 전환
secret이 안생김 cert-manager 파드 에러 kubectl logs -n cert-manager deploy/cert-manager 확인

재적용 / 갱신

# 인증서 강제 재발급
kubectl -n nginx delete certificate test-gift1000-co-kr-tls
kubectl -n nginx delete secret test-gift1000-co-kr-tls
kubectl apply -f ingress.yaml

# cert-manager 재시작
kubectl rollout restart deploy -n cert-manager

# 갱신 상태 확인
kubectl describe certificate test-gift1000-co-kr-tls -n nginx

# 최종 확인
# HTTPS 접근 확인
curl -v https://home.gift1000.co.kr

# 브라우저에서 인증서 발급자 확인 → "R3 / Let's Encrypt"