데이터 내보내기 예약

이 페이지에서는 Cloud Firestore 데이터의 내보내기를 예약하는 방법에 대해 설명합니다. 일정에 따라 내보내기를 실행하려면 Cloud Firestore 관리형 내보내기 서비스 기능을 호출하는 App Engine 서비스를 배포하는 것이 좋습니다. 일단 배포되면 App Engine 크론 서비스를 사용해 이 서비스에 호출을 예약할 수 있습니다.

시작하기 전에

내보내기 관리 기능으로 데이터 내보내기를 예약하기 전에 다음 작업을 완료해야 합니다.

  1. Google Cloud Platform 프로젝트에 결제를 사용 설정합니다. 결제가 사용 설정된 GCP 프로젝트만 내보내기 및 가져오기 기능을 사용할 수 있습니다.
  2. Cloud Firestore 데이터베이스 위치와 가까운 위치에 프로젝트에 사용할 Cloud Storage 버킷을 생성합니다. 내보내기/가져오기 작업에는 요청자 지불 버킷을 사용할 수 없습니다.
  3. Google Cloud SDK를 설치해 액세스 권한을 부여하고 애플리케이션을 배포합니다.

액세스 권한 설정하기

이 앱은 App Engine 기본 서비스 계정을 사용해 내보내기 작업을 인증하고 승인합니다. 프로젝트를 만들면 다음과 같은 형식의 기본 서비스 계정이 생성됩니다.

YOUR_PROJECT_ID@appspot.gserviceaccount.com

서비스 계정에서 내보내기 작업을 시작하고 Cloud Storage 버킷에 작성하려면 권한이 필요합니다. 이러한 권한을 부여하려면 다음 IAM 역할을 기본 서비스 계정에 할당합니다.

  • Cloud Datastore Import Export Admin
  • 버킷에 대한 Owner 또는 Storage Admin 역할

Google Cloud SDK에서 gcloudgsutil 명령줄 도구를 사용하면 역할을 할당할 수 있습니다.

  1. Cloud Datastore Import Export Admin 역할을 할당합니다.

    gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \
        --member serviceAccount:YOUR_PROJECT_ID@appspot.gserviceaccount.com \
        --role roles/datastore.importExportAdmin
    
  2. 버킷에 대한 Storage Admin 역할을 할당합니다.

    gsutil iam ch serviceAccount:YOUR_PROJECT_ID@appspot.gserviceaccount.com:storage.admin \
        gs://BUCKET_NAME
    

애플리케이션 파일

새 폴더에서 아래 코드를 사용해 다음 애플리케이션 파일을 만듭니다.

app.yaml
App Engine 런타임을 구성합니다. 이 앱은 표준 환경 Node.js 런타임을 사용합니다.
app.js
기본 앱 코드입니다. 이 앱은 내보내기 작업을 시작하는 https://YOUR_PROJECT_ID.appspot.com에 웹 서비스를 설정합니다.
package.json
앱 및 종속 항목에 대한 정보를 포함합니다.
cron.yaml
웹 서비스를 호출하는 크론 작업을 구성합니다.

app.yaml

runtime: nodejs8

위 코드에서는 이 앱이 기본 애플리케이션이라고 가정합니다. 기본 애플리케이션이 아니라면 다음 행을 추가합니다.

target: cloud-firestore-admin

app.js

const axios = require('axios');
const dateformat = require('dateformat');
const express = require('express');
const { google } = require('googleapis');

const app = express();

// Trigger a backup
app.get('/cloud-firestore-export', async (req, res) => {
  const auth = await google.auth.getClient({
    scopes: ['https://www.googleapis.com/auth/datastore']
  });

  const accessTokenResponse = await auth.getAccessToken();
  const accessToken = accessTokenResponse.token;

  const headers = {
    'Content-Type': 'application/json',
    Authorization: 'Bearer ' + accessToken
  };

  const outputUriPrefix = req.param('outputUriPrefix');
  if (!(outputUriPrefix && outputUriPrefix.indexOf('gs://') == 0)) {
    res.status(500).send(`Malformed outputUriPrefix: ${outputUriPrefix}`);
  }

  // Construct a backup path folder based on the timestamp
  const timestamp = dateformat(Date.now(), 'yyyy-mm-dd-HH-MM-ss');
  let path = outputUriPrefix;
  if (path.endsWith('/')) {
    path += timestamp;
  } else {
    path += '/' + timestamp;
  }

  const body = {
    outputUriPrefix: path
  };

  // If specified, mark specific collections for backup
  const collectionParam = req.param('collections');
  if (collectionParam) {
    body.collectionIds = collectionParam.split(',');
  }

  const projectId = process.env.GOOGLE_CLOUD_PROJECT;
  const url = `https://firestore.googleapis.com/v1beta1/projects/${projectId}/databases/(default):exportDocuments`;

  try {
    const response = await axios.post(url, body, { headers: headers });
    res
      .status(200)
      .send(response.data)
      .end();
  } catch (e) {
    if (e.response) {
      console.warn(e.response.data);
    }

    res
      .status(500)
      .send('Could not start backup: ' + e)
      .end();
  }
});

// Index page, just to make it easy to see if the app is working.
app.get('/', (req, res) => {
  res
    .status(200)
    .send('[scheduled-backups]: Hello, world!')
    .end();
});

// Start the server
const PORT = process.env.PORT || 6060;
app.listen(PORT, () => {
  console.log(`App listening on port ${PORT}`);
  console.log('Press Ctrl+C to quit.');
});

package.json

{
  "name": "solution-scheduled-backups",
  "version": "1.0.0",
  "description": "Scheduled Cloud Firestore backups via AppEngine cron",
  "main": "app.js",
  "engines": {
    "node": "8.x.x"
  },
  "scripts": {
    "deploy": "gcloud app deploy --quiet app.yaml cron.yaml",
    "start": "node app.js"
  },
  "author": "Google, Inc.",
  "license": "Apache-2.0",
  "dependencies": {
    "axios": "^0.18.0",
    "dateformat": "^3.0.3",
    "express": "^4.16.4",
    "googleapis": "^34.0.0"
  },
  "devDependencies": {
    "prettier": "^1.14.3"
  }
}

cron.yaml

cron:
- description: "Daily Cloud Firestore Export"
  url: /cloud-firestore-export?outputUriPrefix=gs://BUCKET_NAME[/PATH]&collections=test1,test2
  target: cloud-firestore-admin
  schedule: every 24 hours

url 행을 수정해 내보내기 작업을 구성합니다. 앱이 다음 URL 매개변수를 허용하는 https://YOUR_PROJECT_ID.appspot.com/cloud-firestore-export에 서비스를 설정합니다.

outputUriPrefix
Cloud Storage 버킷의 위치이며 gs://BUCKET_NAME 형식으로 표시됩니다.
collections
내보낼 컬렉션 ID를 쉼표로 구분한 목록입니다. 지정하지 않으면 작업에서 모든 컬렉션을 내보냅니다.

예를 들어 컬렉션 ID가 Songs 또는 Albums인 모든 컬렉션을 내보내려면 다음과 같은 명령어를 사용합니다.

url: /cloud-firestore-export?outputUriPrefix=gs://BUCKET_NAME&collections=Songs,Albums

예제 cron.yaml은 내보내기를 24시간마다 실행합니다. 일정 옵션을 다르게 지정하려면 일정 형식을 참조하세요.

앱 및 크론 작업 배포

gcloud를 사용해 앱과 크론 작업을 배포합니다.

gcloud app deploy app.yaml cron.yaml

크론 작업 테스트

Google Cloud Platform Console의 크론 작업 페이지에서 배포된 크론 작업 테스트를 시작할 수 있습니다.

  1. GCP Console에서 크론 작업 페이지를 엽니다.
    크론 작업 페이지 열기

  2. 매일 Cloud Firestore 내보내기 설명이 포함된 크론 작업의 경우 지금 실행을 클릭합니다.

  3. 작업이 완료되면 상태에 상태 메시지가 표시됩니다. 보기를 클릭하여 작업 로그를 살펴보세요. 상태 메시지 및 작업 로그는 작업의 성공 또는 실패에 대한 정보를 제공합니다.

내보내기 보기

내보내기 작업이 완료된 후에는 Cloud Storage 버킷에서 내보내기를 볼 수 있습니다.

GCP Console에서 Cloud Storage 브라우저를 엽니다.
Cloud Storage 브라우저 열기

다음에 대한 의견 보내기...

도움이 필요하시나요? 지원 페이지를 방문하세요.