본문 바로가기
MegazoneCloud
← 전체 글
GCP

Cloud SQL Backup을 Cloud Run(Function), Cloud Scheduler을 통해 정기적으로 백업 받기

목표 : Cloud SQL은 GCP에서 제공하는 관리형 DBMS로 DB만 잘 쓰고 관리는 GCP가 해주는 부분입니다..
백업도 알아서 시간대만 지정해 주면, 하루에 한번 해당 시간대에 백업을 해줍니다.
그외에는 사용자가 GUI(Console)에서 수동으로 실행하거나, gcloud 명령어를 통해 수동백업을 받을 수 있습니다.

하지만 운영에는 여러사정이 있고, 예를들어 6시간 간격으로 백업이 필요한 경우가 있습니다.

파이썬 코드+Cloud Run(Function)+Cloud Scheduler 을 통해 일회성 백업과 지정된 시간에 백업을 하는 방안에 대해 작성하였습니다.
필요권한 : 
Cloud SQL 백업을 트리거하려면 최소 cloudsql.backupRuns.create 권한이 필요합니다.
일반적으로 Cloud SQL Admin(roles/cloudsql.admin) 역할에 포함되어 있으며, 커스텀 역할로 최소 권한만 부여할 수도 있습니다.
https://cloud.google.com/sql/docs/mysql/iam-roles?hl=ko

1. Cloud Run (기존 Cloud Function) 에서 함수 작성을 선택합니다.

본 문서 최하단에 있는 코드를 Cloud Run main.py 소스코드에 입력합니다. 함수 진입점은 “backup\_sql\_instance” 으로 설정하며

필요한 라이브러리를 작성하는 “requirements.txt”에는 아래의 라이브러리를 입력합니다.
google-api-python-client: Google API 호출을 위한 클라이언트 라이브러리
google-auth: Google 인증을 위한 공식 라이브러리

2. 코드에 직접 프로젝트, CloudSQL명을 넣지 않고 환경변수로 실행하기에 아래의 방법으로 진행합니다.

변수 및 보안 비밀에서 환경 변수 탭 이동 변수 2개를 설정합니다.
“PROJECT\_ID” 백업할 Cloud SQL 이 있는 Project ID
“INSTANCE\_ID” 백업할 Cloud SQL 인스턴스 이름

3. 모든 설정이 완료 된 후 상단 URL을 확인합니다.

해당 URL을 웹에서 실행해보면 아래와 같이 Backup successfully 메시지를 확인할 수 있습니다.
다만 본문서에서는 Cloud Run(Function)을 통해 진행하는 방안에 대해 중점을 두고 작성하였습니다.
해당 함수 실행시 보안 부분( “서비스 계정 권한 최소화”, “HTTP 엔드포인트 인증” )에 대해서는 차 후 다른 문서에 작성하도록 하겠습니다.)

Cloud Run(Function)작업은 마무리 되었으므로, 지정된 시간에 실행될 수 있도록 Cloud Scheduler설정을 진행해보겠습니다.

실행할 리전을 지정하고, 빈도를 설정합니다.
Unix, Linux의 Crontab과 동일합니다.
분 시 일 월 요일

필드의미값의 범위
Minute0-59
Hour0-23
Day of month1-31
Month1-12
요일Day of week0-7 (0과 7은 일요일)


예시로는 아래와 같습니다. 0 2 \* \* \* → 매일 새벽 2시 0분에 실행

15 14 \* \* 1 → 매주 월요일 오후 2시 15분에 실행

0 \/6 \ \* \* → 매 6시간마다(0시, 6시, 12시, 18시) 실행

0 9 \* \* 1-5 → 매주 월~금 오전 9시에 실행

본 문서에서는 25분마다 실행하기로 했기에 25 \* \* \* \* 으로 설정하였습니다.

실행 구성부분은 다음과 같이 설정합니다.
대상 유형 : HTTP
URL : Cloud Run(Function)에서 생성된 URL
HTTP 메소드 : POST

그외는 빈란으로 진행되어도 무방합니다.

모든 설정이 완료되면 내용을 확인하고 강제 실행으로 성공 되는지 확인합니다.

최종적으로 Cloud Scheduler로 인해 25분마다 실행되며
위와 같이 해당 Cloud SQL 백업이 정상적으로 완료됨을 알 수 있습니다.

Cloud SQL Backup Python코드

import os
import googleapiclient.discovery
from google.auth import compute_engine

def backup_sql_instance(request):
    PROJECT_ID = os.environ.get("PROJECT_ID")
    INSTANCE_ID = os.environ.get("INSTANCE_ID")

    if not PROJECT_ID:
        print("Error: Environment variable 'PROJECT_ID' is not set or is empty.")
        return "Configuration error: PROJECT_ID not set.", 500

    if not INSTANCE_ID:
        print("Error: Environment variable 'INSTANCE_ID' is not set or is empty.")
        return "Configuration error: INSTANCE_ID not set.", 500

    try:
        credentials = compute_engine.Credentials()
        sql_admin_service = googleapiclient.discovery.build(
            "sqladmin", "v1beta4", credentials=credentials, cache_discovery=False
        )

        backup_request_body = {
            "description": f"Automated backup for {INSTANCE_ID} triggered by HTTP call."
        }
        
        api_request = sql_admin_service.backupRuns().insert( # 
            project=PROJECT_ID,
            instance=INSTANCE_ID,
            body=backup_request_body
        )
        response = api_request.execute()

        print(f"Backup operation successfully initiated for instance {INSTANCE_ID}. Operation details: {response}")
        return f"Backup initiated successfully for {INSTANCE_ID}.", 200

    except googleapiclient.errors.HttpError as e:
        error_message = f"Google API HTTP Error triggering backup for instance {INSTANCE_ID}: {e}"
        print(error_message)
        # Google API를 호출할 때(예: 인증 문제, 권한 문제, 요청 형식 오류 등) 발생하는 HTTP 에러
        return error_message, 500
    except AttributeError as e: 
        error_message = f"AttributeError (likely an issue with API client usage) for instance {INSTANCE_ID}: {e}"
        print(error_message)
        # API 클라이언트 객체를 잘못 사용했거나, 없는 속성/메서드를 호출했을 때 발생
        return error_message, 500
    except Exception as e:
        error_message = f"An unexpected error occurred while triggering backup for instance {INSTANCE_ID}: {e}"
        print(error_message)
        # 위에서 처리하지 못한 모든 일반적인 예외
        return error_message, 500

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다