-
HTTPS 통신을 위해서는 SSL/TLS 인증서 관리가 필요하다.
만료일을 깜빡하면 HTTPS 통신이 안되어 서비스가 마비되는 대참사가 간혹 나오고 있는데, 쿠버네티스에서는 cert-manager를 사용하여 이 같은 상황을 막는 것이 거의 표준으로 자리 잡고 있다.

위 그림은 cert-manager가 인증서를 발급하고 관리하는 전체적인 흐름이다.
크게 4가지 컴포넌트로 구성된다.
1. Issures(Cluster Issures): 인증서를 실제로 발급해주는 인증기관(CA)에 대한 정보이다. Let's Encrypt, Hashicorp Valut, 혹은 자체 생성한 CA등이 여기에 해당한다. Cluster가 붙는 것은 클러스 전체 공유 가능한 인증서이다.
2. cert-manager: 모든 과정을 컨트롤 하는 컨틀롤러(Controller)이다. 리소스를 감시하며 인증서를 자동으로 발급/갱신한다.
3. Certificates: 어떤 도메인(ex. foo.bar.com)에 대해 어떤 Issuer를 사용해 인증서를 만들 것인지에 대한 명세서이다.
4. Kubernetes Secret: cert-manager가 최종 발급 받은 개인키(Private Key)와 인증서(signed keypair)를 저장하는 공간이다. Ingress나 Application은 이 Secret을 마운트 하여 HTTPS 통신을 가능하게 한다.
내부용 HTTPS vs 외부용 HTTPS
인증서를 발급할 때, 서비스가 클러스터 내부에서만 도메인을 쓰는지, 외부에 노출되는지에 따라 내부 설정이 달라진다.

아래는 각각의 예시이다.
예시 전: cert-manager helm 설치
helm install cert-manager jetstack/cert-manager \ --namespace cert-manager \ --create-namespace \ --set crds.enabled=true내부용 HTTPS 인증서 발급
클러스터 내부 통신용이며, 사내 개발 환경등 내부에서만 접근이 필요할때 사용할 수 있는 구성이다.
cert-manager가 직접 자체 루트 CA(root CA)역할을 하게할 수 있다.
1. cert-manager를 통해 직접 root CA 인증서 발급: 자체서명(Self-Signed)기능을 사용하여 cert-manager가 직접 루트 CA용 인증서와 비밀키를 만들고, 그걸 internal-ca-key-pair라는 이름의 secret으로 저장하게 만든다.
apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: selfsigned-root-issuer spec: selfSigned: {} --- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: internal-root-ca namespace: cert-manager spec: isCA: true # 중요: 이 인증서가 다른 인증서를 발행할 수 있는 'CA' 역할을 하겠다고 선언 commonName: "my-internal-root-ca" secretName: internal-ca-key-pair # 여기에 입력한 이름으로 Secret이 자동 생성 privateKey: algorithm: ECDSA size: 256 issuerRef: name: selfsigned-root-issuer kind: ClusterIssuer2. clusterIssuer: 먼저 내부 사설 CA 역할을 할 Issure를 정의한다.
apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: internal-ca-issuer spec: ca: # 미리 생성해둔 내부 CA의 비밀키가 담긴 Secret을 지정 secretName: internal-ca-key-pair3. Certificate 생성 및 Secret 자동 발급: 내부에서 사용할 내부 도메인(ex. foo.bar.com)에 대한 인증서를 요청한다.
apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: internal-service-cert namespace: default spec: # 위에서 만든 내부 CA Issuer를 지정 issuerRef: name: internal-ca-issuer kind: ClusterIssuer # 최종 인증서(signed keypair)가 저장될 쿠버네티스 시크릿 이름 secretName: internal-service-tls dnsNames: - "foo.bar.com"이제 cert-manager가 internal-ca-issuer를 통해 서명한 뒤, internal-service-tls 라는 secret을 자동으로 만들어준다.
외부 도메인 연결 인증서 발급(Let's Encrypt)
인터넷을 통해 실제 유저가 접속하는 서비스(ex. example.com)을 위한 구성이다.
글로벌 공인CA인 Let's Encrypt를 사용한다.
1. clusterIssuer: Let's Encrypt와 통신하여 도메인 유효성을 체크하는 Issuer을 생성한다.
apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-prod spec: acme: # Let's Encrypt 프로덕션 서버 주소 server: https://acme-v02.api.letsencrypt.org/directory email: devops-team@example.com # 만료 알림 등을 받을 이메일 privateKeySecretRef: name: letsencrypt-prod-account-key solvers: - http01: ingress: class: nginx # 클러스터에서 사용 중인 Ingress Controller 지정2. Certifacate 생성: 외부용 인증서는 Certificate 리소스를 따로 열어도 되지만, 사실 대부분 Ingress설정에 어노테이션을 설정하여 관리하는 것이 대부분의 사례이다.
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: wwww-service-ingress namespace: default annotations: # 이 어노테이션을 보고 cert-manager가 알아서 Certificate를 생성 cert-manager.io/cluster-issuer: "letsencrypt-prod" kubernetes.io/ingress.class: "nginx" spec: rules: - host: "example.com" http: paths: - path: / pathType: Prefix backend: service: name: web-service port: number: 80 tls: - hosts: - "example.com" # cert-manager가 Let's Encrypt에서 받아온 공인 인증서를 이 시크릿에 담는다 secretName: example-com-tls댓글

