ブログのしゅーくりーむ

技術的なメモとかライフログとか。

Cloud Dataflow の FlexTemplate は何者か

先月、さらりと Cloud Dataflow に FlexTemplate という新機能のベータ版がリリースされました。

cloud.google.com

残念ながらまだあまりドキュメントがなく、これを用いるとなにが嬉しいのかが掴みにくいところです。 本記事では FlexTemplate 周りを軽く試してどのような機能で何が嬉しいのか探ってゆきます。

従来のテンプレート

Cloud Dataflow はジョブの一部パラメータを実行時に置き換え可能にしたビルド済みのテンプレートを作ることができます。 また Google はこの機能を用いた公式テンプレートを何種類か用意してくれており、 GCP 上のリソースに対してコーディングなく ETL 処理をすることが可能になっています。

cloud.google.com

ちなみにこのテンプレートの機能なのですが、 FlexTemplate の登場の都合からかドキュメント上で "従来のテンプレート" という見出しになってしまったようです。。。

f:id:syu_cream:20200512002131p:plain

実行時にパラメータを置き換え可能にするには、その値を ValueProvider でラップしてあげる必要があります。 ValueProvider の実装としてテンプレートのステージング時に静的に値が決まる StaticValueProvider と実行時に決まる RuntimeValueProvider が存在しており、これによりパラメータを渡すタイミングを柔軟に選べます。 また Apache Beam の SDK 内の IO 関連ビルダークラスには ValueProvider を受け取って振る舞いを変えてくれるものが多々あります。

beam.apache.org

逆に言うとこの ValueProvider で賄えないような性質のパラメータは実行時に指定可能なパラメータとして扱えません。 これは分かりやすい部分で言うと Beam の SDK のインタフェース的に ValueProvider を受け取ってくれないような部分、もっと複雑な例で言うと内容によってパイプラインのグラフが変わるようなパラメータは扱えません(あるいは扱うのが困難)

FlexTemplate

FlexTemplate は、おそらくなのですが、与えられるパラメータに柔軟性を与えるものです。 ドキュメントだけでは正体が定かにはならないですが、 gcr.io/dataflow-templates-base/java11-template-launcher-base をベースとした Docker image を用いて Dataflow ジョブを実行するようになります。 テンプレートジョブの構築手順は「従来のテンプレート」に似ており FlexTemplate によるテンプレートの作成と、実行の 2 つのフェーズがあります。

前者では前述の Docker image を GCR に push して、かつその Docker image で解釈可能なパラメータを示した metadata.json を GCS に upload します。 Docker image の build & push は従来のテンプレートでは存在しなかった手順ですね。

https://cloud.google.com/dataflow/docs/guides/templates/using-flex-templates#creating_a_flex_template

後者では実際にパラメータを与えてジョブを実行します。

cloud.google.com

このジョブの実行時に興味深いことに、ジョブの launch 用に GCE インスタンスが開始され先程作成した Docker image が実行されることが見て取れます。 この Docker コンテナの動作がよくわからないところですが、内部的にはこのタイミングから Dataflow ジョブのステージングと実行を開始してくれるものと考えられます。

f:id:syu_cream:20200512004846p:plain

#cloud-configs
...
    ExecStart=/usr/bin/docker run -v /var/log/dataflow/template_launcher:/var/log/dataflow/template_launcher gcr.io/xxx/samples/dataflow/streaming-beam-sql --template-container-args='{"consoleLogsLocation":"gs://xxx/staging/template_launches/xxx/console_logs","environment":{"region":"us-central1","serviceAccountEmail":"xxx","stagingLocation":"gs://xxx/staging","tempLocation":"gs://xxx/tmp"},"jobId":"xxx","jobName":"streaming-beam-sql-20200512-004931","jobObjectLocation":"gs://xxx/staging/template_launches/xxx/job_object","operationResultLocation":"gs://xxx/staging/template_launches/xxx/operaton_result","parameters":{"inputSubscription":"test","outputTable":"foo:bar.baz","stagingLocation":"gs://xxx/staging","tempLocation":"gs://xxx/tmp"},"projectId":"xxx"}'
...

さてこの FlexTemplate で何が嬉しいのかというと、大きな差異として実行時パラメータを ValueProvider で包む必要が無くなった点があります。 FlexTemplate を利用したジョブのサンプルがいくつか公開されているのですが、この内の PipelineOptions の getInputSubscription() など、実行時に指定可能なパラメータでありつつも ValueProvider 型で扱われていないことが見てとれます。

github.com

これにより、従来のテンプレートでは課題になっていた ValueProvider を受け取ってくれないような値を実行時に変更したいだとか、パイプラインの構造が変わるようなパラメータを渡したいような部分に効果を発揮するものと思われます。 とは言ってもデメリットもあり、ジョブが Queue に入ってから Running の状態になるまで数分待たされる(ステージングのタイミングが遅延したのなら妥当に思えるが)だとか、今のところ Streaming Engine や FlexRS のサポートがないとか課題が存在します。

終わりに

軽く触れてみた限り FlexTemplate はシンプルな仕組みながら Dataflow のテンプレートに相当な柔軟性を持たせることができそうです。 FlexTemplate にどこまでを期待して、どのように従来のテンプレートと棲み分けすべきかのか(上位互換の位置付けなのか?)、今後のサポート具合など気になるところですね。