GCP Compute Engine(GCE)는 VM의 현 상태를 저장 후 복원할 수 있는 스냅샷(snapshot)기능을 제공합니다.
스냅샷은 영구 디스크의 백업입니다.
스냅샷의 주요 용도는
운영 중인 VM을 특정 스냅샷 시점으로 복구할 수 있습니다.
스냅샷을 사용하여 신규 디스크를 만들고, 이를 바탕으로 새로운 VM(GCE) 인스턴스를 생성할 수 있습니다.
데이터 복구, 데이터 전송, 또는 프로젝트의 다른 리소스에서 데이터에 접근하는 데 사용됩니다.
GCP에서는 GUI(콘솔)를 통해 클릭 몇 번으로 이 작업을 수행할 수 있습니다.
CLI(gcloud+shell script)로도 동일한 설정이 가능합니다.
특히 대량의 작업을 수행해야 할 경우, CLI 방식이 훨씬 유리합니다. 이 글에서는 두 가지 방식을 모두 상세히 다루겠습니다.
- GUI 진행
스냅샷부터 생성해보겠습니다.
Google Cloud Console에 접속하여 'Compute Engine' -> '스냅샷' 메뉴로 이동한 후, '스냅샷 만들기'를 클릭합니다.
이름설정, 소스는 “디스크" , 대상이 될 VM의 disk를 선택합니다.
해당 스냅샷으로 신규 디스크→ VM을 생성하기에 “표준스냅샷”으로 선택합니다.
스냅샷이 생성된 것을 확인합니다.
해당 스냅샷으로 VM을 생성해 보겠습니다.
GCP에서는 스냅샷을 이용해 VM을 생성하는 두 가지 주요 방안이 있습니다.
방법 1: 스냅샷에서 디스크를 먼저 만들고, VM 생성 시 해당 디스크를 연결.
방법 2: VM 생성 과정에서 부팅 디스크로 스냅샷을 직접 선택 (권장). 이 방법은 GCP가 자동으로 디스크 생성 및 연결을 처리해줍니다.
'Compute Engine' -> 'VM 인스턴스' -> '인스턴스 만들기'로 이동합니다.
'운영체제 및 스토리지' 에서 부팅 디스크 '변경'을 클릭합니다.
상단 탭에서 '스냅샷'을 선택합니다.
필요한 경우 디스크 유형, 크기 등을 조정한 후 나머지 VM 설정을 완료하고 인스턴스를 생성합니다. - CLI (gcloud+shell script) 방안
한두 대의 VM을 생성하는 경우 GUI가 직관적이지만, 다수의 VM을 빠르게 생성해야 하거나 반복적인 작업을 자동화해야 할 때 CLI 방식이 매우 효과적입니다.
이 문서에서 제공하는 쉘 스크립트는 대화형으로 진행되며, GCP 프로젝트 ID, 사용할 스냅샷, Zone 등의 정보를 입력받아 새 디스크를 생성하고, 해당 디스크를 사용하여 새 VM 인스턴스를 만듭니다.
네트워크, 태그, 지역 등 VM 생성 시 필요한 여러 설정값에 대해 기본값이 제안되며, Enter 키를 누르면 기본값이 사용되도록 하여 편의성을 높였습니다.
스크립트 실행 후, 생성된 VM에 바로 접속할 수 있는 gcloud compute ssh 명령어도 출력해줍니다.
스크립트 주요 입력 항목
1. GCP 프로젝트 ID: 기본 프로젝트 ID가 있다면 자동으로 제안됩니다.
2. 사용할 스냅샷 선택: 프로젝트 내 사용 가능한 스냅샷 목록이 최신 생성일 순으로 표시되며, 번호로 선택합니다
3. 리소스 Zone: 디스크와 인스턴스를 생성할 Zone을 입력합니다 (예: asia-northeast3-a).
4. 새 디스크 정보:
디스크 이름 (예: test-disk).
디스크 유형 (예: pd-standard, pd-ssd, pd-balanced).
디스크 크기 (비워두면 스냅샷 크기를 따름).
5. 새 인스턴스 정보:
인스턴스 이름 (예: restore-vm).
인스턴스 머신 유형 (예: e2-medium, e2-micro).
6. 네트워크 정보:
네트워크 이름 (예: default 또는 사용자 정의 네트워크 ix-dr-test-seoul).
서브넷 이름 (선택 사항, 예: seoul-prd).
7. 서비스 계정 및 액세스 범위 (선택 사항):
서비스 계정 이메일
액세스 범위 (기본값: https://www.googleapis.com/auth/cloud-platform )
8. 태그 및 레이블 (선택 사항):
인스턴스 태그 (쉼표로 구분, 예: http-server,allow-ssh).
인스턴스 레이블 (KEY=VALUE 형식, 쉼표로 구분, 예: env=dev,owner=user).
9. 부팅 디스크 자동 삭제: 인스턴스 삭제 시 부팅 디스크 자동 삭제 여부 (yes/no).
최종 확인 및 실행: 모든 입력 값을 지정한 후, 최종 설정값을 확인하고 진행 여부를 결정합니다.
스크립트 내부 주요 gcloud 명령어:
스냅샷 목록 조회: gcloud compute snapshots list 디스크 생성: gcloud compute disks create "[NEW_DISK_NAME]" --source-snapshot="[SOURCE_SNAPSHOT_NAME]" 인스턴스 생성: gcloud compute instances create "[INSTANCE_NAME]" --disk="name=[NEW_DISK_NAME],boot=yes,auto-delete=[AUTO_DELETE_DISK]"
- 모든 입력 값을 지정 후 최종 진행여부 확인
- 최종 진행 후 완료화면
- GUI에서 생성된 VM, Disk 확인

- shell script 내용
#!/bin/bash "==============================================================" echo "이 스크립트는 GCP 프로젝트, 스냅샷, Zone 등의 정보를 입력받아" echo "새 디스크를 생성하고, 해당 디스크를 사용하여 새 VM 인스턴스를 만듭니다." echo "기본값이 제안되는 경우, Enter 키를 누르면 기본값이 사용됩니다." echo " echo 2025.05 Choi SeongGi Create --------------------------------------------------------------" set -e # 오류 발생 시 스크립트 즉시 중단 echo "========================================================================" echo " 스냅샷 선택 후 디스크 생성 및 새 인스턴스 생성 (대화형)" echo "========================================================================" # (이하 스크립트 설명 동일) echo "------------------------------------------------------------------------" echo "" # --- 1. 프로젝트 ID 입력 --- DEFAULT_PROJECT_ID=$(gcloud config get-value project 2>/dev/null) if [[ -n "$DEFAULT_PROJECT_ID" ]]; then read -p "1. GCP 프로젝트 ID를 입력하세요 [${DEFAULT_PROJECT_ID}]: " PROJECT_ID PROJECT_ID="${PROJECT_ID:-$DEFAULT_PROJECT_ID}" else read -p "1. GCP 프로젝트 ID를 입력하세요: " PROJECT_ID if [[ -z "$PROJECT_ID" ]]; then echo "오류: 프로젝트 ID는 필수 입력 항목입니다." exit 1 fi fi PROJECT_FLAG="--project=${PROJECT_ID}" echo " > 프로젝트 ID: ${PROJECT_ID}" echo "" # --- 2. 사용 가능한 스냅샷 목록 표시 및 선택 --- echo "2. 프로젝트 '${PROJECT_ID}'에서 사용 가능한 스냅샷 목록을 가져오는 중..." SNAPSHOT_TEMP_FILE=$(mktemp) if ! gcloud compute snapshots list ${PROJECT_FLAG} \ --format="value(name,creationTimestamp.date('%Y-%m-%d %H:%M:%S %Z'),sourceDisk.basename(),diskSizeGb)" \ --sort-by "~creationTimestamp" > "${SNAPSHOT_TEMP_FILE}"; then echo " 오류: 스냅샷 목록을 가져오는 데 실패했습니다." rm -f "${SNAPSHOT_TEMP_FILE}" exit 1 fi declare -a SNAPSHOT_NAMES declare -a SNAPSHOT_DISPLAY_LINES line_num=0 while IFS=$'\t' read -r name timestamp sourcedisk size || [[ -n "$name" ]]; do if [[ -z "$name" ]]; then continue fi line_num=$((line_num + 1)) SNAPSHOT_NAMES+=("$name") SNAPSHOT_DISPLAY_LINES+=("$(printf "%-5s %-40s %-25s %-20s %-10s" "${line_num}." "$name" "$timestamp" "$sourcedisk" "$size")") done < "${SNAPSHOT_TEMP_FILE}" rm -f "${SNAPSHOT_TEMP_FILE}" if [ ${#SNAPSHOT_NAMES[@]} -eq 0 ]; then echo " 오류: 프로젝트 '${PROJECT_ID}'에서 사용 가능한 스냅샷을 찾을 수 없습니다." exit 1 fi echo "" echo "다음은 사용 가능한 스냅샷 목록입니다 (최신 생성일 순):" echo "-----------------------------------------------------------------------------------------------------" printf "%-5s %-40s %-25s %-20s %-10s\n" "번호" "스냅샷 이름" "생성일시" "소스 디스크" "크기(GB)" echo "-----------------------------------------------------------------------------------------------------" for display_line in "${SNAPSHOT_DISPLAY_LINES[@]}"; do echo "$display_line" done echo "-----------------------------------------------------------------------------------------------------" choice="" # 또는 그냥 다음 줄에서 바로 read -p 사용 while true; do read -p "사용할 스냅샷의 번호를 입력하세요: " choice if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le "${#SNAPSHOT_NAMES[@]}" ]; then SOURCE_SNAPSHOT_NAME="${SNAPSHOT_NAMES[$((choice-1))]}" break else echo "잘못된 선택입니다. 1과 ${#SNAPSHOT_NAMES[@]} 사이의 숫자를 입력해주세요." fi done echo " > 선택된 스냅샷: ${SOURCE_SNAPSHOT_NAME}" echo "" # --- 3. 리소스 Zone 입력 (디스크 및 인스턴스) --- DEFAULT_ZONE="asia-northeast3-a" read -p "3. 디스크와 인스턴스를 생성할 Zone을 입력하세요 (예: asia-northeast3-a) [${DEFAULT_ZONE}]: " RESOURCE_ZONE RESOURCE_ZONE="${RESOURCE_ZONE:-$DEFAULT_ZONE}" if [[ -z "$RESOURCE_ZONE" ]]; then echo "오류: Zone은 필수 입력 항목입니다." exit 1 fi echo " > 리소스 Zone: ${RESOURCE_ZONE}" echo "" # --- 4. 새 디스크 정보 입력 --- DEFAULT_DISK_NAME="disk-from-${SOURCE_SNAPSHOT_NAME,,}" read -p "4a. 새로 생성할 디스크의 이름을 입력하세요 [${DEFAULT_DISK_NAME}]: " NEW_DISK_NAME NEW_DISK_NAME="${NEW_DISK_NAME:-$DEFAULT_DISK_NAME}" DEFAULT_DISK_TYPE="pd-standard" read -p "4b. 디스크 유형을 입력하세요 (예: pd-standard, pd-ssd, pd-balanced) [${DEFAULT_DISK_TYPE}]: " DISK_TYPE DISK_TYPE="${DISK_TYPE:-$DEFAULT_DISK_TYPE}" read -p "4c. 디스크 크기를 지정하시겠습니까? (예: 50GB. 스냅샷 크기를 따르려면 비워두세요): " DISK_SIZE echo " > 새 디스크 이름: ${NEW_DISK_NAME}" echo " > 디스크 유형 : ${DISK_TYPE}" [[ -n "${DISK_SIZE}" ]] && echo " > 디스크 크기 : ${DISK_SIZE}" echo "" # --- 5. 새 인스턴스 정보 입력 --- DEFAULT_INSTANCE_NAME="instance-from-${SOURCE_SNAPSHOT_NAME,,}" read -p "5a. 새로 생성할 인스턴스의 이름을 입력하세요 [${DEFAULT_INSTANCE_NAME}]: " INSTANCE_NAME INSTANCE_NAME="${INSTANCE_NAME:-$DEFAULT_INSTANCE_NAME}" DEFAULT_MACHINE_TYPE="e2-medium" read -p "5b. 인스턴스 머신 유형을 입력하세요 (예: e2-medium, n1-standard-1) [${DEFAULT_MACHINE_TYPE}]: " MACHINE_TYPE MACHINE_TYPE="${MACHINE_TYPE:-$DEFAULT_MACHINE_TYPE}" echo " > 새 인스턴스 이름: ${INSTANCE_NAME}" echo " > 머신 유형 : ${MACHINE_TYPE}" echo "" # --- 6. 네트워크 정보 입력 --- DEFAULT_NETWORK_NAME="default" read -p "6a. 사용할 네트워크 이름을 입력하세요 [${DEFAULT_NETWORK_NAME}]: " NETWORK_NAME NETWORK_NAME="${NETWORK_NAME:-$DEFAULT_NETWORK_NAME}" read -p "6b. 특정 서브넷을 사용하려면 서브넷 이름을 입력하세요 (기본값 사용 시 비워둠): " SUBNET_NAME echo " > 네트워크 이름: ${NETWORK_NAME}" [[ -n "${SUBNET_NAME}" ]] && echo " > 서브넷 이름 : ${SUBNET_NAME}" echo "" # --- 7. (선택) 서비스 계정 및 액세스 범위 --- read -p "7a. 특정 서비스 계정을 사용하려면 이메일을 입력하세요 (기본값 사용 시 비워둠): " SERVICE_ACCOUNT_EMAIL DEFAULT_SCOPES="https://www.googleapis.com/auth/cloud-platform" read -p "7b. 인스턴스 액세스 범위를 입력하세요 (예: compute-rw,storage-ro 또는 전체) [${DEFAULT_SCOPES}]: " SCOPES SCOPES="${SCOPES:-$DEFAULT_SCOPES}" [[ -n "${SERVICE_ACCOUNT_EMAIL}" ]] && echo " > 서비스 계정: ${SERVICE_ACCOUNT_EMAIL}" echo " > 액세스 범위: ${SCOPES}" echo "" # --- 8. (선택) 태그 및 레이블 --- read -p "8a. 인스턴스에 적용할 태그를 쉼표로 구분하여 입력하세요 (예: http-server,allow-ssh): " INSTANCE_TAGS read -p "8b. 인스턴스에 적용할 레이블을 KEY=VALUE 형식으로 쉼표로 구분하여 입력하세요 (예: env=dev,owner=user): " INSTANCE_LABELS [[ -n "${INSTANCE_TAGS}" ]] && echo " > 태그 : ${INSTANCE_TAGS}" [[ -n "${INSTANCE_LABELS}" ]] && echo " > 레이블 : ${INSTANCE_LABELS}" echo "" # --- 9. (선택) 부팅 후 자동 삭제 여부 --- read -p "9. 인스턴스 삭제 시 부팅 디스크를 자동으로 함께 삭제하시겠습니까? (yes/no) [yes]: " AUTO_DELETE_DISK AUTO_DELETE_DISK="${AUTO_DELETE_DISK:-yes}" echo " > 부팅 디스크 자동 삭제: ${AUTO_DELETE_DISK}" echo "" # --- 입력값 확인 --- # (이하 동일) echo "------------------------------------------------------------------------" echo "입력된 설정값으로 다음 작업을 진행합니다:" echo " 1. 프로젝트 ID : ${PROJECT_ID}" echo " 2. 선택된 스냅샷 : ${SOURCE_SNAPSHOT_NAME}" echo " 3. 리소스 Zone : ${RESOURCE_ZONE}" echo " 4. 새 디스크 이름 : ${NEW_DISK_NAME}" echo " 디스크 유형 : ${DISK_TYPE}" [[ -n "${DISK_SIZE}" ]] && echo " 디스크 크기 : ${DISK_SIZE}" echo " 5. 새 인스턴스 이름 : ${INSTANCE_NAME}" echo " 머신 유형 : ${MACHINE_TYPE}" echo " 6. 네트워크 : ${NETWORK_NAME}" [[ -n "${SUBNET_NAME}" ]] && echo " 서브넷 : ${SUBNET_NAME}" [[ -n "${SERVICE_ACCOUNT_EMAIL}" ]] && echo " 7. 서비스 계정 : ${SERVICE_ACCOUNT_EMAIL}" echo " 액세스 범위 : ${SCOPES}" [[ -n "${INSTANCE_TAGS}" ]] && echo " 8. 태그 : ${INSTANCE_TAGS}" [[ -n "${INSTANCE_LABELS}" ]] && echo " 레이블 : ${INSTANCE_LABELS}" echo " 9. 부팅 디스크 자동 삭제: ${AUTO_DELETE_DISK}" echo "------------------------------------------------------------------------" read -p "위 설정으로 진행하시겠습니까? (yes/no): " CONFIRM if [[ "${CONFIRM,,}" != "yes" ]]; then echo "작업이 취소되었습니다." exit 0 fi echo "" # --- 작업 실행 --- # (이하 동일) echo "작업 1: 스냅샷 '${SOURCE_SNAPSHOT_NAME}'으로부터 새 디스크 '${NEW_DISK_NAME}'을(를) 생성합니다..." DISK_CREATE_CMD="gcloud compute disks create \"${NEW_DISK_NAME}\" \ --source-snapshot=\"${SOURCE_SNAPSHOT_NAME}\" \ --zone=\"${RESOURCE_ZONE}\" \ --type=\"${DISK_TYPE}\" \ ${PROJECT_FLAG}" if [[ -n "${DISK_SIZE}" ]]; then DISK_CREATE_CMD="${DISK_CREATE_CMD} --size=\"${DISK_SIZE}\"" fi if eval "${DISK_CREATE_CMD}"; then echo " 성공: 디스크 '${NEW_DISK_NAME}'이(가) 성공적으로 생성되었습니다." else echo " 오류: 디스크 '${NEW_DISK_NAME}' 생성에 실패했습니다." exit 1 fi echo "" echo "작업 2: 생성된 디스크 '${NEW_DISK_NAME}'을(를) 사용하여 새 인스턴스 '${INSTANCE_NAME}'을(를) 생성합니다..." INSTANCE_CREATE_CMD="gcloud compute instances create \"${INSTANCE_NAME}\" \ --zone=\"${RESOURCE_ZONE}\" \ --machine-type=\"${MACHINE_TYPE}\" \ --disk=\"name=${NEW_DISK_NAME},boot=yes,auto-delete=${AUTO_DELETE_DISK}\" \ --network=\"${NETWORK_NAME}\" \ ${PROJECT_FLAG}" if [[ -n "${SUBNET_NAME}" ]]; then INSTANCE_CREATE_CMD="${INSTANCE_CREATE_CMD} --subnet=\"${SUBNET_NAME}\"" fi if [[ -n "${SERVICE_ACCOUNT_EMAIL}" ]]; then INSTANCE_CREATE_CMD="${INSTANCE_CREATE_CMD} --service-account=\"${SERVICE_ACCOUNT_EMAIL}\"" fi if [[ -n "${SCOPES}" ]]; then INSTANCE_CREATE_CMD="${INSTANCE_CREATE_CMD} --scopes=\"${SCOPES}\"" fi if [[ -n "${INSTANCE_TAGS}" ]]; then INSTANCE_CREATE_CMD="${INSTANCE_CREATE_CMD} --tags=\"${INSTANCE_TAGS}\"" fi if [[ -n "${INSTANCE_LABELS}" ]]; then INSTANCE_CREATE_CMD="${INSTANCE_CREATE_CMD} --labels=\"${INSTANCE_LABELS}\"" fi if eval "${INSTANCE_CREATE_CMD}"; then echo " 성공: 인스턴스 '${INSTANCE_NAME}'이(가) 성공적으로 생성되었습니다." else echo " 오류: 인스턴스 '${INSTANCE_NAME}' 생성에 실패했습니다." exit 1 fi echo "" echo "========================================================================" echo "완료: 모든 작업이 성공적으로 완료되었습니다." echo "========================================================================" echo " 생성된 디스크: ${NEW_DISK_NAME} (Zone: ${RESOURCE_ZONE})" echo " 생성된 인스턴스: ${INSTANCE_NAME} (Zone: ${RESOURCE_ZONE})" echo " 인스턴스 접속: gcloud compute ssh \"${INSTANCE_NAME}\" --zone \"${RESOURCE_ZONE}\" ${PROJECT_FLAG}" echo ""
'Cloud > GCP' 카테고리의 다른 글
[GCP] Cloud SQL Backup을 Cloud Run(Function), Cloud Scheduler을 통해 정기적으로 백업 받기 (0) | 2025.05.25 |
---|---|
[GCP] Cloud SQL 백업을 타프로젝트 및 다른 인스턴스로 복원하기 (gcloud+shell script) (0) | 2025.05.21 |
[GCP] Secret Manager Key 자동 삭제 스크립트 (0) | 2025.05.13 |
[GCP] Cloud SQL 사용 현황, GUI보다 빠르고 정확하게 파악하기 (gcloud & Shell Script 활용) (0) | 2025.05.03 |
[GCP] 전체 프로젝트의 Cloud storage 사용량 조회 (0) | 2025.04.22 |
[GCP] VM기준으로 방화벽 내용을 조회 하는 스크립트 (0) | 2025.04.19 |
[GCP] Asset Inventory로 내부 자산인 GCE(VM) 확인하기 (0) | 2025.04.09 |