Astro Hub

10.Azure / 33.Certificate

프로젝트: astro-test1

원본 경로: installguide/10.Azure/33.Certificate.md


Certificate

1. 개요

Let's Encrypt를 사용하면 무료 공인 인증서를 발급받을 수 있고, Kubernetes 환경에서는 Ingress에 쉽게 붙일 수 있다. 이를 위해 보통 **cert-manager**를 설치하고, Ingress에 주석(annotation)을 추가하는 방식으로 사용한다.

2. cert-manager

1) cert-manager 설치


kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.4/cert-manager.yaml

설치 후, cert-manager, cert-manager-cainjector, cert-manager-webhook 등의 pod가 올라오는지 확인필요


$ kubectl get pods -n cert-manager
NAME                                       READY   STATUS    RESTARTS   AGE
cert-manager-5b446d88c5-b2zbc              1/1     Running   0          10s
cert-manager-cainjector-7f985d654d-dfk9k   1/1     Running   0          10s
cert-manager-webhook-5655c58dd6-njh55      0/1     Running   0          10s

2) ClusterIssuer 생성 (Let's Encrypt)

처음에는 staging을 써서 테스트하고, 문제 없으면 production으로 바꾸는 것을 권장함

$ echo '
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: atportal@ktds.co.kr
    privateKeySecretRef:
      name: letsencrypt-prod-account-key
    solvers:
    - http01:
        ingress:
          class: nginx
' | kubectl apply -f -


clusterissuer.cert-manager.io/letsencrypt-prod created

확인


$ kubectl get ClusterIssuer
NAME               READY   AGE
letsencrypt-prod   True    6s

3. Ingress에 TLS 적용

1) userlist Ingress

(1) Ingress 적용


# ingress
$ cat <<EOF | kubectl -n temp apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: userlist-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - userlist.cbiz.kubepia.net
    secretName: userlist-tls
  rules:
  - host: "userlist.cbiz.kubepia.net"
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: userlist-svc
            port:
              number: 80
EOF

  • secretName: userlist-tls → cert-manager가 이 이름으로 TLS Secret을 생성함
  • cert-manager.io/cluster-issuer` → ClusterIssuer 이름과 반드시 일치해야 함

(2) 인증서 발급 확인

발급된 TLS Secret 확인:


$ kubectl -n temp get secret atportal-tls
Name:         userlist-tls
Namespace:    temp
Labels:       <none>
Annotations:  <none>
API Version:  cert-manager.io/v1
Kind:         Certificate
Metadata:
  Creation Timestamp:  2025-04-24T14:18:56Z
  Generation:          1
  Owner References:
    API Version:           networking.k8s.io/v1
    Block Owner Deletion:  true
    Controller:            true
    Kind:                  Ingress
    Name:                  userlist-ingress
    UID:                   6d3b6efd-db0f-45df-977e-a2d9feb2208d
  Resource Version:        9686
  UID:                     17daeee0-6178-4c4b-a2de-9f353ca16614
Spec:
  Dns Names:
    userlist.cbiz.kubepia.net
  Issuer Ref:
    Group:      cert-manager.io
    Kind:       ClusterIssuer
    Name:       letsencrypt-prod
  Secret Name:  userlist-tls
  Usages:
    digital signature
    key encipherment
Status:
  Conditions:
    Last Transition Time:  2025-04-24T14:19:02Z
    Message:               Certificate is up to date and has not expired
    Observed Generation:   1
    Reason:                Ready
    Status:                True
    Type:                  Ready
  Not After:               2025-07-23T13:20:28Z
  Not Before:              2025-04-24T13:20:29Z
  Renewal Time:            2025-06-23T13:20:28Z
  Revision:                1
Events:
  Type    Reason     Age   From                                       Message
  ----    ------     ----  ----                                       -------
  Normal  Issuing    85s   cert-manager-certificates-trigger          Issuing certificate as Secret does not exist
  Normal  Generated  85s   cert-manager-certificates-key-manager      Stored new private key in temporary Secret resource "userlist-tls-sw28p"
  Normal  Requested  84s   cert-manager-certificates-request-manager  Created new CertificateRequest resource "userlist-tls-1"
  Normal  Issuing    79s   cert-manager-certificates-issuing          The certificate has been successfully issued
song@song-yangjong-ui-MacBookPro ~ %
  • 인증서 발급일 : 2025-04-24
  • 인증서 만료일 : 2025-07-23
  • Renewal Time : 2025-06-23 (만료일 -30 로 설정됨)]
    • cert-manager는 자동 만료 전에 미리 인증서를 갱신한다.

(3) 로그 확인

$ kubectl logs -n cert-manager deploy/cert-manager

2) atportal Ingress

(1) Ingress 적용

$ echo '
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: auth-ingress
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - atportal.cbiz.kubepia.net
    secretName: atportal-tls
  rules:
  - host: atportal.cbiz.kubepia.net
    http:
      paths:
      - path: /auth
        pathType: Prefix
        backend:
          service:
            name: auth-svc
            port:
              number: 80
      - path: /dash
        pathType: Prefix
        backend:
          service:
            name: dash-svc
            port:
              number: 8090
      - path: /
        pathType: Prefix
        backend:
          service:
            name: front-svc
            port:
              number: 80
' | kubectl -n atportal apply -f -

중요한 부분:

  • secretName: atportal-tls → cert-manager가 이 이름으로 TLS Secret을 생성함
  • cert-manager.io/cluster-issuer → ClusterIssuer 이름과 반드시 일치해야 함

(2) 인증서 발급 확인

발급된 TLS Secret 확인:

$ kubectl -n temp get secret atportal-tls
Name:         userlist-tls
Namespace:    temp
Labels:       <none>
Annotations:  <none>
API Version:  cert-manager.io/v1
Kind:         Certificate
Metadata:
  Creation Timestamp:  2025-04-24T14:18:56Z
  Generation:          1
  Owner References:
    API Version:           networking.k8s.io/v1
    Block Owner Deletion:  true
    Controller:            true
    Kind:                  Ingress
    Name:                  userlist-ingress
    UID:                   6d3b6efd-db0f-45df-977e-a2d9feb2208d
  Resource Version:        9686
  UID:                     17daeee0-6178-4c4b-a2de-9f353ca16614
Spec:
  Dns Names:
    userlist.cbiz.kubepia.net
  Issuer Ref:
    Group:      cert-manager.io
    Kind:       ClusterIssuer
    Name:       letsencrypt-prod
  Secret Name:  userlist-tls
  Usages:
    digital signature
    key encipherment
Status:
  Conditions:
    Last Transition Time:  2025-04-24T14:19:02Z
    Message:               Certificate is up to date and has not expired
    Observed Generation:   1
    Reason:                Ready
    Status:                True
    Type:                  Ready
  Not After:               2025-07-23T13:20:28Z
  Not Before:              2025-04-24T13:20:29Z
  Renewal Time:            2025-06-23T13:20:28Z
  Revision:                1
Events:
  Type    Reason     Age   From                                       Message
  ----    ------     ----  ----                                       -------
  Normal  Issuing    85s   cert-manager-certificates-trigger          Issuing certificate as Secret does not exist
  Normal  Generated  85s   cert-manager-certificates-key-manager      Stored new private key in temporary Secret resource "userlist-tls-sw28p"
  Normal  Requested  84s   cert-manager-certificates-request-manager  Created new CertificateRequest resource "userlist-tls-1"
  Normal  Issuing    79s   cert-manager-certificates-issuing          The certificate has been successfully issued
song@song-yangjong-ui-MacBookPro ~ %

(3) 로그 확인

$ kubectl logs -n cert-manager deploy/cert-manager

(4) 도메인과 DNS 설정 확인

Let's Encrypt는 http-01 challenge 방식을 사용하는데, 이를 위해:

  • atportal.cbiz.kubepia.netIngress Controller (예: nginx) 가 있는 외부 IP로 연결되어 있어야 함
  • 외부에서 http://atportal.cbiz.kubepia.net/.well-known/acme-challenge/... 요청이 접근 가능한지 확인필요

4. 인증서 갱신

인증서는 3개월짜리로 발급되며 2개월이 지난 시점부터 자동으로 인증서 갱신을 시도한다.

1) 자동갱신 작동방식

  1. cert-manager는 Kubernetes 리소스 상태를 계속 감시하면서
  2. Renewal Time이 가까워지면 자동으로 새 CertificateRequest를 생성하고
  3. 기존 인증서를 갱신합니다 (→ 동일한 Secret 이름으로 덮어씀)

사용자는 아무것도 할 필요 없이 자동으로 갱신됨

2) 강제로 갱신시도를 원할때



$ kubectl cert-manager renew <certificate-name>

# 실제 예시
$ kubectl cert-manager renew userlist-tls

or

# secret 삭제 후 재발급도 가능
$ kubectl delete secret

프로젝트 홈으로 돌아가기