[GCP] Cloud SQL 사용 현황, GUI보다 빠르고 정확하게 파악하기 (gcloud & Shell Script 활용)
달빛궁전-2025. 5. 3. 20:04
GCP의 핵심 서비스 중 하나인 Cloud SQL을 운영하다 보면, 웹 콘솔(GUI)만으로는 필요한 정보를 신속하게 얻기 어려울 때가 있습니다. 여러 인스턴스의 머신 타입을 비교하거나, 할당된 용량이 아닌 실제 디스크 사용량을 확인하고 싶을 때, 또는 HA(고가용성) 구성 여부를 한눈에 파악하고 싶을 때 GUI는 종종 여러 번의 클릭과 페이지 이동을 요구하여 번거로움을 느끼게 합니다.
이러한 불편함을 해소하고자 gcloud와 쉘스크립트를 활용하여 터미널 환경에서 Cloud SQL 현황을 파악하는 방법들을 작성하였습니다. GCP 인프라 관리자, DevOps 엔지니어, DBA 등 Cloud SQL을 운영하는 분들이라면 누구나 겪어봤을 법한 문제들에 대한 해결책을 제시하는 것을 목표로 합니다.
본문에서는 먼저 Cloud Asset Inventory를 사용하여 조직 전체의 Cloud SQL 인스턴스 목록을 빠르게 확인하는 방법을 알아봅니다. 이어서 gcloud sql 명령어를 통해 특정 프로젝트 내 인스턴스의 상세 정보(HA 상태, 머신 타입, 디스크 크기 등)를 효과적으로 조회하고 필터링하는 기법을 살펴봅니다. 마지막으로, 반복적인 확인 작업을 자동화할 수 있는 쉘 스크립트 예제들(HA 상태 점검, 실제 디스크 사용량 조회 - 단일/전체 인스턴스)을 작성했습니다. 이 글을 통해 gcloud와 스크립트의 강력함을 활용하여 Cloud SQL 관리 효율성을 높이시길 바랍니다.
필수 권한 및 역할 안내:
이 글에서 소개하는 명령어와 스크립트를 실행하려면 적절한 IAM 역할이 필요합니다.
일반적으로 다음과 같은 역할들이 필요하며, 필요한 범위(조직, 폴더, 프로젝트)에 맞게 부여되어야 합니다.
조직 전체 인스턴스 목록 확인 시: 조직 수준의 Cloud Asset 뷰어 (roles/cloudasset.viewer) 역할
프로젝트 내 인스턴스 정보/상태 조회 시: 프로젝트 수준의 Cloud SQL 뷰어 (roles/cloudsql.viewer) 역할
프로젝트 이름으로 ID 조회하는 스크립트 실행 시: 조직 또는 폴더 수준의 브라우저 (roles/browser) 역할
실제 디스크 사용량 조회 스크립트 실행 시: 프로젝트 수준의 Monitoring 뷰어 (roles/monitoring.viewer) 역할
참고: 뷰어(roles/viewer), 편집자(roles/editor), 소유자(roles/owner) 등의 기본 역할에는 위의 권한들이 포함될 수 있지만, 최소 권한 원칙에 따라 가능한 구체적인 역할을 사용하는 것이 좋습니다.
GUI메인 화면에서는 머신타입, 실제사용중인 디스크용량등은 나오지 않습니다.
머신 타입은 “수정” 으로 이동해야 보이며, 실제 디스크 사용량은 Monitoring 탭에서 별도로 조회를 해야합니다.
유의사항
"Cloud Asset Inventory는 특정 시점의 리소스 스냅샷 정보이므로, 실시간 상태와 약간의 지연(분 단위)이 있을 수 있습니다."
#!/bin/bash
# --- 스크립트 사용법 ---
# ./cloudsql_ha_info.sh <GCP_PROJECT_ID> <CLOUDSQL_INSTANCE_NAME>
# 예시: ./cloudsql_ha_info.sh my-gcp-project my-cloudsql-instance
# 입력값 확인 (프로젝트 ID와 Cloud SQL 인스턴스 이름이 주어졌는지)
if [ -z "$1" ] || [ -z "$2" ]; then
echo "스크립트 사용법: $0 <GCP_PROJECT_ID> <CLOUDSQL_INSTANCE_NAME>"
echo "예시: $0 my-gcp-project my-cloudsql-instance"
exit 1
fi
# 입력값을 변수에 저장
PROJECT_ID="$1"
INSTANCE_NAME="$2"
echo "=================================================="
echo " 프로젝트: $PROJECT_ID"
echo " Cloud SQL 인스턴스: $INSTANCE_NAME"
echo " HA 구성 정보를 가져오는 중..."
echo "=================================================="
# gcloud 명령 실행하여 인스턴스 정보 가져오기 (JSON 형식) 및 jq로 파싱
gcloud sql instances describe "$INSTANCE_NAME" \
--project="$PROJECT_ID" \
--format=json | \
jq -r '
# 결과에서 필요한 정보 추출 및 포맷팅
"Availability Type: \(.settings.availabilityType // "N/A")\n" +
"Primary Zone: \(.gceZone // "N/A")\n" +
"Secondary Zone: \(.secondaryGceZone // "N/A")"
'
# gcloud 또는 jq 명령 실행 상태 확인
GCLOUD_EXIT_CODE=${PIPESTATUS[0]}
JQ_EXIT_CODE=${PIPESTATUS[1]}
# gcloud 명령 실패 시
if [ "$GCLOUD_EXIT_CODE" -ne 0 ]; then
echo "[오류] gcloud 명령 실행에 실패했습니다 (Exit Code: $GCLOUD_EXIT_CODE)."
echo " 프로젝트 ID, 인스턴스 이름 또는 권한을 확인하세요."
exit 1
# jq 명령 실패 시 (보통 gcloud가 유효한 JSON을 반환하지 않은 경우 발생 가능)
elif [ "$JQ_EXIT_CODE" -ne 0 ]; then
echo "[오류] 결과 처리 중 오류가 발생했습니다 (jq Exit Code: $JQ_EXIT_CODE)."
exit 1
fi
echo "=================================================="
echo " 작업 완료."
echo "=================================================="
exit 0
실행결과
위에 스크립트는 프로젝트와 Cloud SQL 인스턴스를 지정하여 출력했는데, 프로젝트에 Cloud SQL 인스턴스가 많다면 프로젝트 이름을 입력 받아서 해당 프로젝트의 존재하는 모든 Cloud SQL의 정보를 출력 합니다.
#!/bin/bash
# 사용자로부터 프로젝트 이름(표시 이름) 입력받기
read -p "정보를 조회할 GCP 프로젝트의 이름(표시 이름)을 입력하세요: " PROJECT_NAME
# 프로젝트 이름이 입력되었는지 확인
if [[ -z "$PROJECT_NAME" ]]; then
echo -e "${RED}오류: 프로젝트 이름이 입력되지 않았습니다.${NC}"
exit 1
fi
echo "프로젝트 이름 '$PROJECT_NAME'에 해당하는 프로젝트 ID를 조회합니다..."
echo "(resourcemanager.projects.list 권한이 필요합니다)"
# 프로젝트 이름으로 프로젝트 ID 조회 및 오류 처리
# 동일 이름 프로젝트가 여러 개일 경우를 대비하여 개수 확인
PROJECT_ID_OUTPUT=$(gcloud projects list --filter="name='${PROJECT_NAME}'" --format="value(projectId)" 2>/dev/null)
PROJECT_ID_COUNT=$(echo "$PROJECT_ID_OUTPUT" | grep -c .) # 빈 줄 제외하고 카운트
if [[ $PROJECT_ID_COUNT -eq 0 ]]; then
echo -e "${RED}오류: 프로젝트 이름 '$PROJECT_NAME'에 해당하는 프로젝트를 찾을 수 없거나 조회 권한이 없습니다.${NC}"
exit 1
elif [[ $PROJECT_ID_COUNT -gt 1 ]]; then
echo -e "${RED}오류: 이름이 '$PROJECT_NAME'인 프로젝트가 ${PROJECT_ID_COUNT}개 발견되었습니다. 고유한 프로젝트 ID를 사용해주세요.${NC}"
echo "발견된 ID 목록:"
echo "$PROJECT_ID_OUTPUT"
exit 1
fi
# 조회된 프로젝트 ID 사용
PROJECT_ID=$PROJECT_ID_OUTPUT
echo "프로젝트 ID '$PROJECT_ID' 를 확인했습니다."
echo "----------------------------------------------------------------------"
echo "Cloud SQL 인스턴스 목록 (REGIONAL 타입, MACHINE_TYPE 포함):"
# Cloud SQL 인스턴스 목록 조회 (찾은 PROJECT_ID 사용)
gcloud sql instances list \
--project="$PROJECT_ID" \
--format="table(
name:label=NAME,
region:label=REGION,
settings.availabilityType:label=AVAILABILITY_TYPE,
state:label=STATE,
settings.tier:label=MACHINE_TYPE
)"
# gcloud 명령어 실행 오류 처리
EXIT_CODE=$?
if [[ $EXIT_CODE -ne 0 ]]; then
echo "----------------------------------------------------------------------"
echo -e "${RED}오류: 프로젝트 '$PROJECT_ID'에서 Cloud SQL 인스턴스 목록을 가져오는 데 실패했습니다. (종료 코드: $EXIT_CODE)${NC}"
echo "프로젝트 ID가 올바르고, Cloud SQL Admin API가 활성화되었으며, 필요한 권한(cloudsql.instances.list)이 있는지 확인하세요."
exit 1
fi
echo "----------------------------------------------------------------------"
echo "조회가 완료되었습니다."
exit 0
실행결과
Cloud SQL 실제 디스크 사용량 조회 Cloud SQL 에서 프로비저닝한 디스크 용량이 아닌 Cloud Monitoring 을 이용해 현시점의 디스크 용량 조회 방법 프로젝트 이름과 Cloud SQL명이 필요합니다.
#!/bin/bash
# 1. 사용자로부터 프로젝트 이름 입력 받기
read -p "정보를 조회할 GCP 프로젝트의 이름(표시 이름)을 입력하세요: " project_display_name
# 입력 값 검증
if [[ -z "$project_display_name" ]]; then
echo "오류: 프로젝트 이름을 입력해야 합니다."
exit 1
fi
# 2. 프로젝트 이름을 사용하여 프로젝트 ID 조회
echo "프로젝트 이름 '${project_display_name}'에 해당하는 프로젝트 ID를 조회합니다..."
# gcloud projects list 명령어 실행 및 결과 저장
# 오류 발생 시 stderr 메시지는 숨기고($?로 체크), 결과는 project_id_output에 저장
project_id_output=$(gcloud projects list --filter="name='${project_display_name}'" --format="value(projectId)" 2>/dev/null)
gcloud_exit_status=$?
# gcloud 명령어 실행 자체에 오류가 있었는지 확인
if [[ $gcloud_exit_status -ne 0 ]]; then
echo "오류: 프로젝트 목록을 조회하는 중 오류가 발생했습니다. gcloud 설정 또는 권한을 확인하세요."
# 필요한 경우, 오류 원인 파악을 위해 stderr를 포함하여 다시 실행해 볼 수 있습니다.
# gcloud projects list --filter="name='${project_display_name}'" --format="value(projectId)"
exit 1
fi
# 조회된 프로젝트 ID 개수 확인 (grep -c . 은 비어있지 않은 라인 수를 셉니다)
project_id_count=$(echo "$project_id_output" | grep -c .)
if [[ $project_id_count -eq 0 ]]; then
echo "오류: 프로젝트 이름 '${project_display_name}'에 해당하는 활성 프로젝트 ID를 찾을 수 없습니다."
echo "프로젝트 이름을 다시 확인하거나, 삭제된 프로젝트가 아닌지 확인하세요."
exit 1
elif [[ $project_id_count -gt 1 ]]; then
echo "오류: 프로젝트 이름 '${project_display_name}'에 해당하는 프로젝트가 두 개 이상 발견되었습니다."
echo "더 정확한 프로젝트 이름을 사용하거나 프로젝트 ID를 직접 스크립트에 지정하세요."
echo "발견된 ID 목록:"
echo "$project_id_output"
exit 1
else
# 정확히 하나의 프로젝트 ID를 찾음
PROJECT_ID="$project_id_output"
echo "프로젝트 ID '${PROJECT_ID}'를 확인했습니다."
fi
# 3. 사용자로부터 Cloud SQL 인스턴스 이름 입력 받기
read -p "디스크 사용량을 조회할 Cloud SQL 인스턴스 이름을 입력하세요: " INSTANCE_NAME
# 입력 값 검증
if [[ -z "$INSTANCE_NAME" ]]; then
echo "오류: Cloud SQL 인스턴스 이름을 입력해야 합니다."
exit 1
fi
# 메트릭 및 리소스 필터 정의 (변수 사용)
METRIC_FILTER="metric.type=\"cloudsql.googleapis.com/database/disk/bytes_used\" AND resource.label.database_id=\"${PROJECT_ID}:${INSTANCE_NAME}\""
# API 요청을 위한 시간 범위 설정 (현재 시간 기준 최근 5분)
END_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ)
START_TIME=$(date -u -d '5 minutes ago' +%Y-%m-%dT%H:%M:%SZ) # GNU date 기준
# 필터 문자열 URL 인코딩
ENCODED_FILTER=$(python3 -c "import urllib.parse; print(urllib.parse.quote('''${METRIC_FILTER}'''))")
# Cloud Monitoring API 엔드포인트 URL 구성 (변수 사용)
API_URL="https://monitoring.googleapis.com/v3/projects/${PROJECT_ID}/timeSeries"
# API 요청 파라미터 구성
QUERY_PARAMS="filter=${ENCODED_FILTER}&interval.startTime=${START_TIME}&interval.endTime=${END_TIME}&aggregation.alignmentPeriod=300s&aggregation.perSeriesAligner=ALIGN_NEXT_OLDER"
echo "--------------------------------------------------"
echo "프로젝트 ID '${PROJECT_ID}'의 Cloud SQL 인스턴스 '${INSTANCE_NAME}' 디스크 사용량 조회 중..."
echo "시간 범위: ${START_TIME} 부터 ${END_TIME} 까지 (UTC)"
# echo "사용된 필터 (인코딩 전): ${METRIC_FILTER}" # 디버깅 필요시 주석 해제
# curl을 사용하여 Cloud Monitoring API 호출 및 jq로 결과 파싱
disk_usage_bytes=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" \
"${API_URL}?${QUERY_PARAMS}" | \
jq -r '.timeSeries[0].points[0].value.int64Value // "데이터 없음"')
# 결과 출력
if [[ "$disk_usage_bytes" != "데이터 없음" && ! -z "$disk_usage_bytes" ]]; then
# 바이트를 GB로 변환 (1024^3 기준)
disk_usage_gb=$(echo "$disk_usage_bytes" | awk '{printf "%.2f", $1 / (1024*1024*1024)}')
echo "현재 디스크 사용량 (Bytes): ${disk_usage_bytes}"
echo "현재 디스크 사용량 (GB) : ${disk_usage_gb} GB"
else
echo "오류: 디스크 사용량 데이터를 가져올 수 없습니다."
echo "이유 확인:"
echo "- 입력한 인스턴스 이름 '${INSTANCE_NAME}'이(가) 프로젝트 ID '${PROJECT_ID}'에 정확히 존재하는지 확인하세요."
echo "- 인스턴스가 최근에 시작되어 메트릭 데이터가 아직 없을 수 있습니다 (약 5분 이상 소요될 수 있음)."
echo "- API 응답 형식이 예상과 다르거나 권한 문제가 있을 수 있습니다."
fi
echo "--------------------------------------------------"
실행결과
프로젝트에 존재하는 모든 Cloud SQL의 실제 디스크 사용량 조회 Cloud SQL 에서 프로비저닝한 디스크 용량이 아닌 Cloud Monitoring 을 이용해 현시점의 디스크 용량 조회 방법 위의 스크립트는 프로젝트명과 Cloud SQL을 지정했지만, 아래 쉘스크립트는 입력한 GCP 프로젝트의 모든 Cloud SQL을 조회하여 디스크 사용량을 조회합니다.
#!/bin/bash
# 1. 사용자로부터 프로젝트 이름 입력 받기
read -p "정보를 조회할 GCP 프로젝트의 이름(표시 이름)을 입력하세요: " project_display_name
# 입력 값 검증
if [[ -z "$project_display_name" ]]; then
echo "오류: 프로젝트 이름을 입력해야 합니다."
exit 1
fi
# 2. 프로젝트 이름을 사용하여 프로젝트 ID 조회
echo "프로젝트 이름 '${project_display_name}'에 해당하는 프로젝트 ID를 조회합니다..."
project_id_output=$(gcloud projects list --filter="name='${project_display_name}'" --format="value(projectId)" 2>/dev/null)
gcloud_exit_status=$?
# gcloud 명령어 실행 자체에 오류가 있었는지 확인
if [[ $gcloud_exit_status -ne 0 ]]; then
echo "오류: 프로젝트 목록을 조회하는 중 오류가 발생했습니다. gcloud 설정 또는 권한을 확인하세요."
exit 1
fi
# 조회된 프로젝트 ID 개수 확인
project_id_count=$(echo "$project_id_output" | grep -c .)
if [[ $project_id_count -eq 0 ]]; then
echo "오류: 프로젝트 이름 '${project_display_name}'에 해당하는 활성 프로젝트 ID를 찾을 수 없습니다."
exit 1
elif [[ $project_id_count -gt 1 ]]; then
echo "오류: 프로젝트 이름 '${project_display_name}'에 해당하는 프로젝트가 두 개 이상 발견되었습니다."
echo "더 정확한 프로젝트 이름을 사용하거나 프로젝트 ID를 직접 스크립트에 지정하세요."
echo "발견된 ID 목록:"
echo "$project_id_output"
exit 1
else
PROJECT_ID="$project_id_output"
echo "프로젝트 ID '${PROJECT_ID}'를 확인했습니다."
fi
echo "--------------------------------------------------"
echo "프로젝트 ID '${PROJECT_ID}'의 모든 Cloud SQL 인스턴스 디스크 사용량 조회 시작..."
echo "--------------------------------------------------"
# API 요청을 위한 시간 범위 설정 (루프 밖에서 한 번만 설정)
END_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ)
START_TIME=$(date -u -d '5 minutes ago' +%Y-%m-%dT%H:%M:%SZ) # GNU date 기준
# Cloud Monitoring API 엔드포인트 URL 구성 (루프 밖에서 한 번만 설정)
API_URL="https://monitoring.googleapis.com/v3/projects/${PROJECT_ID}/timeSeries"
# 3. 프로젝트 내 모든 Cloud SQL 인스턴스 이름 목록 가져오기 및 반복 처리
# gcloud sql instances list 명령어 실행 결과를 파이프로 while 루프에 전달
# --format='value(name)' : 각 인스턴스의 이름만 추출
gcloud sql instances list --project="${PROJECT_ID}" --format='value(name)' | while IFS= read -r INSTANCE_NAME; do
# 읽어온 라인이 비어있으면 건너뛰기 (혹시 모를 빈 줄 처리)
if [[ -z "$INSTANCE_NAME" ]]; then
continue
fi
echo ">>> 인스턴스: ${INSTANCE_NAME}"
# --- 루프 내에서 각 인스턴스에 대한 처리 시작 ---
# 메트릭 및 리소스 필터 정의 (현재 인스턴스 이름 사용)
METRIC_FILTER="metric.type=\"cloudsql.googleapis.com/database/disk/bytes_used\" AND resource.label.database_id=\"${PROJECT_ID}:${INSTANCE_NAME}\""
# 필터 문자열 URL 인코딩
ENCODED_FILTER=$(python3 -c "import urllib.parse; print(urllib.parse.quote('''${METRIC_FILTER}'''))")
# API 요청 파라미터 구성
QUERY_PARAMS="filter=${ENCODED_FILTER}&interval.startTime=${START_TIME}&interval.endTime=${END_TIME}&aggregation.alignmentPeriod=300s&aggregation.perSeriesAligner=ALIGN_NEXT_OLDER"
# echo " 조회 필터 (인코딩 전): ${METRIC_FILTER}" # 디버깅 필요시 주석 해제
echo " 조회 시간 범위 (UTC): ${START_TIME} ~ ${END_TIME}"
echo " 데이터 조회 중..."
# curl을 사용하여 Cloud Monitoring API 호출 및 jq로 결과 파싱
disk_usage_bytes=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" \
"${API_URL}?${QUERY_PARAMS}" | \
jq -r '.timeSeries[0].points[0].value.int64Value // "데이터 없음"')
# 결과 출력 (현재 인스턴스에 대한)
if [[ "$disk_usage_bytes" != "데이터 없음" && ! -z "$disk_usage_bytes" ]]; then
# 바이트를 GB로 변환 (1024^3 기준)
disk_usage_gb=$(echo "$disk_usage_bytes" | awk '{printf "%.2f", $1 / (1024*1024*1024)}')
echo " 현재 디스크 사용량 (Bytes): ${disk_usage_bytes}"
echo " 현재 디스크 사용량 (GB) : ${disk_usage_gb} GB"
else
echo " 오류: '${INSTANCE_NAME}'의 디스크 사용량 데이터를 가져올 수 없습니다."
echo " (메트릭 데이터 지연 또는 인스턴스 상태 확인 필요)"
fi
echo # 인스턴스 간 구분을 위한 빈 줄 추가
# --- 루프 내에서 각 인스턴스에 대한 처리 종료 ---
done # while 루프 종료
echo "--------------------------------------------------"
echo "모든 인스턴스 조회가 완료되었습니다."
echo "--------------------------------------------------"
실행결과
정리 지금까지 GCP 웹 콘솔(GUI) 환경에서 확인하기 번거로웠던 Cloud SQL의 다양한 현황 정보들을 gcloud CLI와 쉘 스크립트를 활용하여 효율적으로 파악하는 방법들을 살펴보았습니다. Cloud Asset Inventory를 통한 조직 단위의 빠른 목록 조회부터, gcloud sql 명령어의 강력한 필터링 및 포맷팅 기능을 활용한 상세 정보 확인, 그리고 쉘 스크립트를 이용한 HA 구성 및 실제 디스크 사용량 등의 자동 점검까지, 터미널 환경에서의 Cloud SQL 관리 방법을 확인하였습니다.
이 글에서 소개된 방법들이 Cloud SQL 운영 효율성을 높이고, 반복적인 확인 작업에 소요되는 시간을 절약하여 더 중요한 업무에 집중하는 데 도움이 되기를 바랍니다.