본문 바로가기
Kubernetes

[Kubernetes] Nginx Controller에 Let’s Encrypt 인증서 등록(http01)

by worldcenter 2024. 9. 25.

 

 

Kubernetes에 올라가 있는 웹에 https로 통신해야 하는 경우 Let’s Encrypt 인증서를 발급하고 적용할 수 있다. 해당 테스트에서는 Nginx Ingress Controller를 사용해서 테스트 합니다.

와일드카드 인증서를 발급할 경우 DNS01 문서를 참조해주세요

 

 

사전 준비

  • Nginx Controoler 설치
  • 테스트 용도의 Pod 또는 Deployment와 Cluster IP 타입의 Service 생성

 

Helm으로 Cert-Manager 설치하기

  • Cert-Manager는 Kubernetes 클러스터 내에서 SSL/TLS 인증서를 관리하는 도구(컨트롤러)
  • 사용자와 Provider(letsencrypt) 중간에서 중계 역할
  • Kubernetes에 배포될 때 cert-manager는 자동으로 ingress controller에 필요한 인증서를 발급하고 인증서가 유효하고 최신 상태인지 확인
  • 인증서의 만료 날짜를 추적하고 구성된 시간 간격으로 갱신을 시도
  • 자세한 내용은 다음 Helm 공식 링크에서 확인 가능합니다.

 

1. Helm Repository를 추가합니다.

helm repo add jetstack https://charts.jetstack.io

 

2. 로컬 helm chart repository를 업데이트 합니다.

helm repo update

 

3. CRD(CustomResourceDefinitions)를 설치합니다.

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

 

4. cert-manager를 설치합니다.

helm install \
  cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --version v1.12.0 \
  # --set installCRDs=true

 

 

ClusterIssuer 생성

  • Issuer와 ClusterIssuer는 Cert-Manager에서 사용되는 인증서 발급을 구성하는 리소스
  • 인증서 발급을 위한 정보와 설정을 제공하는 역할
  • Issuer와 ClusterIssuer는 다양한 인증서 발급 기술(ACME, Vault, Self-Signed 등)을 지원하며, 각각의 리소스는 해당 기술에 필요한 구성을 포함합니다. 예를 들어, ACME Issuer는 Let's Encrypt와 같은 ACME 서버와 통신하여 인증서를 자동으로 발급 및 갱신할 수 있습니다.
  • 자세한 내용은 다음 링크에서 확인 가능

 

1) Issuer

  • Kubernetes 네임스페이스에 속하는 리소스로, 네임스페이스 내의 리소스에 대한 인증서를 발급
  • 네임스페이스 범위에서 작동하기 때문에, 동일한 네임스페이스 내의 리소스에 대한 인증서 발급을 관리

2) ClusterIssuer

  • 전체 클러스터 범위에서 동작하는 리소스
  • 클러스터 내의 모든 네임스페이스에 대한 인증서를 발급
  • ClusterIssuer는 여러 네임스페이스에서 사용되는 인증서를 관리할 때 유용
  • 예: Ingress 리소스
ACME가 무엇인가요?
- Automatic Certificate Management Environment의 약자로, SSL/TLS 인증서를 자동으로 발급하고 관리하기 위한 프로토콜
- 가장 널리 사용되는 ACME 구현체는 Let’s Encrypt
- ACME 프로토콜을 사용하면 Let’s Encrypt와 같은 인증기관과 클라이언트(예: Cert-Manager) 간에 자동으로 인증서 발급 및 갱신을 처리

 

Let’s Encrypt ClusterIssuer발급 시 Staging 서버와 Prod 서버 2가지가 존재합니다.

 

1) Staging 서버

  • 개발 및 테스트 환경에서는 일반적으로 staging 서버를 사용
  • Staging 서버는 실제 운영 환경과 유사한 기능을 제공하지만, 발급된 인증서는 실제로 인증되지 않음
  • 이는 인증서를 테스트하고 애플리케이션 통합하는 데 유용
  • Staging 서버를 사용하여 인증서를 발급할 때는 발급 제한이나 제약이 적용되지 않기 때문에 테스트 및 개발 목적으로 자주 사용
// 예시 코드
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
spec:
  acme:
    # You must replace this email address with your own.
    # Let's Encrypt will use this to contact you about expiring
    # certificates, and issues related to your account.
    email: user@example.com
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      # Secret resource that will be used to store the account's private key.
      name: example-issuer-account-key
    # Add a single challenge solver, HTTP01 using nginx
    solvers:
    - http01:
        ingress:
          class: nginx

 

 

2) Prod 서버

  • 실제 운영 환경에서는 prod서버를 사용해야 함
  • Prod 서버는 실제로 인증되고 신뢰할 수 있는 인증서를 발급
  • Prod 서버를 사용할 때 발급 제한이 있으므로, 실제 운영 환경에서 사용하기 전에는 충분한 테스트와 검증을 거쳐야 함
// 예제 코드
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: your-email@example.com
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
      - http01:
          ingress:
            class: nginx

 

1. 본인은 다음과 같이 코드를 배포하여 ClusterIssuer와 Secret을 설치했습니다.

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-issuer
spec:
  acme:
    # You must replace this email address with your own.
    # Let's Encrypt will use this to contact you about expiring
    # certificates, and issues related to your account.
    email: <E-mail주소 기입>
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      # Secret resource that will be used to store the account's private key.
      name: letsencrypt-issuer-account-key
    # Add a single challenge solver, HTTP01 using nginx
    solvers:
    - http01:
        ingress:
          class: nginx

 

 

2. ClusterIssuer와 Secret 생성을 확인 합니다.

ClusterIssuer
Secret

 

 

Ingress 생성

  • ingress생성 시 기존에 생성해 두었던 ClusterIssuer와 Secret 값을 등록하면 자동적으로 Certificate도 생성됩니다.
  • cert-manager와 관련된 annotations은 다음 링크에서 확인 가능합니다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-issuer
  name: nuri-ingress
  namespace: nuri
spec:
  ingressClassName: nginx
  rules:
  - host: "hello.balance.gaonnuri.site"
    http:
      paths:
      - backend:
          service:
            name: nuri-service
            port:
              number: 80
        path: /
        pathType: Prefix
  tls:
  - hosts:
    - "hello.balance.gaonnuri.site"
    secretName: letsencrypt-issuer-account-key

 

Ingress와 Certificate가 제대로 생성되었는지 확인합니다.

kubectl get ing -n <Namespace>

kubectl get certificate -n <Namespace>

 

 

 

Cert-Manager 인증서 발급 메커니즘

  1. cert-manager는 사용자가 정의한 명세(ClusterIssuer, Certificate)를 Let’s Encrypt에 전송
  2. Let’s Encrypt는 여러가지 검증을 수행하고 인증서를 발급
  3. cert-manager는 발급받은 인증서를 secret 리소스에 저장

 

 

Cert-Manager ACME 인증 메커니즘

  1. Ingress 생성 시 자동으로 함께 Certificate가 생성되고 이 때 Certificaterequest도 함께 생성되면서 letsencrypt로 인증서 발급을 요청
  2. Let’s Encrypt는 사용자가 요청한 도메인의 소유자가 사용자 것이 맞는지 검사(acme challenge)
  3. 검사 방법은 2가지가 존재합니다.(challengeType : http01, dns01)

 

1) http01

  • ACME 인증을 위해 HTTP 프로토콜을 사용하는 방법
  • 가장 일반적으로 사용하는 유형
  • 80번 포트가 방화벽에서 차단되어 있는 경우 DNS방식 사용

2) dns01

  • ACME 인증을 위해 DNS TXT레코드를 사용하는 방법
  • 와일드 카드 인증서를 발행할 수 있도록 해줌
  • Let’s Encrypt가 ACME 클라이언트에 토큰을 제공하면 클라이언트는 해당 토큰과 계정 키에서 파생된 TXT 레코드를 생성

 

 

참조 링크