見出し画像

【失敗と対策】Azure Cosmos DB のデータをリストアする際の注意点

こんにちは、アバナード関西オフィス)篠田です。
先日は Azure Functions についての失敗談を書いたのですが、実は担当したシステムでの失敗は他にもありまして…
今回も、私と同じ過ちを繰り返す人が減ることを祈り、Azure Cosmos DB(以下、CosmosDB)についての備忘録を残したいと思います。
忙しい方は目次を見て、知らない情報だったら詳細覗いてみてください。

テーマ:CosmosDB のデータのリストア

私自身、CosmosDB はおろか、NoSQLデータベースの構築に携わったのはこの話で担当したシステムが初めてだったので、設計・構築の際も色々つまづきはあったのですが、1番苦労したのは、データのリストアでした。
今回はそこに絞って、いくつか注意点を書き残したいと思います。

なお、担当した CosmosDB で扱ったAPIは最もポピュラーだと思われる Core(SQL) API だったので、今回はそれに絞った話になります。
バックアップ・リストアに関する新機能追加は他のAPIより早く、最も優遇されていると言えるかと思います。
他のAPIについて気になる方向けの参考情報はこちら↓

※インフラ担当の目線での話で、あまりDBAの方々のようにデータベースの扱いに詳しいわけではないので、それありきで読んでいただけると幸いです。

注意点1:同じ CosmosDB アカウントにリストア出来ない

Azure SQL Database にも最近触ってるんですが、この辺のリストアの仕様がかなり違うんですよね、それも含め記載します。

Azure SQL Database にて、論理サーバ上に各データベース(DBインスタンス)をデプロイしている状況からリストアする場合は、

1.同じ論理サーバ上に新しい名前のデータベースとしてリストアする。

2.T-SQL の ALTER DATABASE コマンドや SSMS(SQL Server Management Studio)を使って、古いデータベースの名前を書き換えた後、新しいデータベースの名前を古いものに置き換える。

という操作をすることによって、元々のデータベース接続文字列を変更しない形でのリストアがスムーズに実施出来ます。

それに対して CosmosDB の場合は、見出しのとおり、同じ CosmosDB アカウント(Azure SQL Database の例で言うと論理サーバに相当)へのデータのリストアが出来ず、データベース単位、及びその内部構造であるコンテナ単位のリストアがしたい場合であっても、必ず新しい CosmosDB アカウントへリストアする事になります。

これ、何が困るかというと、元々のデータベース接続文字列を利用したい場合に、CosmosDB アカウント間でのデータ移行が必要になるんですよね…

リソースを作っては壊し、というのを早いサイクルで出来るのがパブリッククラウドの売りだというのは理解しています。
ファイアウォール等のその他設定を新しい CosmosDB アカウントで整えて、接続文字列の設定値をアプリケーション側で変えれば、確かに同様に動作はするでしょう。

ただ、設計・運用ドキュメントを沢山書いたシステムにおいては、ドキュメント修正が大変だから一度決めたリソース名は変えたくない、という事はあるかなと思っています。
(少なくとも私はこの時そう思いました、そんな事運用フェーズでやったら、ドキュメントの修正漏れが起こる可能性があるなと…)

なので結局、私はリストア手順書内にデータ移行の手順を盛り込みました。
CosmosDB のデータ移行には色々なオプションがあるんですが、手っ取り早いのはデータ移行ツールを使用する方法です。

ちなみに、今は上の参考情報内にある GitHub のリンクから、データ移行ツールのバイナリ版がダウンロード可能なのですが、私がリストア手順作成した時には何故かリンク切れになっていたので、仕方なくソースコードからコンパイルしました。
インフラ担当としては初めて業務で Visual Studio のお世話になり、IDEの偉大さを知る貴重な経験となったのですが、.NET Framework 4.5系はサポート期限が近い(2022年4月26日)ので、早く .NET 6 版なりが開発されることを祈っています…

注意点2:CMKでデータ保存時暗号化したらPITRが現状使えない

見出しだけ読んでも意味が分からないかもしれないので、まずは用語を整理します。

「CMK」とは、カスタマーマネージドキーの略です。
Azure では、データを格納する様々なサービスについて、保存時に暗号化キーによってデータを暗号化する機能が実装されていて、その多くは、Microsoft が管理するキー(サービスマネージドキー)で暗号化するのが既定の設定となっています。
さらに、Azure Key Vault(以下KeyVault) にて利用者で自ら生成したCMKを使用して暗号化するオプションも提供されており、利用する組織の求めるセキュリティレベルに応じて変更する事が可能です。

私の担当したシステムでは、CMKでのデータ保存時暗号化が要件となっていたため、CosmosDB でも次の情報を参考に、暗号化設定を実施していました。

そして「PITR」は、ポイントインタイムリストアの略です。
Azure SQL Database にも同じ名前の機能があって、完全バックアップ+差分バックアップ+トランザクションログから、過去のピンポイントなデータベースのコミット時点へリストア出来ます。
CosmosDB のPITRも似たような機能で、先ほど注意点1て紹介した参考情報にある継続的バックアップを有効化することで利用出来ます。

ただ、このPITR及び継続的バックアップは、CosmosDB では実はまだGAされたばかりの新機能で、制約が沢山あります。
現状特にキツい制約は以下の3つかなと私は考えています。

継続的バックアップでは、SQL および MongoDB 用の Azure Cosmos DB API のみがサポートされます。 Cassandra、Table、Gremlin の API はまだサポートされていません。
※プレビューの頃は、SQL API のみ利用可能でした。
カスタマー マネージド キーを使用するアカウントは、継続的バックアップの使用に対応していません。
複数リージョンの書き込みアカウントはサポートされていません。

ということで、上記の2つ目に該当するので、CMKでデータ保存時暗号化をしている CosmosDB は、現状PITRが利用出来ません。
その場合、バックアップとしては従来の定期的バックアップを利用することになります。

PITRが使用できる継続的バックアップの方が、RPO(目標復旧時点)の観点では優れています。
それに加えてPITRの場合は、利用者が任意のタイミングで、Azure Portal や Azure Cloud Shell を操作して、リストアを開始できます。
え、当たり前じゃん、と思われるかもしれませんが、実は定期的バックアップの場合、Microsoft サポートにリストアをリクエストしないと、データのリストアが出来ません。
リストア作業自体も全て Microsoft サポートによって実行されるので、楽な部分がある反面、リストア作業の進捗が、自ら実施するのに比べて把握・予測しにくいのは難点です、システムのRTO(目標復旧時間)に関わります。

Microsoft サポートへ確認したところ、定期的バックアップからのリストアは、以下の流れで実行されるそうです。

1.お客様にてリストアのサポートチケットを起票
2.弊社サポート担当にてご要件を確認の後、リストア担当部門へリストア依頼
3.リストア担当部門にてリストア作業の実施。
4.リストア作業完了後にサポート部門への完了連絡。
5.サポート部門からお客様への完了連絡。

上記の2~5の Microsoft サポートの対応所要時間について、SLAはありません。
CosmosDB のデータ破損等によって業務停止等が発生し、迅速なリストアが必要な場合は、迷うことなく緊急度Aでサポートリクエストをした方が良い、との事でした。
また、上記の3の所要時間は、当然ですがリストアするデータのサイズによって異なるようで、500 GB のデータに対してリストアが開始された場合、概算の所要時間は約 4 時間だそうです。
それらを加味し、かつ、接続文字列を変えたくない場合はその後のデータ移行の作業時間も含めて、CosmosDB のリストア所要時間は見積る必要があります。

これらの注意点1、2を把握し、リストア手順書をそれなりに苦労して仕上げた頃には、リストア作業の大変さを理解出来ていたので、「リストアが必要になるような事が起こらなければいいな…」と内心思っていました。

しかし、システムは何が起こるか分かりません。
ある日、CosmosDB でデータ破損が発生し、リストアが必要になってしまいました…

あらかじめ準備していた手順に則り、サポートリクエストを起票。
それから15分後、緊急度Aなので、Microsoft サポートより確認の電話が入ります。
会話時間は1~2分程度で、確認終了後、「リストア作業完了まで数時間かかるのでお待ちください」と伝えられました。

よし、これで後はデータ移行だけだな…と思っていたんですが、それから2時間後、

「リストアに失敗しています」

と Microsoft サポートより告げられてしまい、窮地に追い込まれてしまいました…

注意点3:CMKのある KeyVault のアクセスポリシーで CosmosDB のマネージドIDのみに許可設定したらリストアに失敗する

どうしてリストア出来なかったのか。
理由は見出しの通りなのですが、ちょっと伝えにくいので、お絵描きしてみました。

↓リストア失敗パターンの絵

失敗の図

CMKでのデータ保存時暗号化が施された CosmosDB-old のデータをバックアップからリストアするためには、Microsoft サポートのリストア作業にて新規作成される CosmosDB-new から、そのCMKへアクセス可能で、バックアップデータを復号化出来る必要があります。
今回、CMK及びその他のキーへのアクセスポリシーを KeyVault にて設定する際に、CosmosDB-old にてマネージドIDを有効化し、そのマネージドIDのみにアクセス許可を与えていたため、CosmosDB-new からCMKへアクセス出来なくなっていました。

注意点2で載せた参考情報に記載があるのですが、実はCMK暗号化は CosmosDB アカウント作成時でないと有効化出来ず、かつその時点ではマネージドIDが有効化されていないので、最初のCMK暗号化の際は、Azure Cosmos DB プリンシパル(ID: a232010e-820c-4083-83bb-3ace5fc29d0b)という、任意の CosmosDB を表すファーストパーティIDに対し、KeyVault へのアクセス許可をアクセスポリシーで設定する必要があります。

ただ、そのまま Azure Cosmos DB プリンシパルからのアクセス許可をした状態の場合、KeyVault のリソース名とキーの名前が分かりさえすれば、そのCMKが他者の CosmosDB のデータ保存時暗号化にも使用されてしまう可能性があります。
調べた限り、CMKのキー文字列を CosmosDB 経由で第三者が把握するような事は機能上出来なさそうなのですが、この状態は何だか気持ち悪いです。

なので私は追加設定として、CosmosDB のマネージドIDを有効化し、KeyVault のキーへのアクセス許可設定にマネージドIDを追加して、Azure Cosmos DB プリンシパルのアクセス許可は削除していました。

ここまで書くと気付かれた方もいるかと思いますが、CMK暗号化のためにマネージドIDで KeyVault へのアクセス許可を設定した CosmosDB をリストアをするためには、リストアを Microsoft サポートへ依頼する前に、Azure Cosmos DB プリンシパルからCMKへのアクセス許可を KeyVault のアクセスポリシーへ追加する必要があります。
また、リストアが終わった後は、当然ですが Azure Cosmos DB プリンシパルのアクセス許可は削除すべきです、あくまでリストアのための一時的な設定と考えるべきでしょう。

↓リストア成功パターンの絵

成功の図

リストア出来ないという悲報から30分後に、Microsoft サポートより、Azure Cosmos DB プリンシパルのアクセス許可手順について提示がありました。
計2時間半のロスが発生してしまいましたが、幸いにまだデータ量が少なかったので、それ以降のリストア・データ移行は想定以上に速く進み、何とか目標復旧時間は守れました。
その後、リストア手順も当たり前ですが修正しました。

余談ですが、注意点3は、Microsoft Docs には私がリストア失敗した時点では書いてありませんでした。
私のケースを受けて以下記載が追加になったとのことで、Microsoft サポートより英語版のURLを先日提供いただいたので、共有しておきます。
そのうち日本語版にも反映されるとの事です。

If you used a system-assigned managed identity in the Azure Key Vault access policy of the source account, you must temporarily grant access to the Azure Cosmos DB first-party identity in that access policy as described here before restoring your data. Once the data is fully restored to the target account, you can remove the first-party identity from the Key Vault access policy and set your desired identity configuration.

(和訳)
ソースアカウントの Azure Key Vault アクセスポリシーでシステム割り当てマネージドIDを使用した場合は、データをリストアする前に、ここで説明するように、そのアクセスポリシーで Azure Cosmos DB ファーストパーティID へのアクセスを一時的に許可する必要があります。 データがターゲットアカウントに完全に復元されたら、Key Vault アクセスポリシーからファーストパーティIDを削除し、必要なID構成を設定できます。

まとめ:得た教訓・CosmosDBに期待すること

今回は、CosmosDB のデータのリストアする際の注意点について記載しましたが、特に注意点2、3については、CMKでのデータ保存時暗号化というセキュリティ要件が深く関わっていたように思います。

ボタンをポチポチするだけで誰でも必要なリソースをすぐ作成できる事が Azure もといパブリッククラウドの売りですが、法人レベルで求められるセキュリティ要件を設計・運用に落とし込む能力は、オンプレと同程度か、パブリックであるがためにそれ以上が求められているようにも感じています。

そんな中で、セキュリティと利便性を両立するのは、機能豊富なパブリッククラウドでもやはり難しいですね。
どうしてもサービスの仕様上使えない機能が出てきたり、やらないといけない運用操作が多くなってしまったりします。

このジレンマは結構、クラウドベンダー側の機能修正・追加によって解消される事があるようなので、Azure の機能アップデートは、今後も継続的にチェックしていきたいと思います。

冒頭に書いたように私はDBAではなく、NoSQLは初心者ですが、技術的な難しさ等は分からないので無視させて頂いて、最後に、CosmosDB に期待する機能アップデートについて、勝手ですが書き残しておこうと思います。

まず、同じ CosmosDB アカウントへ別名データベース・コンテナとしてリストアして、Azure SQL Database と同様に、名前の付け替えだけでリストアが完了するようになれば、大変ありがたいです。
あと、やっぱりCMK暗号化した状態でもPITRを使用したいです。

また、そもそも大掛かりなデータのリストアをしなくて済むのが理想なので、Azure Storage Accounts の BLOB ストレージのように、各アイテムの論理的な削除(Soft-Delete)やバージョン管理の機能が標準であったら嬉しいなあと思います。

現状、論理削除はアイテム内でフラグを設定すれば、変更フィード機能と組み合わせることで自力実装できる、というような情報もありますが、やっぱり標準搭載の方が楽だし、機能として信頼できますよね。


この記事が皆さんのお役に立てましたらいいねやフォローをお願いします。
内容に関するご指摘や、その他何かございましたら下記に連絡ください。
アバナード関西オフィス 篠田 諭
satoshi.shinoda(@)avanade.com

[会社紹介]最近また Wantedly にアバナード関西オフィスの記事が掲載されました!


この記事が気に入ったらサポートをしてみませんか?