世界のやまさ

SEKAI NO YAMASA

サーバーレスでお手軽 Storage お掃除

Microsoft Azure Advent Calendar 2017 16日目の記事です。

qiita.com

これはなに?

Logic Apps で Azure Blob Storage に保存されたファイルを定期的にお掃除します。

皆さんそろそろ年末の大掃除の季節ですよね?大掃除毎年大変ですよね?でも、お掃除は毎日やっていれば大掃除しなくて済みますよね?でも、面倒臭いですよね?

そうですよね。毎日やりましょう。それもお手軽簡単に。

今回のイメージは次の図のような感じです。例えば Linux から cron で定期的に Azure Blob Storage に保存されているファイル(ログとかDBバックアップとか)を、Logic Apps で毎晩30日より古いファイルを削除します。

f:id:nnasaki:20171214105954p:plain

Logic Apps についてはリンク先を見てください。簡単にいうとコーディング無しでサーバーレスで動きます。

azure.microsoft.com

なにが嬉しいの?

沢山あります。某牛丼風に言うとこんな感じです。

  • 安い
    • 1アクション ¥0.002856 円!
    • 1000 アクションで ¥2.8 円です
    • 毎日定期実行で年間数円レベルですよ
  • 早い
    • 実行速度はそんなに速くありませんが、生産性がめちゃめちゃ高いです。すぐ作れます。
    • 今まで何世代前削除というのをシェルでゴニョゴニョ書いてcronで回すという手間が省けます
  • うまい
    • SLAがついていますので安心して実行を任せられます
    • 実行したログも残りますのでエビデンスガー勢も押さえ込めます

ね?もう VM 立てて cron でバッチとかやる必要無いでしょ?

どうやるの?

Azure Storage にBackup をする

Linux から Azure Storage にバックアップを保存。今回の本題から外れるので省略します。 Azure CLI 2.0 などを使ってシェルを作成し、cron で回したりすれば出来ます。 Linux からの Backup は結局 cron 使うのかよっていうツッコミはとりあえず置いておきます。

Logic Apps を作成する

ポータルから Logic Apps を作成し、テンプレートのカテゴリで「スケジュール」を選択後、「Delete old Azure blobs」を選択

f:id:nnasaki:20171213150541p:plain

「このテンプレートを使用する」を選択

f:id:nnasaki:20171213151218p:plain

「作成」を選択

f:id:nnasaki:20171213151406p:plain

「接続名」に名前を入力し、「ストレージアカウント」を選択して、「作成」をクリック

f:id:nnasaki:20171213151529p:plain

「続行」をクリック

f:id:nnasaki:20171213151634p:plain

沢山出てきますが、ひとつひとつ設定していきます。

f:id:nnasaki:20171213152356p:plain

Recurrence

繰り返す頻度です。デフォルトで1日1回になっています。 これで良ければ変更する必要はありません。

f:id:nnasaki:20171213152006p:plain

Set expiration age variable

何日前のファイルを消すか設定します。デフォルトは30日前です。 これで良ければ変更する必要はありません。

f:id:nnasaki:20171213152420p:plain

List blobs

削除対象のフォルダーを指定します。必須です。

f:id:nnasaki:20171213152528p:plain

今回は backup-test を選択しました。

f:id:nnasaki:20171213152743p:plain

For each

実際の削除処理です。先ほど選択したフォルダ内のファイルを1つずつ最終更新日時を見て、 Set expiration age variable で設定した日数より古ければ削除します。特にここも変更する必要はありません。

f:id:nnasaki:20171213152615p:plain

最後に保存して完了です。

Logic Apps を実行する

実行は1日に1回されますが、すぐに確認したい場合は「概要」の「トリガーの実行」をクリックします。

f:id:nnasaki:20171213153741p:plain

起動に成功すればこのように実行の履歴に「成功」と表示されます。

f:id:nnasaki:20171213153850p:plain

さらに、履歴をクリックすると、「実行の履歴」を表示します。

f:id:nnasaki:20171213154007p:plain

さらに、各項目をクリックすると実行結果も表示してくれるのでデバッグも楽ですね。

f:id:nnasaki:20171213154121p:plain

ファイルを確認すると本日(執筆時点の12/13)のファイルがあるときに実行したしたので、まだ消されていませんでした。

f:id:nnasaki:20171213154455p:plain

まとめ

Logic Apps 便利で簡単で良いですね!


【オマケ】本当に動いているかテストする

ここから下は本当に動作しているか不安な人向けの記述です。手っ取り早く試したい人には不要なので読まなくて良いです。オマケのほうが本編より長いので。

さきほどは31日前のファイルが実際に削除するかは確認出来ませんでした。というのも、Azure Blob Storage の最終更新日(last-modified)を参照しているのですが、このプロパティはユーザーが手動で変更出来ないためです。

そこで、今回はストレージに meta-data を手動で付与して、強制的に31日前にして動作確認することにしました。

流れとしてはこんな感じです。先の Logic Apps に追加分を【追加】としています。

  • 【追加】Storage の meta-data に date を設定する
  • 【追加】Storage の SAS トークンを取得
  • ファイルの一覧を取得
  • 一覧をループ
    • 【追加】ファイルの meta-data から日付を取得
    • 【追加】ファイルの meta-data で比較して削除する

順番に見ていきましょう

【追加】Storage の meta-data に date を設定する

動作確認なので portal にて設定してしまいましょう。 BLOBのメタデータの編集は次の図のようにクリックしていきます。

f:id:nnasaki:20171214123530p:plain

キーに date を追加し、値に 2017-12-13T06:01:56+00:00 を入れて保存。

f:id:nnasaki:20171214123559p:plain

削除したいファイルのほうはとりあえず11/1にしてみましょう。 同じようにキーに date を追加し、値に 2017-11-01T06:01:56+00:00 を入れて保存。

【追加】Storage の SAS トークンを取得

上記で設定した meta-data ですが、Logic Apps の Storage Connector から取得する方法がありません。 そこで、後述の「【追加】ファイルの meta-data から日付を取得」にて Storage の REST API を使用して取得します。この Storage の REST API の呼び出しは認証が必要でして、認証には Storage の SAS トークン(認証トークンのようなもの)取得が別途必要です。若干込み入った処理になりますので、今回は次の Azure Functions をデプロイして使います。

github.com

上記を Azure Functions に展開して、Logic Apps から REST API を呼び出すアクションを加えます。アクションの追加は「+」のボタンを押すことで追加できます。次のような設定になりました。

f:id:nnasaki:20171214124402p:plain

ファイルの一覧を取得

ここは変更ありません。

一覧をループ

【追加】ファイルの meta-data から日付を取得

For each の最初に次のような感じで追加します。

f:id:nnasaki:20171214125004p:plain

URI の部分は手動で設定が必要です。Logic Apps 上部のコードビューをクリックしてコードで編集します。

f:id:nnasaki:20171214143714p:plain

アクション名に「Get metadata」と付けていたので、「Get_metadata」で検索します。(スペースがアンダースコアに変わっているのに注意してください)

uriの部分に https://[ストレージアカウント名].blob.core.windows.net/[ストレージコンテナ名]/@{items('For_each')?['DisplayName']}?comp=metadata&@{body('Get_storage_SAS_token')?['token']} と入れてください。 @{body('Get_storage_SAS_token')?['token']} が Azure Functions を呼び出したアクションの Response Body 中の JSON token の部分となります。

f:id:nnasaki:20171214143921p:plain

【追加】ファイルの meta-data で比較して削除する

先ほどのコードビューにてループの Condition の expression を先ほど取得した meta-data の date を使用するように変更します。

下図の expression の部分を @less(ticks(outputs('Get_metadata')['headers']?['x-ms-meta-date']), ticks(addDays(utcnow(), variables('ExpirationAgeInDays')))) と書き換えます。

meta-data は REST API の Response Header に x-ms-meta- と付いてくるので注意してください。

f:id:nnasaki:20171214144603p:plain

この辺の書き方はちょっと慣れが必要ですが、ある程度 MS 系で XML をいじったことがある人は、なんとなく雰囲気で理解できるかと思います。文法など詳しいドキュメントはこちらにあります。

docs.microsoft.com

実行結果

1日も待っていられないのでまた、トリガーで実行してみます。今回2個のファイルを入れました。早速実行結果を見てみましょう。

1個目は条件を満たしていないのでスキップされました。

f:id:nnasaki:20171214150244p:plain

2個目は For each の「次へ」をクリックすると確認できます。先ほどと違って削除されました。

f:id:nnasaki:20171214150415p:plain

【オマケ】まとめ

動作テストついでに Logic Apps の組み方をちょっと説明してみました。こんな感じでチャチャっと組めます。足りない機能は Azure Functions を使ったり、アクションを追加すれば解決出来ます。料金も格安ですので、皆さん是非使ってくださいね!

尚、Logic Apps は日本語のユーザーグループ LogicFlow-ja があります。ご興味のある方は参加してください。