DatabricksとAWS CodePipelineによるサーバーレス継続的デリバリー

[Serverless Continuous Delivery with Databricks and AWS CodePipeline \- The Databricks Blog](https://databricks.com/blog/2017/07/13/serverless-continuous-delivery-with-databricks-and-aws-codepipeline.html)の翻訳です。

:::note info
2017年時点の記事です。
:::

一般的に、二つの特性が多くの企業を成功に導いています。第一に、彼らは新技術をクイックに適応しています。第二に、結果として、技術的なリーダーシップを獲得しマーケットシェアを拡大しています。迅速に洞察をアクションにつなげることができる企業は、自身の競争において大きな優位性を維持しています。迅速かつ繰り返し可能な方法で、分析を活用するための鍵は、複雑なデータアプリケーションに対して開発からプロダクションへの移行を容易にするための、堅牢な継続的インテグレーション(CI)、継続的デリバリー(CD)システムとなります。

Databricksのインタラクティブなワークスペースは、コラボレーティブな開発とインタラクティブな分析に対する理想的な環境となります。このプラットフォームは、継続的デリバリーパイプラインの作成を実現するだけでなく、シンプルにするために必要な全ての機能をサポートしています。この記事では、サーバーレスCI/CDを用いて、完全なエンドツーエンドのパイプラインを提供するために、どのように[Databricks](https://databricks.com/jp/)と[AWS CodePipeline](https://aws.amazon.com/codepipeline/)を活用するのかをウォークスルーします。

# パイプラインの4つのステップ

シンプルなシナリオを考えましょう。最初に、ノートブックで作業している開発者がGitHubの開発ブランチに対してコミットを行います。これによって、自動でCodePipelineによる以下の4つのステージの順次実行をキックします。

- ソース - GitHubからブランチをプル
- ステージング - Jobs APIがDatabricksにおけるインテグレーションテストジョブを起動
- 承認 - メールを通じてレビュー依頼をQA(品質保証)に通知
- デプロイメント - レビューを通過後、Workspace APIを用いて、プロダクション目的のためにS3にライブラリがアップロードされ、ノートブックがDatabricksにデプロイされます。
![image3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/252a1633-e2c5-9691-400a-a764949249fb.png)

この例では、ユーザーによるDatabricksノートブックのコミットから構成されており、ビルドステージは含まれていません。しかし、CodePipelineは最も人気のあるビルドシステムのいくつか(Jenkins、Solano、CodeBuild)をサポートしており、これらの実装もよくドキュメント化されています。

## ソース

パイプラインの設定の最初の一歩は、ソースの指定です。CodePipelineは現状3つのソースをサポートしています。Github、S3、CodeCommitです。DatabricksはGitHubとのインテグレーションをビルトインしているので、シームレスにCodePipelineを自動化を行うことができます。DatabricksをGitHubにリンクする際に用いたものと同じトークンで、GitHubの特定のブランチをCodePipelineをリンクすることができます。データサイエンティストとデータエンジニアは、Databricksワークスペースから直接[GitHubにノートブックをコミット](https://docs.databricks.com/user-guide/notebooks/github-version-control.html)することができます。ノートブックがコミットされた際にパイプラインを自動で実行できるように、CodePipelineは継続的にブランチをモニタリングします。
![image8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/86c6bc68-ea9f-93fc-6131-fa43c1c013e9.png)

## ステージ

この時点でコードはコミットされ、インテグレーションテストを実行する必要があります。Apache Sparkのジョブのテストの一般的な方法は、既知のデータセットに対して処理を行い結果を比較するというものです。ベストプラクティスは、実行モード(prod、testなど)に基づいてノートブック上の変数を設定できるようにセットアップするというものであり、これは[Databricksのウィジェット](https://docs.databricks.com/user-guide/notebooks/widgets.html)で設定することができます。例えば、ソース、ターゲット、モードのウィジェットを用いて、テストモードで実行するようにノートブックをセットアップします。
![image1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/7919fb25-1dcf-6c88-1b61-9536130f992f.png)

ノートブックをテストのために実行する際、ソースはS3のテストデータセットとして定義され、ターゲットはS3のテスト出力先となります。モードが`test`と設定された際、ノートブックはデータが書き込まれたS3の場所を返却し、これはDatabricksの[Utils Notebook runコマンド](https://docs.databricks.com/user-guide/notebooks/notebook-workflows.html)で捕捉することができます。この戻り値は、通過/失敗ステータスを提供するデータフレーム比較関数に引き渡されます。
![image2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/0675b239-d8d6-e390-7d5c-2a392412837a.png)

これは複雑のように聞こえますが、[Jobs API](https://docs.databricks.com/api/latest/jobs.html)を用いることで、Jobsの呼び出し、パラメーターの引き渡しが非常に容易にすることができます。このステージは、実際のところ3つのAPIのみで実行されます。[runs now、runs list、runs get](https://docs.databricks.com/api/latest/jobs.html)です。Run nowにはJobのIDのみが必要となります(ジョブのパラメーターはオプションです)。ジョブが実行されると、`runs get`でポーリングすることができます。これによって、次にステップに移行することができます。このステージはAWSのLambda関数を起動して実行することができます(私はこれをサーバーレスといいましたよね？)。
![image9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/ef63c06f-2553-1ee5-dad8-505238121260.png)

このアプローチにおける唯一のハードルは、Lambdaの300秒の期間のリミットへの対応ですが、幸運なことにCodePipelineはすでに継続トークンによってこの問題を解決しています。Lambda関数は3つのステータスのいずれかをCodePipelineに返却します。成功、失敗、継続です。継続トークンがCodePipelineに返却された際には、再びLambda関数を起動し、関数が再度起動されたことを示すインジケータを含めます。これは、単にモニターされる必要があるだけであり、すでに実行されているジョブを再起動する必要はありません。
![image5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/d48936c1-a04f-4948-9136-1cd54ae81943.png)

継続トークンの利用を通じて、開発者はもはや300秒制限に縛られることはなく、ジョブを無限にポーリングすることができます。しかし、ジョブにタイムアウトを設定することが最良です。

## 承認

CodePipelineは、パイプラインを継続する前にコミットを取り消す必要がある人に対して通知を送信する承認ステージを提供しています。これにより、開発者はレビューを行う対象のURLリンクを送信することができます。これにより、GitHubのリポジトリの場所に加え、Databricksにおけるジョブのアウトプットを含めることができます。
![image6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/0d254ac6-5c21-2423-6e65-16613fe31ec1.png)

これはSNSのトピックに紐づけられており、最初にSNSのサブスクリプションを作成する必要があります。これは基本的にメールをの送り先を割り当てます。パイプラインはテストジョブを通過した場合にのみ承認ステージに到達するので、失敗した際に即時のフィードバックを取得するためには、Databricksにおけるジョブの失敗時のアラートを設定すべきです。

## デプロイ

これでコードが承認されたので、デプロイを行う必要があります。インテグレーションテストのように、デプロイメントはLambda関数の起動によって実行されます。CodePipelineにおいては、ソースコードはアーティファクト、およびステージ間でやり取りされる場所情報がzipされた状態でS3に保存されます。このため、最初のステップはファイルの解凍となります。Lambdaのメモリーの制限を理解し、多くのリポジトリは単にノートブック、ライブラリから構成されるわけではないことを知っているので、ファイル名を読み込み、適切な拡張子、ファイルパスにマッチするファイルのみを解凍するのが最良となります。

ノートブックは、ワークスペースAPIを用いて特定のDatabricksワークスペースにデプロイされます。ワークスペースAPIは、ノートブックのインポート/エクスポート、ディレクトリの作成などの基本的なファイルシステム機能を提供します。これは二つのAPIコールで実現されます。ImportとMkdirsです。ノートブックをインポートする際に注意すべきことがいくつかあります。第一に、ノートブックのコンテンツはbase64エンコーディングで送信されるので、データファイルはエンコードする必要があります。
![image4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/9c3d6c4c-3764-8e3f-0262-0828cbcf1e91.png)

第二に、ベースのディレクトリが存在していない場合インポートが失敗します。エラーレスポンス400を返し、エラーメッセージは`RESOURCE_DOES_NOT_EXIST`で始まるものになります。ディレクトリを作成し、再度インポートしてください。
![image7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/5ade5d9f-fd0b-0358-babf-ba9449bd53a8.png)

ライブラリをワークスペースにインポートすることに加え、Databricksは[S3](https://docs.databricks.com/api/latest/libraries.html)からのライブラリの直接呼び出しをサポートしています。これによって、S3で作業したいというチームに追加の選択肢を提供します。例えば、ノートブックをワークスペースにインポートしている間に、ファイルの拡張子を読み込み、.jarや.eggファイルを指定のS3バケットとキーに書き込みことができます。このバケットにおいてはS3のバージョン管理機能をオンにすべきです。

# まとめ

お客様の進化するニーズに応え続けるためには、企業は価値を素早く提供できる迅速な開発プロセスを活用する必要があります。堅牢な継続的デリバリーパイプラインは、お客様を幸せにしつつデリバリーに要する時間を削減することができます。上で説明した通り、Databricksは堅牢かつサーバーレス、コスト効率性の高い継続的デリバリーモデルを構築するためにCodePipelineとインテグレーションするために必要な全てのツールを提供します。

Databricksに関する詳細を知りたいのであれば、[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)を始めてみてください。

### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)