서비스 계정으로 Cloud Platform 인증

이 가이드에서는 Google Cloud 서비스 계정을 만들고 Cloud Platform 서비스 인증을 위한 역할을 할당하고, GKE에서 실행되는 애플리케이션에서 서비스 계정 사용자 인증 정보를 사용하는 방법을 설명합니다.

이 예시에서는 Cloud Pub/Sub가 사용되지만 모든 Cloud Platform 서비스에 같은 안내를 사용할 수 있습니다. 이 가이드의 애플리케이션 예시는 서비스 계정을 사용하여 Cloud Pub/Sub에 인증하고 Python 기반 애플리케이션에서 Pub/Sub 주제에 게시된 메시지를 구독합니다.

목표

이 가이드에는 다음 단계가 포함됩니다.

  • 서비스 계정 생성 방법
  • 서비스 계정을 Cloud Pub/Sub에서 사용하기 위해 필요한 역할 할당 방법
  • 계정 키를 Kubernetes 보안 비밀로 저장하는 방법
  • 서비스 계정을 사용하여 애플리케이션을 구성 및 배포하는 방법

이 가이드에서 사용된 샘플 애플리케이션은 Pub/Sub 주제를 구독하고 게시된 메시지를 표준 출력으로 인쇄합니다. 올바른 권한으로 애플리케이션을 구성하고, gcloud를 사용하여 메시지를 게시하고, 컨테이너의 출력 스트림을 조사하여 메시지가 올바르게 수신되었는지 확인해야 합니다.

서비스 계정으로 인증

GKE 내에서 서비스 계정을 사용하여 Google Cloud 서비스에 인증하는 방법에는 세 가지가 있습니다.

1. 워크로드 아이덴티티 사용

워크로드 아이덴티티는 GKE에서 Google Cloud 서비스에 인증하는 데 권장되는 방식입니다. 워크로드 아이덴티티를 사용하면 Kubernetes 리소스를 사용하여 Google Cloud 서비스 계정을 구성할 수 있습니다. 사용 사례에 맞는 경우 가장 먼저 이 옵션을 선택해야 합니다. 이 예시는 워크로드 아이덴티티가 적합하지 않은 사용 사례를 다룹니다.

2. 기본 Compute Engine 서비스 계정 사용

GKE 클러스터의 각 노드는 Compute Engine 인스턴스입니다. 따라서 기본적으로 GKE 클러스터에서 실행되는 애플리케이션은 'Compute Engine 기본 서비스 계정'을 사용하여 인증을 시도하고 연결된 범위를 상속합니다.

이 기본 서비스 계정에는 필요한 Google Cloud 서비스 사용 권한이 있을 수도 있고 없을 수도 있습니다. 기본 서비스 계정에 대한 범위를 확장할 수 있지만, 이는 보안 위험이 발생할 수 있으며 권장되지 않습니다.

3. 보안 비밀을 사용하여 서비스 계정 사용자 인증 정보 관리

마지막 옵션은 애플리케이션의 서비스 계정을 만들고 인증 키를 Kubernetes 보안 비밀로 삽입하는 것입니다. 이 가이드에서는 이 방식을 집중적으로 다룹니다.

서비스 계정을 사용하는 이유

애플리케이션별로 서비스 계정을 개별적으로 사용할 때의 이점은 다음과 같습니다.

  • 애플리케이션이 수행하는 API 요청을 더 효과적으로 식별하고 감사할 수 있습니다.

  • 서비스 계정을 공유하고 모든 애플리케이션의 API 액세스를 한 번에 취소할 필요 없이 특정 애플리케이션의 키를 취소할 수 있습니다.

  • 서비스 계정의 사용자 인증 정보가 손상되는 보안 이슈가 발생할 경우 노출 범위를 줄일 수 있습니다.

시작하기 전에

다음 단계에 따라 Kubernetes Engine API를 사용 설정합니다.
  1. Google Cloud Console에서 Kubernetes Engine 페이지로 이동합니다.
  2. 프로젝트를 만들거나 선택합니다.
  3. API 및 관련 서비스가 사용 설정될 때까지 기다립니다. 몇 분 정도 걸릴 수 있습니다.
  4. Google Cloud 프로젝트에 결제가 사용 설정되어 있는지 확인합니다. 프로젝트에 결제가 사용 설정되어 있는지 확인하는 방법을 알아보세요.

이 가이드에 사용된 다음 명령줄 도구를 설치합니다.

  • gcloud는 Kubernetes Engine 클러스터를 만들고 삭제하는 데 사용됩니다. gcloudGoogle Cloud SDK에 포함되어 있습니다.
  • kubectl은 Kubernetes Engine에서 사용되는 클러스터 조정 시스템인 Kubernetes를 관리하는 데 사용됩니다. gcloud를 사용하여 kubectl을 설치할 수 있습니다.
    gcloud components install kubectl

gcloud 명령줄 도구의 기본값 설정

gcloud 명령줄 도구에 프로젝트 IDCompute Engine 영역 옵션을 입력하는 시간을 절약하려면 기본값을 설정하면 됩니다.
gcloud config set project project-id
gcloud config set compute/zone compute-zone

API 사용 설정

이 가이드에서는 프로젝트에서 Pub/Sub API 및 Resource Manager API를 사용 설정해야 합니다.

gcloud services enable cloudresourcemanager.googleapis.com pubsub.googleapis.com

컨테이너 클러스터 만들기

pubsub-test라는 컨테이너 클러스터를 만들어 Pub/Sub 구독자 애플리케이션을 배포합니다.

gcloud container clusters create pubsub-test

1단계: Pub/Sub 주제 만들기

개발자가 배포하는 Pub/Sub 구독자 애플리케이션은 echo라는 Pub/Sub 주제에서 echo-read라는 구독을 사용합니다. 애플리케이션을 배포하기 전에 이러한 리소스를 만듭니다.

먼저 Pub/Sub 주제를 만듭니다.

gcloud

gcloud pubsub topics create echo

구성 커넥터

참고: 이 단계에는 구성 커넥터가 필요합니다. 설치 안내를 따라 클러스터에 구성 커넥터를 설치합니다.

apiVersion: pubsub.cnrm.cloud.google.com/v1beta1
kind: PubSubTopic
metadata:
  name: echo
이 매니페스트를 배포하려면 머신에 topic.yaml로 다운로드하고 다음을 실행합니다.
kubectl apply -f topic.yaml

그런 다음 구독을 만듭니다.

gcloud

gcloud pubsub subscriptions create echo-read --topic=echo

구성 커넥터

apiVersion: pubsub.cnrm.cloud.google.com/v1beta1
kind: PubSubSubscription
metadata:
  name: echo-read
spec:
  topicRef:
    name: echo
이 매니페스트를 배포하려면 머신에 subscription.yaml로 다운로드하고 다음을 실행합니다.
kubectl apply -f subscription.yaml

2단계: Pub/Sub 구독자 애플리케이션 배포

다음으로 Pub/Sub 주제에 게시된 메시지를 검색하기 위해 애플리케이션 컨테이너를 배포합니다. 이 애플리케이션은 Google Cloud Pub/Sub 클라이언트 라이브러리를 사용하여 Python으로 작성되었으며, GitHub에서 소스 코드를 찾을 수 있습니다.

다음 매니페스트 파일은 이 애플리케이션의 Docker 이미지의 단일 인스턴스를 실행하는 배포를 설명합니다.

# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pubsub
spec:
  selector:
    matchLabels:
      app: pubsub
  template:
    metadata:
      labels:
        app: pubsub
    spec:
      containers:
      - name: subscriber
        image: gcr.io/google-samples/pubsub-sample:v1

이 매니페스트를 배포하려면 pubsub.yaml로 머신에 다운로드하고 다음을 실행합니다.

kubectl apply -f pubsub.yaml

애플리케이션이 배포되었으면 다음을 실행하여 Pod를 쿼리합니다.

kubectl get pods -l app=pubsub
결과:
NAME                      READY     STATUS             RESTARTS   AGE
pubsub-2009462906-1l6bh   0/1       CrashLoopBackOff   1          30s

컨테이너가 시작되지 않고 CrashLoopBackOff상태로 전환된 것을 볼 수 있습니다. 다음을 실행하여 Pod에서 로그를 조사합니다.

kubectl logs -l app=pubsub

출력:

...
google.gax.errors.RetryError: RetryError(Exception occurred in retry method that
was not classified as transient, caused by <_Rendezvous (StatusCode.PERMISSION_DENIED, scopes.) of RPC that terminated with Request had insufficient authentication>)

스택 추적 및 오류 메시지에는 애플리케이션에 Cloud Pub/Sub 서비스 쿼리 권한이 없는 것으로 표시됩니다.

3단계: 서비스 계정 사용자 인증 정보 만들기

GKE에서 실행되는 애플리케이션에 Google Cloud Platform 서비스에 대한 액세스 권한을 부여하려면 서비스 계정을 사용해야 합니다. 서비스 계정을 사용하면 애플리케이션과 연결된 IAM 권한 집합을 정의할 수 있습니다.

Console

서비스 계정을 만들려면 Cloud Console에서 서비스 계정으로 이동하고 서비스 계정 만들기를 클릭합니다.

  1. 서비스 계정 이름을 지정합니다(예: pubsub-app).
  2. 역할 드롭다운에서 'Pub/Sub → 구독자'를 선택합니다.
  3. 키 만들기를 클릭하고 키 유형을 JSON으로 선택합니다.
  4. 만들기를 클릭합니다.

서비스 계정이 생성되면 서비스 계정의 사용자 인증 정보가 포함된 JSON 키 파일이 컴퓨터에 다운로드됩니다. 이 키 파일은 Cloud Pub/Sub API를 인증하도록 애플리케이션을 구성하는 데 사용됩니다.

구성 커넥터

먼저 다음 리소스를 service-account.yaml로 다운로드합니다.

apiVersion: iam.cnrm.cloud.google.com/v1beta1
kind: IAMServiceAccount
metadata:
  name: pubsub-app
spec:
  displayName: Service account for PubSub example

그런 후 다음을 실행합니다.

kubectl apply -f service-account.yaml

다음으로 서비스 계정에 'Pub/Sub Subscriber' 역할을 적용합니다. 다음 리소스를 service-account-policy.yaml로 다운로드합니다. [PROJECT_ID]를 프로젝트 ID로 바꿉니다.

apiVersion: iam.cnrm.cloud.google.com/v1beta1
kind: IAMPolicyMember
metadata:
  name: policy-member-binding
spec:
  member: serviceAccount:pubsub-app@[PROJECT_ID].iam.gserviceaccount.com
  role: roles/pubsub.subscriber
  resourceRef:
    apiVersion: resourcemanager.cnrm.cloud.google.com/v1beta1
    kind: Project
    external: projects/[PROJECT_ID]

그런 후 다음을 실행합니다.

kubectl apply -f service-account-policy.yaml

4단계: 사용자 인증 정보를 보안 비밀로 가져오기

이제 서비스 계정 키를 보유하고 있으므로 이를 컨테이너에 로드할 방법이 필요합니다. 우선 Dockerfile에 단계를 추가해야 한다고 생각할 수 있겠지만, 서비스 계정 키는 컨테이너 이미지에 저장할 수 없는 보안에 민감한 파일입니다.

대신 Kubernetes는 런타임 시 Pod 내에서 비공개 파일을 안전하게 마운트할 수 있도록 보안 비밀 리소스 유형을 제공합니다.

kubectl

JSON 키 파일을 이름이 pubsub-key라는 보안 비밀로 저장하려면 다운로드된 서비스 계정 사용자 인증 정보 파일 경로를 사용하여 다음 명령어를 실행합니다.

kubectl create secret generic pubsub-key --from-file=key.json=PATH-TO-KEY-FILE.json

이 명령어는 Cloud Console에서 다운로드한 비공개 키 콘텐츠가 포함된 key.json 파일이 있는 pubsub-key라는 보안 비밀을 만듭니다. 보안 비밀을 만든 후에는 컴퓨터에서 키 파일을 삭제해야 합니다.

구성 커넥터

다음 리소스를 service-account-key.yaml로 다운로드합니다.

apiVersion: iam.cnrm.cloud.google.com/v1beta1
kind: IAMServiceAccountKey
metadata:
  name: pubsub-key
spec:
  publicKeyType: TYPE_X509_PEM_FILE
  keyAlgorithm: KEY_ALG_RSA_2048
  privateKeyType: TYPE_GOOGLE_CREDENTIALS_FILE
  serviceAccountRef:
    name: pubsub-app

그런 후 다음을 실행합니다.

kubectl apply -f service-account-key.yaml

5단계: 보안 비밀로 애플리케이션 구성

애플리케이션에서 pubsub-key 보안 비밀을 사용하려면 배포 사양을 다음과 같이 수정해야 합니다.

  1. 보안 비밀을 사용하여 볼륨을 정의합니다.
  2. 애플리케이션 컨테이너에 보안 비밀 볼륨을 마운트합니다.
  3. 보안 비밀 볼륨 마운트에 있는 키 파일을 가리키도록 GOOGLE_APPLICATION_CREDENTIALS 환경 변수를 설정합니다.

업데이트된 매니페스트 파일은 다음과 같습니다.

# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pubsub
spec:
  selector:
    matchLabels:
      app: pubsub
  template:
    metadata:
      labels:
        app: pubsub
    spec:
      volumes:
      - name: google-cloud-key
        secret:
          secretName: pubsub-key
      containers:
      - name: subscriber
        image: gcr.io/google-samples/pubsub-sample:v1
        volumeMounts:
        - name: google-cloud-key
          mountPath: /var/secrets/google
        env:
        - name: GOOGLE_APPLICATION_CREDENTIALS
          value: /var/secrets/google/key.json

이 매니페스트 파일은 애플리케이션에 사용자 인증 정보를 제공하도록 다음을 정의합니다.

  • pubsub-key라는 보안 비밀을 사용하는 google-cloud-key라는 볼륨

  • 컨테이너 내부의 /var/secrets/google 디렉터리에서 google-cloud-key를 사용할 수 있게 해 주는 볼륨 마운트

  • /var/secrets/google/key.json으로 설정된 GOOGLE_APPLICATION_CREDENTIALS 환경 변수. 보안 비밀이 컨테이너에 볼륨으로 마운트될 때 이 환경 변수에 사용자 인증 정보가 포함됩니다.

GOOGLE_APPLICATION_CREDENTIALS 환경 변수는 Google Cloud 클라이언트 라이브러리(이 경우에는 Python용 Cloud Pub/Sub 클라이언트)에서 자동으로 인식됩니다.

이 매니페스트를 배포하려면 pubsub-with-secret.yaml로 머신에 다운로드하고 다음을 실행합니다.

kubectl apply -f pubsub-with-secret.yaml

올바르게 배포되었으면 Pod 상태가 Running으로 표시됩니다.

kubectl get pods -l app=pubsub
결과:
NAME                     READY     STATUS    RESTARTS   AGE
pubsub-652482369-2d6h2   1/1       Running   0          29m

6단계: Pub/Sub 메시지 수신 테스트

이제 애플리케이션이 구성되었으므로, echo라는 Pub/Sub 주제에 메시지를 게시합니다.

gcloud pubsub topics publish echo --message="Hello, world!"

몇 초 후 애플리케이션에서 메시지가 선택되고 출력 스트림으로 출력됩니다. 배포된 포드의 로그를 조사하려면 다음을 실행합니다.

kubectl logs -l app=pubsub
결과:
Pulling messages from Pub/Sub subscription...
[2017-06-19 12:31:42.501123] ID=130941112144812 Data=Hello, world!

서비스 계정 사용자 인증 정보를 사용하여 Pub/Sub API에 인증을 수행하도록 GKE에서 애플리케이션을 성공적으로 구성했습니다.

삭제

이 가이드에서 사용한 리소스 비용이 Google Cloud Platform 계정에 청구되지 않도록 하는 방법은 다음과 같습니다.

  1. Pub/Sub 구독 및 항목을 삭제합니다.

    gcloud pubsub subscriptions delete echo-read
    gcloud pubsub topics delete echo
  2. 컨테이너 클러스터를 삭제합니다.

    gcloud container clusters delete pubsub-test

다음 단계