[K3s-05] K3s ingress에 TLS 인증서 발급 자동화
목차
Let’s encrypt + ACME dns-01 (Recommended) #
Let's encrypt
와 cert-manager
를 사용하면 우리의 k3s 클러스터에 TLS 인증서를 첨부할 수 있습니다. helm
을 사용하여 cert-manager
를 설치합니다. 이 게시글에서는 helm
의 설치 방법과 helm
이 무엇인지 설명하지 않겠습니다. 만약 helm
이 설치되어 있지 않다면 helm 문서를 참조하세요.
helm repo add jetstack https://charts.jetstack.io
helm repo update
curl -L -o cert-manager.yaml https://github.com/cert-manager/cert-manager/releases/download/v1.8.0/cert-manager.crds.yaml
kubectl apply -f cert-manager.yaml
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.8.0
kubectl get pods -n cert-manager
먼저, 전체 네임스페이스에서 접근할 수 있는 ClusterIssuer를 생성합니다. 또한 Cloudflare API 토큰을 저장하는 k3s secret을 생성합니다. 이 Cloudflare API 토큰은 dns-01 챌린지에서 DNS zone을 편집할 수 있는 접근 권한을 있어야 합니다. AWS의 Route53을 사용하는 경우, 이 블로그(와일드카드 인증서와 관련된 미디엄 블로그)에 자세히 기술되어 있습니다. 따라서 기본적으로는 현재 DNS를 설정하기 위해 사용하고 있는 Cloud provider를 먼저 알아내는 합니다. cert-manager
가 지원하는 DNS 제공업체의 상세 목록은 acme dns01관련된 cert-manager 설정에 기재되어 있습니다.
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-stg
spec:
acme:
email: [email protected]
# let's encrypt staging 환경
server: https://acme-staging-v02.api.letsencrypt.org/directory
privateKeySecretRef:
# 계정의 개인 키를 저장할 Secret 리소스
name: le-issuer-acct-key
solvers:
- dns01:
cloudflare:
email: [email protected]
apiTokenSecretRef:
name: cloudflare-api-token-secret
key: api-token
selector:
dnsZones:
- 'jaehong21.com'
- '*.jaehong21.com'
---
apiVersion: v1
kind: Secret
metadata:
name: cloudflare-api-token-secret
namespace: cert-manager
type: Opaque
stringData:
api-token: <cloudflare-api-token>
그런 다음 kubectl get clusterissuer -A
로 발행자의 상태 Ready
가 True
인지 확인하세요. 이 작업은 시간이 조금 걸릴 수 있습니다.
! 중요: https://letsencrypt.org/docs/staging-environment/
위의 예제는 Let’s Encrypt의 스테이징 환경을 사용하는 것으로, 인증서 발급에 대한 속도 제한이 없습니다. 브라우저에서 신뢰할 수 있는(유효한) 인증서를 받고자 할 때는 위 URL을 https://acme-v02.api.letsencrypt.org/directory
로 교체해야 합니다.
이제 기존 ClusterIssuer를 사용하여 인증서를 생성합니다. dns-01 challenge를 이용할 때는 와일드카드 인증서를 발급받을 수 있지만, http-01 challenge를 사용하는 경우에는 와일드카드 인증서를 획득하기 어려우며, 발급받고자 하는 인증서의 특정 URL을 직접 명시해주어야합니다.
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: le-jaehong21-com
namespace: default
spec:
secretName: le-jaehong21-com
issuerRef:
name: letsencrypt-stg
kind: ClusterIssuer
commonName: '*.jaehong21.com'
dnsNames:
- "*.jaehong21.com"
# 인증서가 생성되었는지 확인
# 처음에는 `Ready` 상태가 `False`입니다
kubectl get certs -A
# 아래 명령어로 인증서 발급 진행 상황을 확인할 수 있습니다
# 완료되면 리소스가 표시되지 않습니다
kubectl get challenges -A
# 이후에 인증서의 `Ready`도 `True`인지 다시 확인하세요
(Cloudflare) 대시보드를 확인하여 dns-01 챌린지와 함께 사용되는 호스팅 존에 TXT 레코드가 추가되었는지 진행 상황을 볼 수도 있습니다.
Finally, implement the tls secret that is created with certificate to the ingress.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: traefik-ingress
annotations:
traefik.ingress.kubernetes.io/router.tls: "true"
spec:
ingressClassName: traefik
rules:
- host: k3s.jaehong21.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-deployment
port:
number: 80
tls:
- hosts:
- k3s.jaehong21.com
secretName: le-jaehong21-com
Cloudflare Origin CA #
저의 경우에는 Cloudflare에서 DNS 레코드들을 관리하고 있습니다. Cloudflare는 Let’s Encrypt에 비해 훨씬 긴 만료 날짜의 인증서를 발급할 수도 있습니다.
kubectl create secret generic k3s-tls-secret --from-file=tls.crt=./server.crt --from-file=tls.key=./server.key --namespace dev
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: traefik-ingress
annotations:
traefik.ingress.kubernetes.io/router.tls: "true"
spec:
ingressClassName: traefik
rules:
- host: k3s.jaehong21.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-deployment
port:
number: 80
tls:
- secretName: k3s-tls-secret
그러나 Origin CA는 Cloudflare Network 자체에서만 유효한 자체 서명 인증서(Self-signed certifiacte)입니다. 따라서 아래 예와 같이 프록시 설정을 이용하여, Cloudflare Network를 거칠 수 있도록 해야 합니다. 이 경우 요청이 Cloudflare Network를 통해 전송되므로 LAX 위치를 통해 다시 라우팅될 수 있습니다.
resource "cloudflare_record" "k3s_test" {
zone_id = var.jaehong21_com.zone_id
name = "k3s"
value = "43.202.242.99"
proxied = true
type = "A"
ttl = 1
}
위 예시처럼, terraform으로 Cloudflare DNS 레코드를 관리하는 경우, terraform cloudflare 제공자를 최신 버전으로 업그레이드해야 합니다(최소한 버전 4 이상). 버전 3에서는 terraform에서 proxied
값을 true
로 수정하고 유지하는 데 버그가 있었습니다.