第1回でGo判定を出し、クラスタの構築に着手する段階になると、最初に燃えるのは技術ではなく組織です。「このマニフェストは誰が書くのか」「Podが落ちたとき、最初に動くのは誰か」――この2つに答えを用意しないまま構築を進めると、クラスタが動き始めた瞬間から境界紛争が始まります。
この紛争は、コミュニケーションを改善すれば解消する類の問題ではありません。誰がどの権限を持ち、どの結果に責任を負うのかという設計が欠落していることが原因です。設計の欠落は、設計で埋めます。
本記事は、その設計書――「責任境界定義書」の書き方を扱います。構成要素は、平時の役割分担を定めるRACIマトリクスと、開発者にどこまでマニフェストを触らせるかを決めるマニフェスト所有権モデルの2つです。
目次
責任境界を定義しないまま動き出したクラスタで起きること
責任境界の不在が引き起こす事故には、再現性の高いパターンがあります。以下の3つは、境界定義を省いた現場でほぼ確実に発生します。
Namespace払い出しのリードタイムが決まっていない
開発チームが新しい環境を必要としたとき、運用チームへの依頼から払い出しまでに何日かかるかが定義されていないと、待機時間は際限なく伸びます。運用チームは構築作業で手一杯であり、払い出し依頼は優先度の低いタスクとして後ろに積まれるためです。
待機が2週間に達したあたりで、開発者は自力で環境を用意し始めます。個人裁量でクラウドの別サービスに立てられた環境は、統制の外側に置かれます。第1回で定義したコスト按分のラベリングも、セキュリティ部門と握ったコンプライアンス要件も、その環境には適用されません。
この事故が示しているのは、責任境界定義書が運用チームを守るだけの文書ではないという点です。運用チーム側が提供品質を数値で約束しなければ、開発チームは境界の外へ出ていきます。
Requests未設定のPodが混入する
resources.requestsの値を誰が決めるのかが決まっていないと、この項目は空欄のままデプロイされます。開発チームは「インフラの値だから運用が決めるもの」と考え、運用チームは「アプリの特性を知らないので決められない」と考えるためです。
Requestsが未設定のPodは、スケジューラから見ればリソース消費がゼロのPodです。ノードには実際の消費量と無関係にPodが詰め込まれ、メモリが逼迫した時点でkubeletによるEvictionが始まります。
さらに悪いことに、RequestsもLimitsも設定されていないPodはQoSクラスがBestEffortになります。kubeletがEviction対象を選ぶ順序はBestEffort、Burstable、Guaranteedの順であり、値を設定しなかったPodが真っ先に停止させられます。設定を怠ったチームのアプリケーションが最初に落ちるという意味では合理的ですが、その事実を誰も認識していないまま本番が動き始めます。
深夜にEvictionのアラートが鳴ったとき、次に問題になるのが「これはアプリの問題かクラスタの問題か」を判定する担当が決まっていないことです。運用チームはアプリのメモリ挙動を知らず、開発チームはノードの状況を見る権限を持っていません。判定者が不在のまま、朝まで放置されます。
証明書・シークレット更新の担当が不在になる
クラスタ構築の初期に手動で発行した証明書は、担当者が明示されないまま引き継がれます。cert-managerによる自動更新が導入される前に発行されたものや、外部システムとの連携用にアプリケーション側で保持しているものが該当します。
有効期限が切れるのは、たいてい構築から1年後です。その頃には初期メンバーが異動しており、誰も期限を管理していません。本番のIngressが停止し、原因の特定に半日を要します。
この事故を防ぐ手段は、担当を決めることではありません。手動更新が必要な証明書をゼロにすることです。RACIに「TLS証明書の発行・更新」の行を作る目的は、担当者を決めることに加えて、自動更新の対象外になっている証明書を棚卸しの過程で洗い出すことにあります。行を埋める段階で「この証明書は誰が更新するのか」と問われて初めて、自動化されていない箇所が可視化されます。
この3つに共通しているのは、いずれも「誰かがやるだろう」で放置されたタスクだという点です。RACIマトリクスの役割は、この「誰か」を実名のチームに置き換えることにあります。
RACIマトリクスに並べる15タスク
RACIは、タスクごとに4つの役割を割り当てる責任分担の記法です。R(Responsible)は実行者、A(Accountable)は結果責任者、C(Consulted)は事前に相談する相手、I(Informed)は事後に報告する相手を指します。
RACIマトリクスの品質は、行の設計でほぼ決まります。「Kubernetesの運用」「監視」といった粒度の行を作ると、埋めた瞬間に意味を失います。境界線が引ける粒度まで分解した結果が、以下の15タスクです。
次の表は、モデルB(共通Helm Chart型・後述)を採用した組織における記入例です。自組織の所有権モデルに応じて値は変わりますが、行の一覧はそのまま流用してください。
なお、I(Informed)の列は省略しています。実務ではほぼ全てのタスクで両チームがIに該当するため、記載しても情報量が増えません。列を作るのは、報告しなければ気づかれない相手が存在するタスクに限ってください。
| タスク | R(実行) | A(結果責任) | C(相談) |
|---|---|---|---|
| 1. Namespaceの払い出しとResourceQuotaの設定 | 運用 | 運用 | 開発 |
| 2. Deployment / Service マニフェストの記述 | 開発 | 開発 | 運用 |
| 3. 本番クラスタへのマニフェストの適用 | 運用 | 運用 | 開発 |
| 4. Requests / Limits の値の決定 | 開発 | 開発 | 運用 |
| 5. HPAの閾値設定 | 開発 | 開発 | 運用 |
| 6. Liveness / Readiness Probe の実装と設定値 | 開発 | 開発 | 運用 |
| 7. Ingressの作成とドメイン登録 | 運用 | 運用 | 開発 |
| 8. TLS証明書の発行・更新 | 運用 | 運用 | — |
| 9. NetworkPolicyの記述 | 運用 | 運用 | セキュリティ / 開発 |
| 10. Secretの登録とローテーション実行 | 開発 | 開発 | セキュリティ |
| 11. コンテナのベースイメージ選定と更新 | 運用 | 運用 | セキュリティ |
| 12. 脆弱性スキャン検出時の修正 | 開発 | 開発 | セキュリティ |
| 13. Kubernetesマイナーバージョンアップの実施 | 運用 | 運用 | 開発 |
| 14. バージョンアップに伴うアプリ側のAPI追従修正 | 開発 | 開発 | 運用 |
| 15. コスト超過時の是正 | 開発 | 開発 | 運用 |
タスク2と3を分けている理由
「マニフェストの記述」と「本番クラスタへの適用」を、多くの組織は「デプロイ」という1行にまとめます。この統合が、後から2つの問題を生みます。
1つ目は、運開分離が求められる組織でRACIが成立しなくなることです(後述のセクションで扱います)。2つ目は、将来GitOpsへ移行したときに、この行の意味が変わってしまうことです。
分離要件がない組織であっても、この2行は最初から分けておいてください。「開発者がマニフェストを書き、承認を経て適用される」という形に移行する際、RACIを書き換えずに済みます。
セキュリティチームにAを持たせていない理由
上の表では、セキュリティチームはCにのみ登場し、Aを持つ行がありません。これは意図的な設計です。
セキュリティチームの役割は、何を禁止し何を許可するかというポリシーを定義することにあります(この設計は第5回のゼロトラスト・ガバナンス設計書で扱います)。ポリシーの定義者に運用実行の結果責任まで負わせると、自分で決めたルールを自分で運用することになり、相互牽制が働かなくなります。
NetworkPolicyの行を例に取ると、通信制御ルールの内容を決めるのはセキュリティチーム、マニフェストとして記述し適用するのは運用チームです。ルールが正しく実装されているかをセキュリティチームが監査する構造になります。
RACI記入の3原則
表を埋める際、以下の3点を守ってください。いずれも、運用開始後に紛争が起きた現場を分析すると共通して破られている項目です。
| 原則 | 破った場合に起きること |
|---|---|
| Aは1タスクにつき必ず1チームのみ | Aが2つ付いた行は、問題が起きたときに両者が相手の責任だと主張します。RACIを作った意味が完全に失われるため、この点だけは例外を認めないでください |
| Cは1タスクにつき2つまで | 3つ以上のチームへの相談を必須にすると、意思決定が止まります。関係者を漏らさないようにCを増やすのは、丁寧さではなく設計の失敗です |
| 実行権限のないチームにAを置かない | 典型的な失敗は「R=開発 / A=運用」です。運用チームは開発チームに作業を強制する権限を持たないため、結果責任だけが残ります。Aは原則としてRと同じチームに置き、異なる場合はその理由を文書に明記してください |
現場で必ず揉めるグレーゾーン3件の分解
15タスクのうち、担当を決めようとすると必ず議論が長引く行があります。揉める理由は、そのタスクが1つの作業ではなく、性質の異なる2つの作業を含んでいるためです。
解決策は、タスクを「決める人」と「ガードレールを引く人」に分解することです。以下の3件について、分解の実例を示します。
グレーゾーン1:Requests / Limits の値
値を決めるのは開発チームです。アプリケーションが実際にどれだけメモリを使い、どこでCPUを消費するかを把握しているのは開発側だけであり、運用チームがこの値を決めに行くと、アプリケーションの改修のたびに運用チームが呼び出される構造になります。
運用チームが担うのは、値の妥当性ではなく上限の管理です。LimitRangeで1Podあたりの上限とデフォルト値を設定し、ResourceQuotaでNamespace全体の総量を制限します。Requestsが未設定のPodをそもそも受け付けない構成にすることで、前述の「未設定Podの混入」を仕組みで防ぎます。
つまり、値は開発が決め、範囲は運用が縛るという分解です。Requests / Limits の算出方法論そのものは第11回のPodリソース・耐障害性設計書、ResourceQuotaの設計は第4回のFinOps・スケーリング設計書で扱います。
グレーゾーン2:OOMKilled / CrashLoopBackOff の一次切り分け
これを「調査は運用、修正は開発」と分けると失敗します。調査という言葉の範囲が曖昧で、どこまでやれば運用チームの責任を果たしたことになるのかが決まらないためです。
正しい分解は「情報提供は運用、原因判断と修正は開発」です。運用チームの責任は、判断に必要な情報を開発チームがいつでも取得できる状態を維持することにあります。具体的には、以下を提供できていれば運用チームの責任は果たされています。
- Pod単位のメモリ・CPU使用量の時系列グラフ(OOMKilled発生時点の直前まで遡れること)
kubectl describe podで得られるEventと、終了コード・再起動回数- 該当Podの標準出力ログ(Pod再作成後も参照できるよう永続化されていること)
- ノード側のリソース状況(同居Podによる圧迫が起きていないかの確認材料)
この情報を見てメモリリークなのか設定値の不足なのかを判断し、コードや値を修正するのは開発チームの責任です。この線を引かないと、運用チームがアプリケーションのソースコードを読み始めることになります。
なお、ここで定義しているのは平時の役割分担です。障害発生時に誰が最初に呼ばれ、どの時間内にどこへエスカレーションするかというプロセスは、第16回のインシデント対応・ポストモーテムプロセス設計書で扱います。
グレーゾーン3:コンテナイメージの脆弱性対応
Trivyなどのスキャナが検出する脆弱性は、発生元のレイヤーによって責任の所在が変わります。この区別をしないまま「脆弱性対応」という1行を作ると、検出されたCritical件数が誰のバックログにも入らない状態が生まれます。
| 脆弱性の発生レイヤー | 責任を持つチーム | 具体的な作業 |
|---|---|---|
| OS層・言語ランタイム層(ベースイメージ) | 運用 | パッチ適用済みのベースイメージを再ビルドし、新しいタグで配布する |
| アプリケーション依存ライブラリ | 開発 | 依存関係のバージョンを更新し、動作確認の上でリリースする |
| ベースイメージの更新版への追従 | 開発 | 運用チームが配布した新タグを参照するようマニフェストを更新する |
運用チームは新しいベースイメージを配布するところまでを担い、それを使うかどうかは開発チームの判断です。ここで運用チーム側に必要なのが、後述するSLAの1項目である「破壊的変更の事前予告」です。予告なくベースイメージを差し替えると、開発チームのビルドが突然壊れます。
検出された脆弱性のうち、どの深刻度からリリースをブロックするかというルールの定義は第5回、そのルールをCIパイプラインのどこに組み込むかという設計は第9回で扱います。
運開分離が求められる場合、責任境界の形は規制側から決まる
ここまでは、責任境界を自組織の都合で設計できることを前提としてきました。業種によっては、この前提が成り立ちません。開発と運用の職務分離(運開分離)が規制上の要求として課される場合、RACIの「誰が実行するか」は組織の好みではなく外部の基準で決まります。
この制約の有無は、第1回のヒアリングでセキュリティ部門から取得したコンプライアンス・監査要件の中に含まれています。第1回で握っていない場合、所有権モデルを選ぶ前にここで確認してください。
根拠となる要件
カード情報を扱うシステムの場合、PCI DSSが該当します。
| 基準 | 該当箇所 | 要求内容 |
|---|---|---|
| PCI DSS v4.0 | 要件 6.5.4 | 本番環境と本番前環境の間で役割と機能が分離されていること。レビューおよび承認された変更のみがデプロイされるよう、説明責任を担保する |
| PCI DSS v4.0 | 要件 6.5.3 | 本番前環境が本番環境から分離され、その分離がアクセス制御によって強制されていること |
| PCI DSS v3.2.1 | 要件 6.4.2 | 開発/テスト環境と本番環境の職務の分離(v4.0の6.5.4に相当) |
自社が準拠すべき基準は業種によって異なります。金融機関であれば別途適用される基準がありますので、自組織のセキュリティ部門および準拠する基準書の原典で確認してください。
Kubernetesにおける具体的な帰結
運開分離が必要な場合、RACIと所有権モデルに以下の制約がかかります。
1. タスク2と3の分離が必須になる
「マニフェストの記述」はR=開発チームで構いません。しかし「本番クラスタへの適用」を開発チームに持たせることはできません。この2つを1行にまとめているRACIは、監査の時点で分離が成立していないと判定されます。
2. モデルA(フルオープン型)が選択肢から外れる
開発者が本番Namespaceに対して直接kubectl applyを実行する運用は、役割と機能の分離に抵触します。組織の規模がモデルAの適用範囲(開発チーム3以下)に収まっていても、モデルB以上を選ぶことになります。
3. GitOpsが分離とセルフサービスを両立させる
開発者の書き込み権限をマニフェストリポジトリに限定し、クラスタへの適用はArgo CDなどのコントローラーが行う構成にします。人間が本番クラスタへ直接変更を加える経路が存在せず、変更履歴はすべてプルリクエストとして残ります。
この構成であれば、開発者は自分のペースでマニフェストを変更でき(セルフサービス)、かつ本番への適用権限は持たない(分離)という状態が両立します。運開分離を理由に開発者の生産性を犠牲にする必要はありません。

4. 本番向けプルリクエストの承認者ルールをRACIに書き込む
要件6.5.4は「レビューおよび承認された変更のみがデプロイされる」ことを求めています。これを満たすため、本番向けのプルリクエストには開発チーム以外から最低1名の承認を必須とする、というルールをRACIに明記してください。
承認者を定義していないGitOpsは、技術的には分離できていても、監査では分離されていないと判定されます。GitHubであればCODEOWNERSと必須レビュー設定、GitLabであればApproval Rulesで強制し、その設定自体を責任境界定義書に記載しておいてください。
なお、Argo CDのApplication構成や同期ポリシーの設計は第9回、開発者に本番Namespaceの書き込み権限を与えないRole定義は第5回で扱います。本記事では、規制要件がRACIと所有権モデルの形を制約するという観点までを扱います。
マニフェスト所有権モデルの選択
マニフェスト所有権モデルとは、開発者にどこまでマニフェストを触らせるかの設計です。3つの類型があります。
どのモデルが優れているかという議論には意味がありません。自組織の規模がどのモデルの適用範囲に入っているかで決まります。規模に合わないモデルを選ぶと、運用チームが破綻するか、開発者体験が悪化するかのどちらかが起きます。

モデルA:フルオープン型
開発者が生のマニフェストを書き、運用チームはレビューのみを担当する形です。
- 適用条件:開発チーム数3以下、各チームにKubernetesの実務経験者が1名以上、Namespace数10以下
- 崩壊ライン:チーム数が5を超えると記述品質の分散が制御できなくなります。運用チームのレビュー工数は1プルリクエストあたり15〜30分であり、月間50件を超えた時点で専任1名分の工数を消費します
- 制約:運開分離が必要な組織では選択できません
モデルB:共通Helm Chart型
運用チームが1つの共通Helm Chartを提供し、開発者はvalues.yamlのみを記述する形です。多くの組織にとって、これが現実的な着地点になります。
- 適用条件:開発チーム数4〜15、アプリケーションの形態がWeb API / Worker / Batchの2〜3類型に収まる
- 設計上の閾値:公開する
values.yamlのパラメータ数は20個以内を目安とします。40個を超えると、生のマニフェストを書くより学習コストが高くなり、抽象化の意味が失われます - 運用コスト:Chart自体のバージョニングと、全チームへのローリング適用に月0.3〜0.5人月を継続的に消費します。この工数を見込まずにモデルBを選ぶと、Chartが更新されないまま放置されます
パラメータ数の閾値には理由があります。抽象化の目的は、開発者がKubernetesの詳細を知らなくてもデプロイできる状態を作ることです。公開パラメータが増えるほど、開発者は「このパラメータは何を意味するのか」を理解する必要が生じ、結局マニフェストの知識が要求されます。
パラメータが40個を超えたときに疑うべきは、Chartの設計ではなくアプリケーションの類型が多すぎることです。Web APIとBatchで別のChartに分割するほうが、1つのChartに条件分岐を積むより保守できます。
values.yamlとしてどのパラメータを公開するかというインターフェース仕様の設計は、第10回のマニフェスト抽象化・IDP設計書で扱います。
モデルC:IDP型
Backstageなどの開発者ポータルを用意し、開発者がセルフサービスで環境を払い出す形です。
- 適用条件:開発チーム数15以上、または開発者100名以上
- 初期構築コスト:Backstage本体の構築と、ゴールデンパステンプレートの整備に3〜6人月
- 判断基準:開発者100名未満では、削減できる問い合わせ工数が初期投資を下回ります
モデルCを検討する際は、第1回で算出した投資回収期間の枠内に、この3〜6人月が収まるかを確認してください。IDPの構築はプラットフォーム構築そのものとは別の投資であり、第1回のROI計算に含めていないことが多い項目です。
モデルの移行はダウングレードできない
A→B→Cの順に段階を進めることは可能です。逆方向、たとえばIDPで環境を払い出せていた状態からHelm Chartの記述に戻す変更は、開発者体験の明確な劣化として受け取られ、強い反発を招きます。
したがって、モデルの選択では現在の規模ではなく、今後2〜3年のチーム数の見込みで判断してください。判断材料になるのは、第1回で確定させた移行対象システムの棚卸し結果と、事業計画上の開発組織の拡大見込みです。
迷った場合はモデルBを選んでください。モデルAからBへの移行はChartを作れば済みますが、Aのまま規模が拡大すると、運用チームがレビュー工数に飲み込まれた状態でChartを作ることになります。
運用チームが約束するSLA
ここでいうSLAは、システムの可用性目標(99.9%といった数値)とは別のものです。可用性目標の設定は第3回のクラスタトポロジー・ネットワーク設計書で扱います。本セクションで扱うのは、運用チームが開発チームという内部の利用者に対して約束する対応品質です。
ここまでのRACIは、開発チームに制約を課す内容を多く含んでいます。この文書を運用チーム側の都合だけで作ると、開発チームからは責任の押し付けとして受け取られ、合意を得られません。
責任を引き受ける以上、提供品質を数値で約束してください。以下は、責任境界定義書に記載すべき最低限の項目です。
| 項目 | 目安となる数値 | この数値である理由 |
|---|---|---|
| Namespaceの払い出しリードタイム | 営業日2日以内 | これを超えると開発チームが統制外の環境を用意し始めます |
| 運用チームへの問い合わせの一次応答 | 営業時間内4時間以内 | 解決ではなく、受領と対応方針の連絡までの時間です |
| 共通Helm Chartの破壊的変更の事前予告 | 30日前 | 開発チームがスプリント1〜2回分の中で対応を計画できる期間です |
| Kubernetesマイナーバージョンアップの事前告知 | 60日前 | 非推奨APIの調査と修正、および検証に要する期間です |
| バージョンアップに伴う開発チームの検証期間 | 2週間 | Stg環境で新バージョンを稼働させ、開発チームが動作確認を行う期間です |
逆に、開発チーム側に守ってもらう前提条件も同じ文書に明記します。以下を満たしていないアプリケーションは、運用チームがSLAを保証できません。
resources.requestsが設定されていること(未設定のPodはポリシーエンジンで拒否します)- ログを標準出力へJSON形式で出力していること(第15回で扱います)
- SIGTERMを受けて処理を完了させるGraceful Shutdownが実装されていること(第11回で扱います)
- Readiness Probeが、依存する外部サービスへの疎通を含めて正しく状態を返すこと
この双方向の約束が揃って、責任境界定義書は合意可能な文書になります。片側だけの文書は、運用開始後に守られません。
【実務テンプレート】責任境界定義書
ここまでの内容を統合したテンプレートです。両チームのリーダーの承認を得た上で、後続の設計フェーズに進んでください。
責任境界定義書
プロジェクト名: ________________
作成日: ____/____/____
作成者: ________________
承認者(運用): ________________
承認者(開発): ________________
セクション1: 対象チームの定義
運用チーム: 人数___名 / 責任者___________________
開発チーム: ___チーム / 総人数___名 / 担当システム___________________
セキュリティチーム: 人数___名 / 責任者___________________
セクション2: 前提条件の確認
運開分離の要求: [あり / なし]
ありの場合の準拠基準と該当箇所: _______________________
→ ありの場合、モデルAは選択不可。タスク2と3の分離は必須
セクション3: マニフェスト所有権モデル
選択したモデル: [A フルオープン / B 共通Helm Chart / C IDP]
判断根拠: 現在の開発チーム数___、3年後の見込み___
開発者総数___名
Bの場合の公開パラメータ数: ___個(20個以内を目安)
Chart保守の割当工数: ___人月/月
セクション4: RACIマトリクス(15タスク)
本記事の表を転記し、自組織の値で埋めること。記入時は3原則(Aは1つ / Cは2つまで / 実行権限のないチームにAを置かない)を確認する。
セクション5: グレーゾーンの分解ルール
Requests / Limits: 値の決定___________ / 上限の管理___________
OOMKilled等の切り分け: 情報提供___________ / 原因判断と修正___________
脆弱性対応: ベースイメージ___________ / 依存ライブラリ___________
セクション6: 運用チームのSLA
Namespace払い出し: ___営業日以内
問い合わせ一次応答: ___時間以内
Chart破壊的変更の予告: ___日前
K8sバージョンアップ告知: ___日前 / 検証期間___週間
セクション7: 開発チームが満たす前提条件
Requests設定: [必須 / 強制方法___________]
ログのJSON標準出力: [必須 / 期限____/____]
Graceful Shutdown実装: [必須 / 期限____/____]
Readiness Probe実装: [必須 / 期限____/____]
セクション8: 例外申請プロセスと見直しサイクル
例外の申請先: ___________________
例外の承認者: ___________________
例外の有効期限: ___ヶ月(無期限の例外を認めない)
本文書の見直し: ___ヶ月ごと / 次回見直し日____/____/____
この文書の置き場所についても決めておいてください。文書管理ツールの階層の奥に置かれた責任境界定義書は、半年後に誰も参照しなくなります。運用チームのリポジトリに置き、変更はプルリクエストで行う運用にすると、変更の経緯が履歴として残ります。
見直しサイクルは四半期ごとを推奨します。チーム構成の変化、所有権モデルの移行、新しいタスクの発生に追従できていない責任境界定義書は、存在しないのと同じです。次回の見直し日をカレンダーに登録するところまでを、作成作業に含めてください。
次回予告
本記事では、平時の責任分担を定めるRACIマトリクスの15タスクと、マニフェスト所有権モデルの選択基準を扱いました。誰が何に責任を持つかが決まると、次に決めるべきはその分担が成立する土台、つまりクラスタそのものの形です。
次回の第3回「クラスタトポロジー・ネットワーク設計書」では、SLA/SLO目標に基づくシングルクラスタとマルチクラスタの選択、Dev/Stg/Prodの環境分離戦略、Pod/Service CIDRのIPアドレス計画、そしてIngressによる外部公開方針を扱います。
