CosmosDBのバックアップ&世代管理にAzure Data Factoryを使う

# はじめに

CosmosDBのバックアップに関しては「[Azure Cosmos DB でのオンライン バックアップとオンデマンドのデータ復元](https://docs.microsoft.com/ja-jp/azure/cosmos-db/online-backup-and-restore)」にある通り自動で取得されたものをサポートを使って戻す方法がありますがこれに頼りきるのは現実的ではありません。

手動で任意のタイミングに戻すには5/20に発表された[PITR（ポイントインタイムリストア）](https://azure.microsoft.com/ja-jp/updates/pointintimerestore-pitr-for-azure-cosmos-db/)を利用したいわけですがいつ来るかわかりません・・・。

ということで今回はCosmosDBのバックアップをDataFactoryを使って取っていこうと思います。

# DataFactoryとは？

フルマネージド型のETLツールで、バックエンドはSparkで動いておりFunctionsやBatch,Webhook,Databricksなど様々なサービスにイベントを起こすことも可能です。
AWSでいうとGlueですね。
イベントのソースにAWSのS3などがあったりとなかなか面白いですね。

# バックアップ編

## 今回やろうとしていること

- CosmosDBの中身をコンテナ毎にjson.gzの形でエクスポートし、BlobStorageのYYYY-MM-DD仮想ディレクトリに配置します。
- 古い世代のバックアップファイルを削除します。

これを1日に1回実行し、失敗した場合はメールでアラートメールが送信されるようにしてみたいと思います。

## 前提事項

CosmosDBとバックアップ先のBlobStorageは準備できていることとします。

## CosmosDBからのエクスポート＆BlobStorageへの格納の設定

DataFactoryをつくります。数分待つとデプロイできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/5f6b15b4-09a3-199d-e15a-68c8d8fc05cb.png)

「Author & Monitor」をクリックする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/8383068b-57f5-1ce4-ae05-1b1cb8fcdbe8.png)

エディタが起動するので鉛筆マークをクリックします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/1b213ee2-6efe-207b-1210-789931a5b5d9.png)

CopyDataをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/3ab0ca5e-fc46-b01b-c583-f7e3751178e0.png)

名前を適当に付けて、1日1回起動するようにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/2f840d84-f771-89e6-42ae-245f3472dd96.png)

「＋Create new connection」→「Azure CosmosDB(SQL API)」をクリックして、データソースを設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/d6d2d883-fb90-e728-2e0a-c05576dfd973.png)

バックアップするテーブルを選択します。何も考えず次へ次へ・・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/76454836-7770-bcca-984b-80eec8c8bca8.png)

出力先のBlobStorageを設定します。同じように「＋Create new connection」→「Azure Blob Storage」を選択して出力先のデータソースを設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/5b55ffaa-b61c-9f4f-20f3-3ff46a846926.png)

output fileについての定義を行います

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/164f500b-7bc1-a7ba-11c8-75f2f57fff9d.png)

フォルダパスには以下のように記載してください。（ディレクトリ書いたんですけどなぜかうまく反映されないので後で設定します）

```
cosmosdb/@dataset().cw_fileName
```

jsonで圧縮形式(gzip)で保存する旨設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/892504a0-d760-185e-972f-84741a5d2afd.png)

マッピングの設定を行います。エラーがあれば解消します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/f76ea194-1f23-7b9c-e6c2-d600cd1729e8.png)

ログの設定を行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/d4fb194e-5ca5-cd67-6f36-34939dd7cc0b.png)

あとはサマリを確認して完了してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/5720e9e8-7b29-4f19-8ff1-12c928923eea.png)

YYYY-MM-DDのディレクトリに出力したいので、DestinationDataset_xxxを選択し、FilePathを設定して「Publish all」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/62c07dfb-d9d5-337f-cad0-c7fcf11100e2.png)

## CosmosDBのエクスポートの動作確認

1日待つわけにはいかないのでパイプラインを選択して「Trigger now」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/a455654c-4644-0ccd-37a6-4504f8d305d8.png)

少し待つとBlobにデータができています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/17bc3bae-7645-6c54-b693-7161d89ab7df.png)

## 古いデータを削除してみます。

パイプラインを選択し、「Delete Activities」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/245d7529-5667-76ac-cfc7-75294bd85750.png)

「Delete Activities」を選択して新しくSourceを設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/1f59494a-4866-c289-5bdd-6ba24892f734.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/8fab5d15-b85b-b66e-2111-44c63a5abd63.png)


FilePathのディレクトリは以下のように指定します。今回は-1と指定していますが2日前のデータを削除したければ-2と指定してください

```
@adddays(utcnow(), -1, 'yyyy-MM-dd')
```

FilePathにWildCardで*を指定しておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/4467c848-1ad4-9a19-8383-1ed05397e1f6.png)


最後にパイプラインを繋げます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/148624e0-e668-a469-9e8f-bf3b27124675.png)

## 動作確認

BlobStorageに一日前のディレクトリを作成して実行してみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/afb980d1-a07d-409d-b3bb-eb5819a5fb16.png)

実行後に1日前のBlobデータが消えていることを確認しましょう

## アラートを作成する

パイプラインが失敗したらアラートをあげるようにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/3dd59da0-aeb1-0cc2-e30c-8514f0bd6e4d.png)

パイプラインの失敗のカウントが1以上だったらアラートをあげるように設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/1b87f278-4a6c-a86c-3953-e946ecbec2ce.png)

アラートグループの設定も必要に応じて行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/0057a9c6-13f5-804b-8cae-0c72dca9cd1e.png)


## 失敗させてみる

先ほどのDeleteActivityですが、対象のBlobがなかった場合はエラーになりますので、1日前のデータを作成せずにパイプランを動かしてみましょう。

以下のようなメールが来ていれば成功です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57686/5102cd4b-baa1-15fc-e544-bf605374ef34.png)