Certificate Authority Service를 사용하여 Cloud Service Mesh 인그레스 게이트웨이의 TLS 인증서 관리 자동화
이 튜토리얼에서는 플랫폼 운영자를 위해 cert-manager 도구의 Certificate Authority Service(CA 서비스) 발급기관을 사용해서 Cloud Service Mesh 인그레스 게이트웨이에 대해 TLS 인증서 관리를 자동화하는 방법을 보여줍니다. 이 인증서를 사용하면 인그레스 게이트웨이가 Virtual Private Cloud(VPC)의 클라이언트에서 시작하지만 서비스 메시 외부에 있는 HTTPS 및 기타 TLS 및 mTLS 트래픽을 종료할 수 있습니다. 이 튜토리얼에서는 사용자에게 Kubernetes 및 TLS 인증서 관련 기본 지식이 있다고 가정합니다.
소개
Cloud Service Mesh는 서비스 메시의 모든 워크로드에 대해 TLS 인증서를 프로비저닝합니다. 이러한 인증서는 서비스 메시에 있는 워크로드 사이에 암호화되고 상호 인증된 TLS(mTLS) 통신을 사용 설정합니다. 지원되는 CA 문제 중 하나이고 인증서를 서명합니다.
하지만 Cloud Service Mesh는 서비스 메시에 들어가는 트래픽에 대해 인그레스 게이트웨이로 인증서를 자동으로 프로비저닝하지 않습니다. 한 가지 일반적인 솔루션은 오픈소스 cert-manager 도구를 사용해서 인그레스 게이트웨이 인증서 관리를 자동화하는 것입니다.
cert-manager 도구는 인증 기관(CA)에 해당하는 발급기관에게서 인증서를 요청합니다. CA 서비스는 고유한 비공개 CA를 만들 수 있는 Google Cloud 서비스입니다. cert-manager 도구는 오픈소스 CA 서비스 외부 발급기관을 사용하여 CA 서비스에게서 인증서를 요청할 수 있습니다.
비공개 CA는 내부 네트워크 내에서 트래픽을 인증하고 암호화하는 TLS 인증서를 발급할 수 있습니다. Cloud Service Mesh 인그레스 게이트웨이는 VPC 내부에 있지만 서비스 메시 외부에 있는 클라이언트에서 수신되는 트래픽을 허용하도록 설정되는 경우가 많습니다. 내부 네트워크 트래픽의 경우 CA Service의 비공개 CA를 사용해서 인그레스 게이트웨이에 대해 인증서를 발급할 수 있습니다.
이 튜토리얼에서는 인그레스 게이트웨이에 대한 TLS 인증서 프로비저닝 및 갱신을 자동화하도록 cert-manager 도구 및 CA Service 발급기관을 설정하는 방법을 보여줍니다. cert-manager 도구는 인증서를 TLS 유형의 Kubernetes 보안 비밀 리소스로 프로비저닝합니다. cert-manager 도구는 인증서를 갱신할 때 새 인증서로 보안 비밀 리소스를 업데이트합니다. 인그레스 게이트웨이는 Envoy 프록시를 실행하고 Envoy 보안 비밀 검색 서비스(SDS)를 지원합니다. SDS는 관리자가 프로세스를 다시 시작하거나 다시 로드하지 않아도 인그레스 게이트웨이가 새 인증서를 사용할 수 있게 해줍니다.
메시에 포함된 사이드카 프록시는 CA 서비스 또는 Cloud Service Mesh 인증 기관에서 TLS 인증서를 가져올 수 있습니다. 이 튜토리얼에서는 사이드카 프록시 및 인그레스 게이트웨이 인증서에 CA 서비스를 사용합니다. 이렇게 하면 모든 TLS 인증서에 대해 하나의 루트 CA를 사용할 수 있습니다.
다음 다이어그램은 이 튜토리얼에서 프로비저닝하는 리소스를 보여줍니다.
인그레스 게이트웨이에 대해 내부 패스 스루 네트워크 부하 분산기를 프로비저닝합니다. 내부 패스 스루 네트워크 부하 분산기는 프록시가 아닙니다. 따라서 TCP 연결을 종료하거나 TLS 핸드셰이크를 수행하지 않습니다. 대신 istio-ingressgateway
배포의 포드로 연결을 라우팅합니다.
hello-example-com-credential
보안 비밀에는 인증서 및 비공개 키가 포함되어 있습니다. hello
게이트웨이는 호스트 이름이 hello.example.com
인 요청에 대해 TLS 핸드셰이크를 수행하기 위해 이 인증서 및 비공개 키를 사용하도록 istio-ingressgateway
배포의 포드를 구성합니다.
cert-manager
네임스페이스에서 google-cas-issuer
배포의 포드는 CA 서비스에서 만드는 CA로부터 인증서를 요청합니다. ca-service-isser
포드가 워크로드 아이덴티티를 사용해서 Google 서비스 계정을 가장할 수 있게 해주는 Identity and Access Management 정책 바인딩을 만듭니다. 이 Google 서비스 계정에 CA 풀에서 IAM 정책 바인딩을 만들어 CA 서비스의 CA에서 인증서를 요청할 수 있는 권한을 부여합니다.
목표
- CA 서비스 구성
- GKE 클러스터 만들기
- Cloud Service Mesh 제어 영역 설치
- 인그레스 게이트웨이 설치
- cert-manager 도구 설치
- CA Service 발급기관 컨트롤러 설치
- 인증서 발급기관 만들기
- 샘플 애플리케이션 배포
- 솔루션 확인
- (선택사항) 트러스트 저장소에 CA 인증서 추가
비용
이 튜토리얼에서는 비용이 청구될 수 있는 다음과 같은 Google Cloud 구성요소를 사용합니다.
프로젝트 사용량을 기준으로 예상 비용을 산출하려면 가격 계산기를 사용하세요. Google Cloud를 처음 사용하는 사용자는 무료 체험판을 사용할 수 있습니다.
이 튜토리얼을 마친 후에 계속 비용이 청구되지 않도록 하려면 만든 리소스를 삭제하면 됩니다. 자세한 내용은 삭제를 참조하세요.
시작하기 전에
Google Cloud 콘솔에서 프로젝트 선택기 페이지로 이동한 후 프로젝트를 선택하거나 만듭니다.
Google Cloud 프로젝트에 결제가 사용 설정되어 있는지 확인합니다.
Google Cloud 콘솔에서 Cloud Shell로 이동합니다.
Google Cloud 콘솔 하단에서 Cloud Shell 세션이 열리고 명령줄 프롬프트가 표시됩니다. Cloud Shell을 사용하여 튜토리얼의 모든 명령어를 실행합니다.
이 튜토리얼에 사용할 Google Cloud 콘솔 프로젝트를 설정합니다.
gcloud config set core/project PROJECT_ID
PROJECT_ID를 Cloud 프로젝트의 ID로 바꿉니다.
Cloud Shell 승인 대화상자에서 승인을 클릭합니다. 승인을 클릭하면 Cloud Shell에서 실행하는
gcloud
명령어가 사용자 인증 정보를 사용해서 Google API로 인증을 수행할 수 있습니다.Resource Manager, GKE, GKE Hub, Cloud Service Mesh 인증 기관, CA 서비스 API를 사용 설정합니다.
gcloud services enable \ cloudresourcemanager.googleapis.com \ container.googleapis.com \ gkehub.googleapis.com \ meshca.googleapis.com \ privateca.googleapis.com
CA 서비스 구성
이 섹션에서는 CA Service에서 루트 CA 하나와 종속 CA 2개를 만듭니다. 종속 CA 하나는 인그레스 게이트웨이에 대해 인증서를 발급하고, 다른 종속 CA는 메시의 사이드카 프록시에 대해 인증서를 발급합니다.
이 튜토리얼에서는 편의상 GKE 클러스터와 루트 및 종속 CA에 동일한 프로젝트를 사용합니다. 사용자의 고유 환경에서는 GKE 클러스터 및 CA에 대해 서로 다른 프로젝트를 사용할 수 있습니다.
Cloud Shell에서 루트 CA에 사용할 CA 풀을 만듭니다.
gcloud privateca pools create ROOT_CA_POOL \ --location CA_LOCATION \ --tier enterprise
- ROOT_CA_POOL은 CA 풀의 이름입니다. 예:
root-ca-pool-tutorial
- CA_LOCATION은 CA 풀의 위치입니다. 예를 들면
us-central1
입니다.
사용 가능한 CA 서비스 위치를 나열하려면
gcloud privateca locations list
명령어를 실행하면 됩니다.- ROOT_CA_POOL은 CA 풀의 이름입니다. 예:
루트 CA를 만들고 사용 설정합니다.
gcloud privateca roots create ROOT_CA \ --auto-enable \ --key-algorithm ec-p384-sha384 \ --location CA_LOCATION \ --pool ROOT_CA_POOL \ --subject "CN=Example Root CA, O=Example Organization" \ --use-preset-profile root_unconstrained
- ROOT_CA는 루트 CA에 사용하려는 이름입니다.
root-ca-tutorial
).
- ROOT_CA는 루트 CA에 사용하려는 이름입니다.
인그레스 게이트웨이에 인증서를 발급하는 종속 CA에 사용할 CA 풀을 만듭니다.
gcloud privateca pools create SUBORDINATE_CA_POOL_GATEWAYS \ --location CA_LOCATION \ --tier devops
- SUBORDINATE_CA_POOL_GATEWAYS는 CA 풀의 이름입니다.
subordinate-ca-mtls-pool-gateways-tutorial
).
- SUBORDINATE_CA_POOL_GATEWAYS는 CA 풀의 이름입니다.
인그레스 게이트웨이에 인증서를 발급하는 종속 CA를 만들고 사용 설정합니다.
gcloud privateca subordinates create SUBORDINATE_CA_GATEWAYS \ --auto-enable \ --issuer-location CA_LOCATION \ --issuer-pool ROOT_CA_POOL \ --key-algorithm ec-p256-sha256 \ --location CA_LOCATION \ --pool SUBORDINATE_CA_POOL_GATEWAYS \ --subject "CN=Example Gateway mTLS CA, O=Example Organization" \ --use-preset-profile subordinate_mtls_pathlen_0
- SUBORDINATE_CA_GATEWAYS는 종속 CA에 사용하려는 이름입니다. 예를 들면
subordinate-ca-mtls-gateways-tutorial
입니다. --use-preset-profile
플래그는 종속 mTLS 인증서 프로필을 사용하도록 종속 CA를 구성합니다. 이 프로필은 종속 CA가 mTLS용으로 클라이언트 및 서버 TLS 인증서를 모두 발급하도록 허용합니다.
mTLS 대신 단순 TLS를 인그레스 게이트웨이에 사용하려는 경우에는 종속 CA가 서버 TLS 인증서만 발급하면 됩니다. 이 경우에는 대신 종속 서버 TLS(
subordinate_server_tls_pathlen_0
) 인증서 프로필을 사용할 수 있습니다.- SUBORDINATE_CA_GATEWAYS는 종속 CA에 사용하려는 이름입니다. 예를 들면
인증서 발급 정책을 만듭니다.
cat << EOF > policy.yaml baselineValues: keyUsage: baseKeyUsage: digitalSignature: true keyEncipherment: true extendedKeyUsage: serverAuth: true clientAuth: true caOptions: isCa: false identityConstraints: allowSubjectPassthrough: false allowSubjectAltNamesPassthrough: true celExpression: expression: subject_alt_names.all(san, san.type == URI && san.value.startsWith("spiffe://PROJECT_ID.svc.id.goog/ns/") ) EOF
이 발급 정책은 CA가 메시에 있는 워크로드에 대해서만 인증서를 발급하도록 제한합니다.
메시에 있는 사이드카 프록시에 인증서를 발급하는 종속 CA에 사용할 CA 풀을 만듭니다. 발급 정책을 CA 풀에 적용합니다.
gcloud privateca pools create SUBORDINATE_CA_POOL_SIDECARS \ --issuance-policy policy.yaml \ --location CA_LOCATION \ --tier devops
- SUBORDINATE_CA_POOL_SIDECARS는 CA 풀의 이름입니다.
subordinate-ca-mtls-pool-sidecars-tutorial
).
- SUBORDINATE_CA_POOL_SIDECARS는 CA 풀의 이름입니다.
메시에 있는 사이드카 프록시에 인증서를 발급하는 종속 CA를 만들고 사용 설정합니다.
gcloud privateca subordinates create SUBORDINATE_CA_SIDECARS \ --auto-enable \ --issuer-location CA_LOCATION \ --issuer-pool ROOT_CA_POOL \ --key-algorithm ec-p256-sha256 \ --location CA_LOCATION \ --pool SUBORDINATE_CA_POOL_SIDECARS \ --subject "CN=Example Sidecar mTLS CA, O=Example Organization" \ --use-preset-profile subordinate_mtls_pathlen_0
- SUBORDINATE_CA_GATEWAYS는 종속 CA에 사용하려는 이름입니다. 예:
subordinate-ca-mtls-sidecars-tutorial
- SUBORDINATE_CA_GATEWAYS는 종속 CA에 사용하려는 이름입니다. 예:
Google Kubernetes Engine 클러스터 만들기
Cloud Shell에서 GKE 클러스터를 만듭니다.
gcloud container clusters create CLUSTER_NAME \ --enable-ip-alias \ --num-nodes 4 \ --release-channel regular \ --scopes cloud-platform \ --workload-pool PROJECT_ID.svc.id.goog \ --zone ZONE
CLUSTER_NAME을 클러스터에 사용할 이름으로 바꿉니다. 예를 들면
asm-ingress-cert-manager-ca-service
입니다.ZONE을 클러스터에 사용할 영역으로 바꿉니다. 예를 들면
us-central1-f
입니다.이 명령어에 관해서는 다음 사항에 유의하세요.
--release-channel
플래그는 클러스터에 대해 GKE 출시 채널을 선택합니다.- cert-manager 도구의 Cloud Service Mesh 및 CA 서비스 발급기관 모두 클러스터 노드에
cloud-platform
범위를 설정해야 합니다. --workload-pool
인수는 CA 서비스 발급기관 Kubernetes 서비스 계정이 Google 서비스 계정을 가장하도록 허용하는 워크로드 아이덴티티를 사용 설정합니다. 이러한 가장에 따라 Google 서비스 계정에 대해 키 파일을 다운로드하지 않아도 CA 서비스 발급기관 포드가 CA Service API에 액세스할 수 있습니다.
사용자 계정에 클러스터 관리자 권한을 부여합니다.
kubectl create clusterrolebinding cluster-admin-binding \ --clusterrole cluster-admin \ --user $(gcloud config get-value core/account)
Cloud Service Mesh에 대해 역할 기반 액세스 제어(RBAC) 규칙을 만들고 cert-manager 도구를 설치하려면 Kubernetes
cluster-admin
ClusterRole에서 제공되는 권한이 필요합니다.
Anthos Service Mesh 제어 영역 설치
이 튜토리얼에서는 모든 리소스가 하나의 프로젝트에 포함된 상태로 Google Cloud에서 GKE 클러스터에 대해 관리형 Cloud Service Mesh를 설치합니다. 사용자의 고유 환경에서는 관리형 Cloud Service Mesh 또는 클러스터 내 컨트롤 플레인 을 사용하여 이 문서에 설명된 솔루션을 적용할 수 있습니다.
Cloud Service Mesh는 여러 시나리오를 위해 다양한 설치 옵션을 제공합니다. 이 튜토리얼을 완료한 후에는 설치 가이드를 참조해서 해당 환경에 가장 적합한 옵션을 선택하는 것이 좋습니다.
Cloud Shell에서
asmcli
설치 도구를 다운로드합니다.curl --location --output asmcli https://storage.googleapis.com/csm-artifacts/asm/asmcli_1.15 chmod +x asmcli
asmcli
를 사용하여 Cloud Service Mesh 제어 영역을 설치합니다.Cloud Service Mesh 제어 영역 설치
./asmcli install \ --ca gcp_cas \ --ca_pool projects/PROJECT_ID/locations/CA_LOCATION/caPools/SUBORDINATE_CA_POOL_SIDECARS \ --cluster_location ZONE \ --cluster_name CLUSTER_NAME \ --enable_all \ --enable_registration \ --fleet_id PROJECT_ID \ --managed \ --output_dir asm-files \ --project_id PROJECT_ID \ --verbose
--ca gcp_cas
및--ca_pool
플래그는 CA 서비스의 사이드카 CA 풀을 사용해서 메시에 있는 사이드카 프록시에 대해 인증서를 발급할 수 있도록 Cloud Service Mesh 제어 영역을 구성합니다.--enable_registration
플래그는--fleet_id
플래그로 지정된 프로젝트의 Fleet에 GKE 클러스터를 등록합니다. 이 튜토리얼에서는 GKE 클러스터와 Fleet이 동일한 프로젝트를 사용합니다.--managed
플래그는 관리형 Cloud Service Mesh 제어 영역을 설정합니다.--output_dir
플래그는asmcli
에서 Cloud Service Mesh 설치에 필요한 파일 및 구성을 다운로드하기 위해 사용되는 디렉터리를 지정합니다. 이러한 파일은 이후 튜토리얼에서 사용됩니다.
설치하려면 몇 분 정도 걸립니다. 설치가 완료되면 다음 출력이 표시됩니다.
asmcli: Successfully installed ASM.
인그레스 게이트웨이 설치
Cloud Shell에서 인그레스 게이트웨이의 Kubernetes 네임스페이스를 만듭니다.
kubectl create namespace GATEWAY_NAMESPACE
- GATEWAY_NAMESPACE는 인그레스 게이트웨이에 사용하려는 네임스페이스 이름입니다. 예를 들면
istio-ingress
입니다.
- GATEWAY_NAMESPACE는 인그레스 게이트웨이에 사용하려는 네임스페이스 이름입니다. 예를 들면
인그레스 게이트웨이 내부 패스 스루 네트워크 부하 분산기에 사용할 고정 내부 IP 주소를 예약합니다.
LOAD_BALANCER_IP=$(gcloud compute addresses create \ asm-ingress-gateway-ilb \ --region REGION \ --subnet default \ --format 'value(address)')
- REGION을 GKE 클러스터 노드에 사용되는 영역이 포함된 리전으로 바꿉니다. 예를 들어 클러스터에
us-central1-f
영역이 사용되는 경우 REGION을us-central1
로 바꿉니다.
이 명령어는 지정된 리전에서 기본 서브넷의 IP 주소를 예약합니다.
- REGION을 GKE 클러스터 노드에 사용되는 영역이 포함된 리전으로 바꿉니다. 예를 들어 클러스터에
인그레스 게이트웨이에 대해 연산자 매니페스트를 만듭니다.
cat << EOF > ingressgateway-operator.yaml apiVersion: install.istio.io/v1alpha1 kind: IstioOperator metadata: name: ingressgateway-operator annotations: config.kubernetes.io/local-config: "true" spec: profile: empty revision: asm-managed components: ingressGateways: - name: istio-ingressgateway namespace: GATEWAY_NAMESPACE enabled: true k8s: overlays: - apiVersion: apps/v1 kind: Deployment name: istio-ingressgateway patches: - path: spec.template.metadata.annotations value: inject.istio.io/templates: gateway - path: spec.template.metadata.labels.sidecar\.istio\.io/inject value: "true" - path: spec.template.spec.containers[name:istio-proxy] value: name: istio-proxy image: auto service: loadBalancerIP: $LOAD_BALANCER_IP serviceAnnotations: networking.gke.io/load-balancer-type: Internal networking.gke.io/internal-load-balancer-allow-global-access: "true" EOF
연산자 매니페스트에 관해서는 다음 사항에 유의하세요.
revision
필드는 데이터 영역에 사용할 관리형 Cloud Service Mesh 출시 채널을 지정합니다. 제어 영역에 신속 또는 공개 버전 출시 채널을 사용하는 경우 이 필드의 값을 변경합니다.overlays
섹션에 지정된annotation
,label
,image
는 인그레스 게이트웨이 배포를 위한 프록시 구성 자동 삽입을 사용 설정합니다.loadBalancerIP
필드는 부하 분산기에 사용할 IP 주소를 지정합니다. 매니페스트에서 이 필드를 삭제하면 부하 분산기에 임시 IP 주소가 사용됩니다.인그레스 게이트웨이에서 서비스 주석
networking.gke.io/load-balancer-type: Internal
은 GKE가 인그레스 게이트웨이 포드 앞에 내부 패스 스루 네트워크 부하 분산기를 프로비저닝함을 의미합니다. 이 주석을 삭제하면 GKE가 대신 외부 패스 스루 네트워크 부하 분산기를 프로비저닝합니다.선택적인 서비스 주석인
networking.gke.io/internal-load-balancer-allow-global-access: "true"
를 사용하면 VPC에서 모든 리전의 클라이언트가 내부 패스 스루 네트워크 부하 분산기에 액세스할 수 있습니다. 이 주석을 삭제하면 내부 패스 스루 네트워크 부하 분산기가 VPC에서 동일한 리전에 있는 클라이언트의 트래픽만 허용합니다.
제어 영역을 설치할 때
asmcli
스크립트로 다운로드된istioctl
도구 및 연산자 매니페스트를 사용하여 인그레스 게이트웨이 설치 매니페스트를 만듭니다../asm-files/istioctl manifest generate \ --filename ingressgateway-operator.yaml \ --output ingressgateway
인그레스 게이트웨이를 설치합니다.
kubectl apply --recursive --filename ingressgateway/
cert-manager 도구 설치
Cloud Shell에서 cert-manager 도구 설치 매니페스트를 다운로드하고 적용합니다.
CERT_MANAGER_VERSION=v1.5.4 curl --location --output cert-manager.yaml "https://github.com/jetstack/cert-manager/releases/download/${CERT_MANAGER_VERSION}/cert-manager.yaml" kubectl apply --filename cert-manager.yaml
cert-manager 도구 설치는 완료하는 데 1분 정도 걸립니다.
CA Service 발급기관 컨트롤러 설치
CA Service 발급기관 컨트롤러는 cert-manager 도구가 CA Service를 사용해서 인증서를 요청할 수 있게 해줍니다. 이 컨트롤러는 cert-manager 도구 외부 발급기관 확장 메커니즘을 사용합니다.
Cloud Shell에서 Google 서비스 계정을 만듭니다.
gcloud iam service-accounts create CAS_ISSUER_GSA \ --display-name "CA Service issuer for cert-manager"
- CAS_ISSUER_GSA는 Google 서비스 계정의 이름입니다.
cert-manager-ca-service-issuer
).
Certificate Authority Service 발급기관 컨트롤러는 이 Google 서비스 계정을 사용해서 Certificate Authority Service API에 인증을 수행합니다.
- CAS_ISSUER_GSA는 Google 서비스 계정의 이름입니다.
Certificate Authority Service 발급기관 컨트롤러 Google 서비스 계정이 종속 CA를 포함하는 CA 풀에서 인증서를 요청하도록 허용하는 Identity and Access Management 정책 바인딩을 만듭니다.
gcloud privateca pools add-iam-policy-binding SUBORDINATE_CA_POOL_GATEWAYS \ --location CA_LOCATION \ --member "serviceAccount:CAS_ISSUER_GSA@PROJECT_ID.iam.gserviceaccount.com" \ --role roles/privateca.certificateRequester
Certificate Authority Service 발급기관 컨트롤러 설치 매니페스트를 다운로드합니다.
CAS_ISSUER_VERSION=v0.5.3 curl --location --output ca-service-issuer.yaml "https://github.com/jetstack/google-cas-issuer/releases/download/${CAS_ISSUER_VERSION}/google-cas-issuer-${CAS_ISSUER_VERSION}.yaml"
cert-manager
네임스페이스에서ksa-google-cas-issuer
Kubernetes 서비스 계정이 워크로드 아이덴티티를 사용하여 Google 서비스 계정(GSA)을 가장하도록 허용하는 IAM 정책 바인딩을 만듭니다.gcloud iam service-accounts add-iam-policy-binding \ CAS_ISSUER_GSA@PROJECT_ID.iam.gserviceaccount.com \ --member "serviceAccount:PROJECT_ID.svc.id.goog[cert-manager/ksa-google-cas-issuer]" \ --role roles/iam.workloadIdentityUser
CA 서비스 발급기관 컨트롤러 포드는
ksa-google-cas-issuer
Kubernetes 서비스 계정을 사용합니다.GKE 클러스터에 CA Service 발급기관 컨트롤러를 설치합니다.
kubectl apply --filename ca-service-issuer.yaml
CA 서비스 발급기관 컨트롤러 포드에 사용되는 Kubernetes 서비스 계정에 워크로드 아이덴티티 주석
iam.gke.io/gcp-service-account
를 추가합니다.kubectl annotate serviceaccount ksa-google-cas-issuer --namespace cert-manager \ "iam.gke.io/gcp-service-account=CAS_ISSUER_GSA@PROJECT_ID.iam.gserviceaccount.com"
이 주석은 Kubernetes 서비스 계정이 Google API에 액세스하기 위해 Google 서비스 계정을 가장할 수 있음을 GKE에 알려줍니다.
인증서 발급기관 만들기
Cloud Shell에서 GoogleCASIssuer 매니페스트를 만들고 적용합니다.
cat << EOF > gateway-cas-issuer.yaml apiVersion: cas-issuer.jetstack.io/v1beta1 kind: GoogleCASIssuer metadata: name: gateway-cas-issuer namespace: GATEWAY_NAMESPACE spec: caPoolId: SUBORDINATE_CA_POOL_GATEWAYS location: CA_LOCATION project: PROJECT_ID EOF kubectl apply --filename gateway-cas-issuer.yaml
발급기관은 cert-manager 도구가 인그레스 게이트웨이 네임스페이스에 있는 종속 CA 풀에서 인증서를 프로비저닝할 수 있게 해줍니다.
샘플 애플리케이션 배포
이 섹션에서는 cert-manager 도구가 CA Service 발급기관을 사용해서 CA Service로부터 인증서를 가져올 수 있는지 확인합니다. 이를 확인하기 위해 요청 라우팅 구성과 인그레스 게이트웨이에 대한 인증서가 포함된 샘플 애플리케이션을 배포합니다.
Cloud Shell에서 샘플 애플리케이션 리소스에 대한 네임스페이스를 만듭니다.
cat << EOF > sample-app-namespace.yaml apiVersion: v1 kind: Namespace metadata: name: APP_NAMESPACE annotations: mesh.cloud.google.com/proxy: '{"managed":"true"}' labels: istio.io/rev: asm-managed EOF kubectl apply --filename sample-app-namespace.yaml
- APP_NAMESPACE는 샘플 애플리케이션의 네임스페이스 이름입니다. 예를 들면
sample-app
입니다.
mesh.cloud.google.com/proxy
주석은 네임스페이스에 관리형 데이터 영역을 사용 설정합니다.istio.io/rev: asm-managed
라벨은 샘플 애플리케이션 네임스페이스에서 관리형 데이터 영역에 일반 출시 채널을 선택합니다. 신속 또는 정식 출시 채널을 사용하는 경우 이 라벨 값을 변경합니다.- APP_NAMESPACE는 샘플 애플리케이션의 네임스페이스 이름입니다. 예를 들면
샘플 애플리케이션에 대해 배포 리소스를 만듭니다.
cat << EOF > deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: hello namespace: APP_NAMESPACE labels: app: hello spec: replicas: 1 selector: matchLabels: app: hello template: metadata: labels: app: hello spec: containers: - image: gcr.io/google-samples/hello-app:1.0 name: hello-app ports: - containerPort: 8080 EOF kubectl apply --filename deployment.yaml
샘플 애플리케이션에 대해 서비스 리소스를 만듭니다.
cat << EOF > service.yaml apiVersion: v1 kind: Service metadata: name: SERVICE_NAME namespace: APP_NAMESPACE spec: ports: - name: http-hello port: 8080 selector: app: hello type: ClusterIP EOF kubectl apply --filename service.yaml
- SERVICE_NAME은 서비스의 이름입니다. 예를 들면
hello
입니다.
- SERVICE_NAME은 서비스의 이름입니다. 예를 들면
인증서 발급기관을 사용해서 도메인 이름
hello.example.com
에 대한 인증서 리소스를 만듭니다.cat << EOF > certificate.yaml apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: hello-example-com-certificate namespace: GATEWAY_NAMESPACE spec: secretName: hello-example-com-credential commonName: hello.example.com dnsNames: - hello.example.com duration: 24h renewBefore: 8h issuerRef: group: cas-issuer.jetstack.io kind: GoogleCASIssuer name: gateway-cas-issuer EOF kubectl apply --filename certificate.yaml
인증서 네임스페이스는 인그레스 게이트웨이 네임스페이스와 일치해야 합니다. 변경사항이 전체 서비스 메시에 영향을 줄 수 있기 때문에 일반적으로 플랫폼 관리자만 이 네임스페이스의 리소스를 변경할 수 있습니다. cert-manager 도구는 동일한 네임스페이스에서 TLS 인증서에 대해 보안 비밀 리소스를 만듭니다. 즉, 애플리케이션 관리자가 인그레스 게이트웨이 네임스페이스에 액세스할 필요가 없습니다.
인증서에서
dnsNames
목록에 추가 호스트 이름을 추가할 수 있습니다. 이러한 호스트 이름은 인증서에 주체 대체 이름(SAN)으로 포함됩니다.샘플 애플리케이션에 대해 게이트웨이 리소스를 만듭니다.
cat << EOF > gateway.yaml apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: GATEWAY_NAME namespace: GATEWAY_NAMESPACE spec: selector: istio: ingressgateway servers: - hosts: - APP_NAMESPACE/hello.example.com port: name: https-hello number: 443 protocol: HTTPS tls: credentialName: hello-example-com-credential mode: MUTUAL EOF kubectl apply --filename gateway.yaml
- GATEWAY_NAME은 게이트웨이 이름입니다. 예를 들면
hello
입니다. - 게이트웨이의
credentialName
필드는 인증서의secretName
필드와 일치합니다. cert-manager 도구는 CA Service의 TLS 인증서로 Kubernetes 보안 비밀을 만듭니다. 인그레스 게이트웨이는 이 인증서를 사용하여hello.example.com
대상의 TLS 트래픽을 종료할 수 있습니다.
게이트웨이 매니페스트는 상호 TLS(mTLS)를 지정합니다. 일반 TLS에 대해 게이트웨이를 구성하려면 게이트웨이의 TLS 모드를 대신
SIMPLE
로 설정합니다.- GATEWAY_NAME은 게이트웨이 이름입니다. 예를 들면
샘플 애플리케이션에 대해 VirtualService 리소스를 만듭니다.
cat << EOF > virtual-service.yaml apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: hello namespace: APP_NAMESPACE spec: hosts: - hello.example.com gateways: - GATEWAY_NAMESPACE/GATEWAY_NAME http: - route: - destination: host: SERVICE_NAME port: number: 8080 EOF kubectl apply --filename virtual-service.yaml
게이트웨이 및 VirtualService에는 서로 다른 네임스페이스가 사용됩니다. 이 공통 패턴은 게이트웨이에서 호스트 기반 라우팅 변경을 인그레스 게이트웨이 네임스페이스에서 리소스 변경 권한이 있는 플랫폼 관리자로 제한합니다.
샘플 애플리케이션 네임스페이스에서 VirtualService 수정 권한이 있는 애플리케이션 관리자는 플랫폼 관리자의 도움 없이 URL 경로와 같은 다른 요청 필드로 라우팅을 변경할 수 있습니다.
다른 구성 옵션을 살펴보려면 인증서, 게이트웨이, VirtualService 리소스에 대한 API 문서를 참조하세요.
인그레스 게이트웨이를 통해 서비스 메시에 들어가는 트래픽에 인증 및 승인 정책을 적용할 수 있습니다. 이렇게 하려면 Istio PeerAuthentication 및 AuthorizationPolicy API 문서를 참조하세요.
솔루션 확인
이 섹션에서는 mTLS를 사용하여 HTTPS 요청을 서비스 메시 외부에서 샘플 애플리케이션으로 전송할 수 있는지 확인합니다. 확인을 위해 Compute Engine VM 인스턴스를 만들고 CA 서비스에서 클라이언트 TLS 인증서를 요청한 다음 이 인증서를 사용하여 샘플 애플리케이션에 대한 요청을 인증합니다.
VM 인스턴스에 대한 SSH 액세스 권한이 필요합니다. 기본 네트워크에는 SSH 액세스를 허용하는 방화벽 규칙이 포함되어 있습니다. SSH 액세스 권한이 없으면 방화벽 규칙 문서에 따라 포트 22에서 수신되는 TCP 연결을 허용하는 방화벽 규칙을 만듭니다.
Cloud Shell에서 Google 서비스 계정을 만듭니다.
gcloud iam service-accounts create CLIENT_VM_GSA \ --display-name "CA Service tutorial VM instance service account"
- CLIENT_VM_GSA는 Google 서비스 계정의 이름입니다.
cas-tutorial-client
).
이 Google 서비스 계정을 Compute Engine VM 인스턴스에 할당합니다.
- CLIENT_VM_GSA는 Google 서비스 계정의 이름입니다.
Google 서비스 계정에 게이트웨이 종속 CA 풀에 대한 CA 서비스 인증서 요청자 역할을 부여합니다.
gcloud privateca pools add-iam-policy-binding SUBORDINATE_CA_POOL_GATEWAYS \ --location CA_LOCATION \ --member "serviceAccount:CLIENT_VM_GSA@PROJECT_ID.iam.gserviceaccount.com" \ --role roles/privateca.certificateRequester
이 역할은 CA 풀에서 인증서 요청 권한을 제공합니다.
GKE 클러스터와 동일한 VPC에서 Compute Engine VM 인스턴스를 만듭니다.
gcloud compute instances create cas-tutorial-client \ --scopes cloud-platform \ --service-account CLIENT_VM_GSA@PROJECT_ID.iam.gserviceaccount.com \ --zone ZONE
CA 서비스 API에 액세스하려면 VM 인스턴스에
cloud-platform
범위가 필요합니다.인그레스 게이트웨이 내부 패스 스루 네트워크 부하 분산기의 IP 주소를 파일에 저장합니다.
kubectl get services istio-ingressgateway \ --namespace GATEWAY_NAMESPACE \ --output jsonpath='{.status.loadBalancer.ingress[0].ip}' > ilb-ip.txt
루트 CA의 공개 키 인증서를 파일에 저장합니다.
gcloud privateca roots describe ROOT_CA \ --location CA_LOCATION \ --pool ROOT_CA_POOL \ --format 'value(pemCaCertificates)' > root-ca-cert.pem
루트 CA 인증서 및 인그레스 게이트웨이 내부 패스 스루 네트워크 부하 분산기의 IP 주소가 포함된 파일을 VM 인스턴스에 복사합니다.
gcloud compute scp root-ca-cert.pem ilb-ip.txt cas-tutorial-client:~ \ --zone ZONE
SSH를 사용하여 VM 인스턴스에 연결합니다.
gcloud compute ssh cas-tutorial-client --zone ZONE
SSH 세션에서 이 섹션의 나머지 명령어를 실행합니다.
ca-certificates
및coreutils
패키지를 설치하고,curl
,openssl
,jq
명령줄 도구를 설치합니다.sudo apt-get update --yes sudo apt-get install --yes ca-certificates coreutils curl jq openssl
클라이언트 TLS 인증서에 대해 키 쌍을 만듭니다.
openssl genrsa -out private-key.pem 2048 openssl rsa -in private-key.pem -pubout -out public-key.pem
메타데이터 서버를 쿼리하여 VM 인스턴스에 연결된 Google 서비스 계정 ID의 이메일 주소를 가져옵니다.
GSA_EMAIL=$(curl --silent --header "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/email)
Certificate Authority Service API에서 클라이언트 TLS 인증서를 요청할 때 요청 본문으로 사용하는 JSON 파일을 만듭니다.
cat << EOF > request.json { "config": { "publicKey": { "format": "PEM", "key": "$(base64 --wrap 0 public-key.pem)" }, "subjectConfig": { "subject": { "commonName": "$(hostname --short)", "organization": "Example Organization" }, "subjectAltName": { "dnsNames": [ "$(hostname --fqdn)" ], "emailAddresses": [ "$GSA_EMAIL" ] } }, "x509Config": { "caOptions": { "isCa": false }, "keyUsage": { "baseKeyUsage": { "digitalSignature": true, "keyEncipherment": true }, "extendedKeyUsage": { "clientAuth": true } } } }, "lifetime": "86400s" } EOF
구성 섹션의 필드에 대해 자세히 알아보려면 CA 서비스 API 문서의
CertificateConfig
유형을 참조하세요.메타데이터 서버에서 OAuth 2.0 액세스 토큰을 요청합니다.
TOKEN=$(curl --silent --header "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token | jq --raw-output ".access_token")
이 액세스 토큰은 VM 인스턴스에 연결된 Google 서비스 계정에 부여된 권한을 제공합니다.
CA 서비스 API에서 클라이언트 TLS 인증서를 요청하고 응답 본문을 파일에 저장합니다.
curl --silent --request POST \ --header "Authorization: Bearer $TOKEN" \ --header "Content-Type: application/json" \ --data @request.json \ --output response.json \ "https://privateca.googleapis.com/v1/projects/PROJECT_ID/locations/CA_LOCATION/caPools/SUBORDINATE_CA_POOL_GATEWAYS/certificates"
이 명령어는 액세스 토큰을 사용하여 API 요청을 인증합니다.
클라이언트 인증서 및 인증서 체인을 파일에 저장합니다.
jq --raw-output --join-output ".pemCertificate , .pemCertificateChain[]" response.json > client-cert-chain.pem
curl
을 사용하여 VM 인스턴스에서 샘플 애플리케이션으로 HTTPS 요청을 전송합니다.curl --cert client-cert-chain.pem --key private-key.pem \ --cacert root-ca-cert.pem \ --resolve hello.example.com:443:$(cat ilb-ip.txt) \ --silent https://hello.example.com | head -n1
출력 형식은 다음과 같습니다.
Hello, world!
이 응답은
curl
이 mTLS를 사용하여 HTTPS 요청을 성공적으로 전송했음을 보여줍니다. 터미널 출력에 표시되는 메시지로 샘플 애플리케이션이 응답했습니다.curl
명령어는 다음을 수행합니다.--cert
및--key
플래그는 요청 인증을 위해 클라이언트 TLS 인증서 및 비공개 키를 사용하도록curl
에 지시합니다. 클라이언트 인증서 파일에는 클라이언트 인증서부터 루트 CA까지 전체 인증서 체인이 포함됩니다.--cacert
플래그는 이 튜토리얼에서 만든 루트 CA 또는 해당 종속 CA 중 하나가 서버 인증서를 발급했는지 확인하도록curl
에 지시합니다.이 플래그를 생략하면
curl
이 Debian의ca-certificates
패키지와 같은 운영체제의 기본 CA 번들을 사용해서 서버 인증서 확인을 시도합니다. 하지만 이 튜토리얼에서 만든 루트 CA가 기본 CA 번들에 포함되지 않기 때문에 확인이 실패합니다.--resolve
플래그는 포트 443에서hello.example.com
을 호스팅하기 위해 내부 패스 스루 네트워크 부하 분산기 IP 주소를 요청 대상으로 사용하도록curl
에 지시합니다.이 플래그를 생략하면
curl
이 DNS를 사용해서hello.example.com
호스트 이름 확인을 시도합니다. 하지만 이 호스트 이름에 대한 DNS 항목이 없기 때문에 DNS 변환이 실패합니다.사용자의 고유 환경에서는 내부 패스 스루 네트워크 부하 분산기 IP 주소(
$LOAD_BALANCER_IP
)를 가리키는 DNS A 레코드를 만드는 것이 좋습니다. 레코드 관리 문서에 따라 Cloud DNS를 사용하여 이 레코드를 만듭니다.--silent
플래그는 터미널 출력에 응답 다운로드 진행 상태가 보고되지 않도록 억제합니다.이 명령어는 curl 출력을
head -n1
로 보냅니다. 그 결과 터미널 출력에는 응답 본문의 첫 번째 줄만 포함됩니다.
SSH 세션을 종료합니다.
exit
이 섹션에서는 CA Service API에서 직접 클라이언트 TLS 인증서를 요청했습니다. 클라이언트가 개별 Kubernetes 클러스터에서 다른 서비스 메시의 이그레스 게이트웨이인 경우, cert-manager 도구 및 동일한 루트 CA를 사용하는 Certificate Authority Service 발급기관을 사용하여 이그레스 게이트웨이에 클라이언트 인증서를 제공할 수 있습니다.
다른 상황에서는 Hashicorp Vault, Terraform, gcloud
와 같은 도구를 사용해서 서비스 메시 외부의 워크로드에 대해 클라이언트 TLS 인증서를 요청할 수 있습니다. 자세한 내용은 샘플 솔루션에 대한 CA Service 문서 및 CA Service에 대한 gcloud
문서를 참조하세요.
(선택사항) 트러스트 저장소에 CA 인증서 추가
이 선택적인 섹션에서는 Linux Debian 배포판에 대해 신뢰할 수 있는 CA 인증서 저장소에 CA 인증서를 추가하는 방법을 보여줍니다. 이 안내는 Ubuntu와 같이 Debian에서 파생되는 배포판에도 적용됩니다.
이 저장소에 CA 인증서를 추가한다는 것은 curl
, Python, Go, Ruby를 사용하여 HTTPS 요청을 전송할 때 신뢰할 수 있는 CA 인증서 위치를 지정할 필요가 없다는 것을 의미합니다.
SSH를 사용하여 VM 인스턴스에 연결합니다.
gcloud compute ssh cas-tutorial-client --zone ZONE
SSH 세션에서 이 섹션의 나머지 명령어를 실행합니다.
루트 CA 인증서를
/usr/local/share/ca-certificates
디렉터리에 복사하고 파일 확장자가.crt
인지 확인합니다.sudo cp root-ca-cert.pem /usr/local/share/ca-certificates/cas-rootca.crt
모든 사용자가 루트 CA 인증서 파일을 읽을 수 있도록 파일 권한을 설정합니다.
sudo chmod 644 /usr/local/share/ca-certificates/cas-rootca.crt
update-ca-certificates
스크립트를 실행합니다.sudo update-ca-certificates
이 스크립트는
/etc/ssl/certs
디렉터리의 신뢰할 수 있는 인증서 집합 및/etc/ssl/certs/ca-certificates.crt
파일에 인증서를 추가합니다.출력은 다음과 같습니다.
Updating certificates in /etc/ssl/certs... 1 added, 0 removed; done. Running hooks in /etc/ca-certificates/update.d... done.
curl
을 사용하여 VM 인스턴스에서 샘플 애플리케이션으로 HTTPS 요청을 전송합니다.curl --cert client-cert-chain.pem --key private-key.pem \ --resolve hello.example.com:443:$(cat ilb-ip.txt) \ --silent https://hello.example.com | head -n1
출력 형식은 다음과 같습니다.
Hello, world!
이 응답은
curl
이 mTLS를 사용하여 HTTPS 요청을 성공적으로 전송했고 기본 CA 인증서 저장소를 사용해서 인그레스 게이트웨이에서 서버 TLS 인증서를 검증했음을 보여줍니다.SSH 세션을 종료합니다.
exit
문제 해결
CA Service 발급기관 컨트롤러로 TLS 인증서 보안 비밀이 생성되지 않으면 CA 인증서 발급기관 컨트롤러의 로그를 확인합니다.
kubectl logs deployment/google-cas-issuer --namespace cert-manager
Cloud Service Mesh를 설치할 때 문제가 발생하면 asmcli
도구를 실행하여 클라우드 프로젝트 및 GKE 클러스터를 검증합니다.
이 튜토리얼에서 문제가 발생하면 다음 문서를 검토하세요.
- CA Service 자주 묻는 질문(FAQ)
- Cloud Service Mesh 단계별 문제 해결
- 관리형 Cloud Service Mesh 문제 해결
- Istio 작업 일반적인 문제
- GKE 문제해결
- Kubernetes 클러스터 문제해결
삭제
이 튜토리얼에서 사용된 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 프로젝트를 삭제하거나 개별 리소스를 삭제하면 됩니다.
프로젝트 삭제
Cloud Shell에서 프로젝트를 삭제합니다.
gcloud projects delete PROJECT_ID
리소스 삭제
이 가이드에서 사용된 Google Cloud 프로젝트를 유지하려면 개별 리소스를 삭제합니다.
Cloud Shell에서 GKE 허브에 등록된 GKE 클러스터를 해제합니다.
gcloud container hub memberships unregister CLUSTER_NAME \ --gke-cluster ZONE/CLUSTER_NAME
GKE 클러스터를 삭제합니다.
gcloud container clusters delete CLUSTER_NAME \ --zone ZONE --async --quiet
종속 CA 풀에서 IAM 정책 바인딩을 삭제합니다.
gcloud privateca pools remove-iam-policy-binding SUBORDINATE_CA_POOL_GATEWAYS \ --location CA_LOCATION \ --member "serviceAccount:CAS_ISSUER_GSA@PROJECT_ID.iam.gserviceaccount.com" \ --role roles/privateca.certificateRequester gcloud privateca pools remove-iam-policy-binding SUBORDINATE_CA_POOL_GATEWAYS \ --location CA_LOCATION \ --member "serviceAccount:CLIENT_VM_GSA@PROJECT_ID.iam.gserviceaccount.com" \ --role roles/privateca.certificateRequester
종속 CA 및 루트 CA의 삭제를 사용 중지하고 예약합니다.
gcloud privateca subordinates disable SUBORDINATE_CA_GATEWAYS \ --location CA_LOCATION \ --pool SUBORDINATE_CA_POOL_GATEWAYS \ --quiet gcloud privateca subordinates delete SUBORDINATE_CA_GATEWAYS \ --location CA_LOCATION \ --pool SUBORDINATE_CA_POOL_GATEWAYS \ --ignore-active-certificates \ --quiet gcloud privateca subordinates disable SUBORDINATE_CA_SIDECARS \ --location CA_LOCATION \ --pool SUBORDINATE_CA_POOL_SIDECARS \ --quiet gcloud privateca subordinates delete SUBORDINATE_CA_SIDECARS \ --location CA_LOCATION \ --pool SUBORDINATE_CA_POOL_SIDECARS \ --ignore-active-certificates \ --quiet gcloud privateca roots disable ROOT_CA \ --location CA_LOCATION \ --pool ROOT_CA_POOL \ --quiet gcloud privateca roots delete ROOT_CA \ --location CA_LOCATION \ --pool ROOT_CA_POOL \ --ignore-active-certificates \ --quiet
CA 서비스 발급기관 컨트롤러 Google 서비스 계정의 IAM 정책 바인딩을 삭제합니다.
gcloud iam service-accounts remove-iam-policy-binding \ CAS_ISSUER_GSA@PROJECT_ID.iam.gserviceaccount.com \ --member "serviceAccount:PROJECT_ID.svc.id.goog[cert-manager/ksa-google-cas-issuer]" \ --role roles/iam.workloadIdentityUser
Google 서비스 계정을 삭제합니다.
gcloud iam service-accounts delete --quiet \ CAS_ISSUER_GSA@PROJECT_ID.iam.gserviceaccount.com gcloud iam service-accounts delete --quiet \ CLIENT_VM_GSA@PROJECT_ID.iam.gserviceaccount.com
예약된 부하 분산기 IP 주소를 삭제합니다.
gcloud compute addresses delete asm-ingress-gateway-ilb \ --region REGION --quiet
Compute Engine VM 인스턴스를 삭제합니다.
gcloud compute instances delete cas-tutorial-client \ --zone ZONE --quiet
다음 단계
- Certificate Authority Service 안내 가이드를 참조합니다.
- 온프레미스 및 Google Cloud에서 신뢰할 수 있는 서비스 메시 모니터링 및 관리를 도와주는 Istio 기반 도구 모음인 Cloud Service Mesh에 대해 자세히 알아봅니다.
- Cloud Service Mesh 안내 가이드를 살펴봅니다.