이 페이지에서는 Google Kubernetes Engine(GKE) 클러스터에서 인그레스 리소스에 여러 SSL 인증서를 구성하는 방법을 설명합니다.
개요
클라이언트의 HTTPS 요청을 수락하려는 경우 애플리케이션 부하 분산기에 인증서가 있어야 부하 분산기가 클라이언트에게 ID를 증명할 수 있습니다. HTTPS 핸드셰이크를 완료하려면 부하 분산기에 비공개 키도 있어야 합니다.
부하 분산기가 클라이언트의 HTTPS 요청을 수락하면 클라이언트와 부하 분산기 간 트래픽은 TLS를 사용하여 암호화됩니다. 하지만 부하 분산기는 TLS 암호화를 종료하고 암호화 없이 요청을 애플리케이션에 전달합니다. 인그레스를 통해 애플리케이션 부하 분산기를 구성할 때는 최대 10개의 TLS 인증서를 클라이언트에 제공하도록 애플리케이션 부하 분산기를 구성할 수 있습니다.
부하 분산기는 SNI(서버 이름 표시)를 사용하여 TLS 핸드셰이크의 도메인 이름을 기준으로 클라이언트에 제공할 인증서를 결정합니다. 클라이언트가 SNI를 사용하지 않거나 클라이언트가 한 인증서에서 일반 이름(CN)과 일치하지 않는 도메인 이름을 사용하는 경우, 부하 분산기는 인그레스에 나열되는 첫 번째 인증서를 사용합니다.
아래 다이어그램은 요청에서 사용되는 도메인 이름에 따라 트래픽을 다른 백엔드로 보내는 부하 분산기를 보여줍니다.
다음 방법을 사용하여 애플리케이션 부하 분산기에 SSL 인증서를 제공할 수 있습니다.
- Google 관리 SSL 인증서. 인증서 사용 방법에 대한 정보는 관리형 인증서 페이지를 참조하세요.
직접 관리하는 Google Cloud SSL 인증서입니다. SSL 인증서는 Google Cloud 프로젝트에 업로드한 사전 공유 인증서를 사용합니다.
Kubernetes 보안 비밀. 보안 비밀에는 직접 만든 인증서와 키가 포함되어 있습니다. 보안 비밀의 이름을 인그레스 매니페스트의
tls
필드에 추가합니다.
같은 인그레스에서 두 개 이상의 방법을 사용할 수 있습니다. 이렇게 하면 방법 간에 다운타임 없는 마이그레이션이 가능합니다.
개요
다음은 이 문서의 단계 개요입니다.
배포를 만듭니다.
서비스를 만듭니다.
인증서 파일과 키 파일 또는
ManagedCertificate
객체를 각각 두 개씩 만듭니다. 이러한 인증서는 부하 분산기가 배포된 곳과 동일한 프로젝트와 네임스페이스에서 구성해야 합니다.보안 비밀 또는 사전 공유 인증서를 사용하는 인그레스를 만듭니다. 인그레스를 만들면 GKE가 애플리케이션 부하 분산기를 만들고 구성합니다.
애플리케이션 부하 분산기를 테스트합니다.
시작하기 전에
시작하기 전에 다음 태스크를 수행했는지 확인합니다.
- Google Kubernetes Engine API를 사용 설정합니다. Google Kubernetes Engine API 사용 설정
- 이 태스크에 Google Cloud CLI를 사용하려면 gcloud CLI를 설치한 후 초기화합니다. 이전에 gcloud CLI를 설치한 경우
gcloud components update
를 실행하여 최신 버전을 가져옵니다.
- 두 개의 도메인 이름을 소유하고 있어야 합니다. 도메인 이름은 63자(영문 기준) 이하여야 합니다.
제한사항
- Google 관리형 인증서는 외부 애플리케이션 부하 분산기를 사용하는 GKE 인그레스에서만 지원됩니다. Google 관리형 인증서는 서드 파티 인그레스 컨트롤러를 지원하지 않습니다.
- 내부 애플리케이션 부하 분산기의 경우 인그레스 매니페스트에서 HTTP를 사용 중지해야 합니다. 외부 부하 분산기에는 이 작업이 필요하지 않습니다.
- 애플리케이션 부하 분산기의 구성을 수동으로 변경하거나 업데이트하면 안 됩니다. 즉 대상 프록시, URL 맵, 백엔드 서비스를 포함한 부하 분산기 구성요소를 수정해서는 안 됩니다. 수정하면 GKE가 변경사항을 덮어씁니다.
배포 만들기
다음 매니페스트를
my-mc-deployment.yaml
로 저장합니다.apiVersion: apps/v1 kind: Deployment metadata: name: my-mc-deployment spec: selector: matchLabels: app: products department: sales replicas: 3 template: metadata: labels: app: products department: sales spec: containers: - name: hello image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0" env: - name: "PORT" value: "50001" - name: hello-again image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0" env: - name: "PORT" value: "50002"
이 매니페스트는 3개의 포드가 있는 배포를 설명합니다. 각 포드에는 2개의 컨테이너가 있습니다. 한 컨테이너는
hello-app:1.0
을 실행하고 TCP 포트 50001에서 수신 대기합니다. 다른 컨테이너는hello-app:2.0
를 실행하고 TCP 포트 50002에서 수신 대기합니다.매니페스트를 클러스터에 적용합니다.
kubectl apply -f my-mc-deployment.yaml
서비스 만들기
다음 매니페스트를
my-mc-service.yaml
로 저장합니다.apiVersion: v1 kind: Service metadata: name: my-mc-service spec: type: NodePort selector: app: products department: sales ports: - name: my-first-port protocol: TCP port: 60001 targetPort: 50001 - name: my-second-port protocol: TCP port: 60002 targetPort: 50002
이 매니페스트는 다음 필드를 사용해서 서비스를 기술합니다.
selector
:app: products
라벨 및department: sales
라벨이 있는 포드가 이 서비스의 구성원임을 지정합니다.ports
: 클라이언트가my-first-port
에서 서비스에 요청을 보낼 때 GKE가 포트 50001에서 구성원 포드 중 하나로 요청을 전달하도록 지정합니다. 클라이언트가my-second-port
에서 서비스에 요청을 보낼 때 GKE는 포트 50002에서 구성원 포드 중 하나로 요청을 전달합니다.
매니페스트를 클러스터에 적용합니다.
kubectl apply -f my-mc-service.yaml
인증서 및 키 만들기
이 페이지의 실습을 진행하려면 두 개의 인증서가 필요하며, 각각 해당하는 키가 있어야 합니다. 각 인증서에는 소유 중인 도메인 이름과 일치하는 일반 이름(CN)이 있어야 합니다.
이러한 인증서는 수동으로 만들거나 Google 관리형 인증서를 사용할 수 있습니다.적절한 일반 이름 값이 있는 인증서 파일 2개를 이미 가지고 있는 경우 다음 섹션으로 건너뛸 수 있습니다.
사용자 관리 인증서
첫 번째 키를 만듭니다.
openssl genrsa -out test-ingress-1.key 2048
첫 번째 인증서 서명 요청을 만듭니다.
openssl req -new -key test-ingress-1.key -out test-ingress-1.csr \ -subj "/CN=FIRST_DOMAIN"
FIRST_DOMAIN
을 소유하고 있는 도메인 이름(예:example.com
)으로 바꿉니다.첫 번째 인증서를 만듭니다.
openssl x509 -req -days 365 -in test-ingress-1.csr -signkey test-ingress-1.key \ -out test-ingress-1.crt
두 번째 키를 만듭니다.
openssl genrsa -out test-ingress-2.key 2048
두 번째 인증서 서명 요청을 만듭니다.
openssl req -new -key test-ingress-2.key -out test-ingress-2.csr \ -subj "/CN=SECOND_DOMAIN"
SECOND_DOMAIN
을 소유하고 있는 다른 도메인 이름(예:examplepetstore.com
)으로 바꿉니다.두 번째 인증서를 만듭니다.
openssl x509 -req -days 365 -in test-ingress-2.csr -signkey test-ingress-2.key \ -out test-ingress-2.crt
인증서 및 키에 대한 자세한 내용은 SSL 인증서 개요를 참조하세요.
이제 두 개의 인증서 파일과 두 개의 키 파일이 있습니다.
나머지 작업에서는 다음 자리표시자를 사용하여 도메인, 인증서, 키를 참조합니다.
FIRST_CERT_FILE
: 첫 번째 인증서 파일의 경로입니다.FIRST_KEY_FILE
: 첫 번째 인증서와 함께 전달되는 키 파일의 경로입니다.FIRST_DOMAIN
: 소유하고 있는 도메인 이름입니다.FIRST_SECRET_NAME
: 첫 번째 인증서 및 키가 포함된 보안 비밀의 이름입니다.SECOND_CERT_FILE
: 두 번째 인증서 파일의 경로입니다.SECOND_KEY_FILE
: 두 번째 인증서와 함께 전달되는 키 파일의 경로입니다.SECOND_DOMAIN
: 소유하고 있는 두 번째 도메인 이름입니다.SECOND_SECRET_NAME
: 두 번째 인증서 및 키가 포함된 보안 비밀의 이름입니다.
Google 관리형 인증서
Google 관리형 인증서를 만들려면 인그레스의 네임스페이스에 ManagedCertificate
객체를 추가해야 합니다. 다음 템플릿을 사용하여 도메인의 인증서를 정의할 수 있습니다.
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
name: FIRST_CERT_NAME
spec:
domains:
- FIRST_DOMAIN
---
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
name: SECOND_CERT_NAME
spec:
domains:
- SECOND_DOMAIN
다음을 바꿉니다.
FIRST_CERT_NAME
: 첫 번째ManagedCertificate
객체의 이름입니다.FIRST_DOMAIN
: 소유한 첫 번째 도메인입니다.SECOND_CERT_NAME
: 두 번째ManagedCertificate
객체의 이름입니다.SECOND_DOMAIN
: 소유하고 있는 두 번째 도메인입니다.
ManagedCertificate
객체의 이름은 생성하는 실제 인증서의 이름과 다릅니다. 인그레스에서 사용하려면 ManagedCertificate
객체의 이름만 알면 됩니다.
인그레스에 대한 인증서 지정
다음 단계는 인그레스 객체를 만드는 것입니다. 인그레스 매니페스트에서 다음 방법 중 하나를 사용하여 부하 분산기의 인증서를 제공할 수 있습니다.
- 보안 비밀
- 사전 공유 인증서
- Google 관리형 인증서
보안 비밀
첫 번째 인증서 및 키를 포함하는 보안 비밀을 만듭니다.
kubectl create secret tls FIRST_SECRET_NAME \ --cert=FIRST_CERT_FILE \ --key=FIRST_KEY_FILE
두 번째 인증서 및 키를 포함하는 보안 비밀을 만듭니다.
kubectl create secret tls SECOND_SECRET_NAME \ --cert=SECOND_CERT_FILE \ --key=SECOND_KEY_FILE
인그레스 만들기
다음 매니페스트를
my-mc-ingress.yaml
로 저장합니다.apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-mc-ingress spec: tls: - secretName: FIRST_SECRET_NAME - secretName: SECOND_SECRET_NAME rules: - host: FIRST_DOMAIN http: paths: - pathType: ImplementationSpecific backend: service: name: my-mc-service port: number: 60001 - host: SECOND_DOMAIN http: paths: - pathType: ImplementationSpecific backend: service: name: my-mc-service port: number: 60002
FIRST_DOMAIN
및SECOND_DOMAIN
을 소유하고 있는 도메인 이름(예:example.com
및examplepetstore.com
)으로 바꿉니다.매니페스트를 클러스터에 적용합니다.
kubectl apply -f my-mc-ingress.yaml
인그레스를 설명합니다.
kubectl describe ingress my-mc-ingress
출력은 다음과 비슷합니다.
Name: my-mc-ingress Address: 203.0.113.1 ... TLS: FIRST_SECRET_NAME terminates SECOND_SECRET_NAME terminates Rules: Host Path Backends ---- ---- -------- FIRST_DOMAIN my-mc-service:my-first-port (<none>) SECOND_DOMAIN my-mc-service:my-second-port (<none>) Annotations: ... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ADD 3m loadbalancer-controller default/my-mc-ingress Normal CREATE 2m loadbalancer-controller ip: 203.0.113.1
두 개의 보안 비밀이 인그레스에 연결되어 있다고 출력에 표시됩니다. 부하 분산기의 외부 IP 주소도 출력에 표시됩니다. 외부 IP 주소가 설정되어 있지 않으면 몇 분 정도 기다린 후 명령어를 다시 시도하세요.
사전 공유 인증서
인증서 만들기:
gcloud compute ssl-certificates create FIRST_CERT_NAME \ --certificate=FIRST_CERT_FILE \ --private-key=FIRST_KEY_FILE
다음을 바꿉니다.
FIRST_CERT_NAME
: 첫 번째 인증서의 이름입니다.FIRST_CERT_FILE
: 첫 번째 인증서 파일입니다.FIRST_KEY_FILE
: 첫 번째 키 파일입니다.
두 번째 인증서를 만듭니다.
gcloud compute ssl-certificates create SECOND_CERT_NAME \ --certificate=SECOND_CERT_FILE \ --private-key=SECOND_KEY_FILE
다음을 바꿉니다.
SECOND_CERT_NAME
: 두 번째 인증서의 이름입니다.SECOND_CERT_FILE
: 두 번째 인증서 파일입니다.SECOND_KEY_FILE
: 두 번째 키 파일입니다.
인증서 리소스를 확인합니다.
gcloud compute ssl-certificates list
출력은 다음과 비슷합니다.
NAME CREATION_TIMESTAMP FIRST_CERT_NAME 2018-11-03T12:08:47.751-07:00 SECOND_CERT_NAME 2018-11-03T12:09:25.359-07:00
인그레스 만들기
다음 매니페스트를
my-psc-ingress.yaml
로 저장합니다.apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-psc-ingress annotations: ingress.gcp.kubernetes.io/pre-shared-cert: "FIRST_CERT_NAME,SECOND_CERT_NAME" spec: rules: - host: FIRST_DOMAIN http: paths: - pathType: ImplementationSpecific backend: service: name: my-mc-service port: number: 60001 - host: SECOND_DOMAIN http: paths: - pathType: ImplementationSpecific backend: service: name: my-mc-service port: number: 60002
FIRST_DOMAIN
과SECOND_DOMAIN
을 도메인 이름으로 바꿉니다.이 매니페스트는 주석에 사전 공유 인증서 리소스를 나열하는 인그레스를 설명합니다.
매니페스트를 클러스터에 적용합니다.
kubectl apply -f my-psc-ingress.yaml
인그레스를 설명합니다.
kubectl describe ingress my-psc-ingress
출력은 다음과 비슷합니다.
Name: my-psc-ingress Address: 203.0.113.2 ... Rules: Host Path Backends ---- ---- -------- FIRST_DOMAIN my-mc-service:my-first-port (<none>) SECOND_DOMAIN my-mc-service:my-second-port (<none>) Annotations: ... ingress.gcp.kubernetes.io/pre-shared-cert: FIRST_CERT_NAME,SECOND_CERT_NAME ... ingress.kubernetes.io/ssl-cert: FIRST_CERT_NAME,SECOND_CERT_NAME Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ADD 2m loadbalancer-controller default/my-psc-ingress Normal CREATE 1m loadbalancer-controller ip: 203.0.113.2
인그레스가
FIRST_CERT_NAME
및SECOND_CERT_NAME
라는 사전 공유 인증서와 연관된 것으로 출력에 표시됩니다. 부하 분산기의 외부 IP 주소도 출력에 표시됩니다. 외부 IP 주소가 설정되어 있지 않으면 몇 분 정도 기다린 후 명령어를 다시 시도하세요.
Google 관리형 인증서
인그레스 만들기
다음 매니페스트를
my-gmc-ingress.yaml
로 저장합니다.apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-gmc-ingress annotations: networking.gke.io/managed-certificates: "FIRST_CERT_NAME,SECOND_CERT_NAME" spec: rules: - host: FIRST_DOMAIN http: paths: - pathType: ImplementationSpecific backend: service: name: my-mc-service port: number: 60001 - host: SECOND_DOMAIN http: paths: - pathType: ImplementationSpecific backend: service: name: my-mc-service port: number: 60002
FIRST_DOMAIN
과SECOND_DOMAIN
을 도메인 이름으로 바꿉니다.이 매니페스트는 주석에 사전 공유 인증서 리소스를 나열하는 인그레스를 설명합니다.
매니페스트를 클러스터에 적용합니다.
kubectl apply -f my-gmc-ingress.yaml
인그레스를 설명합니다.
kubectl describe ingress my-gmc-ingress
출력은 다음과 비슷합니다.
Name: my-gmc-ingress Address: 203.0.113.2 ... Rules: Host Path Backends ---- ---- -------- FIRST_DOMAIN my-mc-service:my-first-port (<none>) SECOND_DOMAIN my-mc-service:my-second-port (<none>) Annotations: ... ingress.gcp.kubernetes.io/pre-shared-cert: mcrt-a6e41ce4-2b39-4334-84ce-867ff543c424,mcrt-bbff4116-f014-4800-a43a-4095bffeb4f4 ... ingress.kubernetes.io/ssl-cert: mcrt-a6e41ce4-2b39-4334-84ce-867ff543c424,mcrt-bbff4116-f014-4800-a43a-4095bffeb4f4 networking.gke.io/managed-certificates: FIRST_CERT_NAME,SECOND_CERT_NAME Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ADD 2m loadbalancer-controller default/my-gmc-ingress Normal CREATE 1m loadbalancer-controller ip: 203.0.113.2
인그레스가
FIRST_CERT_NAME
및SECOND_CERT_NAME
이라는 관리형 인증서와 연관된 것으로 출력에 표시됩니다. GKE는ManagedCertificate
객체를 사용하여 만든 Google 관리 인증서로ingress.gcp.kubernetes.io/pre-shared-cert
및ingress.kubernetes.io/ssl-cert
주석을 자동으로 채웁니다. 부하 분산기의 외부 IP 주소도 출력에 표시됩니다. 외부 IP 주소가 설정되어 있지 않으면 몇 분 정도 기다린 후 명령어를 다시 시도하세요.
부하 분산기 테스트
GKE가 부하 분산기 구성을 마치도록 5분 정도 기다립니다.
Google 관리형 인증서를 사용한 경우 시스템에서 인증서를 프로비저닝하고 지정된 도메인의 DNS 구성을 확인해야 하므로 구성을 완료하는 데 훨씬 오래 걸릴 수 있습니다.부하 분산기를 테스트하려면 두 개의 도메인 이름을 소유해야 하고 두 도메인 이름 모두가 외부 애플리케이션 부하 분산기의 외부 IP 주소로 해석되어야 합니다.
첫 번째 도메인 이름을 사용하여 부하 분산기에 요청을 보냅니다.
curl -v https://FIRST_DOMAIN
curl -k
옵션으로 안전하지 않은 SSL 전송을 수행하여curl
에서 자체 서명된 인증서를 수락하도록 해야 할 수도 있습니다.출력은 다음과 비슷합니다.
... * Trying 203.0.113.1... ... * Connected to FIRST_DOMAIN (203.0.113.1) port 443 (#0) ... * TLSv1.2 (IN), TLS handshake, Certificate (11): ... * Server certificate: * subject: CN=FIRST_DOMAIN ... > Host: FIRST_DOMAIN.com ... Hello, world! Version: 1.0.0 ...
TLS 핸드셰이크에서 첫 번째 인증서가 사용된 것으로 출력에 표시됩니다.
두 번째 도메인 이름을 사용하여 부하 분산기에 요청을 보냅니다.
curl -v https://SECOND_DOMAIN
출력은 다음과 비슷합니다.
... * Trying 203.0.113.1... ... * Connected to SECOND_DOMAIN (203.0.113.1) port 443 (#0) ... * Server certificate: * subject: CN=SECOND_DOMAIN ... > Host: SECOND_DOMAIN ... Hello, world! Version: 2.0.0
TLS 핸드셰이크에서 두 번째 인증서가 사용된 것으로 출력에 표시됩니다.
인그레스 객체의 호스트 필드
IngressSpec에는 IngressTLS 객체의 배열인 tls
필드가 있습니다. 각 IngressTLS
객체에는 hosts
필드 및 SecretName
필드가 있습니다.
GKE에서 hosts
필드는 사용되지 않습니다. GKE는 보안 비밀의 인증서에서 일반 이름(CN)을 읽습니다. 일반 이름이 클라이언트 요청에 있는 도메인 이름과 일치하면 부하 분산기가 일치하는 인증서를 클라이언트에 제공합니다.
제공되는 인증서
부하 분산기는 다음 규칙을 따라 인증서를 선택합니다.
보안 비밀과 사전 공유 인증서가 모두 인그레스에 나열되면 사전 공유 인증서가 보안 비밀보다 우선시됩니다. 즉, 보안 비밀은 계속 포함되지만 사전 공유된 인증서가 먼저 제공됩니다.
클라이언트 요청에서 도메인 이름과 일치하는 일반 이름(CN)을 가진 인증서가 없는 경우 부하 분산기는 기본 인증서를 제공합니다.
tls
블록에 나열된 보안 비밀의 경우 기본 인증서는 목록의 첫 번째 보안 비밀에 있습니다.주석에 나열된 사전 공유 인증서의 경우 기본 인증서는 목록에서 첫 번째 인증서입니다.
인증서 순환 권장사항
보안 비밀 또는 사전 공유 인증서의 콘텐츠를 순환하려면 다음 권장사항을 따르세요.
- 새 인증서 데이터가 포함된 새 보안 비밀 또는 사전 공유 인증서를 다른 이름으로 만듭니다. 앞부분에 제공된 안내를 따라 이 리소스를 기존 리소스와 함께 인그레스에 연결합니다. 변경사항에 만족하면 인그레스에서 이전 인증서를 삭제해도 됩니다.
- 트래픽 중단을 원하지 않으면 인그레스에서 이전 리소스를 삭제하고 이름은 같지만 콘텐츠가 다른 새 리소스를 프로비저닝한 후 인그레스에 다시 연결합니다.
문제 해결
무효하거나 존재하지 않는 보안 비밀을 지정하면 Kubernetes 이벤트 오류가 발생합니다. 인그레스의 Kubernetes 이벤트는 다음과 같이 확인할 수 있습니다.
kubectl describe ingress
출력은 다음과 비슷합니다.
Name: my-ingress
Namespace: default
Address: 203.0.113.3
Default backend: hello-server:8080 (10.8.0.3:8080)
TLS:
my-faulty-Secret terminates
Rules:
Host Path Backends
---- ---- --------
* * my-service:443 (10.8.0.3:443)
Events:
Error during sync: cannot get certs for Ingress default/my-ingress:
Secret "my-faulty-ingress" has no 'tls.crt'
다음 단계
- GKE 네트워크 개요 읽기
- 고정 IP 주소로 도메인 이름을 구성하는 방법 알아보기
- 서로 다른 리전의 여러 GKE 클러스터에서 애플리케이션을 실행하는 경우 사용자에게 가장 가까운 리전의 클러스터로 트래픽을 라우팅하도록 멀티 클러스터 인그레스를 구성합니다.