Cloud Run 서비스 내 gcloud 명령줄 튜토리얼


이 튜토리얼에서는 Cloud Run 서비스 내에서 gcloudgsutil 명령줄 도구를 사용하여 Cloud Run 서비스의 인벤토리를 만듭니다. 이 튜토리얼에서 배운 내용을 기존 클라우드 운영 스크립트에 적용하거나 보다 강력한 서비스를 만들기 위해 클라이언트 라이브러리를 사용하기 전의 개념 증명을 만들 수 있습니다.

셸 빠른 시작과 같이 웹 서비스 내에서 셸 스크립트와 같은 gcloudgsutil 도구를 사용합니다. Cloud Run에서는 두 도구 모두 Cloud Run 서비스 ID로 자동 인증되어 Google Cloud 서비스와 함께 사용할 수 있습니다. 서비스 ID에 부여된 모든 권한을 gcloud CLI에서 사용할 수 있습니다.

gcloud CLI는 Google Cloud에서 정보 수집 및 리소스 관리 등 너무나 다양하게 사용될 수 있기 때문에 웹 서비스 내에서 이를 사용할 때의 도전과제는 이러한 기능을 호출자가 잘못 사용할 위험을 최소화하는 것입니다. 보안 제어가 없으면 우연한 또는 의도적인 악의적인 활동을 허용하여 동일한 프로젝트에서 실행되는 다른 서비스 또는 리소스에 위험을 일으킬 수 있습니다. 이러한 위험의 예시에는 다음이 포함됩니다.

  • 비공개 가상 머신의 IP 주소 검색 허용
  • 동일 프로젝트의 데이터베이스에서 비공개 데이터에 대한 액세스 사용 설정
  • 실행 중인 다른 서비스의 삭제 사용 설정

이 튜토리얼에서는 사용자 입력을 열어두는 대신 코드로 실행되는 gcloud 명령어를 지정하는 등의 여러 가지 단계로 위험을 최소화하기 위한 제어 방법을 보여줍니다.

Cloud Run 서비스 내에서 명령줄 도구를 사용한 스크립트 작성은 명령줄을 로컬로 사용하는 것과 비슷합니다. 주요 차이는 기본 스크립트 논리에 추가해야 하는 추가적인 제한 사항입니다.

목표

  • Dockerfile커스텀 컨테이너를 작성하고 빌드합니다.
  • Cloud Run 서비스를 작성, 빌드, 배포합니다.
  • 웹 서비스에서 gcloudgsutil 도구를 안전하게 사용합니다.
  • Cloud Run 서비스 보고서를 생성하고 Cloud Storage에 저장합니다.

비용

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

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

시작하기 전에

  1. Google Cloud 계정에 로그인합니다. Google Cloud를 처음 사용하는 경우 계정을 만들고 Google 제품의 실제 성능을 평가해 보세요. 신규 고객에게는 워크로드를 실행, 테스트, 배포하는 데 사용할 수 있는 $300의 무료 크레딧이 제공됩니다.
  2. Google Cloud Console의 프로젝트 선택기 페이지에서 Google Cloud 프로젝트를 선택하거나 만듭니다.

    프로젝트 선택기로 이동

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

  4. Google Cloud Console의 프로젝트 선택기 페이지에서 Google Cloud 프로젝트를 선택하거나 만듭니다.

    프로젝트 선택기로 이동

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

  6. API Artifact Registry, Cloud Build, Cloud Run, and Cloud Storage 사용 설정

    API 사용 설정

  7. gcloud CLI를 설치하고 초기화합니다.

필요한 역할

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

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

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

gcloud 기본값 설정

Cloud Run 서비스의 기본값으로 gcloud를 구성하려면 다음 안내를 따르세요.

  1. 기본 프로젝트를 설정합니다.

    gcloud config set project PROJECT_ID

    PROJECT_ID를 이 튜토리얼용으로 만든 프로젝트 이름으로 바꿉니다.

  2. 선택한 리전에 맞게 gcloud를 구성합니다.

    gcloud config set run/region REGION

    REGION을 지원되는 Cloud Run 리전 중 원하는 리전으로 바꿉니다.

Cloud Run 위치

Cloud Run은 리전을 기반으로 합니다. 즉, Cloud Run 서비스를 실행하는 인프라가 특정 리전에 위치해 있으며 해당 리전 내의 모든 영역에서 중복으로 사용할 수 있도록 Google이 관리합니다.

Cloud Run 서비스를 실행하는 리전을 선택하는 데 있어 중요한 기준은 지연 시간, 가용성 또는 내구성 요구사항입니다. 일반적으로 사용자와 가장 가까운 리전을 선택할 수 있지만 Cloud Run 서비스에서 사용하는 다른 Google Cloud 제품 위치도 고려해야 합니다. 여러 위치에서 Google Cloud 제품을 함께 사용하면 서비스 지연 시간과 비용에 영향을 미칠 수 있습니다.

Cloud Run은 다음 리전에서 사용할 수 있습니다.

등급 1 가격 적용

  • asia-east1(타이완)
  • asia-northeast1(도쿄)
  • asia-northeast2(오사카)
  • europe-north1(핀란드) 잎 아이콘 낮은 CO2
  • europe-southwest1(마드리드)
  • europe-west1(벨기에) 잎 아이콘 낮은 CO2
  • europe-west4(네덜란드)
  • europe-west8(밀라노)
  • europe-west9(파리) 잎 아이콘 낮은 CO2
  • me-west1(텔아비브)
  • us-central1(아이오와) 잎 아이콘 낮은 CO2
  • us-east1(사우스캐롤라이나)
  • us-east4(북 버지니아)
  • us-east5(콜럼버스)
  • us-south1(댈러스)
  • us-west1(오리건) 잎 아이콘 낮은 CO2

등급 2 가격 적용

  • africa-south1(요하네스버그)
  • asia-east2(홍콩)
  • asia-northeast3(대한민국 서울)
  • asia-southeast1(싱가포르)
  • asia-southeast2 (자카르타)
  • asia-south1(인도 뭄바이)
  • asia-south2(인도 델리)
  • australia-southeast1(시드니)
  • australia-southeast2(멜버른)
  • europe-central2(폴란드 바르샤바)
  • europe-west10(베를린)
  • europe-west12(토리노)
  • europe-west2(영국 런던) 잎 아이콘 낮은 CO2
  • europe-west3(독일 프랑크푸르트) 잎 아이콘 낮은 CO2
  • europe-west6(스위스 취리히) 잎 아이콘 낮은 CO2
  • me-central1(도하)
  • me-central2(담맘)
  • northamerica-northeast1(몬트리올) 잎 아이콘 낮은 CO2
  • northamerica-northeast2(토론토) 잎 아이콘 낮은 CO2
  • southamerica-east1(브라질 상파울루) 잎 아이콘 낮은 CO2
  • southamerica-west1(칠레 산티아고) 잎 아이콘 낮은 CO2
  • us-west2(로스앤젤레스)
  • us-west3(솔트레이크시티)
  • us-west4(라스베이거스)

Cloud Run 서비스를 이미 만들었다면 Google Cloud 콘솔의 Cloud Run 대시보드에서 리전을 확인할 수 있습니다.

코드 샘플 검색

사용할 코드 샘플을 검색하려면 다음 안내를 따르세요.

  1. 샘플 앱 저장소를 로컬 머신에 클론합니다.

    git clone https://github.com/GoogleCloudPlatform/cloud-run-samples.git

    또는 zip 파일로 샘플을 다운로드하고 압축을 풀 수 있습니다.

  2. Cloud Run 샘플 코드가 포함된 디렉터리로 변경합니다.

    cd cloud-run-samples/gcloud-report/

코드 검토

이 섹션에는 검색한 코드 샘플에 대한 정보가 포함되어 있습니다.

보고서 생성 및 Cloud Storage에 업로드

이 셸 스크립트는 현재 프로젝트 및 리전에서 Cloud Run 서비스 보고서를 생성하고 결과를 Cloud Storage에 업로드합니다. 결과에는 이름에 제공된 문자열 search 인수가 포함된 서비스가 나열됩니다.

이 스크립트는 gcloud run services list 명령어, gcloud 고급 형식 옵션, gsutil 스트리밍 전송 복사 모드를 사용합니다.

set -eo pipefail

# Check for required environment variables.
requireEnv() {
  test "${!1}" || (echo "gcloud-report: '$1' not found" >&2 && exit 1)
}
requireEnv GCLOUD_REPORT_BUCKET

# Prepare formatting: Default search term to include all services.
search=${1:-'.'}
limits='spec.template.spec.containers.resources.limits.flatten("", "", " ")'
format='table[box, title="Cloud Run Services"](name,status.url,metadata.annotations.[serving.knative.dev/creator],'${limits}')'

# Create a specific object name that will not be overridden in the future.
obj="gs://${GCLOUD_REPORT_BUCKET}/report-${search}-$(date +%s).txt"

# Write a report containing the service name, service URL, service account or user that
# deployed it, and any explicitly configured service "limits" such as CPU or Memory.
gcloud run services list \
  --format "${format}" \
  --filter "metadata.name~${search}" | gsutil -q cp -J - "${obj}"

# /dev/stderr is sent to Cloud Logging.
echo "gcloud-report: wrote to ${obj}" >&2
echo "Wrote report to ${obj}"

많은 비용이 드는 앱 제거 없이 스크립트를 반복적으로 호출하여 보고서를 업데이트하기 때문에 이 스크립트는 서비스로 안전하게 실행할 수 있습니다. gcloud CLI를 사용하는 다른 스크립트는 새 클라우드 리소스를 만들거나 비용이 많이 드는 태스크를 수행하는 등 반복적으로 호출할 경우 많은 요금이 청구될 수 있습니다. 반복 호출 시 동일한 결과를 산출하는 멱등 함수 스크립트가 서비스로 실행하기에 더 안전합니다.

HTTP 요청에서 스크립트 호출

이 Go 코드는 셸 스크립트를 실행하는 웹 서비스를 설정하여 보고서를 생성합니다. 검색어로 사용자 입력이 사용되기 때문에 악성 명령어가 입력되지 않도록 코드에서 문자, 숫자 또는 하이픈만 포함하는지 확인합니다. 이 문자 집합은 명령어 삽입 공격을 막기에 충분할 정도로 범위가 좁습니다.

웹 서비스가 셸 스크립트에 검색 매개변수를 인수로 전달합니다.


// Service gcloud-report is a Cloud Run shell-script-as-a-service.
package main

import (
	"log"
	"net/http"
	"os"
	"os/exec"
	"regexp"
)

func main() {
	http.HandleFunc("/", scriptHandler)

	// Determine port for HTTP service.
	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
		log.Printf("defaulting to port %s", port)
	}

	// Start HTTP server.
	log.Printf("listening on port %s", port)
	if err := http.ListenAndServe(":"+port, nil); err != nil {
		log.Fatal(err)
	}
}

func scriptHandler(w http.ResponseWriter, r *http.Request) {
	search := r.URL.Query().Get("search")
	re := regexp.MustCompile(`^[a-z]+[a-z0-9\-]*$`)
	if !re.MatchString(search) {
		log.Printf("invalid search criteria %q, using default", search)
		search = "."
	}

	cmd := exec.CommandContext(r.Context(), "/bin/bash", "script.sh", search)
	cmd.Stderr = os.Stderr
	out, err := cmd.Output()
	if err != nil {
		log.Printf("Command.Output: %v", err)
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}
	w.Write(out)
}

go.mod 파일이 Go 모듈에서 애플리케이션 종속 항목을 선언합니다.

module github.com/GoogleCloudPlatform/cloud-run-samples/gcloud-report

go 1.19

컨테이너 환경 정의

Dockerfile은 해당 서비스에 맞게 환경을 설정하는 방법을 정의합니다. 이는 최종 컨테이너 이미지가 gcloud Google Cloud CLI 이미지를 기반으로 한다는 점을 제외하고 helloworld-shell 빠른 시작의 Dockerfile과 비슷합니다. 이렇게 하면 Google Cloud CLI의 커스텀 설치 및 구성 단계 없이도 서비스에서 gcloudgsutil을 사용할 수 있습니다.


# Use the official golang image to create a binary.
# This is based on Debian and sets the GOPATH to /go.
# https://hub.docker.com/_/golang
FROM golang:1.20-buster as builder

# Create and change to the app directory.
WORKDIR /app

# Retrieve application dependencies.
# This allows the container build to reuse cached dependencies.
# Expecting to copy go.mod and if present go.sum.
COPY go.* ./
RUN go mod download

# Copy local code to the container image.
COPY invoke.go ./

# Build the binary.
RUN go build -mod=readonly -v -o server

# Use a gcloud image based on debian:buster-slim for a lean production container.
# https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
FROM gcr.io/google.com/cloudsdktool/cloud-sdk:slim

WORKDIR /app

# Copy the binary to the production image from the builder stage.
COPY --from=builder /app/server /app/server
COPY *.sh /app/
RUN chmod +x /app/*.sh

# Run the web service on container startup.
CMD ["/app/server"]

Artifact Registry 표준 저장소 만들기

컨테이너 이미지를 저장할 Artifact Registry 표준 저장소를 만듭니다.

gcloud artifacts repositories create REPOSITORY \
    --repository-format=docker \
    --location=REGION

다음과 같이 바꿉니다.

  • REPOSITORY를 저장소의 고유한 이름으로 바꿉니다.
  • REGION을 Artifact Registry의 Google Cloud 리전으로 바꿉니다.

Cloud Storage 버킷 설정

보고서를 업로드할 Cloud Storage 버킷을 만듭니다.

gsutil mb gs://REPORT_ARCHIVE_BUCKET

REPORT_ARCHIVE_BUCKET을 전역적으로 고유한 버킷 이름으로 바꿉니다.

서비스 ID 설정

서비스가 보유한 다른 인프라에 대한 권한을 제한하기 위해 서비스 ID를 만들고 작업에 필요한 특정 IAM 권한을 맞춤설정합니다.

이 경우 필요한 권한은 Cloud Run 서비스를 읽는 권한과 Cloud Storage 버킷에서 읽고 쓸 수 있는 권한입니다.

  1. 서비스 계정을 만듭니다.

    gcloud iam service-accounts create gcloud-report-identity

  2. 서비스 계정에 Cloud Run 서비스를 읽을 수 있는 권한을 부여합니다.

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member=serviceAccount:gcloud-report-identity@PROJECT_ID.iam.gserviceaccount.com \
      --role roles/run.viewer
  3. 서비스 계정에 Cloud Storage 버킷에서 읽고 쓸 수 있는 권한을 부여합니다.

    gsutil iam ch \
      serviceAccount:gcloud-report-identity@PROJECT_ID.iam.gserviceaccount.com:objectViewer,objectCreator \
      gs://REPORT_ARCHIVE_BUCKET

이 맞춤설정된 서비스 ID의 제한된 액세스 권한으로 인해 서비스가 다른 Google Cloud 리소스에 액세스하지 못하게 됩니다.

서비스 제공

코드 제공은 다음 3가지 단계로 구성됩니다.

  • Cloud Build로 컨테이너 이미지 만들기
  • 컨테이너 이미지를 Artifact Registry에 업로드
  • 컨테이너 이미지를 Cloud Run에 배포

코드를 제공하려면 다음 안내를 따르세요.

  1. 컨테이너를 빌드하고 Artifact Registry에 게시합니다.

    gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/gcloud-report

    다음과 같이 바꿉니다.

    • PROJECT_ID: Google Cloud 프로젝트 ID
    • REPOSITORY를 Artifact Registry 저장소 이름으로 바꿉니다.
    • REGION을 Artifact Registry의 Google Cloud 리전으로 바꿉니다.

    gcloud-report는 서비스 이름입니다.

    성공하면 성공 메시지에 ID, 생성 시간, 이미지 이름이 표시됩니다. 이미지는 Artifact Registry에 저장되며 필요한 경우 다시 사용될 수 있습니다.

  2. 다음 명령어를 실행하여 서비스를 배포합니다.

    gcloud run deploy gcloud-report \
       --image REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/gcloud-report \
       --update-env-vars GCLOUD_REPORT_BUCKET=REPORT_ARCHIVE_BUCKET \
       --service-account gcloud-report-identity \
       --no-allow-unauthenticated

    다음과 같이 바꿉니다.

    • PROJECT_ID를 Google Cloud 프로젝트 ID로 바꿉니다.
    • REPOSITORY를 Artifact Registry 저장소 이름으로 바꿉니다.
    • REGION을 서비스의 Google Cloud 리전으로 바꿉니다.

    gcloud-report는 컨테이너 이름과 서비스 이름의 일부입니다. 컨테이너 이미지는 이전에 gcloud 설정에서 구성한 서비스와 리전(Cloud Run)에 배포됩니다.

    --no-allow-unauthenticated 플래그는 서비스에 대해 인증되지 않은 액세스를 제한합니다. 서비스를 비공개로 유지하면 Cloud Run의 기본 제공 인증을 사용해 승인되지 않은 요청을 차단할 수 있습니다. Identity and Access Management(IAM)를 기반으로 한 인증에 대한 자세한 내용은 IAM을 사용하여 액세스 관리를 참조하세요.

    배포가 완료될 때까지 기다립니다. 이 작업은 30초 정도 걸릴 수 있습니다. 성공하면 명령줄에 서비스 URL이 표시됩니다.

  3. 서비스에 코드 업데이트를 배포하려면 이전 단계를 반복합니다. 서비스에 배포할 때마다 새 버전이 생성되고 준비가 되면 자동으로 트래픽 제공이 시작됩니다.

Google Cloud 사용자에게 이 서비스를 호출할 수 있는 액세스 권한을 부여하는 방법은 IAM을 사용하여 액세스 관리를 참조하세요. 프로젝트 편집자와 소유자에게는 이 액세스 권한이 자동으로 부여됩니다.

보고서 생성

Cloud Run 서비스 보고서를 생성하려면 다음 안내를 따르세요.

  1. curl을 사용해서 인증된 요청을 보냅니다.

    curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" SERVICE_URL

    배포를 완료한 후 SERVICE_URL을 Cloud Run에서 제공한 URL로 바꿉니다.

    새 프로젝트를 만들고 이 튜토리얼을 따랐다면 다음과 비슷한 출력이 표시됩니다.

    Wrote report to gs://REPORT_ARCHIVE_BUCKET/report-.-DATE.txt

    파일 이름의 .는 소스 코드에 설명된 대로 기본 검색 인수입니다.

    검색 기능을 사용하려면 요청에 search 인수를 추가합니다.

    curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" SERVICE_URL?search=gcloud

    이 쿼리는 다음과 비슷한 출력을 반환합니다.

    Wrote report to gs://REPORT_ARCHIVE_BUCKET/report-gcloud-DATE.txt
  2. gsutil 도구를 로컬로 사용하여 파일을 검색합니다.

    gsutil cp gs://REPORT_FILE_NAME .

    명령어의 .는 현재 작업 디렉터리를 의미합니다.

    REPORT_FILE_NAME을 이전 단계에서 출력된 Cloud Storage 객체 이름으로 바꿉니다.

파일을 열어 보고서를 확인합니다. 예를 들면 다음과 같습니다.

프로젝트서 4개의 서비스 속성에 대한 열이 있는 Cloud Run 서비스 목록의 스크린샷입니다.
이 4개의 열은 서비스 설명에서 가져옵니다. 서비스의 이름, 첫 번째 배포에 할당된 URL, 서비스의 초기 생성자, 서비스의 최대 CPU 및 메모리 한도가 포함됩니다.

미래를 위한 견고성 개선

이 서비스를 추가로 개발하려면 Cloud Run Admin APICloud Storage 클라이언트 라이브러리를 사용하여 더 강력한 프로그래밍 언어로 다시 작성해 보세요.

gcloud 명령어에 --log-http를, gsutil 명령어에 -D를 추가하면 전달되는 API 호출을 검사하고 인증 세부정보를 확인할 수 있습니다.

이 작업 자동화

이제 Cloud Run 서비스 보고서가 HTTP 요청에 의해 트리거될 수 있으므로 자동화를 사용해 필요할 때 보고서를 생성합니다.

삭제

이 튜토리얼용으로 새 프로젝트를 만든 경우 이 프로젝트를 삭제합니다. 기존 프로젝트를 사용한 경우 이 튜토리얼에 추가된 변경사항은 제외하고 보존하려면 튜토리얼용으로 만든 리소스를 삭제합니다.

프로젝트 삭제

비용이 청구되지 않도록 하는 가장 쉬운 방법은 튜토리얼에서 만든 프로젝트를 삭제하는 것입니다.

프로젝트를 삭제하려면 다음 안내를 따르세요.

  1. Google Cloud 콘솔에서 리소스 관리 페이지로 이동합니다.

    리소스 관리로 이동

  2. 프로젝트 목록에서 삭제할 프로젝트를 선택하고 삭제를 클릭합니다.
  3. 대화상자에서 프로젝트 ID를 입력한 후 종료를 클릭하여 프로젝트를 삭제합니다.

튜토리얼 리소스 삭제

  1. 이 튜토리얼에서 배포한 Cloud Run 서비스를 삭제합니다.

    gcloud run services delete SERVICE-NAME

    여기서 SERVICE-NAME은 선택한 서비스 이름입니다.

    Google Cloud 콘솔에서 Cloud Run 서비스를 삭제할 수도 있습니다.

  2. 튜토리얼 설정 중에 추가한 gcloud 기본 리전 구성을 삭제합니다.

     gcloud config unset run/region
    
  3. 프로젝트 구성을 삭제합니다.

     gcloud config unset project
    
  4. 이 튜토리얼에서 만든 다른 Google Cloud 리소스를 삭제합니다.

다음 단계