継続的インテグレーションを活用した最新のデータ ウェアハウス開発
執筆者: Naval Tripathi (Senior Software Engineer, Microsoft IT)
このポストは、1 月 25 日に投稿された Modern Data Warehousing with Continuous Integration の翻訳です。
今回の記事は、マイクロソフトの IT 部門で SWE リード主任を務める Mohit Chand と共同で執筆しました。
マイクロソフトは、API (.NET) ベースのアプリケーションで普及が進んでいる「継続的インテグレーション (CI)」という、従来の開発手法を進化させた手法をデータ ウェアハウス開発に導入することにしました。データ ウェアハウス チームでは長い間、最新のソフトウェア エンジニアリング手法を取り入れられていないことが課題となっていましたが、Visual Studio Online (VSTS) や SQL Server Data Tools (SSDT) の登場により、環境をすばやくセットアップしたり、自動化を最大限に活用して複数の環境でコードをデプロイしたりすることが簡単にできるようになりました。こうした最新手法を取り入れた結果、ビジネス分析 (DW) プロジェクトでのエンジニアリング関連の効率が大幅にアップし、2 週間という短いリリース間隔の DW デプロイメントを実現することができました。この記事では、データ ウェアハウスに継続的インテグレーションを実装する手順について詳しく説明したいと思います。具体的には、コードのブランチの作成、プル リクエストによるビルドのトリガー、Azure のリソースや環境のプロビジョニング、スキーマのデプロイメント、シード データの生成、自動テストによる統合環境への毎日のリリース、承認ベースで新しいコードを上位の環境に昇格させるワークフローなど、ビジネス ユーザーのライフ サイクルを説明します。
DevOps
なぜ DevOps がよいのでしょうか? 従来の開発・運用モデルでは、ソフトウェアが期待どおりに動作しない場合に原因を正確に突き止められず、関係者の立場の違いから混乱や言い争いが起きることがありました。開発側は「ソフトウェアは正常に動作しているから、運用に問題があるのではないか」と訴え、運用側は「ソフトウェアの出来が運用に耐えられないものだから、開発に問題がある」と訴えます。このような事態を避けるためには、開発、テスト、運用までの工程を 1 つのチームで行うことが理想とされます。
私たちは、お客様により優れた製品を迅速にお届けするために、ビジネス部門やその他の関係者と密接に連携して業務を効率化しています。DevOps では、製品をより迅速にお届けし、お客様とのつながりを強化すると同時に、技術的負債やリスクを軽減することが可能です。
DW アーキテクチャ
このデータ ウェアハウスでは Azure テクノロジを使用しています。データは、さまざまな送信元から Azure Data Factory を通じて受信領域やステージング領域に届けられます。ここでは、Azure Data Factory (ADF) のジョブを使用してデータの加工や変換を行い、データ ウェアハウスに格納します。準備が完了したら、このデータはディメンション テーブルやファクト テーブルの形でユーザーがアクセスできるようになります。
ツールとテクノロジ
この最新のデータ ウェアハウスでは、次のような各種マイクロソフト テクノロジを使用してユーザーにソリューションを配信しています。
- SQL Azure (PaaS)
- Azure Data Factory
- Azure Blob Storage
- SQL MDS 2016
- Visual Studio Team Services (VSTS)
- アジャイル機能とかんばんボード
- コードのブランチの作成 (Git)
- ゲート チェックイン
- 自動テスト
- ビルド
- リリース
計画
アジャイル スクラム開発では、ユーザー ストーリーが実装の単位となります。エンジニアは、各スプリントでユーザー ストーリーを選択し、配信します。
コード
ブランチ作成戦略
アジャイル開発では、コードのブランチ作成が重要なカギとなります。ブランチ作成には、スプリント ブランチ、機能ブランチ、ストーリー/バグ ブランチなどさまざまな種類があります。私たちは、ユーザー ストーリー レベルのブランチを作成することにしました。協力者は、各自が選択したストーリーに使用するブランチを “develop” ブランチから作成します。ストーリーを完了させるかコード レビューの準備を完了させ、develop ブランチで「プル リクエスト」を作成してマージするまでは、協力者が責任を持って分離させたブランチを維持します。協力者は、メイン ストリーム ブランチにコードを直接マージすることは許可されておらず、少なくとも 2 人のコード レビュー担当者の承認を受ける必要があります。
ストーリーごとにブランチを作成すると、コードを頻繁にメイン ストリームにマージできるようになるため、同一のブランチで長期間作業を行うことを避け、コード統合時に発生する問題を大幅に削減することができます。もう 1 つのメリットとしては、他の開発者のコードを頻繁に取り入れられるようになるため、開発作業がさらに効率化するということがあります。依存するコードを待つ時間が短くなり、開発者にとって無駄な時間が減少します。
以下のように、協力者は VSTS でブランチを新規作成します。
命名規則は、<協力者名>_<ストーリーまたはバグ> となります。
ブランチを作成したら、公開して、他のメンバーからもアクセスできるようにします。
ブランチを設定したら、そのストーリーでの作業の準備はすべて完了です。次にコードを作成して、機能を実装する作業を開始します。
コードのレビューとマージ
コードが完成したら、開発者はコードをチェックインし、VSTS ポータルからプル リクエストを作成します。コードの品質を高く保つために、必ずゲート チェックインを行う必要があります。コードをチェックインするときは、ビルドが破損していないことを必ず確認します。コードをメイン ストリームにマージするには、少なくとも 2 人のレビューを受けて承認してもらう必要があります。コード レビューで 2 人以上の承認を受けないと、ブランチで作成したコードをメイン ストリームのコードにマージすることはできません。
開発者は、プル リクエストを作成し、適切なコメントと作業項目を送信します。
ビルド
協力者が「プル リクエスト」を作成するとすぐに継続的インテグレーションのビルドがトリガーされます。
協力者が新しい「プル リクエスト」を作成したことが、すべてのレビュー担当者にメールで通知されます。レビュー担当者はコードのレビューを開始します。
レビュー担当者は、コードのレビュー内容に応じて「承認」と「拒否」の判断や、質問を行います。
すべてのレビュー担当者がコード レビューを完了したら、開発責任者がコードをメイン ストリームにマージします。
テスト (自動)
DW プロジェクトでは環境ごとにデータが異なるため、あらゆる環境でコードの品質を高く保つことは難しい場合があります。そのため、作成したコードのすべての新規部分に対して、プル リクエストが作成される前に自動的にテストが実行されるようにします。これにより、製品にバグが残ったまま運用環境に入ることを防止できるほか、配信される製品の品質確保にも役立ちます。
下の図は、テスト ケース全体を実行した場合の結果を示しています。デプロイメント工程の 1 つとしてすべてのテスト ケースを実行し、最終製品の整合性と品質を確保します。
リリースとデプロイ
メイン ストリームのコードへのマージが完了したら、新規作成されたコードが自動的にビルドされます。統合 (Integration) 環境には、最新のコードが毎日デプロイされます。
上の図は、この記事のデータ ウェアハウスで管理している 3 つの環境を示したものです。このデータ ウェアハウスには「統合 (Integration)」、「エンドユーザー (EndUser)」、「運用 (Prod)」の 3 つの環境が存在します。統合環境は、継続的に統合とデプロイメントが実施される環境で、動的にプロビジョニングとプロビジョニング解除が実施され、「コードとしてのインフラストラクチャ (Infra as a Code) 」として管理されます。チェックインの「統合」では、設定されたスケジュールに従って毎日以下の手順が順番に実行されます。
- 最新のコードを develop ブランチから取得してビルド (統合されたコードのスキャンを含む)
- 新しい Azure Resource Group を作成し SQL インスタンスを新規作成
- 新規作成された SQL インスタンスを「シード データ」にコピー
- スキーマ名を変更
- DACPAC ファイルをデプロイして変更されたスキーマをデプロイ
- データベースをスケールアップして各手順を高速化
- コードをコピーしてサーバーをビルド
- SQL エンティティを追加デプロイ
- データ同期ジョブを実行
- テスト アセンブリを実行
- Azure Data Factory をデプロイ
- 環境を削除
自動テスト用シード データ
DW で自動テストを実施するには適切なデータにアクセスできることが不可欠です。このデータがなければ、実施できないテストが多数あります。そのためデプロイメント工程では運用環境からコピーしたデータを「シード データ」として使用します。下の図は、毎日統合が実施される環境 (DIT: Daily Integration Environment) でシード データを作成する方法を示しています。データの規模がきわめて大きい場合は、運用環境のデータ全体の複製をコピーするのではなく、一部を含む小規模なデータベースを使用します。
手順 1: DW 環境 (ステージング環境や変換されたデータなど) に分離する、複数のスキーマを含む運用環境のデータ
手順 2: データを Azure ジオ レプリケーションにコピー (災害復旧用コピー)
手順 3: リリースのデプロイメント中に、ジオ レプリケーションの複製を新規作成された DIT SQL Server インスタンスにコピー
手順 4: 運用環境と同一内容のデータのコピーが利用可能に。また、スキーマを新たに追加する際には DACPAC がデプロイされ、その後、自動テスト スイートによって最終製品の品質テストを実施
リリースを上位の環境にデプロイ
ある環境から他の環境にリリースを昇格させる場合には、承認が必要で、直接デプロイすることはできません。このシナリオでは、事前に指定された他の関係者による承認を受けないと Prod 環境にデプロイできません。
上の図は、上位の環境に昇格する場合の承認ワークフローを示しています。上記のワークフローで必要な承認が得られた場合、リリースは次の環境に自動的に昇格します。
監視
DevOps では、運用段階以前の環境での問題と運用環境での問題の両方を同じチームが監視します。私たちはこのシナリオで DRI (直接責任者) モデルを採用し、DRI がシステムの正常性やあらゆる通知の監視と確認をプロアクティブに実施するようにしました。問題が発生した場合は優先順位を付けて修正を行い、アプリケーションの可用性を維持します。また、そのままの状態で使用可能な ADF の監視機能と通知機能と、いくつかのカスタムの監視ツールを使用します。さらに、運用環境ではレポートが毎日自動生成され、複数のデータ品質チェックが実行されて、データの異常が報告されます。それらはバグとして現在のプロセス内で修正されるか、すぐに元のシステムにフィードバックされ、そちらで修正されます。
データ ウェアハウスへの継続的インテグレーションの導入は簡単なことではありませんが、その努力に見合った価値を得られます。各スプリントで新しいコードを追加したときにテスト ケース自体で異常が発生するということも経験しましたが、チームではこのインスタンスの調査を行い、今では新しいコードの追加の際に既存のテスト ケースを更新するようにしました。今後も機能やビルド、環境検証用のテスト ケースを継続的に追加して、着実に製品の品質向上に努めたいと考えています。継続的インテグレーションは、完全なアジャイル開発を実現し、自信のある最終製品をリリースするために不可欠な手法です。また、一般的なバグを運用環境に持ち込まないために、自動テスト スイートを実行します。さらに、これから数四半期の間には、テスト環境の必要性をなくし、運用環境に直接デプロイできるようにしたいと考えています。私たちはこうした目標に向けて、今後もチーム一丸となって取り組んでまいります。