본문으로 건너뛰기
버전: 1.0.3

7.3. 인증서 관리

어떨 때 보는가

  • HTTPS 접속에서 인증서 오류가 날 때
  • 인증서 만료가 가까워졌을 때
  • 새 도메인에 인증서를 발급할 때

인증서가 필요한 이유

HTTPS 로 접속하면 브라우저와 서버가 주고받는 내용이 암호화됩니다. 이때 서버는 "내가 그 도메인의 진짜 주인이다" 를 증명해야 하는데, 그 증명서가 인증서입니다.

인증서에는 유효 기간 이 있습니다. 만료되면 브라우저가 경고를 띄우고 접속을 막습니다. 도메인이 여럿이면 만료 시각도 제각각이라 손으로 관리하기 어렵습니다.

cert-manager 가 하는 일

cert-manager 는 클러스터 안에서 인증서를 자동으로 발급하고 갱신 합니다.

동작 방식은 Kubernetes 의 다른 자원과 같습니다. "이 도메인의 인증서가 필요하다" 는 요청 (Certificate)을 만들어 두면, cert-manager 가 그 상태를 맞추려고 발급을 진행하고, 만료가 가까워지면 스스로 갱신합니다.

발급 결과는 Secret 으로 저장되고, Ingress 가 그 Secret 을 가리켜 씁니다(3.4 장, 5.1 장).

인증서 목록

인증서 관리 > 인증서 로 들어갑니다.

인증서 목록
설명
이름인증서 자원 이름
네임스페이스속한 네임스페이스
준비발급이 끝났는지
발급 기관어떤 Issuer 로 발급했는지
만료인증서 만료 시각

준비True 면 정상입니다.

인증서는 네임스페이스 단위 자원입니다. Ingress 와 같은 네임스페이스 에 있어야 쓸 수 있습니다. 다른 네임스페이스의 Secret 은 참조되지 않습니다.

인증서 상세

이름을 누르면 발급 상태와 만료 시각을 자세히 봅니다.

인증서 상세
항목무엇을 확인하는가
조건(Conditions)Ready 가 True 인지, False 면 사유
만료 시각언제까지 유효한지
갱신 예정 시각cert-manager 가 언제 갱신을 시도할지
대상 도메인이 인증서가 보증하는 주소
저장 Secret발급 결과가 담긴 Secret 이름

대상 도메인이 실제 접속 주소와 다르면 브라우저가 인증서 오류를 냅니다. Ingress 의 호스트와 같은지 확인하십시오(5.1 장).

*.example.com 처럼 와일드카드로 발급하면 하위 도메인 전체에 쓸 수 있습니다. 다만 소유 확인 방식이 달라져(DNS 확인만 가능) 설정이 까다롭습니다.

발급 기관

인증서를 어디서 받을지 정하는 설정입니다.

종류적용 범위
Issuer한 네임스페이스 안에서만
ClusterIssuer클러스터 전체

인증서 관리 > 클러스터 발급자발급자 에서 각각 봅니다.

발급 방식은 크게 세 가지입니다.

방식설명폐쇄망
자체 서명cert-manager 가 스스로 만든 인증서로 서명가능
내부 인증 기관(CA)조직이 가진 CA 인증서로 서명가능. 대개 이 방식을 씁니다
ACME공인 기관에서 자동으로 발급받음외부 통신이 필요해 불가

ACME(Automatic Certificate Management Environment)인증서를 사람 손을 거치지 않고 발급받기 위한 통신 규약 입니다. 예전에는 인증 기관 홈페이지에서 신청서를 넣고 심사를 기다려 파일을 내려받았는데, ACME 는 이 과정을 프로그램끼리 주고받아 끝냅니다.

순서는 이렇습니다.

순서하는 일
1인증서가 필요한 쪽이 인증 기관에 "이 도메인 인증서를 달라" 고 요청합니다
2인증 기관이 "그 도메인이 정말 당신 것인지 증명하라" 며 과제를 냅니다
3요청한 쪽이 과제를 수행합니다 (정해진 경로에 파일을 두거나 DNS 에 값을 넣습니다)
4인증 기관이 밖에서 확인하고, 맞으면 인증서를 발급합니다

2~3 단계 때문에 폐쇄망에서는 쓸 수 없습니다. 인증 기관이 인터넷에서 우리 서버나 DNS 에 접근해야 하는데 폐쇄망은 그 경로가 없습니다. OrderChallenge 라는 자원이 이 규약에서 나온 것입니다(아래 "발급 과정 자원").

ACME 를 쓰는 대표적인 인증 기관이 Let's Encrypt 이고, 무료로 발급합니다. 자세한 절차는 아래 "Let's Encrypt 로 공인 인증서 받기" 에 있습니다.

폐쇄망에서는 내부 CA 를 ClusterIssuer 로 등록해 씁니다. 이 인증서는 공인 기관이 서명한 것이 아니므로, 접속하는 PC 에 조직 CA 인증서를 미리 신뢰 목록에 넣어야 브라우저 경고가 사라집니다.

발급 과정 자원

인증서를 요청하면 다음 자원이 순서대로 만들어집니다.

인증서 발급 과정
자원하는 일
Certificate원하는 인증서를 선언합니다
CertificateRequest실제 서명 요청입니다
OrderACME 방식에서 만들어지는 주문
Challenge도메인 소유를 증명하는 절차

내부 CA 방식에서는 Order·Challenge 가 만들어지지 않습니다. CertificateRequest 에서 바로 서명되기 때문입니다.

발급이 멈추면 이 순서로 따라가며 어느 단계에서 멈췄는지 확인합니다. 각각 인증서 관리 메뉴 아래에 화면이 있습니다.

자체 서명 인증서 만들기 — 단계별

폐쇄망에서 가장 많이 쓰는 방식입니다. 내부 CA 를 한 번 만들어 두고, 그 CA 로 서비스마다 인증서를 찍어 냅니다.

CA 를 거치지 않고 서비스마다 자체 서명 인증서를 따로 만들 수도 있지만 권하지 않습니다. 인증서마다 서명 주체가 달라 접속하는 PC 에 인증서 개수만큼 신뢰 등록을 해야 합니다. 내부 CA 를 하나 두면 그 CA 하나만 등록하면 됩니다.

만드는 순서는 네 단계입니다. 앞 단계가 뒤 단계의 재료가 되므로 순서를 지켜야 합니다.

자체 서명 인증서를 만드는 네 단계

각 단계의 YAML 은 Console 의 자원 만들기 또는 YAML 편집기로 적용합니다 (1.2 장).

1단계 — 자체 서명 발급 기관

CA 인증서 자체를 서명해 줄 것이 필요합니다. 맨 처음 인증서는 서명해 줄 상위가 없으므로 스스로 서명 합니다. 이 발급 기관은 다음 단계에서 한 번 쓰고 끝입니다.

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: selfsigned-cluster-issuer
spec:
selfSigned: {}

spec.selfSigned 가 빈 객체인 것이 맞습니다. 설정할 값이 없습니다.

2단계 — 내부 CA 인증서

조직의 뿌리 인증서를 만듭니다. isCA: true 가 이 인증서를 "다른 인증서를 서명할 수 있는 인증서" 로 만듭니다.

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: cluster-root-ca
namespace: cert-manager
spec:
isCA: true # 다른 인증서를 서명할 수 있는 인증서
commonName: cluster-root-ca
secretName: cluster-root-ca-secret # CA 인증서와 개인키가 여기 저장됩니다
duration: 87600h # 10년
renewBefore: 8760h # 만료 1년 전에 갱신
privateKey:
algorithm: RSA
size: 4096 # CA 는 오래 쓰므로 넉넉히
issuerRef:
name: selfsigned-cluster-issuer
kind: ClusterIssuer
항목설명
isCAtrue 면 서명용 인증서가 됩니다. 서비스 인증서에는 넣지 않습니다
secretName만들어진 인증서와 개인키가 저장될 Secret 이름
duration유효 기간. 시간 단위(h)로 씁니다. 87600h = 10년
renewBefore만료 몇 시간 전에 갱신할지
privateKey.size키 길이. CA 는 4096, 서비스 인증서는 2048 이 일반적입니다

CA 는 길게 잡습니다. CA 가 바뀌면 그것으로 서명한 인증서를 모두 다시 발급해야 하고, 접속하는 PC 의 신뢰 목록도 전부 갈아야 합니다.

namespace: cert-manager 로 두는 이유 는 다음 단계의 ClusterIssuer 가 이 Secret 을 그 네임스페이스에서 찾기 때문입니다. 다른 곳에 만들면 찾지 못합니다.

3단계 — CA 발급 기관

앞에서 만든 CA 로 서명하는 발급 기관입니다. 이제부터 인증서는 모두 이것을 가리킵니다.

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: cluster-ca-issuer
spec:
ca:
secretName: cluster-root-ca-secret # 2단계에서 만든 Secret

여기까지가 한 번만 하는 준비입니다.

4단계 — 서비스 인증서

실제로 서비스에 붙일 인증서입니다. 서비스마다 하나씩 만듭니다.

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: app-tls
namespace: my-app
spec:
secretName: app-tls-secret # Ingress 가 이 이름을 가리킵니다
duration: 8760h # 1년
renewBefore: 720h # 만료 30일 전 갱신
commonName: app.example.com
dnsNames: # 이 인증서가 보장하는 주소 목록
- app.example.com
- app.my-app.svc.cluster.local
privateKey:
algorithm: RSA
size: 2048
issuerRef:
name: cluster-ca-issuer # 3단계에서 만든 발급 기관
kind: ClusterIssuer

dnsNames 에 실제로 접속할 주소를 빠짐없이 적으십시오. 여기 없는 주소로 접속하면 브라우저가 "인증서 이름이 맞지 않는다" 고 경고합니다. 클러스터 안에서만 쓰는 서비스라면 내부 주소(<서비스>.<네임스페이스>.svc.cluster.local)도 함께 적습니다.

commonName 은 옛 방식이고 지금은 dnsNames 를 봅니다. 둘 다 적되 commonName 값은 dnsNames 에도 반드시 포함시키십시오.

발급 확인

Console 의 인증서 관리 > 인증서 목록에서 준비 열이 True 가 되면 끝입니다. 상세 화면에서 유효 기간과 갱신 예정 시각을 확인할 수 있습니다.

접속하는 PC 에 CA 등록

내부 CA 로 만든 인증서는 브라우저가 모르는 CA 라 경고를 냅니다. 2단계에서 만든 CA 인증서를 접속하는 PC 의 신뢰 목록에 넣어야 경고가 사라집니다. 이 배포는 운영 담당자가 합니다 — 회사 PC 에 일괄로 넣는 방식이 일반적입니다.

Let's Encrypt 로 공인 인증서 받기

인터넷에 공개하는 서비스라면 공인 인증서를 받을 수 있습니다. cert-manager 가 앞에서 설명한 ACME 규약으로 Let's Encrypt 에서 자동으로 발급받고 갱신합니다.

폐쇄망에서는 쓸 수 없습니다. 발급 과정에서 Let's Encrypt 서버와 통신해야 하고, 도메인 소유 확인을 위해 외부에서 우리 서비스로 접속할 수 있어야 합니다. COP 는 폐쇄망 설치가 기본이므로 이 방식은 인터넷에 노출된 서비스에만 해당합니다.

도메인 소유를 어떻게 증명하는가

Let's Encrypt 는 "이 도메인이 정말 당신 것인가" 를 확인한 뒤 발급합니다. 확인 방식이 두 가지입니다.

방식확인 방법필요한 것
HTTP-01우리 웹 서버의 특정 경로에 임시 파일을 두고 Let's Encrypt 가 밖에서 읽습니다80 포트가 인터넷에서 열려 있어야 합니다
DNS-01DNS 에 임시 레코드를 넣고 Let's Encrypt 가 조회합니다DNS 제공자 API 접근 권한

HTTP-01 이 간단합니다. 다만 *.example.com 같은 와일드카드 인증서는 DNS-01 로만 받을 수 있습니다.

1단계 — ACME 발급 기관 (연습용)

처음에는 반드시 연습용(staging) 서버로 시험하십시오. Let's Encrypt 운영 서버에는 발급 한도가 있습니다. 특히 같은 도메인 조합으로는 일주일에 5장 까지만 받을 수 있어, 설정을 잘못한 채 여러 번 시도하면 그 주 내내 발급이 막힙니다. 연습용 서버는 한도가 넉넉합니다.

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
email: admin@example.com # 만료 알림을 받을 주소
privateKeySecretRef:
name: letsencrypt-staging-key # 계정 키가 저장될 Secret (자동 생성)
solvers:
- http01:
ingress:
ingressClassName: default # 임시 경로를 만들 Ingress 컨트롤러
항목설명
server연습용 주소. 운영은 아래 2단계 주소를 씁니다
email만료 임박·문제 발생 시 Let's Encrypt 가 알리는 주소. 실제로 받는 주소를 넣습니다
privateKeySecretRefACME 계정 키를 담을 Secret. 미리 만들 필요 없이 자동으로 생깁니다
solvers소유 확인 방식. 여기서는 HTTP-01

연습용 서버가 발급한 인증서는 브라우저가 신뢰하지 않습니다. 경고가 뜨는 것이 정상이며, "발급 절차가 끝까지 도는지" 만 확인하는 용도입니다.

2단계 — ACME 발급 기관 (운영)

연습용으로 발급이 확인되면 주소만 바꿔 운영용을 만듭니다.

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: admin@example.com
privateKeySecretRef:
name: letsencrypt-prod-key
solvers:
- http01:
ingress:
ingressClassName: default

3단계 — 인증서 요청

발급 기관 이름만 바꾸면 자체 서명 방식과 형태가 같습니다.

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: app-tls
namespace: my-app
spec:
secretName: app-tls-secret
dnsNames:
- app.example.com
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer

durationrenewBefore 를 적지 않았습니다. Let's Encrypt 는 유효 기간이 90일로 고정되어 있어 우리가 정할 수 없습니다. 적어도 무시되거나 오류가 납니다. 갱신 시점은 cert-manager 가 알아서 잡습니다.

4단계 — Ingress 에 붙이기

Certificate 를 따로 만들지 않고 Ingress 에 주석 한 줄 만 붙여도 됩니다. cert-manager 가 Certificate 를 대신 만들어 줍니다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
namespace: my-app
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: default
tls:
- hosts:
- app.example.com
secretName: app-tls-secret # cert-manager 가 이 이름으로 만들어 줍니다
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app
port:
number: 8080

이 방식은 자체 서명·내부 CA 발급 기관에도 똑같이 씁니다. 주석의 발급 기관 이름만 바꾸면 됩니다.

DNS-01 을 쓸 때

와일드카드 인증서가 필요하거나 80 포트를 열 수 없으면 DNS-01 을 씁니다. solvers 부분만 달라지며, DNS 제공자마다 설정이 다릅니다. 아래는 형태만 보이는 예입니다.

solvers:
- dns01:
cloudflare:
email: admin@example.com
apiTokenSecretRef:
name: cloudflare-api-token
key: api-token

DNS 제공자 접근 정보를 Secret 으로 미리 만들어 두어야 합니다(3.4 장).

인증서를 서비스에 연결

  1. Certificate 를 만들면서 저장할 Secret 이름을 정합니다.
  2. 준비True 가 될 때까지 기다립니다.
  3. Ingress 의 TLS 설정에 그 Secret 이름을 넣습니다(5.1 장).

Ingress 에 cert-manager.io/cluster-issuer 주석을 붙이면 Certificate 를 따로 만들지 않아도 cert-manager 가 알아서 만들어 줍니다(위 예 참고).

쓰면 좋은 점

인증서를 손으로 관리하면 다음 일이 반복됩니다 — 발급 요청, 파일 내려받기, Secret 만들기, 만료일 달력에 적기, 만료 전에 같은 일 다시. cert-manager 는 이것을 없앱니다.

이점설명
만료로 인한 장애가 없어집니다가장 큰 이유입니다. 서비스 중단 원인 중 인증서 만료는 흔하면서도 예방이 쉬운 축에 듭니다
갱신에 손이 가지 않습니다만료 전에 자동으로 새로 받고 Secret 을 바꿉니다. Ingress 설정은 그대로입니다
설정이 코드로 남습니다어떤 인증서가 어떤 주소를 보장하는지 YAML 에 적혀 있어 형상 관리에 넣을 수 있습니다
개인키가 클러스터 밖으로 나가지 않습니다키는 클러스터 안에서 만들어져 Secret 에 저장됩니다. 메일이나 공유 폴더로 주고받을 일이 없습니다
한눈에 봅니다Console 화면에서 모든 인증서의 만료일과 상태를 함께 확인합니다
서비스마다 따로 발급할 수 있습니다하나로 돌려 쓰지 않아도 되므로, 인증서 하나가 유출돼도 그 서비스만 다시 발급하면 됩니다

주의할 점

항목내용
CA 개인키가 최상위 자산입니다cluster-root-ca-secret 이 유출되면 누구든 우리 조직 이름으로 인증서를 만들 수 있습니다. 이 Secret 을 볼 수 있는 사람을 제한하십시오(7.1 장)
Secret 은 암호화되어 있지 않습니다Kubernetes Secret 은 인코딩만 되어 있습니다. 그 네임스페이스의 Secret 을 읽을 수 있는 사람은 개인키도 읽습니다(3.4 장)
CA 를 바꾸면 전부 다시 해야 합니다그 CA 로 서명한 인증서를 모두 재발급하고 접속하는 PC 의 신뢰 목록도 갈아야 합니다. CA 기간을 길게 잡는 이유입니다
애플리케이션이 직접 읽으면 재시작이 필요합니다Ingress 컨트롤러는 Secret 변경을 알아채지만, 파일을 직접 읽는 애플리케이션은 갱신을 모릅니다. 갱신 뒤 파드를 다시 시작하는 절차를 마련해 두십시오
Let's Encrypt 는 발급 한도가 있습니다연습용 서버로 먼저 시험하십시오. 운영 서버에서 잘못된 설정으로 반복 시도하면 그 주 동안 막힙니다
dnsNames 를 빠뜨리면 경고가 뜹니다나중에 주소를 추가하면 Certificate 를 고쳐 재발급해야 합니다
폐쇄망에서 ACME 는 동작하지 않습니다발급 기관을 잘못 고르면 Challenge 단계에서 멈춘 채 끝나지 않습니다
만료일을 여전히 확인하십시오자동 갱신이 실패할 수도 있습니다(발급 기관 문제, 권한 변경, DNS 변경). Console 목록에서 정기적으로 봅니다

COP 클러스터 자체의 인증서는 cert-manager 가 관리하지 않습니다. 그것은 별도 체계이며 7.4 장에서 다룹니다. 두 가지를 혼동하면 "인증서 관리 화면이 정상인데 클러스터가 멈추는" 상황이 생깁니다.

자동 갱신

cert-manager 는 만료 전에 스스로 갱신합니다. 기본은 유효 기간의 3분의 2 가 지난 시점 입니다. 90일짜리 인증서면 60일쯤에 갱신합니다.

갱신되면 Secret 내용이 자동으로 바뀝니다. Ingress 설정은 고치지 않아도 됩니다.

Ingress 컨트롤러는 Secret 변경을 감지해 새 인증서를 씁니다. 다만 애플리케이션이 인증서를 직접 읽는 구조라면 파드를 다시 시작해야 반영될 수 있습니다.

발급이 안 될 때

증상확인할 것
준비가 False 로 남음Certificate 상세의 조건과 이벤트
CertificateRequest 에서 멈춤Issuer 이름이 맞는지, 그 Issuer 가 준비 상태인지
Challenge 에서 멈춤도메인 소유 확인 방식이 이 환경에서 되는지. 폐쇄망에서는 외부 확인 방식을 쓸 수 없습니다
Secret 이 안 생김인증서가 아직 발급되지 않았습니다. 준비 상태를 먼저 확인
브라우저 경고대상 도메인 불일치, 또는 내부 CA 를 PC 가 신뢰하지 않음

Certificate 상세의 이벤트 에 원인이 남습니다. 먼저 여기를 보십시오.