Kubernetes デプロイ
Kubernetesはコンテナオーケストレーションのオペレーティングシステムです。自動スケーリング, ローリングアップデート, 自己修復機能でアプリケーションを常にオンラインに保ちます。
1. 学ぶこと
- K8s DeploymentとReplicaSet:ローリングアップデートとロールバック戦略
- Serviceタイプ (ClusterIP / NodePort / LoadBalancer)とIngressルーティング
- ConfigMap / Secret:アプリケーション設定と機密情報の管理
- Liveness/Readinessプローブとヘルスチェック
- BobはHelm ChartsでOrderFlowのK8sデプロイ設定を管理します
2. クラウドネイティブ運用の実話
(1) ペインポイント: 手動運用の限界
OrderFlowの本番環境は3台のサーバーで稼働しており, Bobは各サーバーのDockerコンテナを手動管理しています。あるサーバーがダウンした際, Bobは午前3時に別のサーバーで新しいコンテナを手動起動しました。セールイベント時にはスケーリングが必要で, Bobは追加コンテナを手動起動し, ロードバランサーを設定します。各スケーリング操作に30分かかります。Charlieがオートスケーリングを求めても, Bobは「それはできない」と答えるしかありませんでした。
(2) Kubernetesソリューション
K8sの宣言的設定と自動管理:
apiVersion: apps/v1
kind: Deployment
metadata:
name: orderflow
spec:
replicas: 3
template:
spec:
containers:
- name: orderflow
image: orderflow-service:latest
livenessProbe:
httpGet: { path: /actuator/health/liveness, port: 8080 }
readinessProbe:
httpGet: { path: /actuator/health/readiness, port: 8080 }
ノードダウン?K8sが自動的に別ノードでPodを再起動。トラフィック急増?HPAが自動スケールアウト。
(3) 成果
BobがK8sでOrderFlowをデプロイしてから:ノード障害は自動復旧 (MTTRが2時間から30秒に低下), HPAが自動スケーリング (スケールアップ時間が30分から2分に短縮)。Bobはもう深夜にサーバーを修復する必要がなくなりました。
3. K8s核心リソース
(1) リソース依存関係
graph TD
A[Ingress<br/>外部アクセス] --> B[Service<br/>内部LB]
B --> C[Deployment<br/>Podテンプレート]
C --> D[ReplicaSet<br/>Podレプリカ]
D --> E[Pod<br/>コンテナグループ]
E --> F[Container<br/>OrderFlowアプリ]
G[ConfigMap] --> F
H[Secret] --> F
| リソース | 責務 | 例え |
|---|---|---|
| Pod | 最小デプロイ単位, コンテナを含む | プロセスグループ |
| Deployment | Podレプリカ数とアップデートポリシーの管理 | プロセスマネージャー |
| Service | Podに安定したアクセスポイントを提供 | ロードバランサー |
| Ingress | HTTPルーティングルール | Nginxリバースプロキシ |
| ConfigMap | 機密でない設定 | 設定ファイル |
| Secret | 機密設定 | 暗号化設定ファイル |
4. Deploymentとローリングアップデート
(1) ▶ サンプル:OrderFlow Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: orderflow
labels:
app: orderflow
spec:
replicas: 3
selector:
matchLabels:
app: orderflow
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
template:
metadata:
labels:
app: orderflow
spec:
containers:
- name: orderflow
image: registry.example.com/orderflow-service:1.0.0
ports:
- containerPort: 8080
- containerPort: 8081
env:
- name: SPRING_PROFILES_ACTIVE
value: "prod"
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: orderflow-config
key: database.host
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: orderflow-secrets
key: database.password
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"
出力:
Deployment.apps/my-app created
Service/my-app-service exposed
Ingress/my-app-ingress created
| パラメータ (ローリングアップデート) | 意味 | 推奨値 |
|---|---|---|
maxUnavailable |
最大利用不可Pod数 | 1 (または25%) |
maxSurge |
目標を超過する最大インスタンス数 | 1 (または25%) |
(2) ▶ サンプル:ローリングアップデートとロールバック
# イメージバージョンを更新 (ローリングアップデートをトリガー)
kubectl set image deployment/orderflow orderflow=registry.example.com/orderflow-service:2.0.0
# ロールアウトステータスを確認
kubectl rollout status deployment/orderflow
# 前バージョンにロールバック
kubectl rollout undo deployment/orderflow
# ロールアウト履歴を表示
kubectl rollout history deployment/orderflow
出力:
// コマンド実行成功
5. ServiceとIngress
(1) ▶ サンプル:Service定義
# ClusterIP Service (内部アクセス)
apiVersion: v1
kind: Service
metadata:
name: orderflow
spec:
selector:
app: orderflow
ports:
- name: http
port: 80
targetPort: 8080
- name: management
port: 8081
targetPort: 8081
type: ClusterIP
出力:
設定が正常に適用されました
| Serviceタイプ | アクセス範囲 | 適用シナリオ |
|---|---|---|
| ClusterIP | クラスタ内 | マイクロサービス間呼び出し |
| NodePort | クラスタ外 (ノードIP:ポート) | シンプルな外部アクセス |
| LoadBalancer | クラウドプロバイダーのロードバランサー | 本番環境 (クラウド) |
| ExternalName | DNS CNAME | 外部サービスへの参照 |
(2) ▶ サンプル:Ingressルーティング
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: orderflow-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: api.orderflow.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: orderflow
port:
number: 80
tls:
- hosts:
- api.orderflow.example.com
secretName: orderflow-tls
出力:
Deployment.apps/my-app created
Service/my-app-service exposed
Ingress/my-app-ingress created
6. ConfigMapとSecret
(1) ▶ サンプル:ConfigMapとSecret
# ConfigMap: 機密でない設定
apiVersion: v1
kind: ConfigMap
metadata:
name: orderflow-config
data:
database.host: "mysql-service"
database.name: "orderflow"
redis.host: "redis-service"
spring.profiles.active: "prod"
management.server.port: "8081"
---
# Secret: 機密設定 (base64エンコード)
apiVersion: v1
kind: Secret
metadata:
name: orderflow-secrets
type: Opaque
data:
database.password: b3JkZXJmbG93MTIz # "orderflow123"のbase64
redis.password: cmVkaXNwYXNz # "redispass"のbase64
jwt.private-key: LS0tLS1CRUdJTi... # 秘密鍵のbase64
出力:
設定が正常に適用されました
| 次元 | ConfigMap | Secret |
|---|---|---|
| データ型 | 平文 | Base64エンコード |
| 適用内容 | 機密でない設定 | パスワード, 鍵, 証明書 |
| 保存方法 | etcd (平文) | etcd (暗号化) |
| サイズ制限 | 1MB | 1MB |
7. LivenessとReadinessプローブ
(1) ▶ サンプル:プローブ設定
spec:
containers:
- name: orderflow
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 60
periodSeconds: 30
timeoutSeconds: 3
failureThreshold: 3
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 30
出力:
設定が反映されました。
# application-prod.yml: liveness/readinessグループを有効化
management:
endpoint:
health:
show-details: always
group:
liveness:
include: livenessState
readiness:
include: readinessState, db, redis
| プローブタイプ | 目的 | 失敗時の結果 |
|---|---|---|
livenessProbe |
プロセスが動作しているか確認 | コンテナを再起動 |
readinessProbe |
トラフィック受信準備ができているか確認 | Serviceから除外 |
startupProbe |
アプリケーションが起動完了したか確認 | 起動中は他のプローブを無効化 |
8. 総合サンプル:OrderFlowのK8s完全デプロイ
# k8s/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: orderflow
---
# k8s/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: orderflow-config
namespace: orderflow
data:
SPRING_PROFILES_ACTIVE: "prod"
DB_HOST: "mysql-service"
DB_NAME: "orderflow"
REDIS_HOST: "redis-service"
MANAGEMENT_SERVER_PORT: "8081"
---
# k8s/secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: orderflow-secrets
namespace: orderflow
type: Opaque
data:
DB_PASSWORD: b3JkZXJmbG93MTIz
---
# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: orderflow
namespace: orderflow
spec:
replicas: 3
selector:
matchLabels: { app: orderflow }
strategy:
rollingUpdate: { maxUnavailable: 1, maxSurge: 1 }
template:
metadata:
labels: { app: orderflow }
spec:
containers:
- name: orderflow
image: registry.example.com/orderflow-service:1.0.0
ports:
- { containerPort: 8080 }
- { containerPort: 8081 }
envFrom:
- configMapRef: { name: orderflow-config }
- secretRef: { name: orderflow-secrets }
resources:
requests: { memory: "512Mi", cpu: "250m" }
limits: { memory: "1Gi", cpu: "500m" }
livenessProbe:
httpGet: { path: /actuator/health/liveness, port: 8080 }
initialDelaySeconds: 60; periodSeconds: 30; failureThreshold: 3
readinessProbe:
httpGet: { path: /actuator/health/readiness, port: 8080 }
initialDelaySeconds: 30; periodSeconds: 10; failureThreshold: 3
---
# k8s/service.yaml
apiVersion: v1
kind: Service
metadata:
name: orderflow
namespace: orderflow
spec:
selector: { app: orderflow }
ports:
- { name: http, port: 80, targetPort: 8080 }
type: ClusterIP
---
# k8s/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: orderflow-ingress
namespace: orderflow
spec:
ingressClassName: nginx
rules:
- host: api.orderflow.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service: { name: orderflow, port: { number: 80 } }
❓ よくある質問
maxUnavailableを0に設定; 3) preStopフックでグレースフルシャットダウン (sleep 10でトラフィック排出を待機); 4) アプリケーションでグレースフルシャットダウンを実装 (server.shutdown=graceful)。kubectl describe pod <name> でEventsを確認; 2) kubectl logs <name> でコンテナログを確認; 3) kubectl get events --sort-by=.metadata.creationTimestamp でクラスタイベントを確認。📖 まとめ
- DeploymentはPodレプリカとローリングアップデートを管理;maxUnavailableとmaxSurgeでアップデートペースを制御
- Service:Podへの安定したアクセスポイントを提供—内部はClusterIP, 外部はLoadBalancer
- IngressはHTTPルーティングとTLSを設定, K8sのリバースプロキシに相当
- ConfigMapは機密でない設定, Secretは機密情報 (Base64エンコード)の管理に使用
- Liveness, Readiness, Startupプローブがそれぞれ生存, 準備完了, 起動状態を監視
- 宣言的設定 + ローリングアップデート = ゼロダウンタイムデプロイ
📝 練習問題
-
基本問題 (難易度:⭐): OrderFlowのDeploymentとServiceのYAMLファイルを書き, ローカルK8sクラスタ (minikubeまたはkind)にデプロイして, アプリケーションにアクセスできることを確認してください。
-
応用問題 (難易度:⭐⭐): ConfigMap, Secret, Ingress設定を追加し, 外部ドメインからのアクセスを有効にしてください。LivenessとReadinessプローブを設定し, Pod障害をシミュレートして自動復旧を確認してください。
-
チャレンジ (難易度:⭐⭐⭐): Helm ChartでOrderFlowのK8sデプロイを管理し,
values.yamlによる変数置換 (イメージバージョン, レプリカ数, リソース設定)をサポートし,helm upgradeのローリングアップデートとhelm rollbackのロールバックを実装してください。



