GKE용 Identity Service를 사용해서 Cloud Build 비공개 풀에서 비공개 Google Kubernetes Engine 클러스터 액세스


이 튜토리얼에서는 Cloud Build 비공개 풀을 사용해서 비공개 Google Kubernetes Engine(GKE) 클러스터의 제어 영역에 액세스하는 방법을 설명합니다. 이 액세스 권한을 통해 비공개 GKE 클러스터에서 Cloud Buildto 배포 애플리케이션을 사용하고 리소스를 관리할 수 있습니다. 이 튜토리얼은 플랫폼 관리자, 클러스터 관리자, 개발자를 대상으로 합니다. 여기에서는 사용자가 GKE, Cloud Build, OpenID Connect, gcloud 명령줄 도구에 익숙하다고 가정합니다.

Cloud Build 비공개 풀과 GKE 클러스터 제어 영역은 모두 Google 소유의 Virtual Private Cloud(VPC) 네트워크에서 실행됩니다. 이러한 VPC 네트워크는 Google Cloud에서 자체 VPC 네트워크와 피어링됩니다. 그러나 VPC 네트워크 피어링은 전환 피어링을 지원하지 않으며, 이는 Cloud Build 비공개 풀을 사용할 때 제한될 수 있습니다. 이 튜토리얼에서는 GKE용 Identity Service를 사용하여 Cloud Build 비공개 풀의 작업자가 비공개 GKE 클러스터의 제어 영역에 액세스할 수 있도록 하는 솔루션을 제공합니다.

아키텍처 개요

GKE용 Identity Service는 GKE 클러스터 제어 영역의 인증 프록시입니다. 요청을 API 서버에 프록시하고 OpenID Connect(OIDC) ID 공급업체에서 발급되는 ID 토큰을 검증합니다. 프록시가 ID 토큰을 성공적으로 검증한 후에는 프록시가 원래 요청에 사용자 가장 HTTP 헤더를 추가하고 이를 API 서버로 전달합니다. 프록시는 사용자 및 그룹 가장 권한이 있는 Kubernetes 서비스 계정으로 실행됩니다.

GKE용 Identity Service 프록시는 클러스터 노드에서 포드로 실행됩니다. LoadBalancer 유형의 Kubernetes 서비스는 클러스터 외부에 프록시를 노출합니다. GKE용 Identity Service가 비공개 클러스터에 사용 설정되었으면 설치 프로그램이 Kubernetes 서비스에 주석을 추가하여 내부 패스 스루 네트워크 부하 분산기를 프로비저닝합니다. 프록시가 VPC 네트워크의 클러스터 노드에서 실행되기 때문에 Cloud Build 비공개 풀에서와 같이 VPC 네트워크 피어링 연결을 통해 부하 분산기에서 프록시에 액세스할 수 있습니다.

OAuth 2.0 인증 시스템이 OpenID Connect 사양을 준수하기 때문에 GKE용 Identity Service에서 Google을 OpenID Connect ID 공급업체로 구성할 수 있습니다. Google 서비스 계정의 ID 토큰을 가져오려면 Service Account Credentials APIgenerateIdToken 메서드를 사용하면 됩니다. 이 ID 토큰은 Google에서 발급되고 서명됩니다.

요약하자면, 이 솔루션은 GKE용 Identity Service 프록시를 사용해서 비공개 GKE 클러스터 제어 영역에 대한 액세스를 사용 설정합니다. Cloud Build 비공개 풀에서 실행되는 빌드는 VPC 네트워크 피어링 연결을 통해 프록시에 연결됩니다. Cloud Build 비공개 풀에서 실행되는 빌드는 Google 서비스 계정으로 실행됩니다. 이 Google 서비스 계정은 Service Account Credentials API에서 프록시에 대해 인증을 수행하기 위해 ID 토큰을 가져올 수 있습니다.

다음 다이어그램은 앞에서 설명한 아키텍처를 보여줍니다.

GKE용 Identity Service를 사용해서 비공개 GKE 클러스터에 액세스

이 솔루션에서 모든 커뮤니케이션은 내부 IP 주소 공간에서 발생합니다. 비공개 풀의 작업자는 공개 인터넷 연결이 필요하지 않습니다.

사용자 계정 및 Google 서비스 계정에 부여되는 Identity and Access Management(IAM) 권한은 GKE용 Identity Service를 사용하여 인증할 때 적용되지 않습니다. 대신 Kubernetes 역할 기반 액세스 제어(RBAC)를 사용해서 이러한 계정의 클러스터 권한을 관리합니다.

시작하기 전에

  1. Google Cloud 계정에 로그인합니다. Google Cloud를 처음 사용하는 경우 계정을 만들고 Google 제품의 실제 성능을 평가해 보세요. 신규 고객에게는 워크로드를 실행, 테스트, 배포하는 데 사용할 수 있는 $300의 무료 크레딧이 제공됩니다.
  2. Google Cloud CLI를 설치합니다.
  3. gcloud CLI를 초기화하려면 다음 명령어를 실행합니다.

    gcloud init
  4. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  5. Google Cloud 프로젝트에 결제가 사용 설정되어 있는지 확인합니다.

  6. Cloud Build, GKE, Identity-Aware Proxy (IAP), and Service Networking APIs API를 사용 설정합니다.

    gcloud services enable cloudbuild.googleapis.com container.googleapis.com iap.googleapis.com servicenetworking.googleapis.com
  7. Google Cloud CLI를 설치합니다.
  8. gcloud CLI를 초기화하려면 다음 명령어를 실행합니다.

    gcloud init
  9. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  10. Google Cloud 프로젝트에 결제가 사용 설정되어 있는지 확인합니다.

  11. Cloud Build, GKE, Identity-Aware Proxy (IAP), and Service Networking APIs API를 사용 설정합니다.

    gcloud services enable cloudbuild.googleapis.com container.googleapis.com iap.googleapis.com servicenetworking.googleapis.com

비공개 GKE 클러스터 만들기

  1. Cloud Shell에서 제어 영역의 공개 엔드포인트에 대한 클라이언트 액세스 권한이 없고 GKE용 Identity Service가 설치된 GKE 클러스터를 만듭니다.

    gcloud container clusters create CLUSTER  \
      --enable-identity-service \
      --enable-ip-alias \
      --enable-master-authorized-networks \
      --enable-private-endpoint \
      --enable-private-nodes \
      --master-ipv4-cidr CONTROL_PANE_CIDR \
      --network NETWORK\
      --release-channel regular \
      --scopes cloud-platform \
      --subnetwork SUBNET \
      --tags NODE_TAGS \
      --workload-pool PROJECT_ID.svc.id.goog \
      --zone ZONE
    

    다음을 바꿉니다.

    • CLUSTER: 클러스터의 이름입니다. 이 튜토리얼에서는 private-cluster를 사용합니다.
    • CONTROL_PANE_CIDR: 제어 영역의 IP 주소 범위입니다. /28 프리픽스가 있어야 합니다. 이 튜토리얼에서는 172.16.0.32/28을 사용할 수 있습니다.
    • NETWORK: 제어 영역이 연결되는 VPC 네트워크입니다. 이 튜토리얼에서는 default를 사용합니다.
    • SUBNET: GKE 클러스터 제어 영역이 연결되는 서브넷입니다. 이 서브넷은 NETWORK에서 지정된 VPC 네트워크에 속해야 합니다. 이 튜토리얼에서는 default를 사용합니다.
    • NODE_TAGS: 노드에 적용할 네트워크 태그의 쉼표로 구분된 목록입니다. 이 튜토리얼에서는 private-cluster-node를 사용합니다.
    • PROJECT_ID: Google Cloud 프로젝트 ID입니다.
    • ZONE: GKE 클러스터의 영역입니다. 이 튜토리얼에서는 us-central1-f를 사용합니다.

    이 명령어에 관해서는 다음 사항에 유의하세요.

    • --enable-identity-service 플래그는 클러스터에서 GKE용 Identity Service를 사용 설정합니다. 사용자의 고유 환경에서 기존 클러스터에 GKE용 Identity Service를 사용 설정할 수 있습니다.

    • --enable-private-endpoint 플래그는 내부 IP 주소만 사용하여 제어 영역을 액세스할 수 있게 구성합니다.

    • --enable-private-nodes 플래그는 내부 IP 주소만 포함하도록 클러스터 노드를 구성합니다.

    • --enable-master-authorized-networks--enable-private-nodes 플래그는 --network 플래그로 지정된 비공개 네트워크에서만 API 서버에 액세스를 허용합니다.

    • 선택사항인 --workload-pool 플래그는 워크로드 아이덴티티를 사용 설정합니다. 이 튜토리얼에는 필요하지 않습니다.

  2. GKE 클러스터 제어 영역이 ClientConfig 리소스에 대해 검증 승인 웹훅에 연결하도록 허용하는 방화벽 규칙을 추가합니다.

    gcloud compute firewall-rules create allow-control-plane-clientconfig-webhook \
      --allow tcp:15000 \
      --network NETWORK\
      --source-ranges CONTROL_PANE_CIDR\
      --target-tags NODE_TAGS
    

    ClientConfig는 GKE용 Identity Service가 ID 공급업체와 상호작용하는 방법을 구성하기 위해 사용하는 Kubernetes 커스텀 리소스 유형(CRD)입니다.

GKE용 Identity Service를 OAuth 2.0 클라이언트 애플리케이션으로 등록

이 섹션에서는 Google의 OAuth 2.0 인증 시스템을 사용하여 GKE용 Identity Service를 클라이언트 애플리케이션으로 등록합니다.

  1. Google Cloud 콘솔에서 사용자 인증 정보 페이지를 엽니다.

    사용자 인증 정보 페이지 열기

  2. 사용자 인증 정보 만들기를 클릭합니다.

  3. OAuth 클라이언트 ID를 선택합니다.

    동의 화면이 Google Cloud 프로젝트에 아직 구성되지 않았으면 동의 화면 구성을 클릭합니다. 동의 화면 구성 문서를 참조하세요. 이 튜토리얼에서는 다음 값을 설정합니다.

    • 사용자 유형내부 또는 외부일 수 있습니다. 이 튜토리얼에서는 내부를 선택할 수 있습니다.
    • 앱 이름, 사용자 지원 이메일, 개발자 연락처 정보 값은 필수 값이며 모든 값을 사용할 수 있습니다.
    • 이 튜토리얼에는 범위를 추가할 필요가 없습니다.

    동의 화면 구성을 완료했으면 대시보드로 돌아가기를 클릭한 후 현재 절차의 1단계부터 다시 시작합니다.

  4. 애플리케이션 유형 목록에서 웹 애플리케이션을 선택합니다.

  5. 이름 필드에 클라이언트 ID 이름을 입력합니다. 이 튜토리얼에서는 Identity Service for GKE를 사용합니다.

  6. 만들기를 클릭합니다.

    대화상자가 나타납니다. 클라이언트 ID 값을 복사합니다. 이 절차의 뒷부분에서 필요합니다.

  7. 확인을 클릭하여 대화상자를 닫습니다.

  8. Cloud Shell에서 홈 디렉터리 아래에 cloud-build-private-pools-gke-tutorial이라는 디렉터리를 만들고 이 디렉터리로 이동합니다.

    mkdir -p ~/cloud-build-private-pools-gke-tutorial cd ~/cloud-build-private-pools-gke-tutorial

  9. 새 디렉터리에서 나중에 GKE용 Identity Service ClientConfig 리소스를 패치하기 위해 필요한 값이 포함된 client-config-patch.yaml이라는 YAML 파일을 만듭니다.

    cat << EOF > client-config-patch.yaml
    spec:
      authentication:
      - name: google-oidc
        oidc:
          clientID: CLIENT_ID
          cloudConsoleRedirectURI: https://console.cloud.google.com/kubernetes/oidc
          extraParams: prompt=consent,access_type=offline
          issuerURI: https://accounts.google.com
          kubectlRedirectURI: http://localhost:10000/callback
          scopes: email
          userClaim: email
          userPrefix: '-'
    EOF
    

    CLIENT_ID를 이전 단계의 OAuth 클라이언트 ID로 바꿉니다.

    패치에 대한 다음 사항에 유의하세요.

    • Google OAuth 2.0 인증 시스템에서 발급하는 ID 토큰에는 하위(제목) 클레임의 고유한 숫자 식별자가 포함됩니다. 역할 바인딩에서 이렇게 불투명한 식별자를 사용하면 역할 바인딩의 제목을 식별하기가 어렵습니다. 따라서 이 패치는 기본 하위 클레임을 사용하는 대신 사용자 식별을 위해 ID 토큰에서 이메일 클레임을 사용하도록 GKE용 Identity Service를 구성합니다.

    • 발급된 ID 토큰에 이메일 클레임이 포함되도록 이메일 범위가 추가됩니다.

    • cloudConsoleRedirectURI, extraParams, kubectlRedirectURI, 범위 필드는 개발자가 GKE용 Identity Service를 사용하여 클러스터에 인증을 수행할 때 사용됩니다. Google 서비스 계정이 클러스터에 인증을 수행할 때는 사용되지 않습니다. kubectlRedirectURI 필드는 필수입니다.

    • userPrefix 필드는 구성된 ID 공급업체를 사용하여 인증을 수행하는 사용자의 프리픽스입니다. '-' 값은 프리픽스가 없음을 의미합니다.

    • spec.authentication 필드는 배열입니다. GKE용 Identity Service에 여러 OpenID Connect ID 공급업체를 사용할 수 있습니다. 예를 들어 Google을 ID 공급업체로 사용해서 Google 서비스 계정을 인증하고 다른 ID 공급업체를 사용해서 개발자를 인증할 수 있습니다.

    이 구성의 필드에 대한 자세한 내용은 외부 ID 공급업체를 사용하여 GKE 인증을 참조하세요.

GKE용 Identity Service 구성을 위해 Google 서비스 계정 만들기

  1. Cloud Shell에서 Google 서비스 계정을 만듭니다.

    gcloud iam service-accounts create ISG_GSA \
      --display-name "Configure Identity Service for GKE"
    

    ISG_GSA를 Google 서비스 계정에 사용하려는 이름으로 바꿉니다. 이 튜토리얼에서는 identity-service-for-gke를 사용합니다.

    클러스터에서 GKE용 Identity Service 및 Kubernetes 역할 기반 액세스 제어를 구성하기 위해 이 Google 서비스 계정을 Compute Engine VM 인스턴스에 할당합니다.

  2. 프로젝트에 Google 서비스 계정에 대해 Kubernetes Engine 관리자 역할을 부여합니다.

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member serviceAccount:ISG_GSA@PROJECT_ID.iam.gserviceaccount.com \
      --role roles/container.admin
    

    이 역할은 이 튜토리얼에서 다음 태스크를 수행하는 데 필요한 권한을 제공합니다.

    • 프로젝트에서 클러스터에 GKE용 Identity Service 설정을 구성합니다.
    • 클러스터에 역할 바인딩 및 클러스터 역할 바인딩을 만듭니다.

GKE용 ID 서비스 구성

GKE용 Identity Service를 구성하려면 클러스터 제어 영역에 대한 액세스 권한이 있어야 합니다. 이 튜토리얼에서는 제어 영역에 액세스하도록 Compute Engine VM 인스턴스를 만듭니다.

VM 인스턴스에 대한 SSH 액세스 권한이 필요합니다. VPC 네트워크 외부에서 VM 인스턴스에 대해 인증 및 승인된 SSH 액세스를 사용 설정하려면 IAP(Identity-Aware Proxy)와 함께 TCP 전달을 사용합니다. 이 기능은 VM 인스턴스에 공개 IP 주소가 없어도 SSH 액세스를 사용 설정합니다.

  1. Cloud Shell에서 SSH 액세스가 ssh-iap 네트워크 태그가 있는 VM 인스턴스로 IAP TCP 전달을 사용하도록 허용하는 방화벽 규칙을 만듭니다.

    gcloud compute firewall-rules create allow-ssh-ingress-from-iap \
      --allow tcp:22 \
      --description "Allow SSH tunneling using Identity-Aware Proxy" \
      --network NETWORK \
      --source-ranges 35.235.240.0/20 \
      --target-tags ssh-iap
    

    소스 범위에는 IAP가 TCP 전달을 위해 사용하는 IP 주소가 포함됩니다.

  2. GKE 클러스터와 동일한 VPC 네트워크에서 Compute Engine VM 인스턴스를 만듭니다.

    gcloud compute instances create VM \
      --metadata enable-oslogin=TRUE \
      --network NETWORK \
      --no-address \
      --scopes cloud-platform,userinfo-email \
      --service-account ISG_GSA@PROJECT_ID.iam.gserviceaccount.com \
      --subnet SUBNET  \
      --tags ssh-iap \
      --zone ZONE
    

    VM을 VM 인스턴스에 사용하려는 이름으로 바꿉니다. 이 튜토리얼에서는 identity-service-for-gke-configuration을 사용합니다.

    위 명령어에 관해 다음 사항에 유의하세요.

    • --service-account 플래그는 Google 서비스 계정을 VM 인스턴스에 연결합니다.

    • cloud-platform 범위는 Service Account Credentials API에 액세스하기 위해 필요합니다.

    • userinfo-email 범위는 Kubernetes 역할 기반 액세스 제어를 관리하기 위해 VM 인스턴스를 만들 때 유용합니다. 이 튜토리얼에서는 선택사항입니다.

    • --no-address 플래그는 외부 IP 주소 없이 VM 인스턴스가 생성됨을 의미합니다.

    • 선택사항인 enable-oslogin 인스턴스 메타데이터 값은 VM 인스턴스에서 OS 로그인을 사용 설정합니다. OS 로그인은 IAM을 사용하여 VM 인스턴스에 대한 SSH 액세스 관리를 사용 설정합니다.

  3. ClientConfig 패치 파일을 VM 인스턴스에 복사합니다.

    gcloud compute scp client-config-patch.yaml VM:~ --tunnel-through-iap --zone ZONE
    

    --tunnel-through-iap 플래그는 gcloud가 IAP를 통해 연결을 터널링하도록 지시합니다.

  4. SSH를 사용하여 VM 인스턴스에 연결합니다.

    gcloud compute ssh VM --tunnel-through-iap --zone ZONE
    

    SSH 세션에서 이 섹션의 나머지 명령어를 실행합니다.

  5. kubectl 명령줄 도구 및 gke-gcloud-auth-plugin binary를 VM 인스턴스에 설치합니다.

    sudo apt-get install -y kubectl google-cloud-sdk-gke-gcloud-auth-plugin
    
  6. GKE 클러스터의 사용자 인증 정보를 가져옵니다.

    export USE_GKE_GCLOUD_AUTH_PLUGIN=True
    gcloud container clusters get-credentials CLUSTER --zone ZONE
    
  7. 기본 ClientConfig 리소스에 패치를 적용합니다.

    kubectl patch clientconfig default \
        --namespace kube-public \
        --patch-file client-config-patch.yaml \
        --type merge
    
  8. 패치된 기본 ClientConfig 리소스에서 certificateAuthorityData 필드를 추출하고 이를 certificateAuthorityData.pem이라는 파일에 저장합니다.

    kubectl get clientconfig default \
         --namespace kube-public \
         --output jsonpath='{.spec.certificateAuthorityData}' \
         | base64 --decode > certificateAuthorityData.pem
    
  9. 패치된 기본 ClientConfig 리소스에서 서버 필드를 추출하고 이를 server.txt라는 파일에 저장합니다.

    kubectl get clientconfig default \
         --namespace kube-public \
         --output jsonpath='{.spec.server}' > server.txt
    
  10. SSH 세션을 종료합니다.

    exit
    

(선택사항) 클러스터 구성 확인

계속하기 전에 GKE용 Identity Service가 클러스터에 올바르게 설정되었는지 확인할 수 있습니다. GKE용 Identity Service를 사용해서 클러스터에 인증을 수행하기 위해 VM 인스턴스에 연결된 Google 서비스 계정을 사용하여 설정을 확인합니다.

  1. Cloud Shell에서 Google 서비스 계정에 서비스 계정 자체에 대한 서비스 계정 OpenID Connect ID 토큰 생성자를 부여합니다.

    gcloud iam service-accounts add-iam-policy-binding \
      ISG_GSA@PROJECT_ID.iam.gserviceaccount.com \
      --member serviceAccount:ISG_GSA@PROJECT_ID.iam.gserviceaccount.com \
      --role roles/iam.serviceAccountOpenIdTokenCreator
    

    이 역할은 Service Account Credentials API에서 서비스 계정의 ID 토큰을 요청하기 위해 필요한 iam.serviceAccounts.getOpenIdToken 권한을 제공합니다.

  2. SSH를 사용하여 VM 인스턴스에 연결합니다.

    gcloud compute ssh VM --tunnel-through-iap --zone ZONE
    

    SSH 세션에서 이 섹션의 나머지 명령어를 실행합니다.

  3. OAuth 클라이언트 ID를 요청된 aud(대상) 클레임으로 사용하여 VM 인스턴스에 연결된 Google 서비스 계정에 대한 메타데이터 서버에서 OAuth 2.0 액세스 토큰을 요청합니다.

    ACCESS_TOKEN=$(curl --silent --header "Metadata-Flavor: Google" \
    http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token \
           | python3 -c 'import json, sys; print(json.load(sys.stdin).get("access_token"))')
    

    메타데이터 서버의 응답 본문은 JSON 문서입니다. 이 명령어는 인라인 Python 스크립트를 사용하여 응답 본문에서 access_token 필드를 추출합니다.

  4. VM 인스턴스에 연결된 Google 서비스 계정에 대해 Service Account Credentials API에서 ID 토큰을 요청합니다.

    ID_TOKEN=$(curl --silent --request POST \
        --data '{"audience": "CLIENT_ID", "includeEmail": true}' \
        --header "Authorization: Bearer $ACCESS_TOKEN" \
        --header "Content-Type: application/json; charset=utf-8" \
    "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/ISG_GSA@PROJECT_ID.iam.gserviceaccount.com:generateIdToken" \
           | python3 -c 'import json, sys; print(json.load(sys.stdin).get("token"))')
    

    위 명령어에 관해 다음 사항에 유의하세요.

    • 요청 본문 JSON의 audience 필드는 ID 토큰의 요청된 aud(대상) 클레임을 지정합니다.
    • 이전 단계의 액세스 토큰은 API 인증을 위해 사용됩니다.
  5. ID 토큰의 클레임을 확인합니다.

    echo $ID_TOKEN \
        | cut -d. -f2 \
        | base64 --decode --ignore-garbage 2> /dev/null \
        | python3 -m json.tool
    

    email 클레임에 Google 서비스 계정의 이메일 주소가 포함되는지 확인합니다.

  6. ID 토큰을 사용해서 GKE용 Identity Service를 사용하여 제어 영역에 인증을 수행합니다.

    kubectl get namespaces \
        --certificate-authority certificateAuthorityData.pem \
        --server $(cat server.txt) \
        --token $ID_TOKEN
    

    다음과 유사한 결과가 출력됩니다.

      Error from server (Forbidden): namespaces is forbidden: User "ISG_GSA@PROJECT_ID.iam.gserviceaccount.com" cannot list resource "namespaces" in API group "" at the cluster scope
    

    이 오류는 예상된 오류입니다. Google 서비스 계정에 프로젝트의 GKE 클러스터에 대한 IAM 권한이 부여되지만 GKE용 Identity Service를 사용하여 인증을 수행할 때 IAM 권한이 적용되지 않습니다. 대신 Kubernetes 역할 기반 액세스 제어(RBAC)를 사용하여 액세스를 구성합니다.

  7. 서비스 계정이 Google OpenID Connect 제공업체를 사용해서 클러스터에 인증을 수행할 때 Google 서비스 계정에 view 클러스터 역할을 부여하는 클러스터 역할 바인딩을 만듭니다.

    kubectl create clusterrolebinding ISG_GSA-cluster-view \
        --clusterrole view \
        --user ISG_GSA@PROJECT_ID.iam.gserviceaccount.com
    

    사용자 고유 환경에서 ClientConfig에 - 이외의 userPrefix 값을 설정할 경우 이 명령어에서 --user 플래그 값에 프리픽스를 추가합니다.

  8. GKE용 Identity Service를 사용하여 GKE 클러스터에 액세스합니다.

    kubectl get namespaces \
        --certificate-authority certificateAuthorityData.pem \
        --server $(cat server.txt) \
        --token $ID_TOKEN
    

    다음과 유사한 결과가 출력됩니다.

    NAME                      STATUS   AGE
    anthos-identity-service   Active   1h
    default                   Active   1h
    kube-node-lease           Active   1h
    kube-public               Active   1h
    kube-system               Active   1h
    
  9. SSH 세션을 종료합니다.

    exit
    

kubectl 도구의 컨텍스트 만들기

kubectl 명령어는 kubeconfig 파일을 사용해서 클러스터 액세스를 구성할 수 있습니다. kubeconfig 파일에는 하나 이상의 컨텍스트가 포함됩니다. 각 컨텍스트에는 이름이 포함되고 선택적으로 클러스터 연결 정보, 클러스터 인증에 사용되는 사용자 인증 정보, 기본 네임스페이스가 포함됩니다.

이 섹션에서는 컨텍스트가 있는 kubeconfig 파일을 만듭니다. 컨텍스트에는 클러스터에 대한 GKE용 Identity Service 프록시의 연결 세부정보가 포함됩니다. kubeconfig 파일에는 사용자 인증 정보를 추가하지 않습니다.

  1. Cloud Shell에서 VM 인스턴스의 인증 기관 데이터 및 서버 URL이 포함된 파일을 현재 디렉터리에 복사합니다.

    gcloud compute scp VM:~/certificateAuthorityData.pem VM:~/server.txt . \
        --tunnel-through-iap --zone ZONE
    
  2. 나중에 Cloud Build에서 GKE 클러스터에 연결하기 위해 사용할 컨텍스트 및 클러스터 구성을 만듭니다.

    kubectl config set-context private-cluster \
        --cluster private-cluster \
        --kubeconfig kubeconfig
    

    --kubeconfig 플래그는 현재 디렉터리에서 kubeconfig라는 새 파일에 컨텍스트 및 클러스터 구성을 만듭니다.

    이 명령어는 GKE 클러스터 이름을 컨텍스트의 클러스터 구성 이름으로 사용합니다. 사용자의 고유 환경에서 컨텍스트에 다른 클러스터 구성 이름을 사용할 수 있습니다.

  3. 클러스터 구성에서 certificateAuthorityData 필드를 설정합니다.

    kubectl config set-cluster private-cluster \
        --certificate-authority certificateAuthorityData.pem \
        --embed-certs \
        --kubeconfig kubeconfig
    
  4. 클러스터 구성에서 server 필드를 설정합니다.

    kubectl config set-cluster private-cluster \
        --kubeconfig kubeconfig \
        --server $(cat server.txt)
    

Cloud Build의 Google 서비스 계정 만들기

  1. Cloud Shell에서 Cloud Build 비공개 풀에서 빌드를 실행하기 위해 Google 서비스 계정을 만듭니다.

    gcloud iam service-accounts create CB_GSA \
      --description "Runs builds on Cloud Build private pools" \
      --display-name "Cloud Build private pool"
    

    CB_GSA를 Google 서비스 계정에 사용하려는 이름으로 바꿉니다. 이 튜토리얼에서는 cloud-build-private-pool을 사용합니다.

  2. 프로젝트에서 Google 서비스 계정에 대해 Cloud Build 서비스 계정 역할을 부여합니다.

    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member serviceAccount:CB_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/cloudbuild.builds.builder
    

    이 역할은 Google에서 관리되는 Cloud Build 서비스 계정의 기본 권한을 제공합니다.

  3. Google 서비스 계정에 서비스 계정 자체에 대해 서비스 계정 OpenID Connect ID 토큰 생성자를 부여합니다.

    gcloud iam service-accounts add-iam-policy-binding \
        CB_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --member serviceAccount:CB_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/iam.serviceAccountOpenIdTokenCreator
    

    이 역할은 Service Account Credentials API에서 서비스 계정의 ID 토큰을 요청하기 위해 필요한 iam.serviceAccounts.getOpenIdToken 권한을 제공합니다.

  4. SSH를 사용하여 VM 인스턴스에 연결합니다.

    gcloud compute ssh VM --tunnel-through-iap --zone ZONE
    

    SSH 세션에서 이 섹션의 나머지 명령어를 실행합니다.

  5. SSH 세션에서 서비스 계정이 Google OpenID Connect 제공업체를 사용하여 클러스터에 인증을 수행할 때 Google 서비스 계정에 cluster-admin 클러스터 역할을 부여하는 Kubernetes 클러스터 역할 바인딩을 만듭니다.

    kubectl create clusterrolebinding CB_GSA-cluster-admin \
        --clusterrole cluster-admin \
        --user CB_GSA@PROJECT_ID.iam.gserviceaccount.com
    

    cluster-admin 클러스터 역할은 클러스터 전체의 광범위한 권한을 부여합니다. 사용자의 고유 환경에서는 Cloud Build가 수행하는 태스크에 필요한 권한만 제공하는 클러스터 역할을 사용할 수 있습니다. 또한 특정 네임스페이스에만 권한을 부여하도록 역할 바인딩을 사용할 수 있습니다.

    사용자의 고유 환경에서 ClientConfig에 userPrefix를 설정할 경우에는 이 명령어의 --user 플래그 값에 이 프리픽스를 추가해야 합니다.

  6. SSH 세션을 종료합니다.

    exit
    

Cloud Build 비공개 풀 만들기

  1. Cloud Shell에서 비공개 풀에 연결할 수 있도록 VPC 네트워크에서 IP 주소 범위를 할당합니다.

    gcloud compute addresses create RESERVED_RANGE_NAME \
    --addresses RESERVED_RANGE_START_IP\
        --description "Cloud Build private pool reserved range" \
        --global \
        --network NETWORK \
        --prefix-length RESERVED_RANGE_PREFIX_LENGTH \
        --purpose VPC_PEERING
    

    다음을 바꿉니다.

    • RESERVED_RANGE_NAME: Cloud Build 비공개 풀을 호스팅하는 할당된 IP 주소 범위의 이름입니다. 이 튜토리얼에서는 cloud-build-private-pool을 사용합니다.
    • RESERVED_RANGE_START_IP: 할당된 IP 주소 범위의 첫 번째 IP 주소입니다. 이 튜토리얼에서는 192.168.12.0을 사용합니다.
    • RESERVED_RANGE_PREFIX_LENGTH: 할당된 IP 주소 범위의 프리픽스 길이(서브넷 마스크)입니다. 프리픽스 길이는 /23 또는 이보다 낮은 숫자여야 합니다. 예: /22 또는 /21. 낮은 숫자는 더 큰 주소 범위를 의미합니다. 이 튜토리얼에서는 23을 사용하고 선행 /(슬래시)를 입력하지 않습니다.
  2. 예약된 IP 주소 범위에서 VPC 네트워크의 다른 리소스로의 인바운드 트래픽을 허용하는 방화벽 규칙을 만듭니다.

    gcloud compute firewall-rules create allow-private-pools-ingress \
        --allow all \
        --network NETWORK \
        --source-ranges RESERVED_RANGE_START_IP/RESERVED_RANGE_PREFIX_LENGTH
    
  3. VPC 네트워크를 서비스 네트워킹 서비스에 연결하는 비공개 서비스 연결을 만듭니다.

    gcloud services vpc-peerings connect \
        --network NETWORK \
        --ranges RESERVED_RANGE_NAME \
        --service servicenetworking.googleapis.com
    

    Cloud Build 비공개 풀은 서비스 네트워킹을 사용하여 작업자를 실행합니다. 비공개 서비스 연결은 VPC 네트워크가 VPC 네트워크 피어링 연결을 사용해서 내부 IP 주소가 할당된 범위에서 비공개 풀과 통신할 수 있도록 사용 설정합니다.

    비공개 서비스 연결을 만들려면 몇 분 정도 걸릴 수 있습니다.

    사용자의 고유 환경에서 공유 VPC를 사용할 경우 비공개 서비스 연결을 만드는 추가 단계는 환경 설정을 참조하세요.

  4. VPC 네트워크와 피어링된 Google 소유의 VPC 네트워크에서 Cloud Build 비공개 풀을 만듭니다.

    gcloud builds worker-pools create PRIVATE_POOL_NAME \
       --no-public-egress \
       --peered-network projects/PROJECT_ID/global/networks/NETWORK \
       --region REGION
    

    다음을 바꿉니다.

    • PRIVATE_POOL_NAME: 비공개 풀의 이름입니다. 이 튜토리얼에서는 private-pool을 사용합니다.
    • REGION: 비공개 풀에 사용할 리전입니다. 이 튜토리얼에서는 us-central1를 사용합니다.

    --no-public-egress 플래그는 비공개 풀의 작업자에 공개 IP 주소가 없음을 의미합니다. 사용자의 고유 환경에서 비공개 풀의 작업자가 공개 IP 주소를 사용해서 인터넷에 연결되도록 하려면 이 플래그를 제거하면 됩니다.

    비공개 풀의 작업자에 대한 머신 유형 및 디스크 크기와 같은 추가적인 구성 옵션은 비공개 풀 만들기 및 관리를 참조하세요.

솔루션 확인

이 섹션에서는 Cloud Build 비공개 풀에서 빌드를 실행하여 솔루션을 확인합니다. 이 빌드는 비공개 GKE 클러스터에 액세스합니다.

  1. Cloud Shell에서 Cloud Build의 빌드 로그를 저장할 Cloud Storage 버킷을 만듭니다.

    gsutil mb -l REGION gs://PROJECT_ID-build-logs
    
  2. Cloud Build에 대한 빌드 구성 파일을 만듭니다.

    cat << "EOF" > cloudbuild.yaml
    steps:
    - id: list-services
      name: gcr.io/google.com/cloudsdktool/google-cloud-cli
      entrypoint: bash
      args:
      - -eEuo
      - pipefail
      - -c
      - |-
        kubectl config use-context $_KUBECTL_CONTEXT
    
        ACCESS_TOKEN=$$(curl --silent \
            --header "Metadata-Flavor: Google" \
            http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token \
            | python3 -c 'import json, sys; print(json.load(sys.stdin).get("access_token"))')
    
        ID_TOKEN=$$(curl --silent --request POST \
            --data '{"audience": "CLIENT_ID", "includeEmail": true}' \
            --header "Authorization: Bearer $$ACCESS_TOKEN" \
            --header "Content-Type: application/json; charset=utf-8" \
            "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/$_SERVICE_ACCOUNT:generateIdToken" \
            | python3 -c 'import json, sys; print(json.load(sys.stdin).get("token"))')
    
        kubectl get services --namespace $_NAMESPACE --token $$ID_TOKEN
    
    logsBucket: gs://PROJECT_ID-build-logs
    
    options:
      env:
      - KUBECONFIG=/workspace/$_KUBECONFIG
    
    substitutions:
      _KUBECONFIG: kubeconfig
      _KUBECTL_CONTEXT: private-cluster
      _NAMESPACE: default
    
    serviceAccount: projects/$PROJECT_ID/serviceAccounts/$_SERVICE_ACCOUNT
    EOF
    

    빌드 구성 파일의 단계에서는 다음을 수행합니다.

    1. _KUBECTL_CONTEXT 대체로 지정된 kubectl 컨텍스트로 전환합니다. 기본 대체 값은 private-cluster입니다.

    2. 메타데이터 서버에서 액세스 토큰을 검색합니다. 액세스 토큰은 빌드를 실행하는 Google 서비스 계정에 발급됩니다.

    3. Service Account Credentials API를 사용하여 ID 토큰을 생성합니다. ID 토큰 생성 요청은 이 액세스 토큰을 사용하여 인증됩니다. ID 토큰의 요청된 aud(대상) 클레임은 _CLIENT_ID 대체로 지정된 OAuth 2.0 클라이언트 ID입니다.

    4. _NAMESPACE 대체로 지정된 네임스페이스의 Kubernetes 서비스를 나열합니다. 기본 대체 값은 default입니다. 요청은 이전 명령어에서 생성된 ID 토큰을 사용하여 인증됩니다.

    빌드 구성 파일에 대해 다음을 확인하세요.

    • $ 문자는 대체 항목의 프리픽스입니다. $$는 bash 매개변수 확장 및 명령어 대체 항목에 사용됩니다.

    • _KUBECONFIG_KUBECTL_CONTEXT 대체 항목은 빌드를 실행할 때 다른 kubeconfig 파일 및 다른 컨텍스트를 지정하도록 허용합니다. 이러한 대체 항목을 사용하면 여러 컨텍스트가 포함된 단일 kubeconfig 파일 또는 여러 kubeconfig 파일을 사용해서 여러 클러스터 구성을 관리할 수 있습니다.

    • 대체 _SERVICE_ACCOUNT에는 기본 값이 포함되지 않습니다. 빌드를 실행할 때 이 대체 항목의 값을 제공해야 합니다.

    • options 블록은 빌드에 포함된 모든 단계에 대해 KUBECONFIG 환경 변수를 설정합니다.

    • 빌드 단계에는 gcr.io/google.com/cloudsdktool/google-cloud-cli 빌더 이미지가 사용됩니다. 이 이미지는 대형 컨테이너 이미지이며 레지스트리에서 비공개 풀 작업자로 가져오는 데 시간이 걸립니다. 빌더 이미지를 가져오는 데 걸리는 시간을 줄이기 위해서는 curl, kubectl, Python과 같이 빌드 단계에 필요한 도구만 포함된 커스텀 빌더 이미지를 만들 수 있습니다.

    빌드 구성 파일의 인라인 셸 스크립트에 대한 자세한 내용은 bash 스크립트 실행을 참조하세요.

  3. 빌드 구성 파일 및 현재 디렉터리의 파일을 사용하여 빌드를 실행합니다.

    gcloud builds submit \
        --config cloudbuild.yaml \
        --region REGION \
        --substitutions _SERVICE_ACCOUNT=CB_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --worker-pool projects/PROJECT_ID/locations/REGION/workerPools/PRIVATE_POOL_NAME
    

    이 명령어는 Cloud Build에서 사용할 수 있도록 현재 디렉터리에 있는 모든 파일을 Cloud Storage에 업로드합니다. 빌드 단계에서는 kubeconfig 파일을 사용하여 GKE 클러스터에 연결합니다.

    출력 끝 부분 근처에 다음과 비슷한 줄이 표시됩니다.

    NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
    kubernetes   ClusterIP   10.0.0.1     <none>        443/TCP   2h
    

    이 출력은 GKE용 Identity Service 인증 프록시를 사용하여 비공개 풀 작업자가 클러스터 제어 영역에 연결된 것을 보여줍니다.

문제 해결

SSH를 사용해서 VM 인스턴스에 연결할 수 없으면 연결 문제 원인을 파악할 수 있도록 --troubleshoot 플래그를 추가합니다.

gcloud compute ssh VM --tunnel-through-iap --zone ZONE --troubleshoot

GKE 클러스터에서 기본 ClientConfig에 패치를 적용할 때 Error from server (NotFound): clientconfigs.authentication.gke.io "default" not found 메시지가 표시되면 비공개 GKE 클러스터 만들기 섹션에 설명된 대로 방화벽 규칙을 만들었는지 확인합니다. 방화벽 규칙이 있는지 확인합니다.

gcloud compute firewall-rules describe allow-control-plane-clientconfig-webhook

GKE용 Identity Service 프록시에 인증할 수 없으면 gke-oidc-service 배포의 포드 로그에서 오류를 확인합니다.

gcloud compute ssh VM --tunnel-through-iap --zone ZONE --command \
    'kubectl logs deployment/gke-oidc-service \
         --namespace anthos-identity-service --all-containers'

이 튜토리얼에서 문제가 발생하면 다음 문서를 검토하는 것이 좋습니다.

정리

이 튜토리얼에서 사용된 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 리소스가 포함된 프로젝트를 삭제하거나 프로젝트를 유지하고 개별 리소스를 삭제하세요.

프로젝트 삭제

    Google Cloud 프로젝트를 삭제합니다.

    gcloud projects delete PROJECT_ID

리소스 삭제

이 튜토리얼에서 사용한 프로젝트를 보존하려는 경우 개별 리소스를 삭제합니다.

  1. Cloud Shell에서 Cloud Build 비공개 풀을 삭제합니다.

    gcloud builds worker-pools delete PRIVATE_POOL_NAME --region REGION --quiet
    
  2. 서비스 네트워킹에 대한 비공개 서비스 연결을 삭제합니다.

    gcloud services vpc-peerings delete --network NETWORK \
      --service servicenetworking.googleapis.com --quiet --async
    
  3. Cloud Build 비공개 풀에 할당된 IP 주소 범위를 삭제합니다.

    gcloud compute addresses delete RESERVED_RANGE_NAME --global --quiet
    
  4. Cloud Storage 버킷 및 모든 콘텐츠를 삭제합니다.

    gsutil rm -r gs://PROJECT_ID-build-logs
    
  5. GKE 클러스터를 삭제합니다.

    gcloud container clusters delete CLUSTER --zone ZONE --quiet --async
    
  6. Compute Engine VM 인스턴스를 삭제합니다.

    gcloud compute instances delete VM --zone ZONE --quiet
    
  7. 방화벽 규칙을 삭제합니다.

    gcloud compute firewall-rules delete allow-private-pools-ingress --quiet
    
    gcloud compute firewall-rules delete allow-ssh-ingress-from-iap --quiet
    
    gcloud compute firewall-rules delete allow-control-plane-clientconfig-webhook --quiet
    
  8. IAM 역할 바인딩을 삭제합니다.

    gcloud projects remove-iam-policy-binding PROJECT_ID \
        --member serviceAccount:CB_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/cloudbuild.builds.builder
    
    gcloud projects remove-iam-policy-binding PROJECT_ID \
        --member serviceAccount:ISG_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/container.admin
    
    gcloud iam service-accounts remove-iam-policy-binding \
        CB_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --member serviceAccount:CB_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/iam.serviceAccountOpenIdTokenCreator
    
    gcloud iam service-accounts remove-iam-policy-binding \
        ISG_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --member serviceAccount:ISG_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/iam.serviceAccountOpenIdTokenCreator
    
  9. Google 서비스 계정을 삭제합니다.

    gcloud iam service-accounts delete CB_GSA@PROJECT_ID.iam.gserviceaccount.com \
       --quiet
    
    gcloud iam service-accounts delete ISG_GSA@PROJECT_ID.iam.gserviceaccount.com \
       --quiet
    

OAuth 2.0 클라이언트 ID 삭제

  1. Google Cloud 콘솔에서 사용자 인증 정보 페이지로 이동합니다.

    사용자 인증 정보 페이지 열기

  2. 프로젝트 선택자 목록에서 프로젝트를 선택합니다.

  3. OAuth 2.0 클라이언트 ID 표에서 GKE용 Identity Service 행을 찾은 후 OAuth 클라이언트 삭제 아이콘을 클릭합니다.

  4. 대화상자에서 삭제를 클릭합니다.

다음 단계