2020/06/19

Azure Data Factory を使って、GCS から Azure Blob Storage へデータ転送

AzureのData Factoryを使って、Google Cloud StorageからAzure Blob Storageへデータを転送する方法です。

が、ほとんどの場合はMSの公式ドキュメント「Azure Data Factory を使用して Google Cloud Storage からデータをコピーする」で間に合っています。

ところが今回、GCSの特定のバケットにのみ閲覧権限を付与してデータを引っ張りたいと思ったら意外に苦労したので、その備忘録です。なお、当方はAzure初心者ですので、もしかしたら当たり前のことなのかもしれませんが、その辺は割り引いてください。

その前に、GCS。

GCSにて、とあるプロジェクトの中にたくさんバケットを持っている場合に、その中から選んで閲覧権限を付与したい場合があります。例えば、releaseバケットと、workバケットがあって、workは内部用として使っており、外部の人にはreleaseのみ閲覧権限を付与したいなど。

この場合、例えば次のどれかで可能です:
  • Google AccountをバケットのACLに登録する
    • これが一番簡単。閲覧権限を付与したい相手がGoogle Accountならば、それをバケット単位のアクセス制御リストに登録すればOK。Google Cloud Consoleのバケットの画面に「権限」タブがあるので、そこから登録できる。
  • Service Accountを作成して、アクセス条件をつける
    • Google IAMにてサービスアカウントを作成し、ストレージオブジェクト閲覧者のロールを付与。また、同時に「条件」にて、特定のバケット名を指定する。例えばバケット名が release ならば、resource.name == "projects/_/buckets/release" ||
      resource.name.startsWith("projects/_/buckets/release/") を条件に入れる。
  • ロールなしのService Accountを作成して、バケットのACLに登録する
    • IAMにて、Service Account作成の際にロールをなにも付与しないと、何もできないサービスアカウントができます。次にGCSのバケットの権限設定にて、そのサービスアカウントにストレージオブジェクト閲覧者の権限を付与すればよいです。
もっと他にもあるかもしれませんが。

さて、これらのアカウントをAzureから見えるようにします。

GCSのコンソールから「設定」「相互運用性」に行って、HMACキーを作成します。Google Accountならば一番下の「ユーザーアカウントのHMAC」から。サービスアカウントなら「サービスアカウントのHMAC」から。HMACキーを作ると、アクセスキーとシークレットがもらえるので、これを記録しておきます。


次にAzure Data Factory。ここもほぼ公式ドキュメントと一緒です。

Data Factoryを立ち上げて、「Manage」「Linked Service」「+New」でNew Linked Serviceが沢山出てくるので、その中から Google Cloud Storage (S3 API) を選択します。


すると、Access Key ID とSecret Access Key を入れる画面になるので、ここに先ほど作成したHMACのアクセスキーとシークレットを入れます。また、service URLにはHMACキーを作った場所に書いてあったリクエストエンドポイント「 https://storage.googleapis.com 」を書きます。名前は適宜、runtimeはそのままでOK。


記入したらCreateするのですが、ここで注意。

「Test Connection」は失敗しますが、気にしない。


ここがはまりポイントでした。Google Account(ユーザーアカウント)を使っている場合はここは成功するのですが、サービスアカウントを使っていて、かつ限定的な閲覧権限しか付与していないと、failします。ドキュメントには「storage.bucket.getとstorage.bucket.listがいるよ」と書いてあるのですが、読み取れるバケットを制限しているので、閲覧権限にそれらを付与してもうまくいきませんでした。(例えば、上の二つ目の方法、サービスアカウントを閲覧+bucket.get, bucket.listでロールを付与し、条件をつけなければ、ここがsuccessしますが、条件をつけるとNG。)

さて、Data Factoryでデータ転送するには、Azure Blob Storageの方もLinked Serviceに入れておかなきゃとのことで、+NewからAzure Blob Storageを選んで作成。

つぎに、一番左に戻って「Author」からDataSets→New Dataset→ Google Cloud Storage(S3 API) → Binary を選んで、Linked Serviceに先ほど作成したGCSのLinked Serviceを指定。これがデータソース。また、シンクとして同様にAzure Blob Storageも作ります。

DataSetsの下に先ほど作ったDatasetが現れるので、パスなどを指定。ここで、GCSのDatasetは、[Browse]をおしてもLoading Errorになります。先ほど、Test Connectionでエラーが出たのと同じ理由です。もし繋がっていると、ここでバケットの選択画面になるのですが、バケット一覧のアクセス権限がないのでダメなのだろうと思います。よって、Browseを押さずにFile Pathを埋めます。Containerの欄にバケット名を、Directoryのところにファイルパスを、Fileのところにファイル名を入れます。Directoryまで入っていれば、Fileは空欄でもワイルドカード扱いしてもらえるようです。

Blob Storageの方も同様に、Containerにコンテナ名をいれて、後は適当に指定します。

最後に、New Pipeline でパイプラインを作成して、Move And Transformから「Copy Data」をドロップ。選択すると出てくるメニュー画面から、SourceとSinkをそれぞれ先ほど作ったDatasetで指定して、「Publish All」し、Add Trigger → Trigger Nowで実行しますと、データがGCSからBlob Storageへ流し込まれます。

以上です。

ほぼ公式ドキュメントと同じなのですが、ポイントは「Connection Failed」でも気にしないというところでした。