비공개 GKE 클러스터의 비공개 HTTP 엔드포인트에서 Pub/Sub 이벤트 수신


이 튜토리얼에서는 Eventarc를 사용하여 Pub/Sub 메시지 이벤트를 수신하는 비공개 Google Kubernetes Engine(GKE) 클러스터에서 비공개 HTTP 엔드포인트를 만드는 방법을 보여줍니다. 이 이벤트 대상에 대한 자세한 내용은 이벤트를 VPC 네트워크의 내부 HTTP 엔드포인트로 라우팅을 참조하세요.

비공개 GKE 클러스터는 노드에 내부 IP 주소만 있는 가상 프라이빗 클라우드(VPC) 기반 클러스터 유형으로, 이는 기본적으로 노드와 포드가 인터넷으로부터 격리되어 있다는 것을 의미합니다. 클라이언트 액세스 권한 없음, 제한된 액세스 또는 제어 영역에 대한 무제한 액세스를 선택할 수 있습니다. 비공개가 아닌 기존 클러스터를 비공개 클러스터로 변환할 수 없습니다. 자세한 내용은 비공개 클러스터 정보를 참조하세요.

터미널이나 Cloud Shell에서 Google Cloud CLI를 사용하여 다음 명령어를 실행할 수 있습니다.

목표

이 가이드에서는 다음 단계를 진행합니다.

  1. 기본 VPC 네트워크에 프록시 전용 서브넷을 만들고 VPC 방화벽 규칙을 만듭니다.
  2. 클라이언트가 공개 엔드포인트에 액세스할 수 없는 비공개 GKE Autopilot 클러스터를 만듭니다.
  3. VPC 네트워크의 지정된 서브넷에 Compute Engine 가상 머신(VM) 인스턴스를 만듭니다.
  4. VM 인스턴스에 SSH 연결을 설정하고 VM 인스턴스에 이벤트 수신자 서비스를 배포합니다.
  5. 클러스터에 게이트웨이 및 HTTPRoute 매니페스트를 배포하여 Kubernetes의 트래픽 라우팅을 애플리케이션 백엔드로 구성합니다.
  6. 제작자 VPC 네트워크가 소비자 VPC 네트워크에 대한 연결을 시작할 수 있도록 네트워크 연결을 만듭니다.
  7. Pub/Sub 이벤트를 VM 인스턴스의 이벤트 수신자로 라우팅하는 Eventarc 트리거를 만듭니다.
  8. Pub/Sub 주제에 메시지를 게시하여 이벤트를 생성하고 애플리케이션 포드 로그에서 이벤트 본문을 확인합니다.

비용

이 문서에서는 비용이 청구될 수 있는 다음과 같은 Google Cloud 구성요소를 사용합니다.

프로젝트 사용량을 기준으로 예상 비용을 산출하려면 가격 계산기를 사용하세요. Google Cloud를 처음 사용하는 사용자는 무료 체험판을 사용할 수 있습니다.

이 문서에 설명된 태스크를 완료했으면 만든 리소스를 삭제하여 청구가 계속되는 것을 방지할 수 있습니다. 자세한 내용은 삭제를 참조하세요.

시작하기 전에

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

    gcloud init
  4. Google Cloud 프로젝트를 만들거나 선택합니다.

    • Google Cloud 프로젝트를 만듭니다.

      gcloud projects create PROJECT_ID

      PROJECT_ID를 만들려는 Google Cloud 프로젝트의 이름으로 바꿉니다.

    • 만든 Google Cloud 프로젝트를 선택합니다.

      gcloud config set project PROJECT_ID

      PROJECT_ID를 Google Cloud 프로젝트 이름으로 바꿉니다.

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

  6. Cloud Resource Manager, Compute Engine, Eventarc, GKE, and Pub/Sub API를 사용 설정합니다.

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

    gcloud init
  9. Google Cloud 프로젝트를 만들거나 선택합니다.

    • Google Cloud 프로젝트를 만듭니다.

      gcloud projects create PROJECT_ID

      PROJECT_ID를 만들려는 Google Cloud 프로젝트의 이름으로 바꿉니다.

    • 만든 Google Cloud 프로젝트를 선택합니다.

      gcloud config set project PROJECT_ID

      PROJECT_ID를 Google Cloud 프로젝트 이름으로 바꿉니다.

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

  11. Cloud Resource Manager, Compute Engine, Eventarc, GKE, and Pub/Sub API를 사용 설정합니다.

    gcloud services enable compute.googleapis.com container.googleapis.com cloudresourcemanager.googleapis.com eventarc.googleapis.com pubsub.googleapis.com
  12. Google Cloud CLI 구성요소를 업데이트합니다.
    gcloud components update
  13. 계정을 사용하여 로그인합니다.
    gcloud auth login
  14. 프로젝트 생성자에게는 기본 소유자 역할(roles/owner)이 부여됩니다. 기본적으로 Identity and Access Management(IAM) 역할에는 대부분의 Google Cloud 리소스에 대한 전체 액세스에 필요한 권한이 포함되며, 이 단계를 건너뛸 수 있습니다.

    프로젝트 생성자가 아니면 프로젝트에서 적합한 주 구성원에 대해 필수 권한을 부여해야 합니다. 예를 들어 주 구성원은 Google 계정(최종 사용자)이거나 서비스 계정(애플리케이션 및 컴퓨팅 워크로드)일 수 있습니다. 자세한 내용은 이벤트 대상의 역할 및 권한 페이지를 참조하세요.

    필수 권한

    빠른 시작을 완료하는 데 필요한 권한을 얻으려면 관리자에게 프로젝트에 대한 다음 IAM 역할을 부여해 달라고 요청하세요.

    역할 부여에 대한 자세한 내용은 액세스 관리를 참조하세요.

    커스텀 역할이나 다른 사전 정의된 역할을 통해 필요한 권한을 얻을 수도 있습니다.

  15. Compute Engine 기본 서비스 계정은 Compute Engine을 사용하는 Google Cloud 서비스를 사용 설정하거나 사용하면 자동으로 생성됩니다.

    테스트 목적으로 이 서비스 계정을 Eventarc 트리거에 연결하여 트리거의 ID를 나타낼 수 있습니다. 트리거를 만들 때 다음과 같이 이메일 형식을 사용합니다.

    PROJECT_NUMBER-compute@developer.gserviceaccount.com
    

    PROJECT_NUMBER를 Google Cloud 프로젝트 번호로 바꿉니다. Google Cloud 콘솔의 시작 페이지에서 또는 다음 명령어를 실행하여 프로젝트 번호를 찾을 수 있습니다.

    gcloud projects describe PROJECT_ID --format='value(projectNumber)'

    Compute Engine 서비스 계정에는 프로젝트에 대한 기본 편집자 역할(roles/editor)이 자동으로 부여됩니다. 하지만 자동 역할 부여가 중지된 경우 관련 역할 및 권한 안내를 참조하여 새 서비스 계정을 만들고 필요한 역할을 부여합니다.

  16. 2021년 4월 8일 이전에 Cloud Pub/Sub 서비스 에이전트를 사용 설정하여 인증된 Pub/Sub 푸시 요청을 지원한 경우 서비스 계정 토큰 생성자 역할(roles/iam.serviceAccountTokenCreator)을 Google 관리 서비스 계정에 부여합니다. 그렇지 않으면 기본적으로 이 역할이 부여됩니다.
    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member=serviceAccount:service-PROJECT_NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com \
        --role=roles/iam.serviceAccountTokenCreator

프록시 전용 서브넷 만들기

이를 금지하는 조직 정책을 만들지 않는 한, 새 프로젝트는 각 리전에 하나의 서브네트워크(서브넷)가 있는 기본 네트워크(자동 모드 VPC 네트워크)로 시작됩니다. 각 VPC 네트워크는 서브넷이라는 하나 이상의 IP 주소 범위로 구성됩니다. 서브넷은 리전별 리소스이며 서브넷과 연결된 IP 주소 범위가 있습니다.

  1. gcloud compute networks subnets create 명령어를 사용하여 기본 네트워크에 프록시 전용 서브넷을 만듭니다.

    gcloud compute networks subnets create proxy-only-subnet \
        --purpose=REGIONAL_MANAGED_PROXY \
        --role=ACTIVE \
        --region=us-central1 \
        --network=default \
        --range=10.10.10.0/24
    

    purpose=REGIONAL_MANAGED_PROXY가 있는 서브넷은 Envoy 기반 부하 분산기용으로 예약되어 있으며 range에서 64개 이상의 IP 주소를 제공해야 합니다.

  2. 프록시 전용 서브넷 범위와 일치하고 TCP 포트 8080에서 트래픽을 허용하는 방화벽 규칙을 만듭니다.

    gcloud compute firewall-rules create allow-proxy-connection \
        --allow tcp:8080 \
        --source-ranges 10.10.10.0/24 \
        --network=default
    

비공개 GKE 클러스터 만들기

gcloud container clusters create-auto 명령어를 사용하여 비공개 노드가 있고 공개 엔드포인트에 대한 클라이언트 액세스 권한이 없는 Autopilot 모드로 비공개 GKE 클러스터를 만듭니다.

다음 예시에서는 private-cluster라는 비공개 GKE 클러스터를 만들고 my-subnet이라는 서브넷도 만듭니다.

gcloud container clusters create-auto private-cluster \
    --create-subnetwork name=my-subnet \
    --enable-master-authorized-networks \
    --enable-private-nodes \
    --enable-private-endpoint \
    --region=us-central1

다음에 유의하세요.

  • --enable-master-authorized-networks는 공개 엔드포인트에 대한 액세스를 사용자가 승인한 IP 주소 범위로 제한합니다.
  • --enable-private-nodes는 클러스터의 노드에 외부 IP 주소가 없음을 나타냅니다.
  • --enable-private-endpoint는 클러스터가 제어 영역 API 엔드포인트의 내부 IP 주소를 사용하여 관리됨을 나타냅니다.

클러스터 생성이 완료되는 데 몇 분이 걸릴 수 있습니다. 클러스터가 생성되면 출력에 클러스터 상태가 RUNNING으로 표시됩니다.

특정 서브넷에 VM 인스턴스 만들기

Compute Engine VM 인스턴스는 Google 인프라에서 호스팅되는 가상 머신입니다. Compute Engine 인스턴스, VM 인스턴스, VM은 같은 의미로 사용되는 동의어입니다. VM 인스턴스에는 GKE 클러스터, App Engine 가변형 환경 인스턴스 및 Compute Engine VM을 기반으로 빌드된 기타 Google Cloud 제품이 포함됩니다.

gcloud compute instances create 명령어를 사용하여 이전에 만든 서브넷에 Compute Engine VM 인스턴스를 만듭니다. 서비스 계정을 연결하고 VM의 액세스 범위를 cloud-platform으로 설정합니다.

gcloud compute instances create my-vm \
    --service-account=PROJECT_NUMBER-compute@developer.gserviceaccount.com \
    --scopes=https://www.googleapis.com/auth/cloud-platform \
    --zone=us-central1-a \
    --subnet=my-subnet

자세한 내용은 VM 인스턴스 만들기 및 시작을 참조하세요.

VM에 이벤트 수신자 배포

사전 빌드된 이미지 us-docker.pkg.dev/cloudrun/container/hello를 사용하여 포트 80에서 수신 대기하고 이벤트를 수신하고 로깅하는 서비스를 VM에 배포합니다.

  1. 다음 명령어를 실행하여 VM 인스턴스에 SSH 연결을 설정합니다.

    gcloud compute ssh my-vm --project=PROJECT_ID --zone=us-central1-a
    

    SSH 서버에 대한 연결이 설정되면 VM 인스턴스에서 나머지 명령어를 실행합니다.

  2. 필요한 경우 kubectl 및 필수 플러그인을 설치합니다.

  3. 만든 클러스터에 kubectl이 작동하도록 하려면 VM 인스턴스에서 get-credentials 명령어를 사용하세요.

    gcloud container clusters get-credentials private-cluster \
        --region=us-central1 \
        --internal-ip
    
  4. Kubernetes 명령어 kubectl create deployment를 사용하여 애플리케이션을 클러스터에 배포합니다.

    kubectl create deployment hello-app \
        --image=us-docker.pkg.dev/cloudrun/container/hello
    

    그러면 hello-app이라는 배포가 생성됩니다. 배포의 포드hello 컨테이너 이미지를 실행합니다.

  5. 애플리케이션을 배포한 후 Kubernetes 서비스를 만들어 애플리케이션을 트래픽에 노출할 수 있습니다. 다음 kubectl expose 명령어를 실행합니다.

    kubectl expose deployment hello-app \
        --type ClusterIP \
        --port 80 \
        --target-port 8080
    

    출력에 service/hello-app exposed가 표시됩니다.

    다음과 유사한 메시지는 무시해도 됩니다.

    E0418 14:15:33.970933    1129 memcache.go:287] couldn't get resource list for metrics.k8s.io/v1beta1: the server is currently unable to handle the request
    

Kubernetes 트래픽 라우팅 구성

게이트웨이 리소스는 Kubernetes에서 트래픽을 라우팅하는 데이터 영역을 나타냅니다. 게이트웨이는 파생된 GatewayClass에 따라 여러 종류의 부하 분산 및 라우팅을 나타낼 수 있습니다. 자세한 내용은 게이트웨이 배포를 참조하세요. HTTPRoute 매니페스트는 경로를 만들고 트래픽을 애플리케이션 백엔드로 전송하도록 배포됩니다.

  1. 클러스터에 게이트웨이를 배포합니다.

    kubectl apply -f - <<EOF
    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: internal-http
    spec:
      gatewayClassName: gke-l7-rilb
      listeners:
      - name: http
        protocol: HTTP
        port: 80
    EOF
    

    다음에 유의하세요.

    • gatewayClassName: gke-l7-rilb는 이 게이트웨이가 파생된 GatewayClass를 지정합니다. gke-l7-rilb는 내부 애플리케이션 부하 분산기에 해당합니다.
    • port: 80은 게이트웨이가 HTTP 트래픽을 리슨하기 위해 포트 80만 노출하도록 지정합니다.
  2. 게이트웨이가 올바르게 배포되었는지 확인합니다. 모든 리소스를 배포하려면 몇 분 정도 걸릴 수 있습니다.

    kubectl describe gateways.gateway.networking.k8s.io internal-http
    

    출력은 다음과 비슷합니다.

    Name:         internal-http
    Namespace:    default
    ...
    API Version:  gateway.networking.k8s.io/v1beta1
    Kind:         Gateway
    ...
    Spec:
      Gateway Class Name:  gke-l7-rilb
      Listeners:
        Allowed Routes:
          Namespaces:
            From:  Same
        Name:      http
        Port:      80
        Protocol:  HTTP
    Status:
      Addresses:
        Type:   IPAddress
        Value:  10.36.172.5
    ...
    Events:
      Type    Reason  Age                From                   Message
      ----    ------  ----               ----                   -------
      Normal  ADD     80s                sc-gateway-controller  default/internal-http
      Normal  UPDATE  20s (x3 over 80s)  sc-gateway-controller  default/internal-http
      Normal  SYNC    20s                sc-gateway-controller  SYNC on default/internal-http was a success
    
  3. HTTPRoute 매니페스트를 배포하여 HTTP 트래픽을 포트 80에서 hello-app 서비스로 라우팅합니다.

    kubectl apply -f - <<EOF
    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: hello-app-route
    spec:
      parentRefs:
      - kind: Gateway
        name: internal-http
      rules:
      - backendRefs:
        - name: hello-app
          port: 80
    EOF
    

네트워크 연결 만들기

네트워크 연결은 프로듀서 VPC 네트워크가 Private Service Connect 인터페이스를 통해 소비자 VPC 네트워크에 대한 연결을 시작할 수 있게 해주는 리소스입니다.

이벤트를 게시하기 위해 Eventarc는 네트워크 연결을 사용해서 VPC 네트워크에 호스팅되는 내부 HTTP 엔드포인트에 대해 연결을 설정합니다.

네트워크 연결을 참조하는 Private Service Connect 인터페이스에서 연결을 자동으로 허용하는 네트워크 연결을 만들 수 있습니다. HTTP 대상 서비스가 포함된 동일한 네트워크 및 리전에서 네트워크 연결을 만듭니다.

gcloud compute network-attachments create my-network-attachment \
    --region=us-central1 \
    --subnets=my-subnet\
    --connection-preference=ACCEPT_AUTOMATIC

자세한 내용은 네트워크 연결 정보를 참조하세요.

Eventarc 트리거 만들기

새 Pub/Sub 주제를 생성하고 메시지가 Pub/Sub 주제에 게시될 때 VM에 배포된 이벤트 수신자로 이벤트를 라우팅하는 Eventarc 트리거를 만듭니다.

  1. 게이트웨이 주소를 검색합니다.

    GATEWAY_ADDRESS=$(kubectl get gateways.gateway.networking.k8s.io internal-http -o=jsonpath="{.status.addresses[0].value}")
    
  2. 트리거를 만듭니다.

    gcloud eventarc triggers create my-trigger \
        --location=us-central1 \
        --destination-http-endpoint-uri="http://$GATEWAY_ADDRESS:80/" \
        --network-attachment="projects/PROJECT_ID/regions/us-central1/networkAttachments/my-network-attachment" \
        --event-filters="type=google.cloud.pubsub.topic.v1.messagePublished" \
        --service-account=PROJECT_NUMBER-compute@developer.gserviceaccount.com
    

    PROJECT_NUMBER를 Google Cloud 프로젝트 번호로 바꿉니다. Google Cloud 콘솔의 시작 페이지에서 또는 다음 명령어를 실행하여 프로젝트 번호를 찾을 수 있습니다.

    gcloud projects describe PROJECT_ID --format='value(projectNumber)'
    

트리거 구성에 대한 자세한 내용은 이벤트를 VPC 네트워크의 내부 HTTP 엔드포인트로 라우팅을 참조하세요.

Pub/Sub 주제 이벤트를 생성하고 확인합니다.

Pub/Sub 주제에 메시지를 게시하여 이벤트를 생성할 수 있습니다.

  1. Pub/Sub 주제를 환경 변수로 찾아서 설정합니다.

    export MY_TOPIC=$(gcloud eventarc triggers describe my-trigger \
        --location=us-central1 \
        --format='value(transport.pubsub.topic)')
    
  2. Pub/Sub 주제에 메시지를 게시하여 이벤트를 생성합니다.

    gcloud pubsub topics publish $MY_TOPIC --message "Hello World"
    

    Eventarc 트리거는 이벤트를 비공개 GKE 클러스터의 내부 HTTP 엔드포인트로 라우팅합니다.

  3. 애플리케이션 포드 로그를 확인하고 이벤트 전송을 확인합니다.

    POD_NAME=$(kubectl get pod --selector app=hello-app --output=name)
    kubectl logs $POD_NAME
    

    이벤트 본문은 다음과 비슷하게 표시됩니다.

    2024/04/18 20:31:43 Hello from Cloud Run! The container started successfully and is listening for HTTP requests on $PORT
    {"severity":"INFO","eventType":"google.cloud.pubsub.topic.v1.messagePublished","message":"Received event of type google.cloud.pubsub.topic.v1.messagePublished.
    Event data: Hello World","event":{"specversion":"1.0","id":"10935738681111260","source":"//pubsub.googleapis.com/projects/my-project/topics/eventarc-us-central1-my-trigger-224","type":"google.cloud.pubsub.topic.v1.messagePublished","datacontenttype":"application/json","time":"2024-04-18T20:40:03Z","data":
    {"message":{"data":"SGVsbG8gV29ybGQ=","messageId":"10935738681111260","publishTime":"2024-04-18T20:40:03Z"}}}}
    

비공개 GKE 클러스터의 내부 HTTP 엔드포인드에 이벤트 수신자 서비스를 성공적으로 배포하고 Eventarc 트리거를 만들고 Pub/Sub에서 이벤트를 생성했으며, 트리거에서 예상대로 이벤트가 대상 엔드포인트로 라우팅되었음을 확인했습니다.

삭제

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

프로젝트 삭제

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

    gcloud projects delete PROJECT_ID

개별 리소스 삭제

  1. Eventarc 트리거를 삭제합니다.
      gcloud eventarc triggers delete my-trigger --location=us-central1
  2. VM을 종료한 후 VM 인스턴스를 삭제합니다.
      gcloud compute instances delete my-vm --zone=us-central1-a
  3. 네트워크 연결을 삭제합니다.
      gcloud compute network-attachments delete my-network-attachment --region=us-central1
  4. 방화벽 규칙을 삭제합니다.
      gcloud compute firewall-rules delete allow-proxy-connection
  5. 다음과 같이 클러스터를 삭제합니다.
      gcloud container clusters delete private-cluster --region=us-central1
      
  6. 서브넷을 삭제:합니다.
      gcloud compute networks subnets delete proxy-only-subnet --region=us-central1

다음 단계