Sansan Tech Blog

Sansanのものづくりを支えるメンバーの技術やデザイン、プロダクトマネジメントの情報を発信

Eight における AWS Backup

技術本部 Eight Engineering Unit(社内通称:Eight EU)の秋本です。普段は Eight をインフラ面からお世話することでご飯を食べています。

酷暑が続いていますね。酷暑は人々の健康を害し、健康が害されると稼動可能な人員が減り、人員が減ると業務負荷が増え、業務負荷が増えるとオペミスが発生しやすくなります。オペミスが発生してもバックアップがあれば最悪なんとかできる事が多く、もはや運用作業にはバックアップ取得が欠かせぬものとなっています。

本項では Eight におけるバックアップ取得の前史を述べ、そのうえで AWS Backup を導入していい感じになった風景を述べるものになります。

AWS Backup 導入まで

Eight で使用しているデータの置き場所は以下があります。Eight では現状 AWS のみを使用しています:

サービス 用途
S3 名刺画像データ、各種ログ、アセット(CSS / JS / 画像 etc)、各種訴求用ランディングページ (LP) など
RDS
(Aurora MySQL)
本番アプリケーションから参照される各種データ
RDS
(Aurora PostgreSQL)
内輪向け Redash 用データ
DynamoDB 本番アプリケーションから参照される各種データであって RDB での取り扱いが難しいもの
OpenSearch 本番アプリケーションから参照される各種データであって柔軟な検索性を確保する必要があるもの
Redshift ユーザ行動状況などの KPI
EBS 常時稼動する EC2 インスタンスが生成する各種ログや OS 用データなど

上記はライフタイム内において永続的に保管されることが想定されるデータを取り扱うものです。揮発してもよいものは別途 ElastiCache や SQS などで扱われる場合もありますが、今回はそのあたりを省略します。

上記サービスで扱われるデータをバックアップするにあたり、Eight では以下手法をとっていました:

サービス バックアップ方法
S3 S3 の堅牢性に任せる
RDS
(Aurora MySQL)
Aurora のバックアップ機能 で自動取得
RDS
(Aurora PostgreSQL)
Aurora のバックアップ機能 で自動取得
DynamoDB 取得していない
OpenSearch 作業用 EC2 インスタンス内から cron でバックアップ取得スクリプトを定期実行
Redshift Redshift のスナップショット管理機能 で自動取得
EBS ●ボリュームがアタッチされているインスタンス内から cron でスナップショット取得スクリプトを定期実行
DLM にてスナップショットを自動取得

こうしてみるとわかるとおり、結構バラバラな状況です。バックアップの取得は(一部実施していないものは除き)できているものの、各サービスの設定把握がやりづらくなっています。

どのサービスもやることは結局「バックアップ取得」なので、うまいことバックアップというくくりで一元管理したいという気持ちがでてくるのは自然なことです。 その解決策として AWS Backup が使えそう、ということになりました。

AWS Backup 導入

AWS Backup とは

AWS Backup は前述の通り「バックアップを一元管理するサービス」です。一元管理できるサービスは以下ドキュメントが詳しいです: docs.aws.amazon.com

前述の内容と比較すると Redshift と OpenSearch は残念ながら AWS Backup 非対応でした。よってこれらについては断念せざるを得ません。 また S3 については2022年2月に対応した旨アナウンスされていますが、本作業実施時点(後述のように2021年夏から冬)では非対応であった為、作業対象から外しています。

概念

いくつか用語があるので、ここで簡単に説明を与えておきます:

  • vault:バックアップデータの管理場所
  • plan:いつどのくらいの期間でどのくらいの数のバックアップを取得するかを定義するもの
  • job:バックアップ操作
    • バックアップ取得
    • バックアップからのリストア
    • バックアップのコピー

plan に従いバックアップ取得を担う job が実行され vault にブツが入る、といった按配です。なお job は plan によらず任意に実行もできます。

設定

こなれた AWS サービスの常として、AWS Backup も各種構成管理ツールで設定を管理できます。バックアップ管理を AWS Backup で一元化し、その設定をコードベースで管理できれば御の字ですね。

Eight ではこの種の作業に Terraform を使用しています。以下に vault と plan の定義をいくつか並べてみます。

plan から vault へ入る対象を絞る方法としては 1) タグで絞る 2) 対象サービス名で絞る 方法があります。Eight ではこれらを併用しているので、それぞれについてサンプルを挙げて説明します。

タグで管理対象サービスを絞る方法

Eight においては以下でこの手法を使用しています:

  • EBS
  • DynamoDB

両者は名前や世代数など以外はほぼ同様の内容な為、ここでは EBS に対しての設定のみ例示します。 以下例では data と resource を一緒くたにしていますが、実際には別ファイルで定義しています:

data "aws_kms_key" "key" {
  key_id = "<AWS Backup 用 KMS キー名>"
}

data "aws_iam_role" "role" {
  name = "<AWS Backup 用 IAM ロール名>"
}

resource "aws_backup_vault" "ebs" {
  name        = "ebs"
  kms_key_arn = data.aws_kms_key.key.arn
}

resource "aws_backup_plan" "ebs" {
  name = "ebs"

  rule {
    rule_name         = "<いいかんじの名前>"
    target_vault_name = aws_backup_vault.ebs.name
    schedule          = "cron(<分> <時>  * * ? *)"
    start_window      = "60"
    completion_window = "120"

    lifecycle {
      delete_after = "<バックアップの世代数>"
    }
  }
}

resource "aws_backup_selection" "ebs" {
  iam_role_arn = data.aws_iam_role.role.arn
  name         = "ebs"
  plan_id      = aws_backup_plan.ebs.id

  selection_tag {
    type  = "STRINGEQUALS"
    key   = "<タグ名>"
    value = "<タグ値>"
  }
}

素直な記述になっていると思います。参考にすべきは以下です:

start_windowschedule に設定されたタイミングから起算して何分以内にバックアップ処理が実行されるかを分単位で指定します。 completion_window はバックアップ処理が開始されてからどのくらいの期間で完了されるべきかを分単位で指定します。

job が両者それぞれに違反(両方とも違反する場合も含む)した場合、その job は失敗扱いになります。 Eight ではかなり広めの値を設定しており、幸いなことにも job が失敗した事例は本稿作成時点でとくにありません。

ところで selection というものが出てきました。これは plan と vault を対応させ、job をどのサービスに対し実行させるかを指定するものです。 マネジメントコンソール上ではこのあたりがうまいこと隠れており、意識されることはありません:

plan の例
vault の例

一方で awscli などを使用して AWS Backup 関連の操作をするとその存在が明らかになります(以下内容は一部ボカしています):

$ aws backup help | grep selection
       o create-backup-selection
       o delete-backup-selection
       o get-backup-selection
       o list-backup-selections

$ aws --profile $PROFILE backup list-backup-selections --backup-plan-id $EBS_BACKUP_PLAN_ID --output json
{
    "BackupSelectionsList": [
        {
            "SelectionId": "xxxx",
            "SelectionName": "ebs",
            "BackupPlanId": "yyyy",
            "CreationDate": "2021-12-23T14:23:12.698000+09:00",
            "IamRoleArn": "arn:aws:iam::zzzz:role/DUMMY"
        }
    ]
}

管理対象サービスを直接指定する方法

Eight においては RDS (Aurora MySQL / PostgreSQL) においてこの手法を使用しています

両者は名前や世代数など以外はほぼ同様の内容な為、ここでは Aurora MySQL について例示します。 以下例でもタグ指定の項と同様に data と resource を一緒くたにしていますが、実際には別ファイルで定義しています:

data "aws_kms_key" "key" {
  key_id = "<AWS Backup 用 KMS キー名>"
}

data "aws_iam_role" "role" {
  name = "<AWS Backup 用 IAM ロール名>"
}

data "aws_rds_cluster" "aurora_mysql_cluster" {
  cluster_identifier = "<Aurora MySQL クラスタ名>"
}

resource "aws_backup_vault" "aurora_mysql" {
  name        = "aurora_mysql"
  kms_key_arn = data.aws_kms_key.key.arn
}

resource "aws_backup_plan" "aurora_mysql" {
  name = "aurora_mysql"

  rule {
    rule_name         = "<いいかんじの名前>"
    target_vault_name = aws_backup_vault.aurora_mysql.name
    schedule          = "cron(<分> <時> * * ? *)"
    start_window      = "60"
    completion_window = "120"

    lifecycle {
      delete_after = "<バックアップの世代数>"
    }
  }
}

resource "aws_backup_selection" "aurora_mysql" {
  iam_role_arn = data.aws_iam_role.role.arn
  name         = "aurora_mysql"
  plan_id      = aws_backup_plan.aurora_mysql.id

  resources = [
    data.aws_rds_cluster.aurora_mysql_cluster.arn,
  ]
}

aws_backup_selection な resource に注目してください。タグでサービスを絞る場合には selection_tag ブロックで条件を指定していましたが、リソースを直接指定する場合は resources へ対象サービスの ARN をリスト形式で指定することになります。

導入後

AWS Backup 以前の Eight におけるバックアップ取得状況を再掲します:

サービス バックアップ方法
S3 S3 の堅牢性に任せる
RDS
(Aurora MySQL)
Aurora のバックアップ機能 で自動取得
RDS
(Aurora PostgreSQL)
Aurora のバックアップ機能 で自動取得
DynamoDB 取得していない
OpenSearch 作業用 EC2 インスタンス内から cron でバックアップ取得スクリプトを定期実行
Redshift Redshift のスナップショット管理機能 で自動取得
EBS ●ボリュームがアタッチされているインスタンス内からスナップショットを自動取得
DLM にてスナップショットを自動取得

これが以下のようになりました:

サービス バックアップ方法
S3 S3 の堅牢性に任せる
RDS
(Aurora MySQL)
AWS Backup で一元管理
RDS
(Aurora PostgreSQL)
AWS Backup で一元管理
DynamoDB AWS Backup で一元管理
OpenSearch 作業用 EC2 インスタンス内から cron でバックアップ取得スクリプトを定期実行
Redshift Redshift のスナップショット管理機能 で自動取得
EBS AWS Backup で一元管理

元々バックアップを取得していなかった DynamoDB については AWS Backup 利用開始により設定管理が簡易になったことで、この機会に取得することとしました。 また RDS については元々 Aurora クラスタの機能としてバックアップ機能が提供されており、そちらを使用していたものの、今回の AWS Backup 導入に際し AWS Backup 側に寄せることにしました。

バックアップ取得状況は AWS Backup の vault たちを、バックアップ取得設定は Terraform コードを、それぞれ参照すればよくなり、バックアップ管理の見通しがとてもよくなったと感じています。

費用について

便利さを享受するには対価を支払わねばなりません。AWS Backup も例外ではなく、その維持には費用が発生します。

……とはいうものの、実のところ AWS Backup 利用そのものについては 費用発生はありません。バックアップされたデータの保持にのみ、対象サービス(Eight の場合は EBS / RDS / DynamoDB)側で費用が発生します。これは以下が詳しいです: aws.amazon.com

しかしここにも若干の落し穴があり、請求書上は DynamoDB に対しての AWS Backup によるバックアップ費用は AWS Backup 側につく もようです。費用変動を確認する際に「あれっ、DynamoDB のバックアップ分の費用が増えてないな」とならぬよう、注意が必要です。

まとめ & 今後の展望

本稿で解説した AWS Backup の導入をおこなったのは実際には2021年の夏から冬に掛けての期間でした。よって本稿が世に出るまでの半年から1年程度、AWS Backup 利用を続けていたかたちになります。

幸運にもバックアップからデータをリストアしなくてならない事態に遭遇することはなくここに至っており、AWS Backup が提供するリストア機能やデータのコピー機能は本稿執筆時点でまだ実際に使われたことはありません。それでもバックアップが一元管理され、どこに何があってどのように取得されるかが簡単に把握できる、という状況は安心感を高めるものです。

サービス稼動期間が長くなるにつれ、構成管理上のエントロピーが高まってゆくのは避けられず、いかにこことうまく付き合うかが課題になります。 バックアップ管理について見通しをよくする AWS Backup の導入はこの一助となることでしょう。

今後の展望としては以下が挙げられます:

  • S3 での AWS Backup 有効化
    • 堅牢性以外の面でのデータ喪失(冒頭の能書きでも挙げたオペミスや障害影響など)に対処したい
  • まだ AWS Backup で対応されていないサービスのバックアップ管理効率化
    • Redshift と OpenSearch が AWS Backup 対応されると御の字です(何卒……)
  • バックアップ専用 AWS アカウントを整備してのクロスアカウントによる集中管理
    • 現状:バックアップ対象サービスを稼動させている AWS アカウント内でのバックアップを取得している
    • 展望:バックアップ専用アカウントにバックアップを集約させ、閉じた権限範囲での管理を可能にしたい

ただしクロスアカウントでの管理には以下ドキュメントを読むに AWS Organizaitons の導入が必要で、まだまだ先は長そうです: docs.aws.amazon.com

サービスのライフタイムが続く限り運用も続くので、このあたりはいずれ別の記事で触れられることでしょう。

参考ドキュメント

本文中で適宜参照した内容以外に以下ページを参照しました: qiita.com qiita.com

© Sansan, Inc.