• Cert Manager 란 무엇인가?

    2026. 5. 28.

    by. Daramu

    HTTPS 통신을 위해서는 SSL/TLS 인증서 관리가 필요하다.

    만료일을 깜빡하면 HTTPS 통신이 안되어 서비스가 마비되는 대참사가 간혹 나오고 있는데, 쿠버네티스에서는 cert-manager를 사용하여 이 같은 상황을 막는 것이 거의 표준으로 자리 잡고 있다.

     

     

     

    위 그림은 cert-manager가 인증서를 발급하고 관리하는 전체적인 흐름이다.

    크게 4가지 컴포넌트로 구성된다.

     

    1. Issures(Cluster Issures):  인증서를 실제로 발급해주는 인증기관(CA)에 대한 정보이다. Let's Encrypt, Hashicorp Valut, 혹은 자체 생성한 CA등이 여기에 해당한다. Cluster가 붙는 것은 클러스 전체 공유 가능한 인증서이다.

    2. cert-manager: 모든 과정을 컨트롤 하는 컨틀롤러(Controller)이다. 리소스를 감시하며 인증서를 자동으로 발급/갱신한다.

    3. Certificates: 어떤 도메인(ex. foo.bar.com)에 대해 어떤 Issuer를 사용해 인증서를 만들 것인지에 대한 명세서이다.

    4. Kubernetes Secret: cert-manager가 최종 발급 받은 개인키(Private Key)와 인증서(signed keypair)를 저장하는 공간이다. Ingress나 Application은 이 Secret을 마운트 하여  HTTPS 통신을 가능하게 한다.

     

    내부용 HTTPS vs 외부용 HTTPS

     

    인증서를 발급할 때, 서비스가 클러스터 내부에서만 도메인을 쓰는지, 외부에 노출되는지에 따라 내부 설정이 달라진다.

     

     

    아래는 각각의 예시이다.

     

    예시 전: cert-manager helm 설치

    helm install cert-manager jetstack/cert-manager \
      --namespace cert-manager \
      --create-namespace \
      --set crds.enabled=true

     

    내부용 HTTPS 인증서 발급

    클러스터 내부 통신용이며, 사내 개발 환경등 내부에서만 접근이 필요할때 사용할 수 있는 구성이다.

    cert-manager가 직접 자체 루트 CA(root CA)역할을 하게할 수 있다.

     

    1. cert-manager를 통해 직접 root CA 인증서 발급: 자체서명(Self-Signed)기능을 사용하여 cert-manager가 직접 루트 CA용 인증서와 비밀키를 만들고, 그걸 internal-ca-key-pair라는 이름의 secret으로 저장하게 만든다.

    apiVersion: cert-manager.io/v1
    kind: ClusterIssuer
    metadata:
      name: selfsigned-root-issuer
    spec:
      selfSigned: {}
    
    ---
    
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: internal-root-ca
      namespace: cert-manager
    spec:
      isCA: true # 중요: 이 인증서가 다른 인증서를 발행할 수 있는 'CA' 역할을 하겠다고 선언
      commonName: "my-internal-root-ca"
      secretName: internal-ca-key-pair # 여기에 입력한 이름으로 Secret이 자동 생성
      privateKey:
        algorithm: ECDSA
        size: 256
      issuerRef:
        name: selfsigned-root-issuer
        kind: ClusterIssuer

     

     

    2. clusterIssuer: 먼저 내부 사설 CA 역할을 할 Issure를 정의한다.

    apiVersion: cert-manager.io/v1
    kind: ClusterIssuer
    metadata:
      name: internal-ca-issuer
    spec:
      ca:
        # 미리 생성해둔 내부 CA의 비밀키가 담긴 Secret을 지정
        secretName: internal-ca-key-pair

     

    3. Certificate 생성 및 Secret 자동 발급: 내부에서 사용할 내부 도메인(ex. foo.bar.com)에 대한 인증서를 요청한다.

    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: internal-service-cert
      namespace: default
    spec:
      # 위에서 만든 내부 CA Issuer를 지정
      issuerRef:
        name: internal-ca-issuer
        kind: ClusterIssuer
      # 최종 인증서(signed keypair)가 저장될 쿠버네티스 시크릿 이름
      secretName: internal-service-tls
      dnsNames:
        - "foo.bar.com"

     

    이제 cert-manager가 internal-ca-issuer를 통해 서명한 뒤, internal-service-tls 라는 secret을 자동으로 만들어준다.

     

    외부 도메인 연결 인증서 발급(Let's Encrypt)

    인터넷을 통해 실제 유저가 접속하는 서비스(ex. example.com)을 위한 구성이다.

    글로벌 공인CA인 Let's Encrypt를 사용한다.

     

    1. clusterIssuer: Let's Encrypt와 통신하여 도메인 유효성을 체크하는 Issuer을 생성한다.

    apiVersion: cert-manager.io/v1
    kind: ClusterIssuer
    metadata:
      name: letsencrypt-prod
    spec:
      acme:
        # Let's Encrypt 프로덕션 서버 주소
        server: https://acme-v02.api.letsencrypt.org/directory
        email: devops-team@example.com  # 만료 알림 등을 받을 이메일
        privateKeySecretRef:
          name: letsencrypt-prod-account-key
        solvers:
        - http01:
            ingress:
              class: nginx  # 클러스터에서 사용 중인 Ingress Controller 지정

     

    2. Certifacate 생성: 외부용 인증서는 Certificate 리소스를 따로 열어도 되지만, 사실 대부분 Ingress설정에 어노테이션을 설정하여 관리하는 것이 대부분의 사례이다.

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: wwww-service-ingress
      namespace: default
      annotations:
        # 이 어노테이션을 보고 cert-manager가 알아서 Certificate를 생성
        cert-manager.io/cluster-issuer: "letsencrypt-prod"
        kubernetes.io/ingress.class: "nginx"
    spec:
      rules:
      - host: "example.com"
        http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web-service
                port:
                  number: 80
      tls:
      - hosts:
        - "example.com"
        # cert-manager가 Let's Encrypt에서 받아온 공인 인증서를 이 시크릿에 담는다
        secretName: example-com-tls

    댓글