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 에
접근해야 하는데 폐쇄망은 그 경로가 없습니다. Order 와 Challenge 라는 자원이 이 규약에서
나온 것입니다(아래 "발급 과정 자원").
ACME 를 쓰는 대표적인 인증 기관이 Let's Encrypt 이고, 무료로 발급합니다. 자세한 절차는 아래 "Let's Encrypt 로 공인 인증서 받기" 에 있습니다.
폐쇄망에서는 내부 CA 를 ClusterIssuer 로 등록해 씁니다. 이 인증서는 공인 기관이 서명한 것이 아니므로, 접속하는 PC 에 조직 CA 인증서를 미리 신뢰 목록에 넣어야 브라우저 경고가 사라집니다.
발급 과정 자원
인증서를 요청하면 다음 자원이 순서대로 만들어집니다.
| 자원 | 하는 일 |
|---|---|
| Certificate | 원하는 인증서를 선언합니다 |
| CertificateRequest | 실제 서명 요청입니다 |
| Order | ACME 방식에서 만들어지는 주문 |
| 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
| 항목 | 설명 |
|---|---|
isCA | true 면 서명용 인증서가 됩니다. 서비스 인증서에는 넣지 않습니다 |
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-01 | DNS 에 임시 레코드를 넣고 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 가 알리는 주소. 실제로 받는 주소를 넣습니다 |
privateKeySecretRef | ACME 계정 키를 담을 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
duration 과 renewBefore 를 적지 않았습니다. 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 장).
인증서를 서비스에 연결
- Certificate 를 만들면서 저장할 Secret 이름을 정합니다.
- 준비 가
True가 될 때까지 기다립니다. - 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 상세의 이벤트 에 원인이 남습니다. 먼저 여기를 보십시오.