Status | Authors | Coach | DRIs | Owning Stage | Created |
---|---|---|---|---|---|
implemented |
@abrandl
|
@glopezfernandez
|
@fabian
@craig-gomes
| devops data_stores | 2021-02-08 |
データベーステスト
お知らせこのブループリントは部分的に実装されています。ツールについてはまだ反復する予定です。以下の内容は、データベース テストを開発ワークフローに組み込む前に書かれた、ブループリントの歴史的バージョンです。
私たちは、マイグレーションが元に戻るという共通のテーマを特定し、開発者環境で正常にテストされた場合でも、本番環境とステージングの両方でマイグレーションが壊れることを発見しました。また、ステージング環境でのテストが成功しても、本番環境でのインシデントが発生することもありました。このような障害は、可用性に大きな影響を与え、デプロイをブロックし、インシデントのエスカレーションを発生させる可能性があります。これらのエスカレーションはトリアージされ、リバートされるか、前倒しで修正されなければなりません。多くの場合、これは時間帯やエスカレーションの重要性のために、元の作成者が関与することなく行われます。デプロイのスピードが上がり、アップタイム要件が厳しくなるにつれ、データベーステストを改善する必要性が、特に開発プロセスの早い段階(左シフト)で重要になっています。
開発者の立場からすると、本番稼動前に十分な規模のデータセットでマイグレーションを検証することは、実現不可能ではないにせよ、困難です。
私たちの主な目標は、本番データベースの完全なコピーでテストされた新しいマイグレーションやその他のデータベース関連の変更について、開発者に即座にフィードバックを提供し、高い効率性(特にインフラコストの面で)とセキュリティでこれを行うことです。
現在
開発者はどのような環境にもデプロイする前にデータベースマイグレーションをテストすることが期待されていますが、GitLab.com のような大規模な環境に対してテストを実行する能力がありません。開発者データベースマイグレーションスタイルガイドはマイグレーションに関するガイドラインを提供しており、私たちはコードレビューやCIやステージングでのテスト時にマイグレーションを検証することに重点を置いています。
コードレビューフェーズでは、データベースレビュアーとメンテナーがコミットされたマイグレーションを手動でチェックします。これには、GitLab.com 上で問題となるパターンやその特有の挙動を経験から知り、発見することがよく含まれます。データベースのマイグレーションをマージする前にテストできるような大規模な環境はありません。
CIでのテストは非常に小さなデータベースで行います。私たちは主にマイグレーションの整合性をチェックし、よく知られている問題のある動作を検出するために RuboCop のルールを評価し(静的コードチェック)、その他いくつかの技術的なチェックを行っています(正しいファイルの追加など)。つまり、通常、コードやその他の単純なエラーは見つかりますが、データ関連のエラーは表面化できません。
マージ後、マイグレーションはステージング環境にデプロイされます。そのデータベースサイズは2021年1月現在、本番データベースサイズの5%未満で、最近のデータディストリビューションは本番サイトに似ていません。ステージング環境ではマイグレーションが成功しても、本番環境ではクエリのタイムアウトやその他の予期せぬ問題で失敗することがよくあります。ステージングで問題を発見できたとしても、このような問題を調整するのはコストがかかるため、理想的には開発サイクルのできるだけ早い段階で問題を発見したいものです。
今日、私たちはシンクローニングされた本番データベースで作業する経験を積み(詳細は後述します)、開発者に本番クエリプランへのアクセス、自動化されたクエリフィードバック、最適化の提案を提供するためにすでに使用しています。これは、Slack(ChatOpsを使用)とpostgres.aiを通じて利用可能なDatabase Labと Joeを中心に構築されています。
ビジョン
開発者として:
- データマイグレーションを含むGitLabのコード変更に取り組んでおり、重いデータベースクエリを変更しています。
- コードをプッシュしてマージリクエストを作成し、説明にクエリの例を示します。
- パイプラインはデータマイグレーションを実行し、大規模環境 (GitLab.com のコピー) でクエリを調べます。
- パイプラインが終了すると、マージリクエストはマイグレーションと私が提供したクエリに関する詳細なフィードバックと情報を取得します。これは、本番環境に非常に近い状態(数分)の本番データベースの完全なクローンに基づいています。
データベースのマイグレーションでは、クローン上の実行から収集される情報には以下が含まれます:
- 全体的な実行時間。
- マイグレーションで実行されたクエリの詳細な統計(クエリを正規化し、その頻度と実行時間をプロットとして表示)。
- マイグレーション中に保持された危険なロック(本番環境でブロッキングが発生する可能性があります)。
データベースのクエリについては、自動的に収集することができます:
- 視覚化されたクエリプラン。
- 実行時間と本番の予測
- Joeからの最適化の提案。
- メモリとIOの統計。
そのフィードバックを得た後
- データマイグレーションに関するパフォーマンスの問題を調査することができます。
- 修正がプッシュされたら、上記のサイクルを繰り返し、最終的にデータベースレビューのためにマージリクエストを送ることができます。データベースレビューの間、データベースのレビュアーとメンテナーは、導入された変更のパフォーマンスについて十分な情報に基づいた判断を下すために、生成されたすべての追加情報を利用できます。
この情報収集は保護された安全な環境で行われ、本番データへの不正アクセスがないこと、この環境で安全にコードを実行できることを確認します。
意図する利点は以下の通りです:
- 左遷:開発者が大規模なデータベースのパフォーマンスやGitLab.comで何が起こるかをセルフサービスで理解できるようにします。
- 実際のデータ(不整合や予期しないパターンを含む)を使って本番スケールのデータセットに対して作業した場合にのみ発生するエラーを特定します。
- コードレビューに関わるすべての人(開発者、レビュアー、メンテナー)が容易になるように、情報収集フェーズを自動化します。
テクノロジーと次のステップ
私たちはすでにpostgres.aiのDatabase Labを使用しています。これはシンクローニング技術です。PostgreSQLのレプリカをメンテナーしており、そのレプリカは本番データで最新ですが、本番トラフィックには対応していません。Database Labを実行することで、本番データセットの完全なクローンを素早く作成することができます(数秒単位)。
内部的には、これはZFSに基づいており、「シン・クローニング・テクノロジー」を実装しています。つまり、ZFSスナップショットを使ってデータをクローンし、クローンされたデータに基づいて完全な読み書き可能なPostgreSQLクラスタを公開します。これはシンクローンと呼ばれます。これはかなり短命で、使い終わるとすぐにまた破棄されます。
シンクローンは完全に読み書き可能です。これにより、その上でマイグレーションを実行することができます。
Database Labはシンクローンを管理するためのAPIを提供しています。マイグレーションとクエリのテストを自動化するために、gitlab/gitlab-org
CIパイプラインにステップを追加します。これは、指定されたマージリクエストに対して以下のステップを実行する自動化をトリガーします:
- このテストセッション用に、本番データを含むシンクローンを作成します。
- マージリクエストから GitLab コードをプルします。
- マイグレーションを実行し、必要な情報を収集します。
- クエリのテストを実行し、必要な情報を収集します。
- マイグレーションとクエリテストの結果をマージリクエストにポストバックします。
- シン・クローンを破棄します。
短期
短期的な焦点は、定期的なマイグレーション(通常はスキーマの変更)のテストと、postgres.ai の既存の Database Lab インスタンスを使用することです。
このプロセスをセキュリティ保護し、コンプライアンス目標を達成するために、Runner環境は本番環境として扱われ、同様にロックダウン、監視、監査されます。データベースメンテナーのみがCIパイプラインとそのジョブ出力にアクセスできます。それ以外の人は、マージリクエストにポストバックされた結果と統計情報しか見ることができません。
私たちはオペレーション用の内部 GitLabに、上記の実行ステップを追加したセキュアな CI パイプラインを実装しています。このパイプラインをセキュアにすることで、次のような問題を解決するのが目的です:
本番データを含むシンクローン上で誰でも(GitLabチーム/開発者)が任意のコードを実行できるようにしながらも、本番データを確実に保護すること。
これは原則的に、コードを実行するGitLab Runnerインスタンスとそのコンテナをネットワークレベルでロックダウンし、データがネットワーク上に漏れないようにすることで実現します。GitLab Railsコード(とそのデータベースマイグレーション)を実行するコンテナ内から外部への通信が起こらないようにします。
さらに、ジョブの結果(コードから出力されたものを含む)を閲覧できるのはGitLab for Operations の内部パイプラインでメンテナーとオーナーレベルに限定し、元の MR にはハイレベルなサマリーのみを提供します。実行されたジョブのひとつにイシューやエラーがあった場合、MR のレビューを担当するデータベースメンテナーは、元のジョブで詳細を確認することができます。
このステップが実装されたことで、シンクローン化されたGitLab.comデータベースに対してGitLab CIから自動的にデータベースマイグレーションを実行し、マージリクエストと開発者にフィードバックを返す機能がすでにあります。そのフィードバックの内容は時間とともに進化していくことが予想され、私たちは継続的にこれを追加していくことができます。
パイプラインのための MVC スタイルの実装と、パイプラインからのフィードバックを含むマージリクエストの例がすでにあります。
短期的な目標はこのエピックに詳しく書かれています。
中期目標 - フィードバックの改善、クエリテスト、バックグラウンドマイグレーションテスト
中期的には、テストパイプラインがマージリクエストに報告する詳細なレベルを拡大し、その範囲をクエリのテストにも拡大する予定です。そうすることで、データベースのコードレビューやシンクローンテクノロジーを使った経験を活かして、GitLab のワークフローに近づけます。異なるツール(postgres.ai
、joe
、 Slack 、プランの視覚化など)に手を伸ばす代わりに、私たちはこれを GitLab に戻し、マージリクエストで直接作業します。
第二に、バックグラウンドマイグレーションのテストもカバーする予定です。これらは通常、長期間にわたって実行するようスケジュールされたデータマイグレーションです。スケジューリングフェーズとジョブ実行フェーズの両方が成功するかどうかは、通常、データのディストリビューションに大きく依存します。バックグラウンドマイグレーションに自信を持つために、以下のフィードバックを提供する予定です:
- スケジューリング段階 - クエリ統計(例えば、クエリ実行時間のヒストグラム)、ジョブ統計(ジョブ数、全体期間など)、バッチサイズ。
- 実行フェーズ - クエリと実行時間の統計情報を収集するために、ジョブのインスタンスをいくつか使用します。
長期段階 - GitLab製品に組み込みます。
ここから GitLab 自身に機能を抽出するために議論する機会があります。例えば、マージリクエストにクエリの例をアノテーションしたり、テスト実行から収集したフィードバックを添付したりすることは、マージリクエストの説明やコメントを使う代わりにファーストクラスの市民になる可能性があります。私たちは、以前のフェーズで使用されているのを見て、これらのアイデアを評価し、私たちの経験を製品に持ち帰る予定です。
議論された代替案匿名化
この問題の核心は、実運用データセット上で(潜在的に任意の)コードを実行し、実運用データが十分に保護されていることを確認することにあります。上述のアプローチは、コードの出力へのアクセスを強く制限することでこれを解決します。
私たちが議論し、断念した別のアプローチは、本番データを「スクラブ」して匿名化することです。これは、データベースから機密データを取り除き、その結果得られたデータセットをデータベースのテストに使用するというものです。これには多くの欠点があり、私たちはこのアイデアを断念しました:
- 匿名化は本質的に複雑であり、「スクラブされたクローン」を実際に公開で安全に扱うのは難しい問題です。また、一度に1つの属性に焦点を当てるだけでは、データセットが完全に匿名化される保証はありません(例えば、ジョイン攻撃や、公開プロフィール/プロジェクトにタイムスタンプを使用して、アクティビティによってユーザーを非匿名化するなど)。
- 匿名化には、データベーススキーマが変更されるたびに、機密とみなされる属性のセットを追跡して更新し、継続的なメンテナンスとセキュリティレビューを行うための追加プロセスが必要です。
- データを「機密」として注記することはエラーになりやすく、データ型に誤った匿名化アプローチを使用したり、ある機密属性が誤ってそのようにマークされなかったりして、データ侵害につながる可能性があります。
- スクラビングは機密データを削除するだけでなく、データのディストリビューションも変更するため、マイグレーションやクエリのパフォーマンスに大きく影響します。
- スクラビングによってデータベースの内容が大きく変更され、多くのデータが更新される可能性があるため、データ格納の詳細が異なり(MVCの肥大化を考えてください)、マイグレーションやクエリのパフォーマンスに影響します。