【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 API | RESTful 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の全コンポーネントに対するワークロード選定をまとめます。
| コンポーネント | ワークロード | 選定理由 |
|---|---|---|
| Nginx | Deployment | ステートレス。どのPodも同等で交換可能。水平スケーリングが容易 |
| TaskBoard API | Deployment | ステートレス(データはMySQLに永続化)。スケールアウト/インに対応する必要がある |
| MySQL | StatefulSet | データの永続化が必須。PodとPVCの安定した対応関係が必要。Pod再作成時に同じデータボリュームが再マウントされることを保証する |
| DB初期化 | Job | スキーマ作成と初期データ投入を一度だけ実行する。完了後はPodが Completedで残り、ログを確認できる |
| DBバックアップ | CronJob | mysqldumpを定期的に実行する。スケジュールに基づいて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つ? | 一度だけ? | 状態を持つ? | 結果 |
|---|---|---|---|---|---|
| Nginx | Yes | No | — | No | Deployment ✓ |
| TaskBoard API | Yes | No | — | No | Deployment ✓ |
| MySQL | Yes | No | — | Yes | StatefulSet ✓ |
| DB初期化 | No | — | Yes | — | Job ✓ |
| DBバックアップ | No | — | No | — | CronJob ✓ |
| ログ収集 | Yes | Yes | — | — | DaemonSet ✓ |
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が持つリソースには限りがあるため、レプリカ数は「可用性を確保しつつ、リソースを使い切らない」バランスで決めます。
| コンポーネント | レプリカ数 | 決定根拠 |
|---|---|---|
| Nginx | 2 | 静的ファイル配信はリクエスト処理が軽量。2レプリカで冗長化しつつ、HPAでピーク時にスケールアウト(max: 6) |
| TaskBoard API | 2 | REST APIの処理はDB操作を含むためNginxより重い。2レプリカで冗長化し、HPAでスケールアウト(max: 4) |
| MySQL | 1 | シングルインスタンス構成。レプリケーション構成は本シリーズの範囲外。可用性はバックアップとリストアで担保する |
| ログ収集 | 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に分散配置します。
| コンポーネント | 分散配置方針 | 根拠 |
|---|---|---|
| Nginx | topologySpreadConstraintsでWorker Node間に分散 | 1 Nodeダウン時にもう1つのPodが存続してサービス継続 |
| TaskBoard API | topologySpreadConstraintsでWorker Node間に分散 | Nginx同様。API層の可用性を確保 |
| MySQL | 分散配置の設定なし | replicas: 1のため分散の対象外 |
| ログ収集 | DaemonSetのため自動的に全Nodeに分散 | 設定不要。DaemonSetの仕様で保証される |
topologySpreadConstraintsとpodAntiAffinityの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設定 | 根拠 |
|---|---|---|
| Nginx | minAvailable: 1 | replicas: 2のうち最低1つが稼働していれば、フロントエンドへのアクセスを継続できる |
| TaskBoard API | minAvailable: 1 | replicas: 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のみ | 他のコンポーネントはステートレス |
| StorageClass | kindデフォルト(standard) | kindのhostPath provisioner。本番ではクラウドプロバイダのStorageClass(gp3、Premium SSD等)に置き換わる |
| アクセスモード | ReadWriteOnce(RWO) | MySQLはシングルインスタンス。1つのPodからのみ読み書きできればよい |
| 容量方針 | 詳細設計で決定 | TaskBoardのデータ量から見積もる。基本設計ではGB単位の目安を提示し、詳細設計で確定する |
| ReclaimPolicy | Retain | PVCを削除してもデータを保持する方針。意図しないデータ削除を防止する |
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種別 | 選定理由 |
|---|---|---|
| Nginx | ClusterIP | 外部からの直接アクセスは不要。Gateway API経由でアクセスされるため、クラスタ内部からの到達性のみ必要 |
| TaskBoard API | ClusterIP | Nginx同様。Gateway API経由でアクセスされる |
| MySQL | Headless 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 API | Nginx Service | nginx.app.svc.cluster.local | フロントエンドへのHTTPルーティング |
| Gateway API | TaskBoard API Service | taskboard-api.app.svc.cluster.local | APIへのHTTPルーティング |
| TaskBoard API | MySQL Headless Service | mysql.db.svc.cluster.local | APIから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 | 収容するコンポーネント | 分離の理由 |
|---|---|---|
| app | Nginx、TaskBoard API | アプリケーション層。外部アクセスを受けるコンポーネントを集約。水平スケーリング対象 |
| db | MySQL、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 API | Ingress | 許可 | ユーザーアクセスの入口 |
| Gateway → Nginx | Ingress | 許可 | パスベースルーティング |
| Gateway → TaskBoard API | Ingress | 許可 | パスベースルーティング |
| TaskBoard API → MySQL | Ingress(db側) | 許可 | APIからDBへのデータ操作 |
| Nginx → MySQL | — | 遮断 | フロントエンドがDBに直接アクセスする理由はない。3層構造の境界を維持する |
| DBバックアップCronJob → MySQL | Ingress(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で対応) | コンテナ内のファイルシステムを読み取り専用にし、不正なファイル書き込みを防止する |
| allowPrivilegeEscalation | false を全Podに適用 | コンテナプロセスが権限昇格することを防止する |
| capabilities | drop: ALL を全Podに適用 | Linuxカーネルのcapabilitiesをすべて剥奪。必要なcapabilityがある場合のみ個別にaddする |
コンポーネントごとの注意点を整理します。
| コンポーネント | 実行ユーザー | 注意点 |
|---|---|---|
| Nginx | 非rootユーザー | デフォルトのNginxイメージはrootで起動する。応用第7回で非root化(ポート80→8080変更)を実施済み |
| TaskBoard API(Payara Micro) | payara(uid=1000) | 公式イメージが元々非root。SecurityContext設定は自然に適用できる |
| MySQL | mysql(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時代の設計プロセスの基本です。
