本記事には広告(アフィリエイトリンク)が含まれます。

Kubernetes実践編 #02

【Kubernetes実践編 #02】基本設計 — 要件を「K8sリソースの選定と組み合わせ」に変換する

2.1 はじめに

2.1.1 前回の振り返り — 構成図が手元にある状態

前回(第1回)で、TaskBoardの構成図を3つの階層で描き上げました。

  • Level 1(クラスタ全体図): 3つのNamespace(app / db / monitoring)とGateway APIによる外部アクセス経路
  • Level 2(Namespace単位図): 各Namespace内のワークロード、Service、NetworkPolicy、RBACの構成
  • Level 3(Pod内部図): TaskBoard API Podのコンテナ構成、Probe設定、SecurityContext、環境変数

構成図で「何があるか」は可視化できました。クラスタの中にどのリソースが存在し、どのような通信経路でつながっているかは一目でわかる状態です。

しかし、構成図だけでは答えられない問いがあります。

2.1.2 本回の問題提起 — 「なぜこの構成にするのか」を説明できるか

上司やチームメンバーから、こう聞かれたとしましょう。

「MySQLにStatefulSetを使っているけど、Deploymentではダメなの?」
「Nginxのレプリカ数が2になっているけど、1ではだめな理由は?」
「フロントからDBへの直接通信を遮断しているのはなぜ?」

構成図はこれらの問いに答えてくれません。構成図が示すのは「What(何があるか)」であり、「Why(なぜそうしたか)」は別の文書の管轄です。その文書が「基本設計書」です。

VMの世界でも同じ状況がありませんでしたか。vSphereの構成図を描いた後、「なぜこのVM構成にしたのか」「なぜこのVLAN設計にしたのか」を説明するために、インフラ設計書を書いていたはずです。K8sでもプロセスは同じです。

2.1.3 本回のゴールと成果物

本回のゴールは、TaskBoardの構成図をもとに「基本設計書」を作成することです。

基本設計書では、以下の5つの設計領域について「何を使うか」と「なぜそれを選ぶか」を文書化します。

  • ワークロード設計: 各コンポーネントにどのワークロードリソースを使うか
  • 可用性設計: 停止を防ぐためにどのような構成にするか
  • データ永続化設計: データを失わないためにどう保護するか
  • ネットワーク設計: コンポーネント間をどう通信させるか
  • セキュリティ設計方針: システムをどう守るか

ここで重要な区別があります。基本設計書は「何を使うか・なぜか」を決める文書です。「具体的にどの値を設定するか」は次回の詳細設計書(第3回)の管轄です。

文書決めること
基本設計書(本回)何を使うか・なぜか「MySQLにはStatefulSetを使用する(理由:データの永続化と安定したネットワークIDが必要)」
詳細設計書(次回)具体的にどの値を設定するか「StatefulSetのreplicas: 1、resources: requests 200m/256Mi, limits 500m/512Mi」

この粒度の違いを意識しながら、基本設計書を段階的に作成していきましょう。

成果物: TaskBoardの基本設計書(5つの設計領域を網羅した文書)

2.2 VMの基本設計書とK8sの基本設計書

2.2.1 VMの世界でのインフラ設計書 — 何を決めるか

VMwareの世界で「インフラ設計書」(基本設計書)を書いた経験がある方は、その構造を思い出してみてください。一般的には、以下のような項目を決めていたはずです。

  • サーバー設計: 物理サーバーの台数、VMのスペック(vCPU数、メモリ容量)、OSの選定と根拠
  • 可用性設計: vSphere HAの有効化、DRSの設定方針、アフィニティ/アンチアフィニティルール
  • ストレージ設計: データストアの種別(VMFS / NFS / vSAN)、容量、シンプロビジョニングの方針
  • バックアップ設計: バックアップ方式(Veeam / vSphere Replication等)、スケジュール、保持世代数
  • ネットワーク設計: VLAN設計、ポートグループ構成、ファイアウォールルール
  • 権限設計: vCenterの権限モデル、Active Directoryのグループ設計、管理者と運用者の権限分離

これらの項目に共通するのは、「何を使うか」と「なぜその選択か」を決めている点です。具体的なIPアドレスやポートグループ名は詳細設計で決めます。基本設計の段階では、方針と選定理由の確定が目的です。

2.2.2 K8sの基本設計書 — 何を決めるか

K8sの基本設計書でも決めることの構造は同じです。ただし、対象がVMからPodに、VLANからNamespaceに、データストアからPVCに置き換わります。

  • ワークロード設計: 各コンポーネントに使用するワークロードリソース(Deployment / StatefulSet / DaemonSet / Job / CronJob)の選定と理由
  • 可用性設計: レプリカ数の決定根拠、Pod分散配置の方針、PodDisruptionBudget(PDB)の設計
  • データ永続化設計: PVCの設計方針(StorageClass、容量、アクセスモード)、バックアップ方針
  • ネットワーク設計: Service種別の選定、Gateway APIの方針、DNS名の設計
  • セキュリティ設計方針: Namespace分離、RBAC方針、NetworkPolicy方針、SecurityContext方針

VMのインフラ設計書を書いた経験があれば、K8sの基本設計書にもその経験がそのまま活きます。「技術は変わったが、設計書の構造と考え方は同じ」——この感覚は本回を通じて体感してもらえるはずです。

2.2.3 VMとK8sの設計項目の対応表

VMの基本設計書とK8sの基本設計書で決める項目の対応関係を整理します。

設計領域VMの基本設計書で決めることK8sの基本設計書で決めること
ワークロードVM数、OS選定、ミドルウェア選定ワークロードリソース種別(Deployment / StatefulSet等)の選定
リソース割当vCPU数、メモリ容量の割当方針resources(requests / limits)の設計方針
可用性vSphere HA、DRS、アンチアフィニティルールレプリカ数、topologySpreadConstraints、PDB
ストレージデータストア種別、容量、シンプロビジョニングStorageClass、PVC容量、アクセスモード
バックアップバックアップ方式、スケジュール、保持世代数CronJobによるバックアップ方式、スケジュール、保持世代数
ネットワークVLAN設計、ポートグループ、ファイアウォールService種別、Gateway API方針、NetworkPolicy方針
権限vCenter権限モデル、AD設計RBAC(Role / RoleBinding / ServiceAccount)
セキュリティSELinux / AppArmor、最小権限設定SecurityContext、Pod Security Standards

左の列を書いたことがある方は、右の列も書けます。決めるべきことの構造は共通です。では、TaskBoardの基本設計書を5つの設計領域ごとに作成していきましょう。

2.3 ワークロード設計 — 「何で動かすか」を決める

2.3.1 TaskBoardの要件を振り返る

ワークロードを選定する前に、TaskBoardの各コンポーネントが満たすべき要件を整理します。第1回の構成図で可視化した6つのコンポーネントについて、それぞれの特性を確認しましょう。

コンポーネント役割動作パターンデータの有無
Nginxフロントエンド(静的ファイル配信)常時稼働。リクエストに応じて応答なし(静的ファイルはイメージ内)
TaskBoard APIRESTful API(Payara Micro)常時稼働。リクエストに応じて応答なし(データはMySQLに永続化)
MySQLデータベース常時稼働。データの読み書きあり(タスクデータを永続化)
DB初期化スキーマ作成・初期データ投入一度だけ実行して完了なし(MySQLに書き込むだけ)
DBバックアップmysqldumpによる定期バックアップ定期実行(日次)なし(バックアップファイルを出力)
ログ収集全Worker Nodeでのログ収集常時稼働。全Nodeに1つずつ必要なし(ログの転送のみ)

この要件整理が、ワークロード選定の入力情報になります。

2.3.2 各コンポーネントのワークロード選定と理由

K8sには5種類のワークロードリソースがあります。応用編で全種類を体験しました。ここでは、TaskBoardの各コンポーネントに対して「なぜこのワークロードか」を設計判断として記述します。

設計判断に迷ったとき、AIを壁打ち相手にする方法を紹介しましょう。たとえば、「MySQLにはStatefulSetとDeploymentのどちらが適切か」という判断で迷った場合、以下のように相談できます。

💬 あなた → AI(Claude):
TaskBoardというWebアプリのDBにMySQLを使います。Kubernetes上でMySQLを動かす場合、DeploymentとStatefulSetのどちらが適切ですか?選定理由も教えてください。

🤖 Claude の回答:
MySQLのようなデータベースにはStatefulSetが適切です。理由は以下の3点です。

1. 安定したネットワークID: StatefulSetのPodは再起動しても同じホスト名(mysql-0)を維持します。他のPodからの接続先が変わりません。
2. 永続データの保持: StatefulSetのvolumeClaimTemplatesにより、Pod再作成時も同じPVCが再マウントされます。Deploymentでは新しいPodが新しいPVCを要求する可能性があり、データの引き継ぎが不確実です。
3. 順序制御: StatefulSetはPodの起動・停止を順番に行います。レプリカ構成でプライマリ/レプリカの起動順を制御する場合に不可欠です。

Deploymentは「どのPodも同等で交換可能」なステートレスアプリ向けです。データの永続化と識別性が必要なMySQLにはStatefulSetを推奨します。

🔍 ここで立ち止まって確認しましょう
AIの回答をそのまま採用する前に、以下をチェックしてください。

  • ☐ AIの回答は「一般論」として正しい。しかし、TaskBoardのMySQLはreplicas: 1のシングルインスタンス構成。3つ目の理由(順序制御)はレプリカ構成時の話であり、TaskBoardでは直接的なメリットにならない
  • ☐ kind環境では、StorageClassはstandard(hostPath相当)を使用する。本番のように高度なストレージ管理が動くわけではない。そのことを設計書に注記すべきか
  • ☐ 「Deploymentでは新しいPodが新しいPVCを要求する可能性がある」というAIの説明は正確か? → DeploymentでもPVCを固定指定すればデータは保持されるが、StatefulSetのvolumeClaimTemplatesの方がPodとPVCの対応関係が明確で、運用上安全

AIの回答は概ね正しい方向を示していますが、自分の環境・要件に合わせて判断を補正する作業は設計者自身の仕事です。AIは「壁打ち相手」であり、「最終判断者」ではありません。

この壁打ちの結果も踏まえて、TaskBoardの全コンポーネントに対するワークロード選定をまとめます。

コンポーネントワークロード選定理由
NginxDeploymentステートレス。どのPodも同等で交換可能。水平スケーリングが容易
TaskBoard APIDeploymentステートレス(データはMySQLに永続化)。スケールアウト/インに対応する必要がある
MySQLStatefulSetデータの永続化が必須。PodとPVCの安定した対応関係が必要。Pod再作成時に同じデータボリュームが再マウントされることを保証する
DB初期化Jobスキーマ作成と初期データ投入を一度だけ実行する。完了後はPodが Completedで残り、ログを確認できる
DBバックアップCronJobmysqldumpを定期的に実行する。スケジュールに基づいてJobを自動生成する
ログ収集DaemonSet全Worker Nodeに1つずつPodを配置する必要がある。Nodeの増減に自動追従する

2.3.3 ワークロード選定フローチャートで検証する

応用第4回で学んだワークロード選定フローチャートを使って、上記の選定が妥当かを検証しましょう。

                     常時稼働させたいか?
                    ┌──── Yes ────┐
                    │              │
              全Nodeに1つずつ?     No → 一度だけ?
              ┌─ Yes ─┐            ┌─ Yes ─┐
              │        │            │        │
          DaemonSet   No        Job     No → CronJob
                       │
                状態(データ)を持つ?
                ┌─ Yes ─┐
                │        │
            StatefulSet  No → Deployment

各コンポーネントをフローチャートに通してみます。

コンポーネント常時稼働?全Nodeに1つ?一度だけ?状態を持つ?結果
NginxYesNoNoDeployment ✓
TaskBoard APIYesNoNoDeployment ✓
MySQLYesNoYesStatefulSet ✓
DB初期化NoYesJob ✓
DBバックアップNoNoCronJob ✓
ログ収集YesYesDaemonSet ✓

6つのコンポーネントすべてがフローチャートの結果と一致しました。フローチャートは機械的に適用するだけでなく、「選定理由を第三者に説明する根拠」としても使えます。設計レビューで「なぜStatefulSetなのか」と聞かれたとき、フローチャートを示して「データの永続化が必要なためです」と答えられます。

これでワークロード設計の基本設計書パートが完成しました。

📄 基本設計書 — 2. ワークロード設計

TaskBoardは6つのコンポーネントで構成される。各コンポーネントに対し、動作パターンとデータ要件に基づいてワークロードリソースを選定した。

Nginx(フロントエンド): Deployment。ステートレスな静的ファイル配信。水平スケーリング対象。
TaskBoard API: Deployment。ステートレスなREST API。データはMySQLに委譲。水平スケーリング対象。
MySQL: StatefulSet。データの永続化が必須。PodとPVCの安定した対応関係を保証する。
DB初期化: Job。スキーマ作成と初期データ投入を一度だけ実行。
DBバックアップ: CronJob。mysqldumpによる定期バックアップ。
ログ収集: DaemonSet。全Worker Nodeに1つずつPodを配置。

2.4 可用性設計 — 「止めないためにどうするか」を決める

2.4.1 レプリカ数の決定根拠

VMの世界では、vSphere HAやDRS(Distributed Resource Scheduler)で可用性を確保していました。VMが落ちれば別のESXiホストで自動再起動し、リソース不足のホストからは自動移行する。K8sでも同じ目的を持つ仕組みがありますが、アプローチが異なります。K8sの可用性確保の基本は「レプリカ数を増やして冗長化する」ことです。

レプリカ数の決定は「多ければ多いほど良い」ではありません。レプリカ1つあたりにCPUとメモリを消費するため、環境の制約を考慮した現実的な判断が必要です。

TaskBoardのkind環境は、Worker Node 3台で構成されています。各Worker Nodeが持つリソースには限りがあるため、レプリカ数は「可用性を確保しつつ、リソースを使い切らない」バランスで決めます。

コンポーネントレプリカ数決定根拠
Nginx2静的ファイル配信はリクエスト処理が軽量。2レプリカで冗長化しつつ、HPAでピーク時にスケールアウト(max: 6)
TaskBoard API2REST APIの処理はDB操作を含むためNginxより重い。2レプリカで冗長化し、HPAでスケールアウト(max: 4)
MySQL1シングルインスタンス構成。レプリケーション構成は本シリーズの範囲外。可用性はバックアップとリストアで担保する
ログ収集Worker Node数と同数(3)DaemonSetの特性により自動決定。Node追加時に自動でPodが増える

MySQLのレプリカ数が1である点について補足します。MySQLのレプリケーション(プライマリ/レプリカ構成)を設計すれば可用性は向上しますが、その構築・運用の複雑さは本シリーズのスコープを超えます。シングルインスタンス構成のリスク(Podが落ちるとDBアクセスが一時的に停止する)は認識した上で、バックアップからの復元で対処する方針とします。これは「やらない判断」も設計の一部であるという例です。

2.4.2 Pod分散配置の方針

レプリカ数を2にしても、2つのPodが同じWorker Nodeに配置されては冗長化の意味がありません。そのNodeが落ちれば両方のPodが停止します。VMの世界でいえば、HAクラスタ内の2台のVMを同じESXiホストに置いてしまうのと同じ失敗です。vSphereではアンチアフィニティルールで防止していました。

K8sではtopologySpreadConstraintsを使って、Podを異なるNodeに分散配置します。

コンポーネント分散配置方針根拠
NginxtopologySpreadConstraintsでWorker Node間に分散1 Nodeダウン時にもう1つのPodが存続してサービス継続
TaskBoard APItopologySpreadConstraintsでWorker Node間に分散Nginx同様。API層の可用性を確保
MySQL分散配置の設定なしreplicas: 1のため分散の対象外
ログ収集DaemonSetのため自動的に全Nodeに分散設定不要。DaemonSetの仕様で保証される

topologySpreadConstraintspodAntiAffinityの2つの方法がありますが、TaskBoardではtopologySpreadConstraintsを採用します。podAntiAffinityは「絶対に同じNodeに配置しない」という厳格なルールを設定できますが、Worker Nodeが3台しかない環境でレプリカ数が増えた場合(HPAによるスケールアウト時)、配置できるNodeがなくなりPodがPendingになるリスクがあります。topologySpreadConstraintsは「可能な限り均等に分散する」という柔軟なルールであり、小規模環境との相性が良い選択です。

2.4.3 PodDisruptionBudget(PDB)の設計

PodDisruptionBudget(PDB)は、応用編では扱っていない新しい概念です。ここで導入します。

VMの世界で、ESXiホストのメンテナンス時にvMotionでVMを退避させた経験があるでしょう。このとき、退避先のホストにリソースが足りなければVMは停止します。K8sでも同様の状況が発生します。Worker Nodeのメンテナンス時にkubectl drainコマンドでNodeからPodを退去させますが、このとき全Podが一斉に退去すると、サービスが完全に停止する可能性があります。

PDBは「計画的なメンテナンス時に、最低何個のPodを稼働させ続けるか」を宣言するリソースです。PDBを設定しておくと、kubectl drainはPDBの条件を満たす範囲でのみPodを退去させます。

重要な注意点として、PDBが効力を持つのは「計画的な中断(Voluntary Disruption)」の場合のみです。Nodeの突然のクラッシュやPodのOOMKilledなど、非計画的な中断にはPDBは効きません。PDBは「計画的なメンテナンスの安全弁」であり、「あらゆる障害からの保護」ではありません。

コンポーネントPDB設定根拠
NginxminAvailable: 1replicas: 2のうち最低1つが稼働していれば、フロントエンドへのアクセスを継続できる
TaskBoard APIminAvailable: 1replicas: 2のうち最低1つが稼働していれば、API処理を継続できる
MySQL設定なし(注記あり)replicas: 1のシングルインスタンス構成のため、PDBを設定してもdrainでPodが退去する際にサービスは一時停止する。PDB設定の効果は限定的だが、drainが「MySQL Podの退去前に一時停止を求める」動作にはなる
ログ収集設定なしDaemonSetのPodはdrain時に退去対象となるが、ログ収集の一時停止は許容範囲

これで可用性設計の基本設計書パートが完成しました。

📄 基本設計書 — 3. 可用性設計

レプリカ数:
Nginx / TaskBoard API: 各2。HPAによる自動スケーリングを併用(Nginx max:6、API max:4)。
MySQL: 1(シングルインスタンス構成)。レプリケーションは範囲外。

Pod分散配置:
Nginx / TaskBoard API: topologySpreadConstraintsでWorker Node間に分散。HPAスケールアウト時にもPendingを回避するため、podAntiAffinityではなくtopologySpreadConstraintsを採用。
MySQL: replicas: 1のため対象外。ログ収集: DaemonSetの仕様で自動分散。

PodDisruptionBudget:
Nginx / TaskBoard API: minAvailable: 1。Nodeメンテナンス時にサービス継続を保証。
MySQL: replicas: 1のためPDBの効果は限定的。メンテナンス時の一時停止を許容する方針。

2.5 データ永続化設計 — 「データを失わないためにどうするか」を決める

2.5.1 PVC設計(StorageClass、容量、アクセスモード)

VMの世界では、データストア(VMFS / NFS / vSAN)の設計がストレージ設計の中心でした。どのデータストアにVMを配置するか、シンプロビジョニングにするか、ディスクのIOPS要件をどう満たすかを設計書に記載していたはずです。

K8sの世界では、PersistentVolumeClaim(PVC)がストレージ設計の中心です。PVCはPodに対して「この容量のストレージが必要」と宣言し、StorageClassに基づいてPersistentVolume(PV)が動的にプロビジョニングされます。

TaskBoardで永続化が必要なコンポーネントはMySQLのみです。NginxとTaskBoard APIはステートレスであり、ログ収集もPodのログファイルを読み取るだけなので永続化は不要です。

設計項目設計方針根拠
対象コンポーネントMySQLのみ他のコンポーネントはステートレス
StorageClasskindデフォルト(standard)kindのhostPath provisioner。本番ではクラウドプロバイダのStorageClass(gp3、Premium SSD等)に置き換わる
アクセスモードReadWriteOnce(RWO)MySQLはシングルインスタンス。1つのPodからのみ読み書きできればよい
容量方針詳細設計で決定TaskBoardのデータ量から見積もる。基本設計ではGB単位の目安を提示し、詳細設計で確定する
ReclaimPolicyRetainPVCを削除してもデータを保持する方針。意図しないデータ削除を防止する

kind環境のStorageClassはhostPath相当であり、本番環境のストレージ(AWS EBS、Azure Disk、GCE Persistent Disk等)とは性能特性が異なります。この差分は実践第10回「本番への道」で整理しますが、PVCのマニフェスト構造自体はkindでも本番でも同じです。「StorageClassの名前を差し替えるだけで本番に移行できる」設計を意識しておくことが重要です。

2.5.2 バックアップ方針

VMの世界では、Veeam Backup & ReplicationやvSphere Replicationでバックアップを取得していました。スケジュール、保持世代数、リストア手順を設計書に記載するのが定番です。

K8sの世界では、アプリケーションレベルのバックアップが基本です。MySQLの場合、mysqldumpでデータをエクスポートするCronJobを用います。応用第4回で構築したDBバックアップCronJobがこれに該当します。

設計項目設計方針根拠
バックアップ方式CronJobによるmysqldump論理バックアップ。リストアが容易で、環境間のデータ移行にも使える
スケジュール日次(毎日深夜)TaskBoardのデータ更新頻度から、1日分のデータロスを許容範囲とする
保持世代数7世代(1週間分)直近1週間以内であれば任意の日のデータに復元可能
バックアップ先PVC上のディレクトリ(kind環境)本番ではオブジェクトストレージ(S3等)に保管する設計に変更する

バックアップの設計で最も重要なのは「リストアが実際にできるか」です。バックアップを取得しているだけで安心してはいけません。リストア手順をあらかじめ設計し、テストしておく必要があります。

2.5.3 リストア方針の概要

バックアップがあっても、リストアの手順が設計されていなければ、障害発生時にパニックになります。基本設計の段階では、リストアの大まかな流れを方針として定めておきます。具体的な手順は運用設計(実践第7回)で詳細化します。

リストアシナリオ対応方針
MySQL Podの再起動PVCのデータが残っているため自動復旧。リストア不要
PVCのデータ破損直近のmysqldumpバックアップからリストア。一時的なJobを作成してmysqlコマンドでインポート
誤操作によるデータ削除直近のバックアップから該当テーブルのみリストア。バックアップの世代を指定して復元

リストア方針の核心は「何が起きたら、どのバックアップを使って、どう復元するか」を事前に決めておくことです。VMの世界で「Veeamのリストアウィザードを使って、指定日時のスナップショットから復元する」と設計書に書いていたのと同じ考え方です。

📄 基本設計書 — 4. データ永続化設計

PVC設計:
対象: MySQL。StorageClass: kindデフォルト(standard)。アクセスモード: ReadWriteOnce。ReclaimPolicy: Retain。容量は詳細設計で確定。

バックアップ方針:
方式: CronJobによるmysqldump(論理バックアップ)。スケジュール: 日次。保持世代数: 7世代。保管先: PVC上(kind環境)。

リストア方針:
Pod再起動時はPVCから自動復旧。データ破損・誤削除時はmysqldumpバックアップからJobでリストア。詳細手順は運用設計で策定する。

2.6 ネットワーク設計 — 「どう通信させるか」を決める

2.6.1 Service設計(種別選定と根拠)

VMの世界では、ネットワーク設計はVLANの設計とファイアウォールルールが中心でした。「このセグメントからこのセグメントへの通信を許可する」「ロードバランサーのVIPでトラフィックを振り分ける」といった設計です。

K8sでは、Service、Gateway API、NetworkPolicyがネットワーク設計の柱です。まずServiceの種別を選定します。

コンポーネントService種別選定理由
NginxClusterIP外部からの直接アクセスは不要。Gateway API経由でアクセスされるため、クラスタ内部からの到達性のみ必要
TaskBoard APIClusterIPNginx同様。Gateway API経由でアクセスされる
MySQLHeadless Service(clusterIP: None)StatefulSetの各Podに対して安定したDNS名を提供する。ロードバランシングは不要(replicas: 1)

NodePortは使用しません。応用第5回で学んだとおり、外部アクセスの入口はGateway APIに集約します。NodePortはポート番号の管理が煩雑で、セキュリティ上も外部にポートを直接開放することになるため、本番環境では推奨されません。

2.6.2 Gateway API方針

外部からTaskBoardへのアクセスは、Gateway APIによるL7ルーティングで制御します。応用第5回で構築した方式を踏襲します。

設計項目設計方針根拠
ルーティング方式パスベースルーティング単一のGateway(ポート80)から、パスでフロントエンドとAPIに振り分ける
ルーティングルール/ → Nginx、/api → TaskBoard APIフロントエンド(HTML/CSS/JS)とAPI(REST)をパスで分離
Gateway APIコントローラーEnvoy Gateway応用第5回で導入済み。CNCFプロジェクトであり、Gateway API標準に準拠
HTTPS対応本シリーズでは非対応(HTTP)TLS証明書の管理はkind環境では不要。本番移行時にcert-manager等で対応する

2.6.3 DNS設計(Headless Service、FQDN規約)

K8sクラスタ内のサービス間通信では、Service名によるDNS解決を使います。IPアドレスのハードコーディングは行いません。これはVMの世界で「IPアドレスではなくDNS名でサーバーを参照する」のと同じ原則です。

通信元通信先DNS名(FQDN)用途
Gateway APINginx Servicenginx.app.svc.cluster.localフロントエンドへのHTTPルーティング
Gateway APITaskBoard API Servicetaskboard-api.app.svc.cluster.localAPIへのHTTPルーティング
TaskBoard APIMySQL Headless Servicemysql.db.svc.cluster.localAPIからDBへの接続

同一Namespace内であればService名だけ(例: nginx)で解決できますが、クロスNamespace通信では完全なFQDN(例: mysql.db.svc.cluster.local)が必要です。TaskBoard APIはapp Namespaceに、MySQLはdb Namespaceに配置されるため、API→DB通信にはFQDNを使用します。

MySQLのHeadless Service(clusterIP: None)は、StatefulSetのPod名に基づいたDNSレコードを自動生成します。mysql-0.mysql.db.svc.cluster.localで特定のPodに直接アクセスできます。replicas: 1の現状では恩恵は限定的ですが、将来的にレプリケーション構成に拡張する際の基盤になります。

📄 基本設計書 — 5. ネットワーク設計

Service設計:
Nginx / TaskBoard API: ClusterIP。Gateway API経由でのみ外部アクセスを受ける。
MySQL: Headless Service(clusterIP: None)。StatefulSetに安定したDNS名を提供。

Gateway API方針:
パスベースルーティング。単一Gateway(ポート80)から / → Nginx、/api → TaskBoard APIに振り分け。コントローラーはEnvoy Gateway。HTTPS対応は本番移行時に対応。

DNS設計:
サービス間通信はFQDNを使用。クロスNamespace通信(API→DB)はmysql.db.svc.cluster.local。IPアドレスのハードコーディングは禁止。

2.7 セキュリティ設計方針 — 「どう守るか」を決める

2.7.1 Namespace分離の設計

VMの世界で「本番環境と開発環境を同じクラスタに入れるのか」「DBサーバーとWebサーバーを同じVLANに入れるのか」を検討したことがあるでしょう。K8sでは、Namespaceがこの分離の境界を担います。

TaskBoardは3つのNamespaceで環境を分離します。この分離方式は応用第1回で設計・構築しました。

Namespace収容するコンポーネント分離の理由
appNginx、TaskBoard APIアプリケーション層。外部アクセスを受けるコンポーネントを集約。水平スケーリング対象
dbMySQL、DB初期化Job、DBバックアップCronJobデータ層。データベースと関連する運用ジョブを集約。アクセス制限の境界を明確にする
monitoringログ収集DaemonSet監視・運用層。アプリケーションやDBとは独立したライフサイクルで管理する

この3Namespace構成は「機能(役割)による分離」です。Namespace分離の方式には「チーム別」「環境別(dev/staging/prod)」「機能別」などがありますが、TaskBoardは単一チームが運用するシステムであり、kind環境は1つの環境(学習環境)であるため、機能別の分離が最も自然です。

各Namespaceには応用第1回で設定したResourceQuotaとLimitRangeを適用し、リソース消費の上限を制御します。詳細な値は第3回の詳細設計で確定します。

2.7.2 RBAC方針

応用第2回で構築したRBAC設計を、基本設計書の方針としてまとめます。VMの世界でvCenterの権限モデルを設計していたのと同じく、K8sでも「誰が何をできるか」を最小権限の原則で設計します。

ServiceAccount権限範囲許可される操作設計意図
developer各Namespace内Podの参照、ログ取得。リソースの作成・更新・削除は不可開発者が状態確認やログ調査を行えるが、誤ってリソースを変更・削除することを防止する
operator各Namespace内Deployment更新、Pod削除、ConfigMap/Secret管理運用者がデプロイやスケーリングなどの運用操作を実行できる

RoleはNamespaceスコープで設定します。ClusterRoleは「全Namespace横断の操作が必要な場合」にのみ使用し、TaskBoardの基本設計では使用しません。これは最小権限の原則に基づく判断です。Namespace内で完結する権限は、Namespaceスコープで管理する方が安全です。

2.7.3 NetworkPolicy方針

応用第6回で学んだ「デフォルト拒否 + ホワイトリスト」の思考を、基本設計の方針として定めます。VMの世界でファイアウォールを「デフォルトDeny、必要なポートのみAllow」で設計していたのと同じアプローチです。

基本方針: 全Namespace(app、db)にデフォルト拒否のNetworkPolicyを適用し、必要な通信のみを明示的に許可する。

通信経路方向許可/遮断根拠
外部 → Gateway APIIngress許可ユーザーアクセスの入口
Gateway → NginxIngress許可パスベースルーティング
Gateway → TaskBoard APIIngress許可パスベースルーティング
TaskBoard API → MySQLIngress(db側)許可APIからDBへのデータ操作
Nginx → MySQL遮断フロントエンドがDBに直接アクセスする理由はない。3層構造の境界を維持する
DBバックアップCronJob → MySQLIngress(db側)許可mysqldumpの実行にMySQL接続が必要。応用第6回で学んだCronJob考慮の適用

応用第6回では、CronJobのPodがNetworkPolicyのデフォルト拒否で遮断される問題に対処しました。バックアップCronJobのPodはバックアップ実行時にのみ生成されるため、NetworkPolicyで明示的に許可しておかなければバックアップが失敗します。この「運用ワークフローまで考慮したNetworkPolicy設計」は、基本設計の段階で方針に含めておくべきポイントです。

monitoring Namespaceについては、応用編の構成ではNetworkPolicyを適用していません。ログ収集DaemonSetは他のNamespaceとのPod間通信を持たないためです。ただし、本番環境では監視コンポーネントが外部の監視サービスに通信する場合があり、その際はEgressルールの設計が必要になります。

2.7.4 SecurityContext方針

応用第7回で学んだSecurityContextの設計を、基本設計の方針としてまとめます。VMの世界でサービスアカウントの最小権限設定やSELinuxのポリシー設計を行っていたのと同じく、コンテナの実行環境を最小権限に制限します。

基本方針: 全Podに対して、以下の4つのSecurityContext設定を基本とする。

設定項目方針根拠
runAsNonRoot全Podに適用root権限でのコンテナ実行を禁止する。コンテナが侵害された場合の影響範囲を限定する
readOnlyRootFilesystem全Podに適用(一時書き込み領域はemptyDirで対応)コンテナ内のファイルシステムを読み取り専用にし、不正なファイル書き込みを防止する
allowPrivilegeEscalationfalse を全Podに適用コンテナプロセスが権限昇格することを防止する
capabilitiesdrop: ALL を全Podに適用Linuxカーネルのcapabilitiesをすべて剥奪。必要なcapabilityがある場合のみ個別にaddする

コンポーネントごとの注意点を整理します。

コンポーネント実行ユーザー注意点
Nginx非rootユーザーデフォルトのNginxイメージはrootで起動する。応用第7回で非root化(ポート80→8080変更)を実施済み
TaskBoard API(Payara Micro)payara(uid=1000)公式イメージが元々非root。SecurityContext設定は自然に適用できる
MySQLmysql(uid=999)公式イメージが元々非root。データディレクトリへの書き込みが必要
busybox(ログ収集、ジョブ系)非rootユーザーを指定runAsUserで明示的に非rootを指定する

Pod Security Standardsについては、Restricted(最も厳格)レベルへの準拠を目指します。応用第7回で学んだとおり、Restrictedレベルは上記のSecurityContext設定をすべて要求するため、方針として整合しています。Namespace単位でPod Security Admissionをwarnモードで適用し、準拠状況を確認します。

📄 基本設計書 — 6. セキュリティ設計方針

Namespace分離:
3Namespace構成(app / db / monitoring)。機能別の分離。各NamespaceにResourceQuota / LimitRangeを適用。

RBAC方針:
ServiceAccount: developer(参照のみ)/ operator(管理操作)。RoleはNamespaceスコープ。ClusterRoleは使用しない。最小権限の原則。

NetworkPolicy方針:
全Namespace(app / db)にデフォルト拒否を適用。必要な通信のみホワイトリストで許可。API→DB、CronJob→DBの運用通信を明示的に許可。フロントエンド→DBの直接通信は遮断。

SecurityContext方針:
全Podに runAsNonRoot / readOnlyRootFilesystem / allowPrivilegeEscalation: false / capabilities drop: ALL を適用。Pod Security Standards Restrictedレベルに準拠。

2.8 この回のまとめ

2.8.1 成果物の確認 — TaskBoardの基本設計書

本回の成果物は、TaskBoardの基本設計書です。5つの設計領域を通して段階的に作成してきた内容を、設計書の全体構造として確認しましょう。

TaskBoard 基本設計書
├── 1. システム概要
│     └── 構成図(第1回の成果物を参照)
├── 2. ワークロード設計
│     ├── コンポーネント一覧とワークロード種別
│     │     Nginx: Deployment / TaskBoard API: Deployment
│     │     MySQL: StatefulSet / DB初期化: Job
│     │     DBバックアップ: CronJob / ログ収集: DaemonSet
│     └── 選定理由(フローチャートで検証済み)
├── 3. 可用性設計
│     ├── レプリカ数: Nginx 2, API 2, MySQL 1
│     ├── Pod分散配置: topologySpreadConstraints
│     └── PDB: Nginx/API minAvailable:1, MySQL 設定なし
├── 4. データ永続化設計
│     ├── PVC設計: MySQL用, RWO, Retain
│     └── バックアップ: CronJob mysqldump, 日次, 7世代保持
├── 5. ネットワーク設計
│     ├── Service: ClusterIP(app)+ Headless(db)
│     ├── Gateway API: パスベースルーティング
│     └── DNS: FQDN使用, IP直書き禁止
└── 6. セキュリティ設計方針
      ├── Namespace分離: app / db / monitoring
      ├── RBAC: developer(参照) / operator(管理)
      ├── NetworkPolicy: デフォルト拒否 + ホワイトリスト
      └── SecurityContext: 非root, readOnly, drop ALL

この基本設計書は、第1回の構成図(What)に対する「Why」を記述した文書です。構成図とセットで管理することで、「何があるか」と「なぜそうしたか」の両方を追跡できます。

フェーズの進捗:

【フェーズ1:設計】
  ✅ 第1回 ── 構成図(完了)
  ✅ 第2回 ── 基本設計(完了)
  ☐ 第3回 ── 詳細設計

【フェーズ2:構築】 ☐ 第4回〜第6回
【フェーズ3:運用】 ☐ 第7回〜第8回
【フェーズ4:障害対応と発展】 ☐ 第9回〜第10回

2.8.2 基本設計のチェックリスト

今回の内容を、実務で基本設計書を書くときのチェックリストとしてまとめます。

チェック項目確認内容
5つの設計領域を網羅しているかワークロード、可用性、データ永続化、ネットワーク、セキュリティのすべてに設計方針が記載されているか
全コンポーネントがカバーされているか構成図に描かれた全コンポーネント(6種)について、ワークロード選定が行われているか
選定理由が添えられているか「何を使うか」だけでなく「なぜそれを選ぶか」が記載されているか
粒度は適切か基本設計の粒度(方針・理由)を逸脱して詳細設計の領域(具体的な値)に踏み込んでいないか
環境の制約を考慮しているかkind環境(Worker 3台)の制約が可用性設計やストレージ設計に反映されているか
構成図との整合性があるか基本設計書の内容と第1回の構成図に矛盾がないか
「やらない判断」が明記されているかMySQLレプリケーション非採用、HTTPS非対応など、「範囲外」の判断とその理由が記載されているか
後続フェーズへの引き継ぎが明確か詳細設計(第3回)に委ねる項目(具体的な値、パラメータ)が明確に区別されているか

2.8.3 次回予告 — 基本設計書から詳細設計(マニフェスト)へ

基本設計書で「何を使うか・なぜか」を決めました。次回(第3回)では、この基本設計書をもとに「詳細設計書」を作成します。

詳細設計書では、基本設計で決めた方針を具体的なマニフェストのパラメータに落とし込みます。「MySQLにStatefulSetを使う」という基本設計の方針が、「replicas: 1、resources: requests 200m/256Mi, limits 500m/512Mi、volumeClaimTemplates: 1Gi」という具体的な値になります。

応用第7回で学んだSecurityContextの知識は「SecurityContextの具体的な設定値」として、応用第8回で学んだProbeの知識は「Probeの各パラメータの設計根拠」として、詳細設計書に落とし込まれます。基本設計書が「方針」なら、詳細設計書は「設計図面」です。

設計フェーズの最後のピース——マニフェストの全パラメータを、根拠を持って決めていきましょう。

AI活用 — 設計方針の壁打ち:対話ログ

本回では2.3節のワークロード設計の中で、AIとの壁打ちを紹介しました。設計フェーズでのAI活用のポイントをまとめます。

AIが得意なこと:

  • 一般的なベストプラクティスの提示(「MySQLにはStatefulSetが適切」といった定石の回答)
  • 選定理由の言語化(自分の中では感覚的に理解していることを、文書に書ける形で整理してくれる)
  • 見落としの指摘(「PDBは検討しましたか?」のように、設計で考慮すべき要素を思い出させてくれる)

AIが苦手なこと:

  • あなたの環境固有の制約の考慮(kind環境の制限、リソース上限、チームの運用体制)
  • 「やらない判断」の妥当性評価(レプリケーションを見送る判断がプロジェクトにとって正しいかは、AIには判断しにくい)
  • 設計の優先順位づけ(可用性とコストのトレードオフは、プロジェクトの事情に依存する)

AIは「壁打ち相手」として設計の初期段階で活用し、最終的な設計判断は自分の環境・要件に基づいて行う。このバランスが、AI時代の設計プロセスの基本です。