gcloud 자동화 완성: --quiet·--format·종료 코드와 키리스 CI/CD 실전 가이드 — gcloud CLI 자동화 운영 플레이북 9/11

2026. 3. 12. 12:06·AI
반응형

시리즈: gcloud CLI 자동화 운영 플레이북 (총 11편) | 9회

gcloud 자동화 완성: –quiet·–format·종료 코드와 키리스 CI/CD 실전 가이드

gcloud 명령어를 CI/CD 파이프라인에 넣었더니 “확인하시겠습니까?” 프롬프트에서 멈춘 적 있지 않아요? 이 글에서는 비대화형 실행의 3대 표준부터 GitHub Actions 키리스 인증, Secret Manager 중앙화까지 CLI 자동화의 모든 것을 정리했어요.

Summary

  • gcloud 자동화의 3대 표준은 --quiet(프롬프트 차단) + --format(구조화 출력) + 종료 코드(성공/실패 판단)야
  • CI/CD 인증은 서비스계정 키 대신 Workload Identity Federation(WIF)이 기본이야
  • GitHub Actions에서는 google-github-actions/auth 액션으로 키리스 인증을 구현할 수 있어
  • 비밀(시크릿)은 코드나 환경변수에 하드코딩하지 말고, Secret Manager로 중앙화해서 런타임에 주입해야 해

이 글의 대상

  • gcloud 명령어를 CI/CD 파이프라인에 통합하려는 DevOps 엔지니어
  • 셸 스크립트로 GCP 리소스 관리를 자동화하고 싶은 인프라 엔지니어
  • GitHub Actions에서 GCP와 안전하게 연동하는 방법을 찾는 개발자

목차

  1. 자동화 3대 표준: –quiet, –format, 종료 코드
  2. 구조화 출력 마스터하기
  3. 종료 코드 기반 흐름 제어
  4. CI 인증: 키리스(WIF)가 기본이야
  5. GitHub Actions + google-github-actions/auth 실전
  6. Secret Manager 중앙화와 런타임 주입
  7. 배치 스크립트 실전 패턴
  8. 실패 케이스와 트러블슈팅

1. 자동화 3대 표준: –quiet, –format, 종료 코드

“사람이 읽는 CLI”에서 “시스템이 실행하는 CLI”로

gcloud를 터미널에서 직접 쓸 때는 사람이 출력을 읽고 판단해. 하지만 자동화(스크립트, CI/CD)에서는 시스템이 출력을 파싱하고 판단해야 하거든. 이 차이를 해결하는 게 3대 표준이야.

표준 역할 없으면 생기는 문제
--quiet 확인 프롬프트 차단 CI에서 “y/n?” 대기 → 타임아웃
--format 출력을 JSON/CSV/value로 구조화 사람용 텍스트를 정규식으로 파싱 → 깨지기 쉬움
종료 코드 성공(0)/실패(비0)로 판단 출력 문자열로 성공 여부 판단 → 언어/버전에 따라 변경

–quiet: 프롬프트 차단의 핵심

# 나쁜 예: CI에서 프롬프트에 걸림
gcloud compute instances delete my-vm
# → "The following instances will be deleted... Do you want to continue (Y/n)?"
# → CI에서 입력 불가 → 타임아웃 → 실패

# 좋은 예: --quiet로 확인 없이 실행
gcloud compute instances delete my-vm --quiet
# → 확인 없이 즉시 삭제

--quiet가 하는 일:
- 확인 프롬프트 비활성화
- 진행 표시줄(progress bar) 비활성화
- 기본값으로 자동 응답
- 오류 메시지는 정상 출력됨 (–quiet가 오류를 숨기지는 않아)

자동화 스크립트 기본 헤더

모든 자동화 스크립트는 이 헤더로 시작하는 게 좋아:

#!/bin/bash
set -euo pipefail

# set -e: 명령어 실패 시 즉시 종료
# set -u: 미정의 변수 사용 시 오류
# set -o pipefail: 파이프 중간 실패도 감지

PROJECT_ID="${PROJECT_ID:?프로젝트 ID가 설정되지 않았어}"
REGION="${REGION:-asia-northeast3}"  # 기본값: 서울

# 프로젝트 설정
gcloud config set project "$PROJECT_ID" --quiet

2. 구조화 출력 마스터하기

–format 옵션 완전 가이드

gcloud의 --format 옵션은 생각보다 훨씬 강력해. 자동화에서 가장 많이 쓰는 3가지 형식을 알아보자.

JSON 출력 (가장 범용적):

# 인스턴스 목록을 JSON으로
gcloud compute instances list \
  --format=json \
  --quiet

# jq로 특정 필드 추출
gcloud compute instances list \
  --format=json \
  --quiet | jq -r '.[].name'

value 출력 (특정 필드만 깔끔하게):

# 인스턴스 이름만 추출
gcloud compute instances list \
  --format='value(name)'

# 여러 필드를 탭으로 구분
gcloud compute instances list \
  --format='value(name, zone, status)'

# 결과 예시:
# my-vm-1    asia-northeast3-a    RUNNING
# my-vm-2    asia-northeast3-b    TERMINATED

csv 출력 (스프레드시트 연동):

# CSV 형식으로 출력
gcloud compute instances list \
  --format='csv(name, zone, machineType, status)'

# 헤더 없이 출력
gcloud compute instances list \
  --format='csv[no-heading](name, zone, status)'

format 실전 활용 패턴

패턴 명령어 용도
ID만 추출 --format='value(name)' 루프 입력용
JSON 파싱 --format=json \| jq '.field' 복잡한 데이터 추출
조건 필터 --filter='status=RUNNING' 서버사이드 필터
정렬 --sort-by=name 정렬된 결과
개수 제한 --limit=10 대량 결과 제한

filter와 format 조합

# 실행 중인 인스턴스의 이름과 IP만 추출
gcloud compute instances list \
  --filter='status=RUNNING' \
  --format='value(name, networkInterfaces[0].accessConfigs[0].natIP)' \
  --quiet

# 특정 라벨이 있는 리소스만
gcloud compute instances list \
  --filter='labels.env=production' \
  --format='table(name, zone, machineType.basename(), status)' \
  --quiet

3. 종료 코드 기반 흐름 제어

왜 출력 문자열이 아닌 종료 코드로 판단해야 해?

# 나쁜 예: 출력 문자열로 성공 여부 판단
RESULT=$(gcloud compute instances describe my-vm 2>&1)
if echo "$RESULT" | grep -q "RUNNING"; then
  echo "실행 중"
fi
# → 문제: gcloud 출력 형식이 바뀌면 깨져

# 좋은 예: 종료 코드로 판단
if gcloud compute instances describe my-vm --quiet > /dev/null 2>&1; then
  echo "인스턴스 존재"
else
  echo "인스턴스 없음 (또는 접근 불가)"
fi

gcloud 종료 코드 규칙

종료 코드 의미 예시
0 성공 리소스 생성/조회 성공
1 일반 오류 잘못된 인자, 권한 부족
2 사용법 오류 잘못된 명령어 구문

실전 흐름 제어 패턴

리소스 존재 확인 후 생성 (멱등성):

# 인스턴스가 없으면 생성, 있으면 스킵
if ! gcloud compute instances describe my-vm \
  --zone=asia-northeast3-a \
  --quiet > /dev/null 2>&1; then
  echo "인스턴스 생성 중..."
  gcloud compute instances create my-vm \
    --zone=asia-northeast3-a \
    --machine-type=e2-medium \
    --quiet
else
  echo "인스턴스가 이미 존재해. 스킵."
fi

재시도 패턴:

# 최대 3회 재시도
MAX_RETRIES=3
RETRY_COUNT=0

while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
  if gcloud compute instances start my-vm \
    --zone=asia-northeast3-a \
    --quiet; then
    echo "인스턴스 시작 성공"
    break
  fi

  RETRY_COUNT=$((RETRY_COUNT + 1))
  echo "실패. 재시도 $RETRY_COUNT/$MAX_RETRIES (30초 대기)"
  sleep 30
done

if [ $RETRY_COUNT -eq $MAX_RETRIES ]; then
  echo "최대 재시도 횟수 초과. 수동 확인 필요."
  exit 1
fi

병렬 실행 + 결과 수집:

# 여러 인스턴스 동시 삭제 (백그라운드)
INSTANCES=("vm-1" "vm-2" "vm-3")
PIDS=()
FAILED=0

for INSTANCE in "${INSTANCES[@]}"; do
  gcloud compute instances delete "$INSTANCE" \
    --zone=asia-northeast3-a \
    --quiet &
  PIDS+=($!)
done

# 모든 작업 완료 대기
for PID in "${PIDS[@]}"; do
  if ! wait $PID; then
    FAILED=$((FAILED + 1))
  fi
done

echo "완료: ${#INSTANCES[@]}개 중 $((${#INSTANCES[@]} - FAILED))개 성공, ${FAILED}개 실패"
[ $FAILED -eq 0 ] || exit 1

4. CI 인증: 키리스(WIF)가 기본이야

왜 키리스인가

8편에서 서비스계정 키의 위험성을 다뤘는데, CI/CD에서는 이 문제가 더 심각해:

방식 키 파일 인증 WIF (키리스)
보안 키 유출 위험 상시 존재 키 파일 자체가 없음
관리 키 회전 주기 관리 필요 자동, 단기 토큰 (1시간)
감사 키 사용처 추적 어려움 Cloud Audit Logs에 자동 기록
확장 리포마다 키 복사/배포 Pool 하나로 여러 리포 커버

WIF 작동 원리 (GitHub Actions 기준)

GitHub Actions 워크플로 실행
       │
       ▼
GitHub OIDC Provider가 토큰 발급
       │
       ▼
google-github-actions/auth가 토큰을 GCP에 전달
       │
       ▼
GCP Workload Identity Pool이 토큰 검증
       │
       ▼
검증 통과 → GCP 단기 토큰 발급 (1시간)
       │
       ▼
gcloud/bq/gsutil 명령어 인증 완료

5. GitHub Actions + google-github-actions/auth 실전

기본 설정 (한 번만 하면 돼)

GCP 측에서 WIF Pool과 Provider를 설정해야 해. 8편에서 다뤘던 명령어를 다시 정리할게:

# 1. Workload Identity Pool 생성
gcloud iam workload-identity-pools create "github-pool" \
  --location="global" \
  --display-name="GitHub Actions Pool" \
  --project=my-project

# 2. OIDC Provider 추가
gcloud iam workload-identity-pools providers create-oidc "github-provider" \
  --location="global" \
  --workload-identity-pool="github-pool" \
  --display-name="GitHub Provider" \
  --attribute-mapping="google.subject=assertion.sub,attribute.repository=assertion.repository" \
  --issuer-uri="https://token.actions.githubusercontent.com" \
  --project=my-project

# 3. 서비스계정 생성 + 권한 부여
gcloud iam service-accounts create github-actions-sa \
  --display-name="GitHub Actions SA" \
  --project=my-project

# 4. WIF → 서비스계정 연결
gcloud iam service-accounts add-iam-policy-binding \
  github-actions-sa@my-project.iam.gserviceaccount.com \
  --role="roles/iam.workloadIdentityUser" \
  --member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/github-pool/attribute.repository/my-org/my-repo" \
  --project=my-project

GitHub Actions 워크플로 예시

# .github/workflows/deploy.yml
name: Deploy to GCP

on:
  push:
    branches: [main]

# WIF에 필요한 권한
permissions:
  contents: read
  id-token: write  # OIDC 토큰 발급에 필요

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      # 1. 코드 체크아웃
      - uses: actions/checkout@v4

      # 2. GCP 인증 (키리스!)
      - id: auth
        uses: google-github-actions/auth@v2
        with:
          workload_identity_provider: 'projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/github-pool/providers/github-provider'
          service_account: 'github-actions-sa@my-project.iam.gserviceaccount.com'

      # 3. gcloud CLI 설정
      - uses: google-github-actions/setup-gcloud@v2
        with:
          project_id: my-project

      # 4. 배포 (gcloud 명령어 사용)
      - name: Deploy to Cloud Run
        run: |
          gcloud run deploy my-service \
            --source=. \
            --region=asia-northeast3 \
            --quiet \
            --format=json

핵심 포인트

워크플로에서 반드시 확인해야 할 것들:

# 이것들을 빠뜨리면 WIF가 작동 안 해!
permissions:
  id-token: write  # 이거 없으면 OIDC 토큰 발급 불가
# auth 액션 버전은 v2 사용
- uses: google-github-actions/auth@v2
  # v1은 deprecated

멀티 프로젝트 배포

여러 GCP 프로젝트에 배포해야 할 때:

jobs:
  deploy-staging:
    runs-on: ubuntu-latest
    steps:
      - uses: google-github-actions/auth@v2
        with:
          workload_identity_provider: 'projects/STAGING_NUMBER/locations/global/...'
          service_account: 'deploy-sa@staging-project.iam.gserviceaccount.com'
      - run: gcloud run deploy my-service --project=staging-project --quiet

  deploy-production:
    needs: deploy-staging  # 스테이징 성공 후에만
    runs-on: ubuntu-latest
    environment: production  # 수동 승인 게이트
    steps:
      - uses: google-github-actions/auth@v2
        with:
          workload_identity_provider: 'projects/PROD_NUMBER/locations/global/...'
          service_account: 'deploy-sa@prod-project.iam.gserviceaccount.com'
      - run: gcloud run deploy my-service --project=prod-project --quiet

6. Secret Manager 중앙화와 런타임 주입

왜 Secret Manager인가

비밀(API 키, DB 비밀번호, 인증 토큰)을 관리하는 잘못된 방법들:

방법 왜 안 돼?
코드에 하드코딩 Git에 커밋 → 영원히 히스토리에 남음
환경변수 파일(.env) 서버에 파일로 남음 → 유출 위험
CI/CD 시크릿 변수 플랫폼 종속 → 중앙 관리 불가
설정 파일 암호화 복호화 키 관리 문제 → 결국 같은 문제

Secret Manager는 이 모든 문제를 해결해:
- 중앙 저장소에서 통합 관리
- IAM으로 접근 통제
- 버전 관리 자동
- 감사 로그 자동 기록
- API/CLI로 런타임 주입

Secret Manager CLI 기본 명령어

# 시크릿 생성
gcloud secrets create db-password \
  --replication-policy=automatic \
  --quiet

# 시크릿 값 추가 (버전 생성)
echo -n "MySecurePassword123!" | \
  gcloud secrets versions add db-password \
  --data-file=- \
  --quiet

# 시크릿 값 조회 (최신 버전)
gcloud secrets versions access latest \
  --secret=db-password \
  --quiet

# 시크릿 목록
gcloud secrets list --format='table(name, createTime)' --quiet

# 특정 버전 조회
gcloud secrets versions access 2 \
  --secret=db-password \
  --quiet

# 이전 버전 비활성화
gcloud secrets versions disable 1 \
  --secret=db-password \
  --quiet

스크립트에서 시크릿 주입

#!/bin/bash
set -euo pipefail

# 런타임에 Secret Manager에서 값 가져오기
DB_PASSWORD=$(gcloud secrets versions access latest \
  --secret=db-password --quiet)
API_KEY=$(gcloud secrets versions access latest \
  --secret=api-key --quiet)

# 환경변수로 주입 (프로세스 내에서만 유효)
export DB_PASSWORD
export API_KEY

# 애플리케이션 실행
python app.py

Cloud Build에서 시크릿 주입

# cloudbuild.yaml
steps:
  - name: 'gcr.io/cloud-builders/gcloud'
    entrypoint: 'bash'
    args:
      - '-c'
      - |
        echo "배포 시작..."
        gcloud run deploy my-service \
          --set-env-vars="DB_HOST=$$DB_HOST" \
          --set-secrets="DB_PASSWORD=db-password:latest" \
          --region=asia-northeast3 \
          --quiet
    secretEnv: ['DB_HOST']

availableSecrets:
  secretManager:
    - versionName: projects/my-project/secrets/db-host/versions/latest
      env: 'DB_HOST'

GitHub Actions에서 시크릿 주입

steps:
  - id: auth
    uses: google-github-actions/auth@v2
    with:
      workload_identity_provider: '...'
      service_account: '...'

  - id: secrets
    uses: google-github-actions/get-secretmanager-secrets@v2
    with:
      secrets: |-
        db-password:my-project/db-password
        api-key:my-project/api-key

  - name: Deploy
    run: |
      gcloud run deploy my-service \
        --set-env-vars="API_KEY=${{ steps.secrets.outputs.api-key }}" \
        --set-secrets="DB_PASSWORD=db-password:latest" \
        --quiet

7. 배치 스크립트 실전 패턴

패턴 1: 리소스 일괄 정리 스크립트

#!/bin/bash
# 사용하지 않는 리소스 일괄 정리
set -euo pipefail

PROJECT_ID="${PROJECT_ID:?프로젝트 ID를 설정해줘}"
DRY_RUN="${DRY_RUN:-true}"  # 기본은 드라이런

echo "=== 미사용 디스크 정리 ==="
UNUSED_DISKS=$(gcloud compute disks list \
  --project="$PROJECT_ID" \
  --filter='NOT users:*' \
  --format='value(name, zone)' \
  --quiet)

if [ -z "$UNUSED_DISKS" ]; then
  echo "미사용 디스크 없음"
else
  echo "$UNUSED_DISKS" | while read -r NAME ZONE; do
    if [ "$DRY_RUN" = "true" ]; then
      echo "[드라이런] 삭제 예정: $NAME ($ZONE)"
    else
      echo "삭제 중: $NAME ($ZONE)"
      gcloud compute disks delete "$NAME" \
        --zone="$ZONE" \
        --project="$PROJECT_ID" \
        --quiet
    fi
  done
fi

echo "=== 중지된 인스턴스 목록 ==="
gcloud compute instances list \
  --project="$PROJECT_ID" \
  --filter='status=TERMINATED' \
  --format='table(name, zone, lastStartTimestamp)' \
  --quiet

패턴 2: 환경별 배포 스크립트

#!/bin/bash
# Cloud Run 환경별 배포
set -euo pipefail

ENVIRONMENT="${1:?사용법: $0 <staging|production>}"
SERVICE_NAME="my-api"
REGION="asia-northeast3"
IMAGE="gcr.io/my-project/$SERVICE_NAME"

case "$ENVIRONMENT" in
  staging)
    PROJECT="my-project-staging"
    MIN_INSTANCES=0
    MAX_INSTANCES=5
    ;;
  production)
    PROJECT="my-project-prod"
    MIN_INSTANCES=2
    MAX_INSTANCES=20
    ;;
  *)
    echo "잘못된 환경: $ENVIRONMENT (staging 또는 production)"
    exit 1
    ;;
esac

echo "=== $ENVIRONMENT 환경 배포 ==="
echo "프로젝트: $PROJECT"
echo "서비스: $SERVICE_NAME"
echo "리전: $REGION"

# 빌드
gcloud builds submit . \
  --tag="$IMAGE:latest" \
  --project="$PROJECT" \
  --quiet

# 배포
gcloud run deploy "$SERVICE_NAME" \
  --image="$IMAGE:latest" \
  --region="$REGION" \
  --min-instances="$MIN_INSTANCES" \
  --max-instances="$MAX_INSTANCES" \
  --set-secrets="DB_PASSWORD=db-password:latest" \
  --project="$PROJECT" \
  --format=json \
  --quiet

# 배포 확인
URL=$(gcloud run services describe "$SERVICE_NAME" \
  --region="$REGION" \
  --project="$PROJECT" \
  --format='value(status.url)' \
  --quiet)

echo "배포 완료: $URL"

# 헬스체크
if curl -sf "$URL/health" > /dev/null; then
  echo "헬스체크 통과"
else
  echo "헬스체크 실패! 롤백 필요"
  exit 1
fi

패턴 3: 로그 수집 + 알림 스크립트

#!/bin/bash
# 에러 로그 수집 및 Slack 알림
set -euo pipefail

PROJECT_ID="${PROJECT_ID:?프로젝트 ID를 설정해줘}"
SLACK_WEBHOOK="${SLACK_WEBHOOK:?Slack Webhook URL을 설정해줘}"
LOOKBACK_MINUTES=30

# 최근 30분 에러 로그 수집
ERROR_COUNT=$(gcloud logging read \
  "severity>=ERROR AND timestamp>=\"$(date -u -d "$LOOKBACK_MINUTES minutes ago" +%Y-%m-%dT%H:%M:%SZ)\"" \
  --project="$PROJECT_ID" \
  --format=json \
  --quiet | jq 'length')

echo "최근 ${LOOKBACK_MINUTES}분 에러 수: $ERROR_COUNT"

# 임계값 초과 시 알림
if [ "$ERROR_COUNT" -gt 10 ]; then
  # 대표 에러 메시지 추출
  TOP_ERRORS=$(gcloud logging read \
    "severity>=ERROR AND timestamp>=\"$(date -u -d "$LOOKBACK_MINUTES minutes ago" +%Y-%m-%dT%H:%M:%SZ)\"" \
    --project="$PROJECT_ID" \
    --format='value(textPayload)' \
    --limit=3 \
    --quiet)

  # Slack 알림 발송
  curl -sf -X POST "$SLACK_WEBHOOK" \
    -H 'Content-type: application/json' \
    -d "{
      \"text\": \"경고: 최근 ${LOOKBACK_MINUTES}분간 에러 ${ERROR_COUNT}건 발생\\n프로젝트: ${PROJECT_ID}\\n대표 에러:\\n${TOP_ERRORS}\"
    }" > /dev/null

  echo "Slack 알림 발송 완료"
fi

8. 실패 케이스와 트러블슈팅

케이스 1: CI에서 “You do not have permission” 오류

상황: GitHub Actions에서 gcloud 명령어 실행 시 권한 오류

확인 순서:

# 1. WIF 설정 확인
gcloud iam workload-identity-pools providers describe github-provider \
  --workload-identity-pool=github-pool \
  --location=global \
  --project=my-project

# 2. 서비스계정 IAM 바인딩 확인
gcloud iam service-accounts get-iam-policy \
  github-actions-sa@my-project.iam.gserviceaccount.com

# 3. 서비스계정 역할 확인
gcloud projects get-iam-policy my-project \
  --flatten="bindings[].members" \
  --filter="bindings.members:github-actions-sa@" \
  --format='table(bindings.role)'

흔한 원인:
- permissions.id-token: write가 워크플로에 없음
- attribute.repository 매핑의 org/repo 이름이 틀림
- 서비스계정에 필요한 역할이 부여되지 않음

케이스 2: –format=json 출력이 비어 있음

상황: gcloud ... --format=json 실행 결과가 [] 빈 배열

원인 분석:

# 필터가 너무 엄격한 경우 - 필터 없이 먼저 확인
gcloud compute instances list --format=json --quiet

# 프로젝트가 잘못된 경우
gcloud config get-value project

# 리전/존이 다른 경우
gcloud compute instances list \
  --zones=asia-northeast3-a,asia-northeast3-b,asia-northeast3-c \
  --format=json \
  --quiet

케이스 3: Secret Manager에서 “NOT_FOUND” 오류

상황: gcloud secrets versions access latest 실행 시 404

확인:

# 시크릿 존재 여부 확인
gcloud secrets describe db-password \
  --project=my-project --quiet

# 프로젝트가 맞는지 확인
gcloud config get-value project

# 활성 버전이 있는지 확인
gcloud secrets versions list db-password \
  --project=my-project \
  --filter='state=ENABLED' \
  --format='table(name, state, createTime)' \
  --quiet

흔한 원인:
- 시크릿 이름 오타 (하이픈 vs 밑줄)
- 다른 프로젝트에 시크릿이 있음
- 모든 버전이 disabled/destroyed 상태

케이스 4: 배치 스크립트가 중간에 멈춤

상황: for 루프로 100개 리소스를 처리하는데 30번째에서 멈춤

해결:

# API Rate Limit에 걸린 경우 - 딜레이 추가
for INSTANCE in $(gcloud compute instances list \
  --format='value(name)' --quiet); do

  gcloud compute instances stop "$INSTANCE" --quiet || {
    echo "실패: $INSTANCE - 10초 후 재시도"
    sleep 10
    gcloud compute instances stop "$INSTANCE" --quiet || echo "재시도도 실패: $INSTANCE"
  }

  # Rate Limit 방지용 딜레이
  sleep 1
done

핵심 정리

1. 자동화 3대 표준: --quiet(프롬프트 차단) + --format(구조화 출력) + 종료 코드(성공/실패 판단)
2. CI/CD 인증은 서비스계정 키가 아니라 WIF(Workload Identity Federation)가 기본이야
3. GitHub Actions는 google-github-actions/auth v2 + permissions.id-token: write 조합으로 키리스 인증해
4. 비밀은 Secret Manager에 중앙화하고, 런타임에 주입하는 패턴이 표준이야

FAQ

Q. –quiet를 붙이면 오류 메시지도 안 나와?

A. 아니야, --quiet는 확인 프롬프트와 진행 표시줄만 비활성화해. 오류 메시지는 정상적으로 stderr에 출력돼. 그래서 CI에서 --quiet를 붙여도 실패 시 로그에서 원인을 확인할 수 있어.

Q. –format=json과 –format=’value(…)’ 중 뭘 쓰는 게 좋아?

A. 단일 필드만 필요하면 value()가 깔끔하고, 여러 필드를 복잡하게 다뤄야 하면 json + jq 조합이 유연해. CI 파이프라인에서 다음 단계에 값을 전달할 때는 value()가 파싱이 필요 없어서 편해.

Q. WIF 설정이 너무 복잡한데, 그냥 키 파일 쓰면 안 돼?

A. 처음 설정은 WIF가 확실히 번거로워. 하지만 한 번 설정하면 키 회전, 유출 걱정, 감사 이슈가 전부 사라져. 키 파일은 단기 프로토타입에서만 쓰고, 정식 파이프라인은 반드시 WIF로 전환하는 걸 추천해.

Q. Secret Manager에 저장하면 비용이 들어?

A. 시크릿당 월 $0.06, 10,000회 접근당 $0.03 정도야. 시크릿 10개를 매일 1,000회 접근해도 월 $1도 안 돼. 비용 대비 보안 이점이 압도적이라 사실상 무료나 다름없어.

Q. set -euo pipefail은 왜 꼭 써야 해?

A. set -e는 명령어 실패 시 즉시 스크립트를 종료하고, set -u는 미정의 변수 사용을 막고, set -o pipefail은 파이프 중간 명령어의 실패도 감지해. 이 3개 없이 스크립트를 돌리면, 중간에 실패해도 다음 명령어가 실행돼서 예측 불가능한 상태가 만들어져.

Q. Cloud Build와 GitHub Actions 중 뭘 쓰는 게 좋아?

A. GCP 생태계에 올인이면 Cloud Build가 통합이 좋고 비용도 저렴해(일 120분 무료). 하지만 GitHub 중심 워크플로라면 GitHub Actions + WIF가 개발자 경험이 더 나아. 둘 다 쓰는 하이브리드도 가능해 — 빌드는 Cloud Build, 배포 승인은 GitHub Actions 같은 조합이지.

Q. gcloud 명령어의 API Rate Limit은 어느 정도야?

A. 서비스마다 다른데, 대부분 분당 수백~수천 요청 정도야. 배치 스크립트에서 수백 개 리소스를 루프로 처리할 때는 sleep 1 정도의 딜레이를 넣는 게 안전해. Rate Limit에 걸리면 429 에러가 나오고, 이때는 지수 백오프(exponential backoff)로 재시도하면 돼.

Q. –format에서 nested 필드를 어떻게 접근해?

A. 점(.)으로 중첩 필드에 접근할 수 있어. 예를 들면 --format='value(networkInterfaces[0].accessConfigs[0].natIP)'처럼. 배열은 인덱스로, 객체는 필드명으로 접근해. 구조를 모르겠으면 먼저 --format=json으로 전체 구조를 확인하는 게 빨라.

Q. Secret Manager 버전 관리는 어떻게 해?

A. 새 값을 추가하면 자동으로 버전이 올라가. gcloud secrets versions add로 새 버전을 만들고, 이전 버전은 disable로 비활성화하면 돼. 코드에서는 latest를 쓰면 항상 최신 버전을 가져오지만, 운영 환경에서는 특정 버전 번호를 고정하는 게 더 안전해.

Q. 여러 프로젝트에 동시에 배포하는 스크립트는 어떻게 만들어?

A. 환경별 설정을 변수로 분리하고, 스크립트 인자로 환경을 받는 패턴이 제일 깔끔해. 7번 섹션의 “패턴 2: 환경별 배포 스크립트”처럼 case 문으로 환경별 변수를 분기하면 돼. 프로젝트가 3개 이상이면 설정 파일(JSON/YAML)에서 읽어오는 것도 방법이야.


참고 자료 (References)

데이터 출처

출처 설명 링크
Scripting gcloud CLI gcloud 비대화형 실행 공식 가이드 Scripting gcloud
Workload Identity Federation 외부 워크로드 키리스 인증 문서 WIF 문서
google-github-actions/auth GitHub Actions용 GCP 인증 액션 GitHub
서비스 계정 키 베스트프랙티스 키 최소화 가이드 IAM 문서
Secret Manager 베스트프랙티스 시크릿 관리 가이드 Secret Manager
Cloud Build 시크릿 사용 Cloud Build에서 시크릿 주입 Cloud Build 시크릿

핵심 인용

“gcloud 스크립팅 가이드는 비대화형 실행과 구조화 출력, 종료 코드 기반 제어를 핵심 원칙으로 제시한다. 이 3가지만 지켜도 사람이 읽는 CLI에서 시스템이 실행하는 CLI로 바뀐다.” — Google Cloud SDK 문서


다음 편 예고

[10편] 교육 커리큘럼과 실습 과제: 2일/5일 온보딩 패키지 완전 가이드

  • 2일 압축형 vs 5일 심화형 커리큘럼 설계
  • 실습 과제 패키지: 프로젝트 생성부터 배포까지
  • 평가 체크리스트와 수료 기준 설정법

반응형

'AI' 카테고리의 다른 글

gcloud를 운영 시스템으로 만드는 법: 표준이 있는 팀과 없는 팀의 결정적 차이 — gcloud CLI 자동화 운영 플레이북 11/11  (1) 2026.03.12
gcloud 교육 커리큘럼 설계: 2일/5일 과정과 실습 과제로 팀 표준을 정착시키는 법 — gcloud CLI 자동화 운영 플레이북 10/11  (0) 2026.03.12
CLI 보안 완성하기: 키리스 운영·KMS 감사·SCC 탐지 데이터 내보내기 실전 가이드 — gcloud CLI 자동화 운영 플레이북 8/11  (0) 2026.03.12
데이터 서비스 CLI 실전 운영: Storage·BigQuery·Pub/Sub 비용과 안전 가드레일 — gcloud CLI 자동화 운영 플레이북 7/11  (1) 2026.03.12
VPC부터 Cloud Run까지, gcloud로 네트워크와 컴퓨트를 검증 가능하게 운영하는 법 — gcloud CLI 자동화 운영 플레이북 6/11  (0) 2026.03.12
'AI' 카테고리의 다른 글
  • gcloud를 운영 시스템으로 만드는 법: 표준이 있는 팀과 없는 팀의 결정적 차이 — gcloud CLI 자동화 운영 플레이북 11/11
  • gcloud 교육 커리큘럼 설계: 2일/5일 과정과 실습 과제로 팀 표준을 정착시키는 법 — gcloud CLI 자동화 운영 플레이북 10/11
  • CLI 보안 완성하기: 키리스 운영·KMS 감사·SCC 탐지 데이터 내보내기 실전 가이드 — gcloud CLI 자동화 운영 플레이북 8/11
  • 데이터 서비스 CLI 실전 운영: Storage·BigQuery·Pub/Sub 비용과 안전 가드레일 — gcloud CLI 자동화 운영 플레이북 7/11
트렌드픽(Trend-Pick)
트렌드픽(Trend-Pick)
지금 뜨는 상품, 급상승 키워드 기반 트렌드 정보를 빠르게 정리합니다.
  • 트렌드픽(Trend-Pick)
    트렌드픽(Trend-Pick)
    트렌드픽(Trend-Pick)
  • 전체
    오늘
    어제
    • 트렌드픽 (536) N
      • AI (142) N
      • Tech (167)
      • Economy (70)
      • Global (72)
      • Culture (85)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

    • 블로그 면책조항 안내입니다
    • 블로그 개인정보처리방침 안내입니다
    • 블로그 소개합니다
  • 인기 글

  • 태그

    아르테미스2
    글로벌 트렌드
    제품
    조직
    chatGPT
    랜덤박스
    비트코인
    API
    클라우드 인프라
    Anthropic
    BTS 광화문
    기술
    AI 인프라
    AI 기술
    sec
    Claude
    기업분석
    BTS
    가차
    우주 데이터센터
  • 최근 댓글

  • 최근 글

  • 반응형
  • hELLO· Designed By정상우.v4.10.6
트렌드픽(Trend-Pick)
gcloud 자동화 완성: --quiet·--format·종료 코드와 키리스 CI/CD 실전 가이드 — gcloud CLI 자동화 운영 플레이북 9/11
상단으로

티스토리툴바