이 가이드에서는 클라이언트 측 사용자 인증 정보 대신 인증 및 승인 로직을 처리하는 프록시를 사용하여 모바일 또는 클라이언트 측 앱에서 Pub/Sub로 메시지를 게시하는 방법을 보여줍니다.
ID 및 액세스 관리(IAM)를 사용하여 클라이언트에서 Pub/Sub로의 메시지를 인증할 수 있으며, 이러한 장기 실행 사용자 인증 정보는 만료되지 않습니다. 클라이언트 측 앱에서 이러한 사용자 인증 정보는 앱 디컴파일 및 리버스 엔지니어링과 같은 기술을 통해 검색할 수 있습니다.
그 대신 다음 작업을 수행하는 프록시에 인증 및 승인 로직을 오프로드할 수 있습니다.
- 수신 요청을 인증하여 사용자를 확인합니다.
- 적절한 IAM 권한과 함께 Pub/Sub에 요청을 전달합니다.
이 가이드에서는 Google Kubernetes Engine(GKE)에서 Pub/Sub 프록시를 구현하는 방법을 보여줍니다. 이 가이드는 모바일 또는 클라이언트 측 애플리케이션의 설계를 정의하고 구현하는 애플리케이션 개발자 및 시스템 설계자를 대상으로 하며, 기본 Kubernetes 개념을 이해하고 Cloud Endpoints에 익숙하다고 가정합니다.
이 가이드의 요청 흐름
Pub/Sub가 스트리밍 파이프라인에 어떻게 적합한지 이해하려면 클릭 스트림 분석을 고려해 보세요. 이 사용 사례에서 사용자가 모바일 앱과 상호작용하는 방식을 이해하는 것이 좋습니다. 이러한 통계를 얻으려면 사용자 활동을 실시간으로 캡처해야 합니다. 다음 다이어그램은 데이터 흐름을 보여줍니다.
앱에서 캡처한 데이터는 프록시를 통해 Pub/Sub로 푸시됩니다. Pub/Sub는 의미 있는 분석을 수행할 수 있도록 데이터를 집계하는 Dataflow 또는 Dataproc 등의 구독자 다운스트림을 가질 수 있습니다.
다음 다이어그램은 이 가이드에서 따르는 요청 흐름을 자세히 보여줍니다.
다음 섹션에서는 이 다이어그램의 다양한 구성요소가 어떻게 상호작용하는지 설명합니다.
사용자 인증
모바일 앱은 다양한 방법으로 사용자를 인증할 수 있습니다. 인증 흐름은 앱에 따라 다르며, 이 가이드에서는 사용자 인증을 위한 솔루션 중 하나를 보여줍니다. 이 솔루션의 구현은 이 가이드와 함께 제공됩니다.
클라이언트 앱에서 Pub/Sub 프록시로 보내는 요청
앱 백엔드는 클라이언트가 로컬에 저장하는 단기 인증 토큰을 생성합니다(예: Android Keystore 시스템 또는 iOS 키체인 서비스 사용). 이 가이드에서는 OpenID Connect(OIDC) ID 토큰을 사용하여 클라이언트 앱을 인증합니다. Google에서는 OIDC ID 토큰을 발급하고 서명합니다.
클라이언트 측 앱은 OIDC ID 토큰을 사용하여 Pub/Sub 프록시에 요청을 보냅니다. Pub/Sub 프록시는 토큰을 검증하고 적절한 IAM 사용자 인증 정보와 함께 Pub/Sub에 요청을 전달합니다.
메시지 게시
클라이언트 앱이 성공적으로 인증되면 Pub/Sub 프록시는 Pub/Sub에 게시 요청을 보냅니다. Pub/Sub는 IAM을 사용하여 호출자(Pub/Sub 프록시)가 게시 요청을 보낼 수 있는 적절한 권한이 있는지 확인합니다. 이 가이드에서 Pub/Sub 프록시는 Compute Engine 기본 서비스 계정을 사용하여 Pub/Sub로 인증합니다. Compute Engine 기본 서비스 계정에는 편집자 IAM 역할(roles/editor
)이 있어 Pub/Sub 프록시에 대한 게시자 액세스를 제공합니다.
목표
- Pub/Sub 프록시를 실행할 GKE 클러스터를 만듭니다.
- Pub/Sub 주제를 만듭니다.
- Pub/Sub 프록시를 배포합니다.
- Pub/Sub 프록시에 대한 요청을 인증하도록 Endpoints를 구성합니다.
- 메시지가 Pub/Sub에 게시되었는지 확인합니다.
비용
이 문서에서는 비용이 청구될 수 있는 다음과 같은 Google Cloud 구성요소를 사용합니다.
프로젝트 사용량을 기준으로 예상 비용을 산출하려면 가격 계산기를 사용하세요.
이 문서에 설명된 태스크를 완료했으면 만든 리소스를 삭제하여 청구가 계속되는 것을 방지할 수 있습니다. 자세한 내용은 삭제를 참조하세요.
시작하기 전에
-
In the Google Cloud console, go to the project selector page.
-
Select or create a Google Cloud project.
-
Google Cloud 콘솔에서 Cloud Shell을 활성화합니다.
Google Cloud 콘솔 하단에서 Cloud Shell 세션이 시작되고 명령줄 프롬프트가 표시됩니다. Cloud Shell은 Google Cloud CLI가 사전 설치된 셸 환경으로, 현재 프로젝트의 값이 이미 설정되어 있습니다. 세션이 초기화되는 데 몇 초 정도 걸릴 수 있습니다.
- 이 가이드에 필요한 환경 변수를 정의합니다.
export PROJECT=$(gcloud config get-value project) export REGION=us-central1 export ZONE=${REGION}-b export CLUSTER=pubsub-proxy export TOPIC=proxy-test export SERVICE_ACCOUNT=publish-test export ENDPOINTS_SERVICE="pubtest.endpoints.${PROJECT}.cloud.goog" export GENERATE_TOKEN="https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts"
- Cloud Build, Compute Engine, Google Kubernetes Engine, Artifact Analysis, Container Registry, Endpoints, Service Management, Service Control, Pub/Sub용 API를 사용 설정합니다.
gcloud services enable \ cloudbuild.googleapis.com \ compute.googleapis.com \ container.googleapis.com \ containeranalysis.googleapis.com \ containerregistry.googleapis.com \ endpoints.googleapis.com \ servicemanagement.googleapis.com \ servicecontrol.googleapis.com \ pubsub.googleapis.com
Pub/Sub 주제 만들기
Cloud Shell에서 메시지를 게시할 Pub/Sub 주제를 만듭니다.
gcloud pubsub topics create $TOPIC
GKE 클러스터 만들기
Cloud Shell에서 GKE 클러스터를 만듭니다.
gcloud container clusters create $CLUSTER \ --zone $ZONE \ --scopes "https://www.googleapis.com/auth/cloud-platform"
실행 중인 클러스터의 사용자 인증 정보를 가져옵니다.
gcloud container clusters get-credentials $CLUSTER \ --zone $ZONE \ --project $PROJECT
컨테이너 이미지 빌드
Cloud Shell에서 코드 저장소를 클론합니다.
git clone https://github.com/GoogleCloudPlatform/solutions-pubsub-proxy-rest
Cloud Build를 사용하여 소스에서 컨테이너 이미지를 빌드한 다음 Container Registry에 저장합니다.
cd solutions-pubsub-proxy-rest && \ gcloud builds submit --tag gcr.io/$PROJECT/pubsub-proxy:v1
고정 외부 IP 주소 만들기
Cloud Shell에서 나중에 Pub/Sub 프록시 부하 분산기에 할당되는 고정 외부 IP 주소를 만듭니다.
gcloud compute addresses create service-ip --region $REGION
고정 IP 주소를 환경 변수
PROXY_IP
에 저장합니다.PROXY_IP=$(gcloud compute addresses describe service-ip \ --region $REGION --format='value(address)')
Endpoints 배포
Pub/Sub 프록시는 Endpoints를 사용하여 사용자의 요청을 인증합니다. Endpoints는 Extensible Service Proxy(ESP)를 사용하여 인증, 모니터링, 추적, API 수명 주기 관리 등의 API 관리 기능을 제공합니다. 이 가이드에서는 Pub/Sub 프록시에 대한 수신 요청을 인증하는 용도로만 Endpoints를 사용합니다.
이 가이드에서는 Pub/Sub 프록시를 사용하여 ESP를 사이드카로 배포합니다. ESP는 수신 요청을 가로채고 인증한 후 Pub/Sub 프록시로 전달합니다.
Cloud Shell에서
[PROJECT_ID]
자리표시자를openapi.yaml
파일의 Google Cloud 프로젝트 ID로 바꿉니다.sed -i -e "s/\[PROJECT_ID\]/$PROJECT/g" openapi.yaml
OpenAPI 매니페스트 파일에서
[IP_ADDRESS]
자리표시자를PROXY_IP
값으로 바꿉니다.sed -i -e "s/\[IP_ADDRESS\]/$PROXY_IP/g" openapi.yaml
Endpoints에 OpenAPI 서비스 정의를 배포합니다.
gcloud endpoints services deploy openapi.yaml
앞의 명령어는 다음을 만듭니다.
openapi.yaml
파일(pubtest.endpoints.project-id.cloud.goog
)의 호스트 필드에 지정한 이름을 사용하는 관리형 서비스. 여기서project-id
는 Google Cloud 프로젝트의 ID입니다.- 서비스 이름과
openapi.yaml
파일의x-google-endpoints
확장 프로그램에 정의된 Pub/Sub 프록시 부하 분산기의 IP 주소 매핑을 사용하는 DNS A 레코드
이 가이드는 인증에 API 키 대신 OIDC ID 토큰을 사용하므로 배포 중에 표시되는 경고는 무시해도 됩니다.
WARNING: openapi.yaml: Operation 'post' in path '/publish': Operation does not require an API key; callers may invoke the method without specifying an associated API-consuming project. To enable API key all the SecurityRequirement Objects (https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-requirement-object) inside security definition must reference at least one SecurityDefinition of type : 'apiKey'.
서비스가 올바르게 배포되었는지 확인합니다.
gcloud endpoints services describe ${ENDPOINTS_SERVICE}
출력은 다음과 비슷합니다.
[...] producerProjectId: project-id serviceConfig: documentation: summary: Pub/Sub proxy exposed as an Endpoint API [...] name: pubtest.endpoints.project-id.cloud.goog title: PubSub Proxy usage: {} serviceName: pubtest.endpoints.project-id.cloud.goog
출력에 표시되는 항목의 의미는 다음과 같습니다.
project-id
: Google Cloud 프로젝트의 ID입니다.
프록시 배포
Cloud Shell에서 자체 서명 SSL 인증서를 생성하여 프록시에 대한 HTTPS 연결을 허용합니다.
openssl req -x509 -nodes -days 365 \ -newkey rsa:2048 -keyout ./nginx.key \ -out ./nginx.crt \ -subj "/CN=${ENDPOINTS_SERVICE}"
SSL 인증서와 비공개 키를 사용하여 Kubernetes 보안 비밀을 만듭니다.
kubectl create secret generic nginx-ssl \ --from-file=./nginx.crt \ --from-file=./nginx.key
배포 매니페스트 파일의
[PROJECT_ID]
자리표시자를 Google Cloud 프로젝트 ID로 바꿉니다.sed -i -e "s/\[PROJECT_ID\]/$PROJECT/g" kube/deployment.yaml
서비스 매니페스트 파일의
[IP_ADDRESS]
자리표시자를PROXY_IP
값으로 바꿉니다.sed -i -e "s/\[IP_ADDRESS\]/$PROXY_IP/g" kube/service.yaml
프록시를 배포합니다.
kubectl apply -f kube/
배포가 성공했는지 확인합니다.
kubectl rollout status deployment/pubsub-proxy
출력은 다음과 비슷합니다.
[...] deployment "pubsub-proxy" successfully rolled out
두 컨테이너(ESP 및 Pub/Sub 프록시)가 Pod에서 실행 중인지 확인합니다.
kubectl get pods $(kubectl get pod \ -l app=pubsub-proxy \ -o jsonpath="{.items[0].metadata.name}") \ -o jsonpath={.spec.containers[*].name}
출력은 다음과 비슷합니다.
esp pubsub-proxy
EXTERNAL-IP
의 값이<pending>
에서 이전에 만든 고정 외부 IP 주소로 변경되는지 감시합니다.kubectl get svc pubsub-proxy -w
출력은 다음과 비슷합니다.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE pubsub-proxy LoadBalancer 10.7.247.212 <pending> 443:31104/TCP 6m32s pubsub-proxy LoadBalancer 10.7.247.212 <PROXY_IP> 443:31104/TCP 6m5s
감시를 중지하려면
CTRL+C
를 누릅니다.Pub/Sub 프록시가 성공적으로 배포되면
https://${ENDPOINTS_SERVICE}/publish
에 노출됩니다. 새 DNS 구성이 전파되는 데 몇 분 정도 걸릴 수 있습니다.DNS 구성을 확인합니다.
watch nslookup ${ENDPOINTS_SERVICE}
출력은 다음과 비슷합니다.
Server: 169.254.169.254 Address: 169.254.169.254#53 Non-authoritative answer: Name: pubtest.endpoints.project-id.cloud.goog Address: gke-load-balancer-ip
출력에 표시되는 항목의 의미는 다음과 같습니다.
gke-load-balancer-ip
: GKE 부하 분산기(프록시 IP)의 IP 주소입니다.
감시를 중지하려면
CTRL+C
를 누릅니다.
위 단계 중 어느 단계에서든 오류가 발생하는 경우 문제해결 단계를 참조하세요.
인증 토큰 생성
인증 토큰을 생성하기 위한 다음 절차는 예시로 만들어졌습니다. 프로덕션 환경의 경우 사용자가 자신의 인증 토큰을 생성할 수 있는 방법이 필요합니다. 예를 들어 프로그래매틱 방식으로 OIDC ID 토큰을 가져오기 위한 샘플 코드는 IAP(Identity-Aware Proxy) 문서에서 찾을 수 있습니다.
인증 토큰을 생성하려면 다음 단계를 따르세요.
OIDC ID 토큰을 생성할 Google Cloud 서비스 계정을 만듭니다.
gcloud iam service-accounts create \ $SERVICE_ACCOUNT \ --display-name $SERVICE_ACCOUNT
서비스 계정의 이메일 ID를 가져옵니다.
SA_EMAIL=${SERVICE_ACCOUNT}@${PROJECT}.iam.gserviceaccount.com
서비스 계정에 서비스 계정 토큰 생성자 IAM 역할(
roles/iam.serviceAccountTokenCreator
)을 부여합니다.gcloud iam service-accounts add-iam-policy-binding $SA_EMAIL \ --member user:$(gcloud config get-value account) \ --role roles/iam.serviceAccountTokenCreator
IAM 사용자 인증 정보 API를 사용하여 OIDC ID 토큰을 생성합니다.
TOKEN=$(curl -s ${GENERATE_TOKEN}/${SA_EMAIL}:generateIdToken \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -d '{"audience": "'${ENDPOINTS_SERVICE}'", "includeEmail": "true"}' | jq -r ".token")
Endpoints 서비스 이름은
audience
필드에 지정됩니다.audience
클레임은 토큰이 대상인 수신자를 식별합니다.토큰이 성공적으로 생성되었는지 확인합니다.
echo $TOKEN
JSON 웹 토큰(JWT)은 다음과 비슷합니다.
eyJhbGciOiJSUzI1NiIsImtpZCI6IjY4NjQyODlm[...].eyJhdWQiOiJwdWJ0ZXN0LmVuZHBvaW50cy52aXR hbC1vY3RhZ29uLTEwOTYxMi5jbG91ZC5nb[...].SjBI4TZjZAlYo6lFKkrvfAcVUp_AJzFKoSsjNbmD_n[...]
프록시를 사용하여 Pub/Sub 호출
Cloud Shell에서 테스트 메시지를 게시합니다.
curl -i -k -X POST https://${ENDPOINTS_SERVICE}/publish \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"topic": "'$TOPIC'", "messages": [ {"attributes": {"key1": "value1", "key2" : "value2"}, "data": "test data"}]}'
출력은 다음과 비슷합니다.
HTTP/2 200 server: nginx date: Sun, 02 Jun 2019 03:53:46 GMT ...
메시지가 Pub/Sub 주제에 성공적으로 게시되었는지 확인합니다.
kubectl logs -f --tail=5 deployment/pubsub-proxy -c pubsub-proxy
Pub/Sub 프록시 배포 로그에
Successfully published
메시지가 표시됩니다.2019-06-02 03:49:39.723:INFO:oejs.Server:main: Started @2554ms Jun 02, 2019 3:53:44 AM com.google.pubsub.proxy.publish.PublishMessage getPublisher INFO: Creating new publisher for: proxy-test Jun 02, 2019 3:53:47 AM com.google.pubsub.proxy.publish.PublishMessage$1 onSuccess INFO: Successfully published: 569006136173844
문제해결
Cloud Shell에서 Pub/Sub 프록시 Pod의 두 컨테이너 상태를 확인합니다.
kubectl describe pods $(kubectl get pod -l app=pubsub-proxy \ -o jsonpath="{.items[0].metadata.name}")
로그 출력에서 컨테이너의 상태는
Running
입니다.[...] Containers: esp: [...] State: Running Started: Fri, 21 Jun 2019 16:41:30 +0530 Ready: True Restart Count: 0 [...] pubsub-proxy: State: Running Started: Fri, 21 Jun 2019 16:41:42 +0530 Ready: True Restart Count: 0 [...]
(선택사항) 컨테이너 로그를 확인하여 다른 오류가 있는지 확인합니다. 예를 들어 Pub/Sub 프록시 로그를 확인하려면 다음 명령어를 실행합니다.
kubectl logs -f --tail=10 deployment/pubsub-proxy -c pubsub-proxy
문제해결과 관련하여 도움이 필요한 경우 다음 문서를 참조하세요.
삭제
이 가이드에서 사용한 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 이 가이드에서 만든 Google Cloud 프로젝트를 삭제하거나 이 가이드와 연결된 리소스를 삭제하면 됩니다.
Google Cloud 프로젝트 삭제
비용이 청구되지 않도록 하는 가장 쉬운 방법은 가이드에서 만든 프로젝트를 삭제하는 것입니다.
- Google Cloud 콘솔에서 리소스 관리 페이지로 이동합니다.
- 프로젝트 목록에서 삭제할 프로젝트를 선택하고 삭제를 클릭합니다.
- 대화상자에서 프로젝트 ID를 입력한 후 종료를 클릭하여 프로젝트를 삭제합니다.
리소스 삭제
이 튜토리얼에서 사용된 Google Cloud 프로젝트를 유지하려면 개별 리소스를 삭제합니다.
Cloud Shell에서 GKE 클러스터를 삭제합니다.
gcloud container clusters delete $CLUSTER --zone $ZONE --async
다운로드한 코드, 아티팩트, 기타 종속 항목을 삭제합니다.
cd .. && rm -rf solutions-pubsub-proxy-rest
Container Registry에 있는 이미지를 삭제합니다.
gcloud container images list-tags \ gcr.io/$PROJECT/pubsub-proxy \ --format 'value(digest)' | \ xargs -I {} gcloud container images delete \ --force-delete-tags --quiet \ gcr.io/${PROJECT}/pubsub-proxy@sha256:{}
Pub/Sub 주제를 삭제합니다.
gcloud pubsub topics delete $TOPIC
서비스 계정을 삭제합니다.
gcloud iam service-accounts delete $SA_EMAIL
Endpoints를 삭제합니다.
gcloud endpoints services delete ${ENDPOINTS_SERVICE}
고정 IP 주소를 삭제합니다.
gcloud compute addresses delete service-ip --region $REGION
다음 단계
- Endpoints로 인증에 대해 알아보기
- 장기 실행 작업을 위한 Pub/Sub 사용 아키텍처에 대해 알아보기
- Google Cloud에 대한 참조 아키텍처, 다이어그램, 권장사항 살펴보기 Cloud 아키텍처 센터 살펴보기