DevOps面接の質問:CI/CDの失敗から安全な変更と復旧を考える
Quick Overview
DevOps面接の質問を、成果物の照合と設定不足で失敗する独自サービスで練習します。27項目と18回のHTTP要求で、CI相当の成功、準備確認、変更条件、構成ドリフトを分離。旧版への切り戻しと設定修正で前進する案を、1332対1333の業務結果まで比較します。
DevOps面接の質問で「CIが成功したのにデプロイ後の確認が失敗したら」と聞かれたら、再実行の前に、何をテストし、何を配置し、どの設定で動かしたかを照合します。同じソースのつもりでも成果物のバイト列が違い、成果物が同じでも設定が違えば、成功したテストの条件から外れます。その差を調べずに再実行すると、同じ失敗を繰り返す可能性があります。
この記事では、金額のプレビューを返す小さなサービスを使います。新しい版だけが必要とする設定が欠け、プロセスの確認は200でも、業務のプレビューは503になります。テスト済み成果物を保ったまま設定を直す案と、旧版・旧設定へ戻す案を比較し、変更前に必要な証拠を説明します。
根拠の区分: 成果物や保護された環境、Deploymentの切り戻しの仕様は公式資料に基づきます。サービス、変更記録、承認条件は独自の演習で、Python 3.12.14による27項目と18回のループバックHTTP要求で検証しました。実際のCIプロバイダー、Kubernetes、本番環境、課金は操作していません。復旧の提案は推論です。候補者報告は使わず、企業の現行選考や合格基準も断定しません。

最初の回答は「変更の組合せ」を確認する
GitLabのDevOpsエンジニア解説は、一般的な面接質問としてCI/CD、構成管理、IaCなどを挙げています。これはGitLabの現行採用試験の問題一覧ではありません。準備では、その用語を一つの変更の追跡へつなげると、どの証拠を見て次の行動を決めるか説明できます。
今回のサービスはGET /previewで固定の小計1234に対する計算結果を返します。v1は端数を切り捨て、v2は四捨五入に相当するhalf_upを使います。どちらも演習用の最小単位の整数で、税務上の正しい計算方式を推奨する例ではありません。応答はpersisted=falseで、保存や請求を行いません。
| 確認対象 | v1 | v2 |
|---|---|---|
| 配布物 | 旧ZIP | テストした新ZIP |
| 共通設定 | TAX_RATE_BPS=800 | TAX_RATE_BPS=800 |
| 追加で必要な設定 | なし | ROUNDING_MODE=half_up |
| 正常なプレビュー | tax=98、total=1332 | tax=99、total=1333 |
| v2を旧設定で起動 | — | 業務確認が503 |
面接の最初に、「影響している操作はプレビューです。新旧の成果物と設定を並べ、テスト時と実行時の差を確認します」と答えられます。CPUやPod数から先に原因を決める必要はありません。まず、失敗している操作と比較対象をそろえます。
このケースで確認する変更は、ソースの版だけではありません。配布したファイル、実際に読んだ設定、適用先、変更前のリビジョン番号、期待する業務結果を一組として扱います。順番に名前を挙げるだけでなく、それぞれがどの観測へ結びつくかを示してください。
成果物の質問:テストしたバイト列を配置したと言えるか
GitHub Actionsの成果物の説明では、ジョブ間で出力を受け渡し、テストやデプロイに使う成果物を保存できます。同資料はSHA-256のdigestによる検証も説明しています。名称やソースのラベルだけでなく、実際の配布物を対応させるための情報です。
ローカル実験では、同じservice.pyと同じ演習用ソースラベルから、二つのv2 ZIPを作りました。片方のbuild記録はbuild-17、再作成したものはbuild-18です。ソースコードは一致していても、記録がZIPに入るため、配布物全体のハッシュは異なりました。
| ローカル配布物 | SHA-256の先頭12桁 | 確認できたこと |
|---|---|---|
| テストに使ったv2 ZIP | bb8333c4b2c7 | 正しい設定でtotal=1333 |
| 再作成したv2 ZIP | 5301204b715e | service.pyとソースラベルは同じ、全体のバイト列は別 |
表では読みやすく先頭だけを示していますが、検証には64桁全体を使いました。fixture-source-A7というラベルは実Gitコミットではありません。また、ZIPのハッシュはコンテナイメージのdigestや署名付きの証明とは別のものです。
「同じコミットだからテスト済み」と言う前に、ビルド時の依存、生成物、設定の組込み方などを確認する必要があります。この実験が直接示したのは、同じソースでもbuild記録の違いだけで配布物が変わることです。依存の差や再現可能ビルドの達成までは検証していません。
復旧案ではテストしたZIPを再利用し、再ビルドを挟みませんでした。ハッシュ一致はバイト列の対応を示しますが、そのバイト列が安全、正しい、信頼できる作者のものだと単独で保証するわけではありません。取得元と実行履歴を確かめる話と、改変検出の話を分けます。
設定の質問:CIの成功条件と実行時の条件は同じか
v2を正しい設定で起動するローカルのスモーク検証は成功し、total=1333を返しました。一方、同じZIPを旧設定で起動すると、ROUNDING_MODEがないため503になります。今回の「CI成功」はCI相当のローカル検証であり、実サービスのCIジョブを実行した記録ではありません。
| HTTP確認 | 正しいv2設定 | 旧設定を渡したv2 |
|---|---|---|
/healthz | 200、process=up | 200、process=up |
/readyz | 200、計算結果を確認 | 503、rounding_mode_required |
/preview | 200、total=1333 | 503、rounding_mode_required |
/healthzは今回、プロセスが応答できることだけを見ています。/readyzはプレビューの計算を実行し、設定契約を確かめます。この名前だけで、すべてのシステムのヘルスチェックが同じ意味になるわけではありません。何を調べる実装かを確認してください。
設定の比較では、リポジトリの期待値だけでなく、実行したプロセスが読んだ値を確認します。デプロイ記録に「v2設定」と書いてあっても、参照したファイルが古い可能性があります。今回の二つのJSONは秘密を含みません。実際の秘密値をログへ出して照合する方法を、この例から推奨するものではありません。
型と範囲も契約の一部です。このサービスは税率を整数0〜3000とし、v2の丸め指定をhalf_upに限定しています。設定キーが存在するだけでは、値が正しいことを証明できません。設定不足、値の違反、業務結果の違いを別々に検証すると、次に直すものを絞れます。
承認の質問:何の変更が許されたのかを固定する
GitHubの環境とデプロイ保護の公式資料には、環境を参照するジョブを条件やレビューで保護する仕組みがあります。利用できる機能はプランとリポジトリの公開状態に依存します。設定されていない承認が自動的に存在する、とは考えないでください。
演習では、変更条件を次の五つへ結びつけました。適用先はlab、対象はテスト済みv2 ZIPの完全なdigest、新設定のdigest、現在のリビジョン18、期待するtotal=1333です。これはテスト用の辞書に保存した条件で、実際の承認者の本人確認や署名を実装したものではありません。
| 入れ替えて試したもの | ローカルの拒否理由 | 適用記録 |
|---|---|---|
| 再作成した別ZIP | artifact_mismatch | 変更なし |
| 旧設定 | config_mismatch | 変更なし |
| labからproductionへの適用先変更 | environment_mismatch | 変更なし |
| ZIP末尾への追加データ | artifact_mismatch | 変更なし |
| 想定17のまま、現状は18 | stale_revision | 変更なし |
| 期待totalだけを1332に変更 | business_output_mismatch | 変更なし |
最後の例は、成果物と設定が合っていても、期待結果と違えば止まることを確かめています。別の検証では、旧設定のdigestを条件へ登録しても、候補の準備確認が失敗し、candidate_not_readyで止まりました。照合だけで実行可能性を決めないための確認です。
本番の承認設計では、承認後に別の成果物や設定へ差し替えられないこと、承認できる主体、記録、適用権限を別に守る必要があります。今回の辞書は誰でも編集できるローカルコード内の値なので、そのようなアクセス制御を証明していません。ここで練習するのは、許可の対象を曖昧にしない説明です。
構成のドリフトを見つけたら、その場で上書きしない
演習の最初の変更条件は、リビジョン17を前提にしていました。その後、現在の記録だけを18に進めると、17向けの変更は拒否されました。新しい状態を読み、条件を18へ更新してから候補を検証し、成功時の記録は19になります。
これは「調べている間に別の変更が入った」という場面を順次実行で再現したものです。実際の同時書込みを試しておらず、読み取りから適用までの原子的なcompare-and-swapも実装していません。並行するデプロイに使うなら、ロックやAPIの条件付き更新など、対象システムが提供する保証を確認します。
ドリフトが見つかったときに必要なのは、古い期待値を最新状態へ無条件に押し付けることではありません。誰のどの変更か、意図した変更か、今回の復旧案が今の状態でも有効かを読み直します。宣言的な管理でも、差分を理解する前に適用すれば別の修正を失う可能性があります。
面接では「リビジョンが違ったので中止しました」で止めず、その後に何を読むかを答えます。この例なら、現在の成果物digest、設定digest、丸め結果を取り直し、承認の対象を更新するかを判断します。リビジョン17と18の差を見つけたことと、18へ変更条件を更新してよいことは別だと説明してください。
切り戻すか前進するかは、業務結果まで比較する
今回の前進案は、テスト済みのv2 ZIPを保ち、新設定を渡すことです。実際にループバックへ要求を送り、準備確認と業務プレビューが200になり、tax=99、total=1333を返しました。ローカルの適用記録を変更したのは、この有効な組合せだけです。
旧v1 ZIPと旧設定を組にした切り戻し案も、別のローカルプロセスで200を返しました。ただしtax=98、total=1332です。応答する状態には戻っても、v2の丸め規則は満たしません。どちらが適切かは、障害中に許される計算規則と変更の承認範囲によります。
以下は、この二つの結果を再現する独立した短いPythonコードです。実際の課金処理や地域の税率計算を表すものではありません。
from decimal import Decimal, ROUND_FLOOR, ROUND_HALF_UP
subtotal, bps = 1234, 800
for name, rounding in [("v1", ROUND_FLOOR), ("v2", ROUND_HALF_UP)]:
tax = int((Decimal(subtotal) * Decimal(bps) / Decimal(10000))
.quantize(Decimal("1"), rounding=rounding))
print(name, tax, subtotal + tax)
# v1 98 1332
# v2 99 1333
KubernetesのDeploymentの公式説明では、以前のrevisionへの切り戻しはPodテンプレートの部分を戻します。この仕様から、外部の設定、データ、既に発生した副作用まで自動的に元へ戻るとは言えません。今回Kubernetesを動かした結果ではなく、復旧範囲を確認する際の公式な境界です。
この実験にはデータベース移行も書込みもありません。したがって、どちらの案でも既存データが安全だと証明したわけではありません。データや他の利用者がいるシステムでは、互換性と進行中の処理を追加で確認する必要があります。

復旧の説明は、観測した操作と残る確認を示す
27項目の検証には、二つのZIPの違い、各拒否で適用記録が変わらないこと、正常な前進案、旧版と旧設定の比較が含まれます。18回のHTTP要求は、六つの起動条件で三つのURLを確認したものです。本番のトラフィック切替や可用性、負荷、永続性を試した回数ではありません。
今回言えるのは「テスト済み成果物に新設定を組み合わせたローカルプロセスが、指定したプレビュー結果を返した」までです。実運用で復旧を宣言するなら、対象利用者の操作、エラーの減少、適用先の実体、監視の観測範囲なども確認します。プロセス一個の200を、利用者全体の復旧へ広げないでください。
面接では、まず設定不足の503という観測を示します。次に成果物が同一であることを確かめ、設定を変えた候補と旧版の結果を比較します。最後に「1333が必要なら前進案、1332へ戻すことが許容されるなら旧版・旧設定の案を検討する」と、判断を変える条件を伝えます。
以下は、成果物の流れ、ジョブ依存、復旧条件を別のケースで練習するPracHub問題です。特定企業がこのDevOpsケースを出題する保証ではありません。
| PracHubの問題 | このケースから確認する問い |
|---|---|
| Design a CI/CD pipeline with scheduler | テストした出力と適用対象をどう対応させるか |
| Explain container image flow in CI/CD | ソース、成果物、配置された実体をどう追うか |
| Design CI/CD Build Caching | キャッシュ利用と同一成果物の保証をどう区別するか |
| Connect Monitoring, Circuit Breakers, Rollback, and CI/CD | 何を観測して停止・復旧を判断するか |
| Design a Dependency-Aware CI/CD Pipeline | 必要な検証が終わる前に適用へ進まないか |
同じZIPでも設定で結果が変わる理由を説明したら、CI/CDパイプライン設計の問題で、成果物のdigest、想定する現在のリビジョン、期待する業務結果を一つの変更条件へまとめてみてください。各段階で失敗した場合に何を変更せず残すかまで決めると、相手と同じ結果を見ながら、復旧案の影響を検討できます。
Comments (0)