インフラエンジニアの羅針盤

インフラエンジニア1〜3年目のための技術ガイド

GKEクラスタ設計|SLOとIPアドレス計画の決め方

公開

第2回で誰が何に責任を持つかが決まりました。次に決めるのは、その分担が乗る土台――クラスタそのものの形です。いくつ作るのか、リージョンかゾーンか、Dev・Stg・Prodをどう分けるのか。そしてIPアドレスをどう切るのか。

このうちIPアドレス計画だけは、後から直せない設計項目を複数含んでいます。クラスタを作り直さなければ変更できない値が存在するため、最初の計算がその後数年を縛ります。本記事で最も分量を割くのはここです。

本記事も第1回と同様、Google Cloud(GKE)を前提に数値と製品名を記載します。

目次
  1. SLOを決めなければ、トポロジーは決まらない
    1. 第2回のSLAとは別物である
    2. 可用性の数値を、許容ダウンタイムの分数に翻訳する
    3. GKEのSLAがトポロジーの上限を規定する
    4. コントロールプレーンが止まったとき、何が止まって何が止まらないか
    5. エラーバジェットをリリースに使うか、障害に使うか
  2. Autopilot か Standard か ― GKEで最初に来る分岐
    1. Standardを選ぶ条件は限定される
    2. セキュリティエージェントをDaemonSetで入れる要件がある場合
  3. シングルクラスタか、マルチクラスタか
    1. まずマルチゾーンとマルチクラスタを区別する
    2. マルチクラスタを正当化する3条件
    3. マルチクラスタが持ち込むコストと複雑性
  4. 環境分離戦略 ― Stg を Prod のミラーにする
    1. Namespaceでは分離できないもの
    2. 「ミラー」で揃えるもの・揃えなくてよいもの
    3. Devはゾーンクラスタにしてコストを削る
    4. 検証を怠ると、クラスタ管理手数料が6倍になる
  5. IPアドレス計画 ― 後から直せない設計項目
    1. VPCネイティブクラスタが使うIPアドレス範囲
    2. ノード1台が消費するCIDRは、max Pods per node で決まる
    3. Podセカンダリ範囲のサイズが、最大ノード数を確定させる
    4. max Pods per node は作成後に変更できない
    5. 設計時に突き合わせるCIDR一覧
  6. Gateway API による外部公開方針
    1. Gateway APIが第2回の責任境界と噛み合う
    2. 公開単位ごとにロードバランサーを作らない
    3. 到達性のレイヤーで内部と外部を分ける
  7. 【実務テンプレート】クラスタトポロジー・ネットワーク設計書
  8. 次回予告

SLOを決めなければ、トポロジーは決まらない

クラスタをいくつ、どの形で作るかは、可用性目標の数値から逆算して決まります。逆算せずに決めたトポロジーは、後から根拠を問われたときに答えられません。

第2回のSLAとは別物である

最初に用語を区別します。第2回で定義した「運用チームのSLA」は、Namespace払い出し2営業日以内、問い合わせの一次応答4時間以内といった対応時間の約束でした。本記事で扱うSLA/SLOはシステムの可用性目標です。同じ略語ですが別のものを指しています。

あわせてSLA・SLO・SLIの関係も整理しておきます。SLIは実測値(例:APIの成功率)、SLOはその実測値に対して自分たちが設定する目標、SLAは顧客との契約であり違反時のペナルティを伴います。本記事で設計するのはSLOです。SLAはSLOより緩く設定します。

可用性の数値を、許容ダウンタイムの分数に翻訳する

「99.99%を目指します」という発言は、それ単体では意味を持ちません。30日(43,200分)を基準に分数へ翻訳してから議論してください。

可用性月間の許容ダウンタイム実務上の意味
99.5%216分(3.6時間)営業時間内に半日かけて復旧しても間に合う水準
99.9%43.2分人が起きて対応を始められる水準。計画メンテナンスの枠も含む
99.95%21.6分検知から復旧着手までを自動化しないと厳しい
99.99%4.32分人手による復旧は事実上不可能。自動フェイルオーバーが前提になる

この表を経営層に提示してから目標を握ってください。「99.99%」と口にした瞬間に、月に4分しか止められないことを意味します。障害を検知して人間が状況を把握するまでに、その4分は消えます。

GKEのSLAがトポロジーの上限を規定する

GKEはコントロールプレーンの可用性についてSLAを公表しています。この数値がトポロジー選択の上限を決めます。

対象月間稼働率許容ダウンタイム
Autopilotクラスタ / リージョンStandardクラスタのコントロールプレーン99.95%月21.6分
ゾーンStandardクラスタのコントロールプレーン99.5%月216分
複数ゾーンのAutopilot Pod99.9%月43.2分

注目すべきは、リージョンとゾーンの差が月21.6分と月216分、ちょうど10倍である点です。「Devはゾーンでいいよね」という判断は、コントロールプレーンの許容停止時間を10倍に緩める判断と同義です。この数字を出さずに決めないでください。

なお、Autopilotクラスタは常にリージョンクラスタです。Autopilotを選んだ時点で、コントロールプレーンは自動的に99.95%の側に入ります。

コントロールプレーンが止まったとき、何が止まって何が止まらないか

ここは正確に理解しておく必要があります。コントロールプレーンが停止しても、既存のPodは動き続けます。kubeletとkube-proxyはノード上で独立して動作しており、すでにスケジュール済みのPodはトラフィックを処理し続けます。

停止するのは以下です。

  • 新規のデプロイとロールアウト
  • HPAを含むスケール動作
  • Podがクラッシュしたときの再スケジュール(自動復旧)
  • kubectlによる一切の操作

したがって、アプリケーションのSLOとコントロールプレーンのSLAは単純な掛け算になりません。ゾーンクラスタの99.5%が、そのままアプリケーションの可用性を99.5%にするわけではありません。

正しい理解はこうです。その216分の間、システムは「今の状態のまま固定される」。平常時であれば影響は出ませんが、同じ時間帯に負荷スパイクが来ればスケールできず、Podが落ちれば復旧しません。障害は単独では起きないことが多いという前提に立つなら、この固定状態が本番環境で許容できるかどうかが判断軸になります。

エラーバジェットをリリースに使うか、障害に使うか

SLOを99.9%に設定した場合、月43.2分が使える予算です。この予算は障害だけのものではありません。計画メンテナンスによる停止も同じ予算から支払います。

月2回のリリースでそれぞれ10分停止するなら、20分を消費します。障害に使える残りは23分です。ゼロダウンタイムデプロイを実装しない限り、リリース頻度がSLOを食いつぶします。第1回で扱ったデプロイ頻度が、ここで可用性目標と衝突します

この衝突が見えた時点で選択肢は3つです。SLOを下げる、リリース頻度を下げる、ゼロダウンタイムデプロイに投資する。どれを選ぶかを要件定義書に記録してください。

Autopilot か Standard か ― GKEで最初に来る分岐

GKEではこの選択を先に済ませないと、IP計画もノード設計も決まりません。しかも両者には、あとから変更できない項目がまたがっています。

項目AutopilotStandard
トポロジー常にリージョン(SLA 99.95%側に固定)リージョン / ゾーンを選択可(ゾーンはSLA 99.5%)
max Pods per nodeGKEが8〜256の範囲から自動決定し、変更不可指定可。ただしクラスタ/ノードプール作成後は変更不可
ノードの管理Google側が担当マシンタイプ・OSイメージ・スケーリングを自分で制御
クラスタ管理手数料$0.10/クラスタ/時(運用モード・規模・トポロジーによらず一律)
ワークロードの課金Podが要求したCPU / メモリ / エフェメラルストレージノードの基盤となるインスタンスに対するCompute Engineの料金

クラスタ管理手数料が運用モードによらず同額である点は、誤解されやすいので押さえておいてください。Autopilotだから管理費が高いということはありません。差が出るのはワークロードの課金方式です。

Standardを選ぶ条件は限定される

以下のいずれかに該当する場合はStandardを選びます。

  • ノードのマシンタイプやOSイメージを固定する要件がある
  • 特権を要するノードエージェントを動かす必要があり、かつそれがAutopilotパートナーの一覧にない(次項で詳述)
  • GPU / TPUの割り当てを細かく制御する必要がある
  • max Pods per nodeを意図的に小さくして、IPアドレスの消費効率を上げたい(後述のIP計画を参照)

いずれにも該当しないのであればAutopilotを選んでください。ノードの管理という作業がGoogle側に移るため、第2回のRACIで運用チームに割り当てたタスクのうち、ノードイメージの更新とノードプールのアップグレードに伴う作業負荷が実質的に下がります。第1回の条件4(専任2名以上)を満たすのが厳しい組織ほど、Autopilotを検討する価値があります。

ただし、最後の項目は無視できません。IPアドレスに余裕がない環境では、max Pods per nodeを制御できるStandardが必要になる場合があります。この判断はIP計画とセットで行ってください。

セキュリティエージェントをDaemonSetで入れる要件がある場合

実務で最も多く「だからStandardにするしかない」と判断されるのが、この要件です。EDRやランタイム保護のエージェントを全ノードにDaemonSetで常駐させることが、セキュリティ部門の要件として決まっているケースです。第1回のヒアリング②(コンプライアンス・監査要件)で確定している場合もあります。

結論から言えば、この要件があってもAutopilotを諦める必要はありません。ただし、確認すべき手順があります。

Autopilotクラスタでは通常、昇格した権限を必要とするワークロードは許可されません。/var/runへのアクセス、privileged: trueNET_RAWSYS_ADMINといった権限の高いLinuxファイル機能へのアクセスが該当します。セキュリティエージェントはこれらをそのまま要求するため、素朴に考えればAutopilotでは動きません。

この制限には例外が用意されています。Autopilotパートナーワークロードです。Google Cloudパートナーの一部は、Autopilotクラスタ向けに特別な権限を持つワークロードを提供しており、これをデプロイすることで、すべてのPodにサイドカーコンテナを入れるといった回避策なしにノードレベルの要件を満たせます。

CrowdStrike Falconはこの一覧に含まれています。ユーザー空間センサーとして動作し、単一のエージェントでGKE Autopilotの可視性と保護を提供、ノードとその上で動くコンテナの両方を保護します。許可リストのパスはCrowdStrike/falcon-sensor/*です。

したがって、判断手順は以下になります。

  1. 入れる予定のエージェントがAutopilotパートナーの一覧に載っているかを確認する
  2. 載っていれば、対応する許可リストをクラスタにインストールする。GKEの特定バージョン以降、パートナーが提供する許可リストをクラスタに入れないと、該当する特権ワークロードは動きません
  3. 載っていなければStandardを選ぶ

ここで確認すべきなのは、製品名が一覧にあるかどうかだけではありません。同じ製品でも、どのセンサー方式を採るかで結果が変わります。CrowdStrike Falconの場合、Autopilot対応の前提はユーザー空間センサーであることです。カーネルモジュールを要求する構成を前提に設計していると、同じ製品名でも成立しません。ベンダーのデプロイガイドで、Autopilot向けの構成を確認してください。

パートナーワークロードは、正しく動作するために必要な最小限の権限に絞られているかという観点でGoogleの審査を経ています。「Autopilotだから何も入れられない」という前提で最初からStandardを選ぶのは、現時点では正確ではありません。要件を持ち込まれた時点で、まずパートナー一覧を確認してください。

なお、どのセキュリティ製品を採用するかという選定理由そのものは第6回、そのエージェントが要求する権限をRBACやPod Security Standardsの観点でどう扱うかは第5回で扱います。

シングルクラスタか、マルチクラスタか

マルチクラスタは可用性を上げる手段であると同時に、運用対象を倍にする決定です。正当化できる理由は3つしかありません。

まずマルチゾーンとマルチクラスタを区別する

「冗長化のためにマルチクラスタにしたい」という要望が出たとき、最初に確認するのはこの区別です。

リージョンクラスタは、コントロールプレーンのレプリカが複数のゾーンに配置されます。ゾーン障害への耐性は、リージョンクラスタを選んだ時点ですでに得られています。そのためにクラスタを2つ作る必要はありません。

冗長化の対象がコントロールプレーンなのかデータプレーンなのか、そしてゾーン障害なのかリージョン障害なのかを言語化できていないなら、その要望はまだ設計要件になっていません。

マルチクラスタを正当化する3条件

  1. SLOがリージョンクラスタの上限を超える ― リージョン障害を跨ぐ自動フェイルオーバーが必要な水準
  2. 規制・コンプライアンス上の分離要求がある ― データや処理をリージョンやプロジェクトで分ける必要がある。第1回のヒアリング②(コンプライアンス・監査要件)の結果がここに入ります
  3. 単一クラスタのスケール限界に達する ― ノード数、Pod数、APIリクエスト量。多くの組織はここに到達しません

いずれにも該当しないのにマルチクラスタを選ぶのは、根拠のない冗長化です。シングルクラスタ+リージョン構成で足ります。

マルチクラスタが持ち込むコストと複雑性

クラスタ管理手数料($0.10/時、月約$73)がクラスタ数だけ積み上がります。ただし金額よりも重いのは、運用対象が増えることです。

  • クラスタ間通信の設計(サービス検出、mTLS、レイテンシ)
  • GitOpsの適用対象が倍になる(第9回で扱います)
  • アドオンのバージョン差分の管理。クラスタごとにバージョンがずれ始めると、検証済みの組み合わせが増殖します
  • 監視対象とダッシュボードの倍増(第15回で扱います)

第1回の条件4で示した「専任2名以上」は、シングルクラスタを前提とした最小値です。マルチクラスタを選ぶのであれば、体制の見直しをセットで提案してください。

環境分離戦略 ― Stg を Prod のミラーにする

本記事が推奨する構成は、Prod(リージョン)/ Stg(リージョン・Prodのミラー)/ Dev(ゾーン)の3クラスタです。ただし「ミラー」という言葉を定義せずに使うと、コストが青天井になるか、検証として機能しないかのどちらかに倒れます。

Prodをリージョンクラスタ、Stgをその構成ミラーのリージョンクラスタ、Devをゾーンクラスタとする3環境構成と、各環境のSLAおよびバージョンアップ検証がStgで行われる流れを示した図
3環境構成。Stgで揃えるのは構成であって規模ではありません。Devだけがゾーンクラスタで、無料枠を適用できる唯一の環境です。

Namespaceでは分離できないもの

コストを理由に「1クラスタをNamespaceで分ける」案が出ることがあります。その前に、Namespaceでは分離できないものを確認してください。

  • Kubernetesのバージョン
  • CRDなどのクラスタスコープリソース
  • ClusterRole / ClusterRoleBinding
  • Admission Webhookの設定
  • ノードのOSイメージとカーネルパラメータ
  • アドオンのバージョン
  • max Pods per node

この一覧は、バージョンアップ時に壊れる可能性がある箇所の一覧とほぼ一致します。つまりNamespace分離では、アップグレードの事前検証ができません。ProdとStgを同一クラスタに置いた時点で、年3回前後のバージョンアップを検証なしで本番に当てることが確定します。

「ミラー」で揃えるもの・揃えなくてよいもの

ミラー環境の要件を定義せずに「本番と同じにしてください」と言うと、Prod同等のノード台数を用意させられてコストが倍になります。以下の表で線を引いてください。

区分項目理由
揃えるKubernetesバージョン(マイナー・パッチまで)検証の対象そのもの
揃えるリージョン / ゾーンの別(StgもリージョンクラスタにするゾーンStgではコントロールプレーンのアップグレード挙動を再現できない
揃えるAutopilot / Standard の別運用モードが違えば検証にならない
揃えるmax Pods per node作成後に変更できないため、Stg作成時に合わせないと永久にずれる
揃えるノードのマシンタイプ系列とOSイメージカーネル依存の不具合を再現するため
揃えるアドオンのバージョン(CSIドライバー、Gatewayコントローラー、cert-manager等)互換性検証の対象
揃えるService IPアドレスの方式(後述の2択のどちらか)ネットワーク挙動の再現
揃えなくてよいノード台数Prodの数分の1でよい。ただしリージョンクラスタとしての最小構成は維持する
揃えなくてよいセカンダリ範囲のサイズ台数に応じて縮小可。ただし設計方式は揃える
揃えなくてよいデータ量性能試験を兼ねる場合を除く
揃えなくてよい外部SaaS連携モック可。ただし通信要件(第5回で扱います)は揃える

この表が示しているのは、ミラーとは構成の同一性であって、規模の同一性ではないということです。この区別を文書に明記してください。明記しないと、コスト削減の議論のたびに「Stgのリージョンをゾーンに落とせないか」という提案が繰り返し出てきます。

特に注意が必要なのがmax Pods per nodeです。これはクラスタまたはノードプールの作成後に変更できません。Stgを作るときにProdと違う値を設定すると、以降ずっとProdと異なるIP消費特性で検証を続けることになります。作り直す以外に修正手段がありません。

Devはゾーンクラスタにしてコストを削る

Devに求めるのは「動くこと」であり、コントロールプレーンの可用性ではありません。ゾーンクラスタ(SLA 99.5%、月216分)を受け入れてください。この3環境でコストを削れる場所はDevだけです。

金額面でも理由があります。GKEには請求先アカウントごとに月$74.40の無料枠クレジットがあり、クラスタ管理手数料1つ分(月$73)にほぼ相当します。ただしこのクレジットが適用されるのはゾーンStandardクラスタとAutopilotクラスタだけで、リージョンクラスタのクラスタ料金には適用されません。Devをゾーンクラスタにすると、この無料枠を使い切れます。

ただし、DevとStgの間には差分が生まれます。Devで再現しない事象がStgで出ることを前提に、Devの位置づけを「アプリケーションの動作確認まで」と文書に明記してください。インフラ構成の検証はStgで行う、という線引きです。

検証を怠ると、クラスタ管理手数料が6倍になる

Stgをミラーにする投資には、金額面の裏付けもあります。

GKEでは、クラスタのマイナーバージョンが拡張サポート期間に入ると、通常のクラスタ管理手数料に加えて$0.50/クラスタ/時の拡張期間手数料が課金されます。通常の$0.10/時と合わせて$0.60/時、月額$73が月額$438です。

検証できる環境がないとアップグレードは先送りされ、この追加課金に行き着きます。第1回で試算したStgクラスタ1環境分のコストは月約$160でした。一方、3クラスタが拡張サポート期間に入ると、管理手数料の増加分だけで月約$1,100です。Stgクラスタを持つコストは、検証を怠って払う追加課金の7分の1以下に収まります。

ただし、第1回の条件4で述べたとおり、体制の要否をこの金額で判断してはいけません。ここで金額が意味を持つのは「Stgクラスタというインフラを持つかどうか」の判断に限られます。人を配置するかどうかは別の軸です。

なお、拡張サポートで留まれるのは最長24ヶ月です。バージョンアップの実行手順とノードドレイン戦略は第14回で扱います。

IPアドレス計画 ― 後から直せない設計項目

ここが本記事で最も事故が多い領域です。GKEにはクラスタ作成後に変更できない設定が複数あり、最初の計算がその後を決めます。

GKEのVPCネイティブクラスタで、サブネットのプライマリ範囲がノードに、セカンダリ範囲がPodに割り当てられる入れ子構造と、ノード1台がmax Pods per nodeに応じたCIDRブロックを丸ごと消費するために最大ノード数が確定する仕組みを示した図
IPアドレスの消費構造。ノード1台がPod用のCIDRブロックを丸ごと予約するため、Podセカンダリ範囲のサイズがそのまま最大ノード数になります。

VPCネイティブクラスタが使うIPアドレス範囲

VPCネイティブ(エイリアスIP)クラスタは、指定したサブネットから以下のようにアドレスを割り当てます。

  • ノード:サブネットのプライマリIPv4アドレス範囲から
  • Pod:1つ以上のサブネットセカンダリIPv4アドレス範囲から
  • Service(ClusterIP):後述の2つの方式のいずれか

Service用のアドレスについては、比較的新しいバージョンで選択肢が増えています。設計時にどちらを採るかを決めてください。

方式内容適用条件
34.118.224.0/20 を使うGoogleがプライベート用途に確保している範囲を使用する。サブネットのセカンダリ範囲を消費しない。この範囲へのルートはインターネットに公開されず、リソースの外部IPアドレスにも使われないGKE Autopilot 1.27以降、GKE Standard 1.29以降
サブネットセカンダリ範囲を使うPod用とは別のセカンダリ範囲をもう1つ用意する従来からの方式

「VPCネイティブクラスタにはPod用とService用の2つのセカンダリ範囲が必要」という説明を見かけたら、それは後者を前提とした記述です。新しいバージョンでは、Service用にサブネットのアドレス空間を割く必要がありません。自社で使えるアドレス空間が逼迫している場合、この差は設計の余裕に直結します。

ノード1台が消費するCIDRは、max Pods per node で決まる

ここが計算の起点です。GKEはノードごとにPod用のCIDRブロックを丸ごと割り当てます。そのサイズは、そのノードで動かせるPod数の上限から決まります。

max Pods per nodeノードあたりCIDRIPアドレス数
8/2816
9〜16/2732
17〜32/2664
33〜64/25128
65〜128/24256
129〜256/23512

割り当てられるブロックは、常にPod数上限の2倍以上のアドレスを含むサイズになります。Podの入れ替え時にアドレスの再利用を待たずに済ませるための余裕です。

Standardクラスタのデフォルトは110 Pods/nodeです。この場合、ノード1台につき/24(256アドレス)が丸ごと予約されます。実際に使えるのは最大110個ですから、IPアドレスの利用効率は約43%です。

Podセカンダリ範囲のサイズが、最大ノード数を確定させる

ノード1台が/24を取るということは、Podセカンダリ範囲を/24で割った数がノード数の上限になるということです。

Podセカンダリ範囲最大ノード数(110 Pods/node の場合)最大ノード数(32 Pods/node の場合)
/21832
/201664
/1932128
/1864256
/17128512
/162561,024

この表の左上を見てください。/21のPodセカンダリ範囲は、デフォルト設定では8ノードで頭打ちになります。9台目のノードは作成できません。

この上限に達したときの現れ方は、わかりにくい形を取ります。オートスケーラーがノードを増やそうとしても増えず、PodはPendingのまま残ります。ノードのマシンタイプにもクォータにも余裕があるのに増えないため、原因の特定に時間がかかります。この事故は負荷が高まった日、つまり最もスケールしてほしい日に発生します。

/21という値は、公式ドキュメントで「中規模のクラスタに十分なIPアドレスを提供する」推奨値として例示されているものです。この記述だけを見て/21で切ると、ノードが8台を超えた時点で詰まります。推奨値をそのまま採るのではなく、必ず自分の max Pods per node と最大ノード数で計算してください。

右列も重要です。max Pods per node を32に下げると、ノードあたりのCIDRが/26になり、同じ範囲で4倍のノードが立ちます。1ノードあたりのPod密度と、立てられるノード数のトレードオフがここにあります。1ノードに110個ものPodを詰める設計が本当に必要かを、この表を見ながら検討してください。

最大ノード数の見込みは、第4回で設計するノードのオートスケーリング上限が入力になります。第4回に着手する前でも、ここで上限の仮置きが必要です。

max Pods per node は作成後に変更できない

この設定はクラスタまたはノードプールの作成後に変更できません。Autopilotではさらに、GKEが8〜256の範囲から自動決定した値が固定されます。

変更するにはノードプール、場合によってはクラスタを作り直すことになります。前述のとおり、Stgをミラーにする際にこの値を揃え忘れると、以降ずっとProdと異なる特性で検証を続けることになります。

Standardクラスタを選ぶ理由としてこの項目を挙げたのは、これが理由です。IPアドレス空間に余裕がない環境では、max Pods per node を明示的に小さく設定できることが、そのままクラスタの上限台数を決めます。

設計時に突き合わせるCIDR一覧

設計の最後に、以下を並べて重複がないことを確認してください。1つでも重複していると、接続できない経路が生まれます。

  • サブネットのプライマリ範囲(ノード用)
  • Podセカンダリ範囲
  • Service用の範囲(34.118.224.0/20 を使う場合は重複確認の対象外)
  • オンプレミス側のCIDR(Cloud VPNやCloud Interconnectで接続する場合)
  • 接続先となる他のVPCのCIDR
  • 将来のクラスタ増設・作り替え用に予約しておく範囲

最後の項目を軽視しないでください。第14回で扱うクラスタの作り替えによるアップグレード(新しいクラスタを並べて構築し、トラフィックを移す方式)を将来の選択肢として残すなら、同サイズのセカンダリ範囲をもう1セット、VPC設計の時点で予約しておきます。後から隣接する空き範囲が取れず、アップグレード方式が実質的に1つに絞られる事故が起きます。

また、Podのセカンダリ範囲は、Cloud Routerによってオンプレミスネットワークからもルーティングされうる範囲です。オンプレミスとの接続がある環境では、Podに割り当てるアドレスがオンプレミス側の既存アドレスと衝突しないことを、設計段階で必ず確認してください。

なお、Pod間の通信を実際に許可・拒否するルール(NetworkPolicy)の設計は第5回、ここで決めたVPCとサブネットをTerraformでどう構築するかは第8回で扱います。本記事で決めるのは、アドレス空間の構造までです。

Gateway API による外部公開方針

GKEで新規に設計するのであれば、IngressではなくGateway APIを第一候補にしてください。理由は機能の豊富さではなく、責務の分割がAPIの構造として定義されている点にあります。

Gateway APIが第2回の責任境界と噛み合う

Gateway APIはロール指向のリソースモデルとして設計されています。クラスタオペレーター、デベロッパー、インフラストラクチャ提供者という組織内のロールに対応するリソースが分かれており、共有インフラストラクチャを複数の独立した開発チームがどう利用できるかを、クラスタオペレーター側が定義できます。

第2回で作成したRACIマトリクスと対応させると、次のようになります。

リソース管理するチーム第2回のRACIとの対応
GatewayClassインフラストラクチャ提供者(実質的にGoogle側)
Gateway運用チームタスク7「Ingressの作成とドメイン登録」
HTTPRoute開発チームタスク2「マニフェストの記述」

Ingressではこの分割をリソース境界で表現できません。1つのIngressリソースにインフラ設定とルーティングが同居し、さらに実装依存のアノテーションが混ざります。第2回で「運用チームがIngressを作り、開発チームがマニフェストを書く」と決めても、実際には同じリソースを両者が編集することになり、RACIが機能しません。

運開分離が求められる組織では、この差はさらに効いてきます。開発チームがHTTPRouteだけを触れる状態は、権限の分離としてそのまま実装できます。

公開単位ごとにロードバランサーを作らない

Gatewayを作るたびにロードバランサーが生成される構成にすると、公開単位の数だけ課金が積み上がります。転送ルールは1つあたり$0.025/時、月に換算すると約$18です。20個の公開単位それぞれにGatewayを立てれば、月$360になります。

1つのGatewayに複数のHTTPRouteをアタッチして集約してください。そのうえで、集約の単位を設計項目として決めます。環境ごとか、公開区分(外部公開 / 社内向け)ごとか、チームごとか。

集約にはトレードオフがあります。1つのGatewayに集約するほど、そのGatewayが単一障害点としての性格を強めます。また、1つのGatewayに紐づけられるルーティングルールの数には上限があるため、集約を進めるほど上限に近づきます。上限値は採用するGatewayClassによって異なるため、設計時に公式ドキュメントで確認し、想定する公開単位数がその範囲に収まるかを検証してください。

到達性のレイヤーで内部と外部を分ける

社内向けサービスを外部公開のロードバランサーに置き、認証だけで守る構成は避けてください。内部向けのGatewayClassを選び、そもそもインターネットから到達できない状態にします。認証の実装ミスが即座に情報公開につながる構成を作らないという、単純な原則です。

コントロールプレーンへのアクセス経路についても同じ判断が必要です。GKEではコントロールプレーンを外部エンドポイントと内部エンドポイントのどちらで公開するかを選択でき、内部エンドポイントのみにすればインターネット上のクライアントからクラスタに接続できなくなります。あわせて承認済みネットワークを設定し、アクセス元を絞ってください。データのプライバシーやセキュリティに関する規制がある場合は、この構成が前提になります。

ここまでは外部から内部への到達性、つまり上り方向の話です。逆方向も設計項目になります。

ノードに外部IPアドレスを持たせない構成にすると、コンテナイメージのpullや外部APIの呼び出しといった下り方向の通信にCloud NATが必要になります。第1回のK8s税の試算にCloud NATのゲートウェイ料金と外部IPアドレス料金を含めたのは、この経路が事実上必須だからです。

Cloud NATの課金は、ゲートウェイを利用するVM数に応じた時間料金($0.0014/時、32台分で頭打ち)と、外部IPアドレスの時間料金($0.005/時)、そして処理データ量に応じた$0.045/GiBの合計です。最初の2つは小規模なクラスタなら月$6程度に収まりますが、3つ目は変動します。ノードを一斉に入れ替えて全ノードが大きなコンテナイメージをpullする日には、データ処理料金だけで想定を超えることがあります。イメージのサイズとレジストリの配置は、ネットワークコストの設計項目です。

どのGatewayコントローラーを採用するかという選定理由そのものは、第6回のCNCFエコシステム選定書(ADR)で扱います。本記事で決めるのは公開方針までです。

【実務テンプレート】クラスタトポロジー・ネットワーク設計書

ここまでの内容を統合したテンプレートです。特にセクション5と6は、後から変更できない項目を含みます。埋めた内容について関係者の承認を得てから構築に着手してください。

クラスタトポロジー・ネットワーク設計書

プロジェクト名: ________________
作成日: ____/____/____
作成者: ________________
承認者: ________________


セクション1: SLO定義

可用性目標: ____%
 → 月間の許容ダウンタイム: ____分
測定するSLI: ______________________________
エラーバジェットの配分: 計画メンテナンス____分 / 障害____分
ゼロダウンタイムデプロイの実装: [必須 / 不要]


セクション2: 運用モードの選択

選択: [Autopilot / Standard]
Standardを選ぶ場合の根拠: [マシンタイプ固定 / GPU・TPU制御 / max Pods per node の制御 / パートナー一覧にない特権エージェント]
 その他の根拠: ______________________________

導入するノードエージェント(EDR等): ______________________________
 Autopilotパートナー一覧への掲載: [あり / なし / 該当なし]
 あり: 許可リストのパス______________________ / クラスタへのインストール [済 / 未]
 ベンダーのAutopilot向けデプロイガイドの確認: [済 / 未]
 センサー方式(ユーザー空間 / カーネルモジュール): ____________


セクション3: トポロジー選択

クラスタ数: [シングル / マルチ]
マルチを選ぶ場合、該当する条件: [1. SLOが上限超過 / 2. 規制上の分離要求 / 3. スケール限界]
 根拠: ______________________________
体制の見直しの要否: [要 / 不要]


セクション4: 環境構成

Prod: [リージョン / ゾーン] / リージョン名________ / 用途________
Stg: [リージョン / ゾーン] / リージョン名________ / 用途________
Dev: [リージョン / ゾーン] / ゾーン名________ / 用途________
バージョンアップの事前検証を行う環境: ________
無料枠クレジットを適用する環境: ________(ゾーンまたはAutopilotのみ)


セクション5: Stgミラー要件チェックリスト

各項目について Prod の値 / Stg の値 / 一致の有無 を記入すること。

Kubernetesバージョン: Prod______ / Stg______ / [一致 / 不一致]
リージョン・ゾーンの別: Prod______ / Stg______ / [一致 / 不一致]
運用モード: Prod______ / Stg______ / [一致 / 不一致]
max Pods per node: Prod______ / Stg______ / [一致 / 不一致] ← 変更不可
マシンタイプ系列: Prod______ / Stg______ / [一致 / 不一致]
OSイメージ: Prod______ / Stg______ / [一致 / 不一致]
アドオンのバージョン: Prod______ / Stg______ / [一致 / 不一致]
Service IPアドレスの方式: Prod______ / Stg______ / [一致 / 不一致]


セクション6: IPアドレス計画(作成後に変更できない項目を含む)

max Pods per node: ______ ← 作成後変更不可
 → ノードあたりCIDR: /______
想定する最大ノード数: ______台(第4回のオートスケーリング上限と整合させること)
 → 必要なPodセカンダリ範囲: /______

サブネット プライマリ範囲(ノード用): ______________
Podセカンダリ範囲: ______________
Service IPアドレスの方式: [34.118.224.0/20 / サブネットセカンダリ範囲]
 セカンダリ範囲を使う場合: ______________
予備セカンダリ範囲(クラスタ作り替え用): ______________ / [確保済 / 未確保]

重複確認(すべて「重複なし」であること)
 オンプレミス側CIDR: ______________ / [確認済]
 接続先の他VPCのCIDR: ______________ / [確認済]


セクション7: 外部公開方式

採用する方式: [Gateway API / Ingress]
Gatewayの集約単位: [環境ごと / 公開区分ごと / チームごと / その他______]
想定する公開単位数: ______
採用するGatewayClassのルール数上限: ______ / [確認済]
内部向けと外部向けの区分: ______________
コントロールプレーンのエンドポイント: [外部と内部 / 内部のみ]
承認済みネットワーク: ______________

次回予告

本記事では、SLOの数値からトポロジーを逆算する手順と、後から直せないIPアドレス計画の計算方法を扱いました。クラスタの形が決まると、次に決めるのは、そのクラスタに何台のノードをどう供給するかです。

次回の第4回「FinOps・スケーリング設計書」では、ノードの自動拡張、Spot VMの比率、NamespaceごとのResourceQuota、そしてコスト按分のためのラベリング設計を扱います。本記事で決めた max Pods per node と最大ノード数が、そのまま第4回の入力になります。ノードの上限台数を先に決めずにオートスケーリングを設計すると、IPアドレスが枯渇する上限まで気づかずにスケールする構成ができあがります。

前の記事
次の記事