전공영역 공부 기록

쿠버네티스 cert-manager로 let's encrypt 인증서 발급

악분 2021. 6. 9. 00:00
반응형
 

목차


    안녕하세요!. 이 글은 쿠버네티스 cert-manager을 이용하여 let's encrypt 인증서를 발급하는 과정을 소개합니다. 실습환경은 온프레미스에서 진행합니다.

     

    쿠버네티스, 인프라 구성 방법, Let's encrypt에 대한 설명은 생략합니다.

    https://youtu.be/jkAlpv4WAUg

     

    0) 실습문서 링크

    1. 영상 pdf: https://drive.google.com/file/d/1SbeXUT73uuBpdVkwa03u5hPSP5LHThpC/view?usp=sharing
    2. git 위키: https://github.com/choisungwook/portfolio/wiki/cert-manager-letsencrypt

     

    1) 준비

    ■ 외부통신이 되는 쿠버네티스 클러스터

    Let's encrypt 인증서를 발급하기 위해서는 Let's encrypt와 통신해야 하므로 폐쇄망은 실습이 불가능합니다.

    ■ 도메인

    ssl인증서가 인증할 도메인이 필요합니다. 저는 가비아에서 xyz도메인을 약 2000원 주고 구매했습니다.

    ■ 네임서버

    도메인을 관리하는 네임서버가 필요하고 cert-manager와 연동이 되야 합니다. 쉽게 사용할 수 있는 cloudflare을 사용했습니다.

    ■ 네임서버 액세스 토큰

    이 실습은 cert-manager dns-01 solver을 사용하므로 액세스 토큰이 필요합니다. 저는 cloudflare 액세스토큰을 사용했습니다. 액세스토큰을 발급할 때 공식문서에 언급된 권한(예: cloudflare-https://cert-manager.io/docs/configuration/acme/dns01/cloudflare/#api-keys)을 설정해야 합니다.

    ■ cert-manager 설치

    cert-manager가 설치되어 있어야 합니다.

    2) 실습환경

    제가 실습한 인프라는 [그림 1]과 같습니다.

    1. 쿠버네티스는 virtualbox안에 VM으로 구성했습니다.
    2. 제가 구매한 도메인은 공유기의 공인IP를 가르킵니다.
    3. ingress controller은 nginx ingress를 사용했고 공유기 80번포트로 포트포워딩 되어 있습니다.

     

    그림1 실습환경 인프라

     

    3) cert-manger 특징

    쉬운 인증서 생성과 만료전 자동갱신 특징이 있습니다.

    1. cert-manager는 yaml로 쉽게 인증서를 생성하고 관리합니다. 실습영상 https://youtu.be/jkAlpv4WAUg?t=255 을 보면 yaml파일을 kubectl로 실행하여 인증서를 쉽게 생성합니다.
    2. 인증서가 만료되기 전 자동갱신을 수행합니다.

     

    4) cert-manager가 let's encrypt인증서를 생성하는 과정 요약

    cert-manager는 사용자와 프로바이더(provider) 중간에서 중계 역할을 수행합니다. 인증서가 생서되면 쿠버네티스 secret리소스에 저장합니다.

    1. cert-manager는 사용자가 정의한 명세(issuer, certificate 커스텀리소스)를 Let's encrypt에 전송합니다.
    2. Let's encrypt는 사용자 여러가지 검증을 수행하고 인증서를 발급해줍니다.
    3. cert-manager는 발급받은 인증서를 secret리소스에 저장합니다.

     

    그림2 네임서버를 사용한 인증서 발급과정



    cert-manager는 인증서 발급과정 커스텀리소스로 관리합니다. kubectl describe을 사용하여 각 단계 로그를 자세히 볼 수 있습니다.

    1. Certificate는 발급받을 인증서 명세가 있는 커스텀리소스입니다. 사용자가 yaml파일로 certificate를 생성합니다.
    2. Certficate를 kubectl로 실행하면 Certificaterequest가 생성되고 let's encrypt로 인증서 발급을 요청됩니다.
    3. let's encrypt는 사용자가 요청한 도메인의 소유자가 사용자 것이 맞는지 검사(acme challenge)를 합니다. 검사 방법(solver)은 http, dns-01방법이 있습니다. Order, Challenge검사 단계를 관리하는 커스텀리소스입니다.
    이 문서에서는 dns-01 solver를 사용합니다.

     

    그림3 인증서 발급과정(출처: https://cert-manager.io/docs/concepts/acme-orders-challenges/)

     

    5) cert-manager 컴퍼넌트

    컴퍼넌트는 크게 3개로 분류됩니다.

    그림4 cert-manager 컴퍼넌트(출처: https://cert-manager.io/docs/)

     

    ① Issuers

    인증서 발급 주체입니다. self-signed, let's encrypt등이 있습니다.

    ■ let's encrypt issuer

    let's encrypt를 사용하면 staging, prod 2개의 Issuer가 있습니다. staging은 테스트용도 prod는 실제 운영단계 적용목적으로 사용됩니다. staging환경에서 발급된 인증서는 self-sisgned인증서처럼 인증되어 있지 않습니다.

    ■ namespace 적용 범위

    Issuer을 모든 namespace에 사용하려면 clussterIssuer, 특정 namespace에서만 사용하려면 Issuer을 사용하면 됩니다.

    ② certificates

    인증서가 인증할 도메인 정보 등 인증서 명세를 정의합니다.

    ③ kubernetes secrets

    Let's encrypt가 발급한 인증서는 쿠버네티스 secret 리소스에 저장됩니다.

    6) 인증서 생성 실습

    이 문서에서는 네임서버를 사용하여 도메인 소유검증(acme challenge)을 완료합니다. clusterissuer가 생성되면 cert-manager namespace의 secret에 저장됩니다.

    ① Issuer생성

     

    네임서버 api-token 생성

    공식문서를 보고 api-token을 관리한 secret리소스를 생성합니다. 이 문서에서는 cloudflare 액세스 토큰을 사용합니다.

    cloudflare 액세스 토큰발급 공식문서: https://cert-manager.io/docs/configuration/acme/dns01/cloudflare/#api-keys

     

    yaml파일 작성

    소스코드는 git wiki에 있습니다. https://github.com/choisungwook/portfolio/wiki/cert-manager-letsencrypt#clusterissue-%EC%83%9D%EC%84%B1


    clusterissue.yml파일을 생성하고 [그림 5]와 같이 설정합니다.

    1. 전체 namespace에서 issuer을 사용하기 위해 clusterIssuer을 사용합니다.
    2. let's encrypt staging서버주소를 입력합니다.
    3. 네임서버에 가입된 이메일주소를 입력합니다.
    4. clusterissuer를 저장할 secret이름을 입력합니다.
    5. 네임서버에 가입된 이메일주소를 입력합니다.
    6. 네임서버 액세스토큰 secret을 설정합니다.

     

    그림5 clusterissuer.yml

     

    yaml파일 실행

    kuebctl create명령어로 정의한 clusterissuer을 실행합니다.

    kubectl create -f clusterissuer.yml


    READY상태가 True인 것을 확인합니다. [그림 6]은 확인 예입니다.

    그림6 clusterissuer 생성확인

     

    ② certificate 생성

    certificate는 let's encrypt가 인증할 도메인 등의 정보를 정의합니다.

    소스코드는 git wiki에 있습니다. https://github.com/choisungwook/portfolio/wiki/cert-manager-letsencrypt#certificate-%EB%AA%85%EC%84%B8-%EC%A0%95%EC%9D%98


    certificate.yml파일을 생성하고 [그림 7]처럼 내용을 작성합니다. [그림 7]은 choilab.xyz, test3.choilab.xyz을 인증하기 위한 예입니다.

    1. certificate커스텀 리소스를 사용합니다.
    2. 발급된 인증서를 저장할 secret리소스 이름을 입력합니다.
    3. 사용할 issuer를 설정합니다.
    4. 인증할 공통도메인을 입력합니다.
    5. 인증할 도메인을 입력합니다.

     

    그림7 certificate.yml

     

    ③ 인증서 생성

    kuebctl create명령어로 정의한 certificate을 실행합니다.

    kubectl create -f certificate.yml


    실행한 순간 let's encrypt로 인증서 생성을 요청합니다. 인증서 생성과정은 [그림 3]과 같습니다. 몇 분정도 기다리면 let's encrypt가 인증서를 발급하고 상태가 READY로 바뀝니다. 생성된 인증서는 cetficate리소스와 같은 namespace에 secret리소스로 저장됩니다.
    장시간 기다려도 READY상태가 False이면 let's encrypt에서 도메인 소유 검증을 실패한 것입니다.

    그림8 인증서 생성 확인

     

    ④ deployment, service, ingress 생성

     

    ■ deployment, service 생성

    https접속 테스트를 위한 deployment, service를 생성합니다. 컨테이너 이미지는 nginx:latest를 사용했습니다.

    소스코드는 git wiki에 있습니다. https://github.com/choisungwook/portfolio/wiki/cert-manager-letsencrypt#%EC%9D%B8%EC%A6%9D%EC%84%9C-%EC%A0%81%EC%9A%A9-%EC%98%88%EC%A0%9C

     

    apiVersion: apps/v1 kind: Deployment metadata: name: nginx-test6 labels: app: nginx-test6 spec: replicas: 1 selector: matchLabels: app: nginx-test6 template: metadata: labels: app: nginx-test6 spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginx-test6 spec: selector: app: nginx-test6 ports: - port: 80 targetPort: 80 type: NodePort

     

    ■ ingress생성

    let's encrypt가 생성한 인증서([그림 7])를 ingress에 적용합니다.

    소스코드는 git wiki에 있습니다. https://github.com/choisungwook/portfolio/wiki/cert-manager-letsencrypt#%EC%9D%B8%EC%A6%9D%EC%84%9C-%EC%A0%81%EC%9A%A9-%EC%98%88%EC%A0%9C

     

    1. certificate.yml에서 설정한 secret을 입력합니다.
    2. certificate.yml에서 설정한 도메인을 입력합니다.

    그림9 ingress.yml

     

    ⑤ 접속확인

    staging Issuer가 발급한 인증서는 테스트 목적이기 때문에 [그림 10]와 같이 경고메세지가 출력됩니다. 발급된 인증서는 발급자가 (STAGING)인 것이 특징입니다.

    그림10 let's encrypt가 인증한 도메인 접속화면

     

    ⑥ prod Issuer생성과 다시 certificate, ingress생성

    진짜 let's encrypt가 인증한 인증서를 발급하기 위해 prod ClusterIssuer을 생성하고 ② ~ ⑤과정을 반복하시면 됩니다. prod CluseterIssuer는 server주소만 다를 뿐 staging입력내용과 동일합니다. 실습 전 staging 리소스는 삭제합니다.

    clusterissuer만 다루고 중복되는 나머지과정은 생략합니다.

     

    ■ clusterissuer 생성

    1. 전체 namespace에서 issuer을 사용하기 위해 clusterIssuer을 사용합니다.
    2. let's encrypt staging서버주소를 입력합니다.
    3. 네임서버에 가입된 이메일주소를 입력합니다.
    4. clusterissuer를 저장할 secret이름을 입력합니다.
    5. 네임서버에 가입된 이메일주소를 입력합니다.
    6. 네임서버 액세스토큰 secret을 설정합니다.

     

    그림11 prod-ClusterIssuer.yml

     

    접속확인

    prod Issuer로 인증서를 성공적으로 발급받으면 [그림 12]와 같이 발급자가 R3으로 표시되고 더이상 경고창이 뜨지 않습니다.

    그림12 인증서 발급 성공

     

    마치며

    이 문서에서는 cloudflare를 사용했지만 aws route 53 등 public cloud와 연동해서 사용할 수 있습니다. 이외에도 self-sisgne인증서도 발급할 수 있습니다.

    EKS를 실습할 수 있는 돈이 충분하다면 열심히 했을텐데ㅜ.ㅜ
    반응형