ビルドは一度、ダイジェストで昇格:ロールバックできるデリバリーパイプライン
stagingでテストした成果物が本番とまったく同じで、ロールバックは前のダイジェストの再デプロイになる、リファレンスのデリバリー経路。
例は汎用的なもので、説明を目的としています。どの顧客環境から取ったものでもありません。しきい値や設定はご自身のシステムに合わせて調整してください。
環境ごとに再ビルドすることの問題
環境ごとにアプリケーションを再ビルドするパイプラインは、ある成果物をテストし、別の成果物をリリースしています。依存関係の解決結果が変わり、ベースイメージが更新され、ビルドフラグが異なる——結果として、本番のバージョンはどこでもテストされていません。ビルドは一度だけ行い、成果物に不変の識別子を与え、その識別子を昇格させます。
リファレンス経路
コミットから本番までの汎用的な経路です。各段階は同じ成果物を次へ渡すか、そこで止めます。
- 01コミットレビューと必須チェックを伴うプルリクエスト。
- 02ビルドコミットごとに1回のビルド。イメージをプッシュし、ダイジェストを記録。
- 03検証テスト、依存関係とイメージのスキャン、署名。
- 04Stagingダイジェストをデプロイし、スモークテストと結合テストを実行。
- 05本番同じダイジェストを段階的にロールアウト。
- 06観測エラーバジェットとアラートが判断:続行かロールバックか。
タグではなくダイジェスト
latestやv2のようなタグは可変のラベルです。ダイジェスト(sha256:…)はイメージの内容のハッシュです。デプロイマニフェストはダイジェストを参照し、パイプラインはその1つの値を変えることで環境を昇格させます。理想的にはデプロイ用リポジトリへのコミットとして行い、すべてのリリースをレビュー済みで元に戻せる変更にします。
# build once and record the digest
docker buildx build --push --metadata-file meta.json \
-t registry.example.com/api:"$GIT_SHA" .
DIGEST=$(jq -r '."containerimage.digest"' meta.json)
# promote: every environment receives the same digest
kustomize edit set image api=registry.example.com/api@"$DIGEST"
データベースの変更:拡張してから縮小する
コードのロールバックが簡単なのは、スキーマが前のバージョンにもまだ合う場合だけです。互換性のないマイグレーションは、それぞれが稼働中のコードと互換になるステップに分けます:新しい列やテーブルを追加し、両方に書き込むコードをデプロイし、データを埋め戻し、読み取りを切り替え、古い構造は後のリリースで初めて削除します。
プログレッシブデリバリーとロールバック
- まずトラフィックやレプリカの一部にロールアウトし、エラー率とレイテンシを現行バージョンと比較します。
- 判断をSLOに結びつけます:ロールアウト中にバーンレートが高ければ、昇格は自動的に止まります。
- ロールバックとは、前のダイジェストを同じ検証済みの経路で再デプロイすることであり、プレッシャーの中で書いたホットフィックスではありません。
- 設定とシークレットはイメージの外に置き、同じ成果物がすべての環境で動くようにします。