👌

定時にバックアップファイルをS3にアップロードする仕組みの作成

に公開

背景

DBサーバーとして使用するEC2内のPostgreSQLコンテナから、毎日定時にバックアップデータを取得する処理を作成するときがありました。

そこで、EventBridge Scheduler,SSM RunCommand を用いて、時間指定したバックアップデータを取得する処理を作成し、取得したバックアップデータをS3にアップロードするようにしました。

また、バックアップデータは、ストレージコストをなるべく削減したかったので、バージョニングとライフサイクルルールを用いて、アップロードしてから、7日経過後に自動削除するようにしました。

その時行ったことを簡単にまとめたので、よかったら参考にしていただけると幸いです。

インフラ構成図

今回作成した毎日定時にバックアップデータをS3にアップロードする処理ですが、インフラ構成図は下記になります。

EC2は今回、DBサーバーとして使用し、PostgreSQLコンテナを立ち上げるため、Dockerをインストールしました。
また、PostgreSQLコンテナを立ち上げることができるようなイメージを作成し、そのイメージ使用してEC2内で、PostgreSQLコンテナを起動しました。

実装手順

実装手順は下記の通りです。

  1. EC2を立て、Dockerをインストールし、EC2内で、PostgreSQLコンテナを起動
  2. バージョニングを有効にしたS3バケットと、7日後に非現行バージョンに変更し、翌日に削除するためのライフサイクルルールの作成
  3. EventBridge Scheduler を用いて、バックアップデータをS3へアップロードする処理を実行する時間と、ターゲットにSSM RunCommand を設定

次から、1つ1つどのように行ったかを記載していきます。

EC2環境構築とPostgreSQLコンテナの起動

手順としては、まず、Amazon EC2インスタンスを作成し、Docker環境を構築します。その上で、PostgreSQLコンテナを立ち上げ、バックアップ対象となるデータベース環境を整えます。

  1. NATインスタンスの作成(プライベートサブネットのDBサーバ用EC2インスタンスが、Dockerのインストールや、イメージをpullするために作成)

AWSコンソールから以下の条件でインスタンスを作成

  • AMI:Amazon Linux 2
  • インスタンスタイプ:t3.micro
  • ネットワーク:パブリックサブネット(インターネットアクセス可)
  1. DBサーバ用EC2インスタンス作成

AWSコンソールから以下の条件でインスタンスを作成

  • AMI:Amazon Linux 2
  • インスタンスタイプ:t3.micro
  • ネットワーク:プライベートサブネット(インターネットアクセス不可)
  1. Dockerのインストール

DBサーバ用EC2インスタンスには、Docker を起動させ、PostgreSQLコンテナを立ち上がらせたかったので、Docker をインストールしました。

インターネットから、NATインスタンス経由で、プライベートサブネットのDBサーバ用EC2インスタンス への接続が確認できたら、下記のコマンドを実行し、Docker をインストールしてください。

# Docker を DBサーバ用EC2インスタンスにインストールするためのコマンド
sudo yum update -y
sudo yum install -y docker
sudo systemctl start docker
sudo systemctl enable docker
sudo usermod -aG docker ec2-user
  1. イメージをpullし、PostgreSQLコンテナが立ち上がるか確認

また、今回は、EC2内でPostgreSQLコンテナを立ち上げ、psqlコマンドを実行し、dumpファイル(バックアップファイル)を取得したかったので、GitLabのコンテナレジストリからEC2にイメージをpullしました。

そして、そのイメージを用いて、PostgreSQLコンテナを立ち上げ、psqlコマンドを使用できるようにしました。

# GitLabのコンテナレジストリからEC2内にイメージをpull(EC2内で実行)
[ec2-user@ip-xx-xx-xx-xx ~]$ docker pull git.example.com:5050/company/app/test_db:test
test: Pulling from company/app/test_db

# イメージの確認
[ec2-user@ip-xx-xx-xx-xx ~]$ docker images
REPOSITORY                                          TAG       IMAGE ID       CREATED       SIZE
git.example.com:5050/company/app/test_db      test      abcd1234efgh   13 days ago   389MB

# コンテナを起動
[ec2-user@ip-xx-xx-xx-xx ~]$ docker run -d --name db_container git.example.com:5050/company/app/test_db:test
xxxxxx1234567890abcdefxxxxxx1234567890abcdefxxxxxx1234

# コンテナが起動しているか確認
[ec2-user@ip-xx-xx-xx-xx ~]$ docker ps
CONTAINER ID   IMAGE                                                    COMMAND                  CREATED          STATUS          PORTS      NAMES
xxxxxx123456   git.example.com:5050/company/app/test_db:test      "/usr/lib/postgresql…"   28 seconds ago   Up 28 seconds   5432/tcp   db_container

# コンテナ内に入り、PostgreSQL に接続
[ec2-user@ip-xx-xx-xx-xx ~]$ docker exec -it db_container bash
postgres@xxxxxx123456:/$ which psql
/usr/bin/psql
postgres@xxxxxx123456:/$ psql -d postgres
psql (9.6.24)
Type "help" for help.

postgres=#

これで、バックアップ対象のPostgreSQL環境がEC2上で稼働します。

S3のバージョニングとライフサイクルルールの設定

次に、バックアップファイルのアップロード先のS3バケットを作成します。

今回は、削除忘れ防止のため、バージョニングを有効化し、7日後に非現行化 → 翌日削除となるライフサイクルルールを設定しました(バージョニングの有効化は、バケット作成時でも、作成後でも対応可能です。参考)。

EventBridge Schedulerによる自動バックアップ実行設定

スケジューラは今回、こちらの記事を参考に作成しました。

ターゲットを設定する箇所には、今回 SSM RunCommandを選択したかったので、SystemManager で、SendCommand を選択しました。

次にSSM RunCommandに渡すパラメータを記載しました(この渡すパラメータが、SSM RunCommandで実行する取得したバックアップファイルをS3にアップロードする処理になります)。

下記が今回作成したパラメータになります。

# SSM RunCommandに渡すパラメータ
{
  "DocumentName": "AWS-RunShellScript",
  "Parameters": {
    "commands": [
      "# 変数",
      "CONTAINER_NAME=db_container",
      "DB_NAME=\"appdb\"",
      "DB_USER=\"postgres\"",
      "DATE=$(date +%Y-%m-%d_%H-%M-%S)",
      "BACKUP_DIR=\"/tmp/db_backups\"",
      "BACKUP_FILE=\"db_backup_${DATE}.sql.gz\"",
      "LOCAL_PATH=\"${BACKUP_DIR}/${BACKUP_FILE}\"",
      "S3_BUCKET=s3://app-daily-backup/",
      "# 初期化",
      "mkdir -p $BACKUP_DIR",
      "# PostgreSQLコンテナ内でバックアップ作成",
      "docker exec $CONTAINER_NAME bash -c \"pg_dump -U $DB_USER $DB_NAME | gzip > /tmp/${BACKUP_FILE}\"",
      "# コンテナ内のファイルを一旦 EC2 にコピー",
      "docker cp $CONTAINER_NAME:/tmp/${BACKUP_FILE} $LOCAL_PATH",
      "# S3 にアップロード",
      "aws s3 cp $LOCAL_PATH ${S3_BUCKET}${BACKUP_FILE}",
      "# EC2内のローカルバックアップを削除",
      "rm -f $LOCAL_PATH",
      "# PostgreSQLコンテナ内の一時ファイルの削除",
      "docker exec $CONTAINER_NAME bash -c \"rm -f /tmp/${BACKUP_FILE}\""
    ]
  },
  "Targets": [
    {
      "Key": "tag:Name",
      "Values": ["app-db"]
    }
  ],
  "MaxConcurrency": "1",
  "MaxErrors": "0",
  "TimeoutSeconds": 600
}

上記のようにすることで、定時にバックアップファイルをS3にアップロードする処理を作成できました。

まとめ

今回は、定時にバックアップファイルをS3にアップロードする仕組みを実装しました。

初めて EventBridge Scheduler と SSM RunCommand を利用しましたが、想像以上に使いやすく感じました。

特に、EventBridge Scheduler はターゲットに Lambda や EC2 なども指定できるため、今回のバックアップ以外にもさまざまな定時処理を柔軟に実装できそうです。

今後は、EventBridge Scheduler のターゲットに他のAWSリソースを使用してみたいと思います。

参考

https://docs.aws.amazon.com/ja_jp/eventbridge/latest/userguide/using-eventbridge-scheduler.html

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/run-command.html

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/object-lifecycle-mgmt.html

GitHubで編集を提案

Discussion