はじめに
Kubernetes は
コンテナを自動で配置・復旧・スケーリングしてくれる非常に強力な基盤です。
しかし、Kubernetesを学び始めた多くの人が、次の壁にぶつかります。
- Webアプリ(Node.js / Python)は動かせた
- でも MySQL / PostgreSQL はどう扱えばいいのか分からない
- Podが消えたらDBのデータは消えるのでは?
- 本番でKubernetes上にDBを置いていいのか?
これらは 非常に正しい疑問 です。
なぜなら、DBはKubernetesが最も苦手とする「ステートフル(状態を持つ)」存在だからです。
本記事では、
- Kubernetesが「状態」をどう扱うのか
- なぜStatefulSetが必要なのか
- PersistentVolume / PVCの本当の役割
- MySQL / PostgreSQLを安全に動かす具体例
- 実務でやってはいけない設計
までを、文章多め・図を想像しながら理解できる構成で解説します。
そもそもKubernetesはDB向きなのか?
まず最初に、現場目線の結論を明確にします。
結論
- 学習・検証・小規模構成 → Kubernetes上でDBを動かすのはアリ
- 重要データ・大規模本番 → マネージドDBを使うことが多い
これは「KubernetesでDBが動かせない」からではありません。
「DBは壊れたときの影響が大きすぎる」 からです。
ステートレスとステートフルの決定的な違い
Kubernetes理解の核心はここです。
ステートレス(Stateless)
例:
- Node.js API
- Python Flaskアプリ
- バッチ処理
特徴:
- Podが消えても問題ない
- データは外部(DB)にある
- 何個起動しても同じ動作
👉 Kubernetesが最も得意な領域
ステートフル(Stateful)
例:
- MySQL
- PostgreSQL
- Redis(永続化あり)
特徴:
- データを内部に保持する
- Podが消えるとデータ消失リスク
- 同じ名前・同じストレージが必要
👉 DBはステートフルの代表格
なぜDeploymentではDBを動かしてはいけないのか
初心者が最初にやりがちなミスがこれです。
kind: Deployment
image: mysql
一見動きます。
しかし 本質的な問題 があります。
- Podが再作成されるたびに名前が変わる
- ストレージが紐づかない
- 再起動でデータが消える可能性
👉 Deploymentは「使い捨て前提」
👉 DBは「同じ存在であり続ける必要がある」
このギャップを埋めるのが StatefulSet です。
StatefulSetとは何か(超重要)
StatefulSetは、ステートフルアプリ専用の仕組みです。
StatefulSetの特徴
- Pod名が固定される(mysql-0 など)
- Podとストレージが1対1で紐づく
- 再作成されても同じIDとして扱われる
👉 「このDBはこのDBであり続ける」
これをKubernetesに理解させるための仕組みです。
データ永続化の要:PV と PVC
ここが一番イメージしづらい部分なので、丁寧に説明します。
PersistentVolume(PV)
- 実際のディスク領域
- 「物理的なストレージ」
PersistentVolumeClaim(PVC)
- 「このくらいのディスクをください」という要求
- Podは直接PVを触らない
なぜ分かれているのか?
- インフラ担当とアプリ担当を分離するため
- ストレージの実装を隠蔽するため
👉 Pod → PVC → PV → ディスク
この間接構造がKubernetesらしさです。
Kubernetes × DB の全体構成イメージ
頭の中では、次のように考えてください。
[ Pod (MySQL) ]
|
volumeMount
|
PVC
|
PV
|
実ディスク
Podが消えても
👉 PVCとPVが残っていればデータは消えない
【ハンズオン①】Kubernetes × MySQL(文章多め解説付き)
目的
- StatefulSetでMySQLを起動
- Pod削除後もデータが残ることを理解する
MySQL StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: mysql
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.4
env:
- name: MYSQL_ROOT_PASSWORD
value: rootpass
- name: MYSQL_DATABASE
value: sampledb
ports:
- containerPort: 3306
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: mysql-data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 5Gi
このYAMLの本質
volumeClaimTemplatesが Podごとのディスクを自動生成mysql-0は 必ず同じディスクを使う- Podが消えても「中身の人格」は変わらない
データ永続化の確認
kubectl exec -it mysql-0 -- mysql -uroot -prootpass
CREATE TABLE test (id INT);
INSERT INTO test VALUES (1);
Podを削除:
kubectl delete pod mysql-0
👉 再作成後もデータが残る理由
→ ストレージがPodの外にあるから
【ハンズオン②】Kubernetes × PostgreSQL(思想は同じ)
PostgreSQLでも 考え方は完全に同じ です。
- StatefulSetを使う
- データディレクトリをvolumeMount
- PVCで永続化
技術が変わっても、Kubernetesの思想は一貫しています。
アプリ側からの接続設計(重要)
Kubernetesでは Service名 = ホスト名 です。
mysql:3306
postgres:5432
これにより、
- Podが変わっても
- IPが変わっても
👉 アプリ側の設定は変えなくてよい
実務で必ず考えるべきこと
- リソース制限(CPU / メモリ)
- バックアップ戦略
- Secretによる認証情報管理
- マネージドDBとの使い分け
やってはいけない設計(重要)
- DeploymentでDBを動かす
- emptyDirを使う
- バックアップなし
- 本番でlatestタグ
👉 「動く」と「安全」は別物 です。
まとめ
Kubernetes × MySQL / PostgreSQLは、
- Kubernetesの本質を理解する最高の教材
- ステートフル設計の考え方が身につく
- 本番設計の判断力が養われる
「DBをどう扱うか分かる=Kubernetesを理解した」
と言っても過言ではありません。
コメントを残す