シンクロ・フード エンジニアブログ

飲食店ドットコムを運営する、株式会社シンクロ・フードの技術ブログです

本番環境 DB の個人情報マスキングフローを Jenkins から StepFunctions に移行しました

初めまして、SRE チームの 辻井 です。

先日、本番環境 DB の個人情報マスキングフローを Jenkins から Step Functions に移行しました。
今回はその対応や検討の経緯を紹介させていただきたいと思います。

背景

本番環境 DB の個人情報マスキングフローでは、最初に本番環境 DB のクローンを作成し、マスキングした後に社内公開しています。

(なお、本稿では上記フローで作成する DB を クローン DB と呼称させて頂きます。)

そもそもクローン DB は何を目的に作成している?

クローン DB が作られている理由は2つあります。

理由1: サービス指標などの分析のため、社内向けに本番環境に近いデータを公開したい

本番環境の DB は個人情報や機密情報を含むため、限られた社員しか閲覧権限がありません。
しかし、各部署で意思決定のために確認したいデータがあります。

例えば、会員登録数、問い合わせ数、応募数などの指標です。

そんな要望に応えるため、マスキング処理済みの クローン DB を社内向けに公開しています。

理由2: テスト環境 DB をなるべく本番環境 DB に近い状態にしたい

テスト環境でのテストの信頼性を高めるためです。

例えば特定の DB テーブル定義に変更を加えたいとして、本番環境での変更時にどれほど実行時間がかかるかを事前にテスト環境で計測する際、なるべく本番環境に近いデータである方がよりテスト結果の信頼性が高くなります。

クローン DB はマスキング後に mysqldump した結果を dump ファイルとして S3 に保存しているため、任意にテスト環境 DB にインポートし活用できるようにしています。

このように、クローン DB は重要な役割を担っています。

どう作られていたか?

クローン DB はバッチ処理にて日次作成しており、朝 07:00 ごろに作成し、23:00 に削除しています。
バッチ処理のワークフロー管理には Jenkins Pipeline を使っていました。

処理の流れについては以下の通りです。

どんな課題があった?

従来の クローン DB 作成フローでは、以下の3つ課題がありました。

  • 1. ジョブが失敗するとリカバリーがしづらい

    • ジョブが失敗した場合は Jenkins Pipeline 上で失敗した地点のジョブから全て手動実行し直す必要がありました。
  • 2. 実行時間が長い

    • 全体の実行時間が5時間近くかかっていました。
      主な原因としてはマスキング処理や mysqldump のタスク処理量が多く、かつ直列実行されていたためです。
    • 通常作成時は問題にならないのですが、失敗した時の再実行に時間がかかり作成完了が夕方 16 時ごろと遅れてしまうことが最大の問題点でした。
  • 3. メンテナンス性が低い

    • テスト環境がない
      • いきなり本番環境でメンテナンスせざるを得ず、不安定な状況でした。
        メンテナンス頻度は低いものの、安全にメンテナンスできることが望ましいです。
    • コード管理できていない
      • Jenkins の Pipeline やジョブ
        • GUI 上から作成されており、コード管理できていませんでした。
      • Jenkins ジョブでの処理内容
        • スクリプトにベタ書きされており、変更履歴が管理されていませんでした。
          そのため、いつどんな理由で変更され、現在のコードになっているのか?が把握しづらい状況でした。

どう対応した?

大きな変更点として、タイトル通り Jenkins から Step Functions に移行しました。
処理の流れは以下の通りです。

Step Functions を採用した理由

以下の4点です。

  • 失敗した処理から容易に再実行可能
    • Step Functions では各タスクが個別のステートとして管理され、リドライブ により失敗したタスクから再実行が可能です。
  • 並列実行用のステート(Map)がある
    • 後述の通り、実行時間の課題解決のために Map ステートが使えそうだと考えました。
    • Map ステートとは、配列を渡すことで配列の要素ごとに同じ処理を繰り返してくれるステートです。今回では DB リストを配列で渡し、マスキング処理を DB ごとに繰り返し実行させています
  • 全て Terraform でコード管理可能
    • Step Functions を含めた必要リソースを Terraform で管理することで、ソースコード管理とバージョン管理が可能になります。
  • AWS サービスと相性がいい
    • 例えば RDS クローン時に RDS API: RestoreDBClusterToPointInTime を使っているのですが、このような API を Step Functions から実行可能だったりと便利です。

※補足: Step Functions 採用理由について
Jenkins Pipeline でも retry による再実行、parallel による並列処理実行は可能です。
ただ、今回はテスト環境構築と、Terraform と Docker によるコード管理も合わせて達成したかったため総合的に見て Step Functions を採用しています。


背景にあった 3つの課題に対しては、以下のように対応しました。

1. ジョブが失敗するとリカバリーがしづらい: Step Functions 採用

  • 上述の通り、Step Functions のリドライブ機能を活用し解決を図りました。
    • 下記のように AWS のマネジメントコンソールからボタン1つで実行可能で、シンプルです。

2. 実行時間が長い: 処理並列化

特に実行時間が長かった マスキング処理、 mysqldump 処理を並列化しました。

  • マスキング処理: Step Functions の Map ステート 採用

    • Map ステートで並列化しました。
      • 下記のように Lambda で取得した DB リストを Map ステートに渡し、Fargate 上で自社製のマスキングプログラム(Java) を対象 DB に対し実行しています。
  • mysqldump: GNU Parallel 採用

    • Fargate で実行する bash 内で GNU Parallel を利用し並列化しました。
    • Map ステートではなく GNU Parallel を使っている理由
      • 複数処理をまとめる上で都合が良かったからです。
        S3 へ dump ファイルを格納するには、mysqldump 実行 + dump ファイル送信と 2ステップ必要です。
        ならば、DB ごとに個別の Fargate コンテナで実行するより単一の巨大な Fargate コンテナでまとめた方が無駄なデータ受け渡しが発生せずスムーズで早いと判断しました。
    • ちなみに、実際に Parallel を使っている箇所は下記のような感じです。
    # parallel はサブシェルで実行されるため、必要な関数や変数を環境変数としてエクスポートして parallel に渡す
    export PARALLEL_HOME=/parallel
    export -f dump_table
    
    echo "Run with $MAX_JOBS parallel jobs"
    
    get_db_tables | while read -r db table; do
      if [ -z "$(echo "$IGNORE_TABLES" | grep "^$db\.$table\$")" ]; then
        echo "$db $table"
      fi
    done | parallel -j "$MAX_JOBS" --colsep ' ' dump_table

3. メンテナンス性が低い: テスト環境整備 + コード管理

  • テスト環境の整備
    テスト環境に Step Functions や必要なリソースを整備し、テストを可能にしました。
    クローン元とする DB 名などはパラメータで変更可能なので、任意の DB をマスキングテスト可能です。

  • Terraform と Docker によるコード管理
    AWS 上のリソース (Step Functions, Fargate, S3 など) は全て Terraform で、Fargate や Lambda 上で実行するスクリプトは Docker イメージにてコード管理しました。

改善効果

背景での課題について、以下の通りに解消することができました。

  • 1. ジョブが失敗するとリカバリーがしづらい

    • Step Functions 採用によりリカバリーが容易になり、ダウンタイム短縮と運用効率化を実現しました。
  • 2. 実行時間が長い

    • 全体の実行時間を約5時間から約3時間20分まで縮められました。
      • マスキング処理
        • 従来の実行時間は約2時間でしたが、約1時間10分まで短縮できました。
      • mysqldump
        • 従来の実行時間は2時間10分でしたが、約1時間に短縮できました。
  • 3. メンテナンス性が低い

    • テスト環境の整備
      テスト環境でのテストが可能となり、アップデート時のリスクを低減しました。
    • Terraform と Docker によるコード管理
      変更履歴が明確になり、環境構築の自動化と再現性が大幅に向上しました。
      特に Step Functions のワークフローと、マスキング等の処理内容をコード管理できたのが大きく、だいぶ管理が楽になりました。

学んだこと

テスト方法を最初から確立させておく

テスト方法をもう少し工夫すべきでした。

Step Functions 移行後も全体での実行時間が4時間弱ほどかかるため、そのまま実行してテストするとかなりの時間がかかります。待ち時間は別タスクを行うものの、コンテキストスイッチが都度入るのは良くありません。

テストしたい処理のみを実行するステートマシンをテスト用に用意するなどでテスト単位を細分化すべきでした。

一気に変更しすぎない

Step Functions への移行時にマスキング、mysqldump の並列化の実装を一気に盛り込みましたが、いざエラーが起きた際に調査範囲が広がり開発工数が伸びてしまいました。

今回は以下のように2ステップに分けるのがベターでした。

  1. Jenkins -> Step Functions へ移行する
  2. Step Functions のマスキング、mysqldump 処理を並列化する

本稿では、本番環境のマスキング DB (クローン DB) の作成フローを Jenkins から Step Functions に移行した経緯をご紹介しました。

この記事がどなたかのお役に立てれば幸いです。