[kubernetes] Cert manager + Let's encrypt
네이버 클라우드에서
kubernetes로 시스템을 구축했단말이지..
그런데 왠일인지...
로드 발란서에 SSL을 사서 붙여야 하더라구
스타트업이 인증서 살 돈이 어딨어?
그래서 let's encrypt랑 cert-manager로 구축했어.
이 이야기를 하려고 했는데..
지금 살펴보니 😅😅
👇👇👇
Certificate manager 뭔데!
왜 로드 발란서에 붙이기 쉬운건데?
Certificate manager에서 발급받고
로드 발란서에 붙이면 끝이네;;;
공짜고 갱신도 필요없고..
좋긴한데 나는 뻘찟했네 ㅠㅠ
아니 분명 없었던거 같은데......🤔
암튼
난 kubernetes에 cert-manager를 설치하고
Let's encrypt에서 발급받아 했어.
그런데 그 과정이 꽤~~
너저분(?)했다고나 할까?
전체적으로 간단하게 설명하면 이래.
1. cert-manager가 let's encrypt에 인증서를 요청햇!
2. let's encrypt는 도메인의 소유주를 확인하기 위한 키를 발급햇!
3. 그 키를 cert-manager가 dns 서버에 등록햇!
4. let's encrypt에 도메인이 확인되면 인증서를 발급햇!
5. cert-manager가 인증서를 잘 저장햇!
6. cert-manager가 동일한 방법으로 3개월마다 자동 갱신햇!
이 때 DNS에 접근할 수 있는 권한을 Cert-manager에 줘야 해.
이런 방식을 DNS01이라고 하는데
아래가 Cert-manager에서 DNS01이 가능한 아이들 목록이야.
여기서 현실적으로 가능한 게 Google DNS 뿐이 없더라구..
(참고로 HTTP01 방식이 훨씬 쉽게 동작하지만 와일드 카드가 안됨)
그래서 후이즈에 있는 도메인의 dns를 gcp dns로 설정하고
gcp iam에서 Cert-manager가 사용할 dns01-solver라는 이름의 롤도 하나 만들어 줬어.
이 다음에는 아래의 명령으로 key 파일을 생성하고
gcloud iam service-accounts keys create key.json \
--iam-account dns01-solver@$PROJECT_ID.iam.gserviceaccount.com
그걸로 다시 kubernetes에 secret을 만들지.
kubectl create secret generic clouddns-dns01-solver-svc-acct \
--from-file=key.json
그 다음에는 인증서가 저장될 secret을 하나 더 만들고~
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: istio-tls
namespace: istio-system
type: kubernetes.io/tls
stringData:
tls.key: ""
tls.crt: ""
이젠 issuer를 만들고
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod-dns01
namespace: istio-system
spec:
acme:
# The ACME server URL
server: https://acme-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: "너의 이메일!"
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-prod-dns01
# Enable the HTTP-01 challenge provider
solvers:
- dns01:
cloudDNS:
# The ID of the GCP project
project: "너의 프로젝트"
# This is the secret used to access the service account
serviceAccountSecretRef:
name: clouddns-dns01-solver-svc-acct
key: key.json
Issuer가 정상적으로 생성되고 나면 Certificate를 만들어 마무으리!
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: test-domain-certificate
namespace: istio-system
spec:
dnsNames:
- "*.test.domain"
- "test.domain"
secretName: istio-tls
issuerRef:
name: letsencrypt-prod-dns01
kind: ClusterIssuer
보통 1-2분? 정도 안에 인증서 발급이 마무리 되는 것 같아.
이렇게 보면 심플해보이는데..
여러가지 문제들 때문에 꽤 애를 먹었어.
👇👇👇
1. kubernetes DNS 문제
cert-manager가 acme 셀프 체크를 하다가 실패하는 경우가 있는데
cert-manager에 기본적으로 등록된 네임서버가 도메인을 못찾아서 그렇데.
그래서 아래처럼 설치할 때 도메인 서버를 지정하면 해결돼.
helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --version v1.12.0 --set installCRDs=true --set 'extraArgs={--dns01-recursive-nameservers-only,--dns01-recursive-nameservers=8.8.8.8:53\,1.1.1.1:53}'
2. CRDs
음.. 잘 기억이 안나는데..
resource type 에러? 비슷한게 나오면
아래와 같이 Cert-manager의 CRDs를 설치해주면 해결돼.
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.2/cert-manager.crds.yaml
이 외에는 딱히 큰 오류가 없었는데
그럼에도 불구하고
인증서가 잘 발급되어지지 않는다면
아래와 같은 명령들로 어디서 오류가 났는지 확인할 수 있어.
k get certificate -n istio-system #인증서 보기
k get clusterissuer -n istio-system #이슈어 보기
k describe clusterissuer letsencrypt-prod-dns01 #이슈어 자세히 보기
k get certificaterequest -n istio-system #인증서 요청 보기
k describe certificaterequest -n istio-system #인증서 요청 자세히 보기
k get order -n istio-system #order
k describe order testx-main-certificate-jn6hn-115670144 -n istio-system #order 자세히
k describe challenge #challenge 자세히 보기
그리고 뭐가 진짜 잘 안된다 그러면!
아래 링크를 참고해.
생각보다 트러블 슈팅이 자세하게 잘 나와 있어.
https://cert-manager.io/docs/troubleshooting/acme/
또 한가지 주의할 점은!
lets encrypt에 요청할 수 있는 인증서, 오더, 챌린지 수에 제한이 있어.
그러니까 너무 많이 인증서를 요청하면 같은 도메인으로 인증서 발급이 제한될 수 있는거지.
그래서 보통 staging 환경에서 인증서를 테스트해보고
그 다음에 production 인증서를 발급받는게 정석임.
뭐 별다른 건 없고 issuer 만들 때 staging 서버에 요청하면 돼.
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging-dns01
namespace: istio-system
spec:
acme:
# The ACME server URL 여기여기여기여기여기여기여기여기가 Staging 서버 주소~!!!!!!!
server: https://acme-staging-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: "제발 너의 이메일~~~~~"
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-staging-dns01
# Enable the HTTP-01 challenge provider
solvers:
- dns01:
cloudDNS:
# The ID of the GCP project
project: "프로젝트 id"
# This is the secret used to access the service account
serviceAccountSecretRef:
name: clouddns-dns01-solver-svc-acct
key: key.json
아래 링크를 참고해!
https://letsencrypt.org/docs/staging-environment/
아이고 길다~~~
걍 네이버 인증서 쓰자!
안녕