📝

Cloud Functions + Cloud Scheduler で Cloud SQL のデータを定期削除する

Kinugasa2022/11/08に公開

はじめに

GCP の Cloud SQL にはストレージの自動増量機能があるため、ストレージ不足を気にしなくて良いのがとても便利です。一方で、一旦ストレージが増量されると減らすことができないので、コストが気になります。そこで、古いデータを自動で定期削除する方法を試してみたので、共有したいと思います。

構成


今回は以下のような仕組みで、データの定期削除を行います。

  • Cloud SQL のインスタンスに対してクエリを実行する関数を Cloud Functions に作成する
  • ソースコードを GitHub のリポジトリから取得して Cloud Functions にデプロイするように Cloud Build を構成し、関数を作成・更新する
  • 定期的に関数を実行するように Cloud Scheduler を設定する

設定ファイル等のディレクトリ構成は以下のようにしました。Cloud Build のトリガー作成と Cloud Scheduler のジョブ作成については、Terraform でコード化する方法も併せて紹介します。

.
├── cloudBuild
│   └── cloudbuild.yaml
├── cloudFunctions
│   └── mysql
│       ├── mysql_execute_query.js
│       ├── mysql_tbl_delete.sql
│       └── package.json
└── infra
    ├── cloud_build.tf
    ├── cloud_scheduler.tf
    ├── cloud_sql.tf
    ├── main.tf
    └── variables.tf

Cloud Functions で実行する処理を作成する

まずは、Cloud Functions で実行する処理を作成します。利用できる言語は、Node.js、Python、Go、Java、.NET、Ruby、PHPから選べますが、今回は Node.js 16 で書きました。クエリが書かれているSQLファイルを読み込んだ後、Cloud SQLインスタンスに接続し、クエリを実行するという流れになっています。

mysql_execute_query.js
const mysql = require('mysql');

exports.executeQuery = (req, res) => {
  const connection = mysql.createConnection({
    socketPath: "/cloudsql/" + process.env.connectionName, // SQLインスタンス接続名
    user: process.env.dbUser, // ログインユーザ名
    password: process.env.dbPassword, // ログインパスワード
    database: process.env.dbName, // データベース名
    multipleStatements: true // 複数クエリの実行を許可する
  });

  // SQL文の読み込み
  const fs = require('fs');
  let sql = fs.readFileSync(process.env.sqlFileName, 'utf-8');

  // Cloud SQLに接続
  connection.connect();
  
  // クエリ実行
  connection.query(sql, (err, results) => {
    if (err) {
      console.error(err);
      res.status(500).send(err);
    } else {
      console.log(JSON.stringify(results))
      res.send(JSON.stringify(results));
    }
  });
  
  // 接続終了
  connection.end();
};
package.json
{
  "version": "0.0.3",
  "dependencies": {
    "mysql": "latest"
  }
}
mysql_tbl_delete.sql
# テーブルから3ヶ月より前のデータを削除する
DELETE FROM TEST_TABLE WHERE DELI_DTE < (CURRENT_DATE() - INTERVAL 3 MONTH);

Cloud Build 構成ファイルを作成する

ソースコードを作成したら、次にビルド構成ファイルを作成します。公式ドキュメントに分かりやすい解説がのっていますので、参考にして書いていきます。

構成ファイルには、関数名やソースコードに関する情報、環境変数、何をトリガーにするかなどを設定します。今回は Cloud Scheduler で関数を実行させるため、HTTPトリガーを選択しています。

cloudbuild.yaml
steps:
  - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
    args:
      - gcloud
      - functions
      - deploy
      - mysql-tbl-delete
      - --region=<region>
      # HTTPトリガー
      - --trigger-http
      # 関数のソースコードのパス
      - --source=./cloudFunctions/mysql
      # 関数で使用される言語ランタイム
      - --runtime=nodejs16
      # エントリーポイント
      - --entry-point=executeQuery
      # 環境変数
      - '--set-env-vars'
      - connectionName=<projectID>:<region>:<sqlInstanceName>
      - '--set-env-vars'
      - dbUser=testuser
      - '--set-env-vars'
      - dbName=testdb
      - '--set-env-vars'
      - sqlFileName=mysql_tbl_delete.sql
      # Secret Manager から取得する環境変数
      - 'set-secrets'
      - 'dbPassword=testdb_password:1'

Terraform 設定ファイルを作成する

関数のソースコードとビルド構成ファイルが準備できたので、次に、Cloud Build と Cloud Scheduler の設定ファイルを作成します。

Cloud Build のトリガー作成

Terraform の公式ドキュメントを参考に作成します。

権限の設定では、Cloud Build から Cloud Functions にデプロイすることを許可するため、Cloud Functions 開発者のロールを有効化します。トリガー設定では、ビルド構成ファイルを指定したり、トリガーイベントを設定します。以下では、「GitHubの指定リポジトリの指定ブランチにpushする」をトリガーイベントにしていますが、プルリクエストをトリガーにしたり、自動でデプロイされると困る場合は、手動呼び出しに設定することも可能です。

cloud_build.tf
// 権限の設定
resource "google_project_iam_member" "cloudbuild_iam" {
  project = var.project
  for_each = toset([
    "roles/cloudfunctions.developer",
    "roles/iam.serviceAccountUser"
  ])
  role    = each.key
  member  = "serviceAccount:${var.project}@cloudbuild.gserviceaccount.com"
}

// トリガー(MySQLの定期削除)
resource "google_cloudbuild_trigger" "mysql-tbl-delete" {
  location = var.region
  name     = "mysql-tbl-delete"

  // Cloud Build構成ファイル
  filename = "cloudBuild/cloudbuild.yaml"

  // トリガーイベント
  github {
    owner = "ownerName"
    name  = "repositoryName"
    // 指定ブランチにpushをトリガーにする
    push {
      branch = "^${var.github_branch}$"
    }
  }
  // フィルタ
  included_files = ["cloudFunctions/mysql/**"]
}

Cloud Scheduler のジョブ作成

こちらも Terraform の公式ドキュメントを参考に作成します。Cloud Scheduler のジョブの作成はとてもシンプルで、実行スケジュールとターゲットとなる Cloud Functions のトリガーURL を設定するだけです。

cloud_scheduler.tf
resource "google_cloud_scheduler_job" "mysql-tbl-delete" {
  name             = "mysql-tbl-delete"
  schedule         = "15 1 1 * *"
  time_zone        = "Asia/Tokyo"

  # HTTPターゲット
  http_target {
    http_method = "GET"
    uri         = "https://${var.region}-${var.project}.cloudfunctions.net/mysql-tbl-delete"
  }
}

まとめ

今回は、Cloud SQL のデータを定期削除する方法を試してみましたが、意外と簡単に設定できることが分かりました!

レスキューナウテックブログ

日本で唯一の危機管理情報を専門に取り扱う防災Techのスタートアップ、(株)レスキューナウです。当社で活躍するエンジニアの技術ブログを中心に公開していきます。

Discussion

ログインするとコメントできます