404 Not Found

404 Not Found


nginx

Kubernetes デプロイ

Kubernetesはコンテナオーケストレーションのオペレーティングシステムです。自動スケーリング, ローリングアップデート, 自己修復機能でアプリケーションを常にオンラインに保ちます。

1. 学ぶこと


2. クラウドネイティブ運用の実話

(1) ペインポイント: 手動運用の限界

OrderFlowの本番環境は3台のサーバーで稼働しており, Bobは各サーバーのDockerコンテナを手動管理しています。あるサーバーがダウンした際, Bobは午前3時に別のサーバーで新しいコンテナを手動起動しました。セールイベント時にはスケーリングが必要で, Bobは追加コンテナを手動起動し, ロードバランサーを設定します。各スケーリング操作に30分かかります。Charlieがオートスケーリングを求めても, Bobは「それはできない」と答えるしかありませんでした。

(2) Kubernetesソリューション

K8sの宣言的設定と自動管理:

YAML
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) リソース依存関係

100%
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

YAML
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"

出力:

TEXT
Deployment.apps/my-app created
Service/my-app-service exposed
Ingress/my-app-ingress created
パラメータ (ローリングアップデート) 意味 推奨値
maxUnavailable 最大利用不可Pod数 1 (または25%)
maxSurge 目標を超過する最大インスタンス数 1 (または25%)

(2) ▶ サンプル:ローリングアップデートとロールバック

BASH
# イメージバージョンを更新 (ローリングアップデートをトリガー)
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

出力:

TEXT
// コマンド実行成功

5. ServiceとIngress

(1) ▶ サンプル:Service定義

YAML
# 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

出力:

TEXT
設定が正常に適用されました
Serviceタイプ アクセス範囲 適用シナリオ
ClusterIP クラスタ内 マイクロサービス間呼び出し
NodePort クラスタ外 (ノードIP:ポート) シンプルな外部アクセス
LoadBalancer クラウドプロバイダーのロードバランサー 本番環境 (クラウド)
ExternalName DNS CNAME 外部サービスへの参照

(2) ▶ サンプル:Ingressルーティング

YAML
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

出力:

TEXT
Deployment.apps/my-app created
Service/my-app-service exposed
Ingress/my-app-ingress created

6. ConfigMapとSecret

(1) ▶ サンプル:ConfigMapとSecret

YAML
# 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

出力:

TEXT
設定が正常に適用されました
次元 ConfigMap Secret
データ型 平文 Base64エンコード
適用内容 機密でない設定 パスワード, 鍵, 証明書
保存方法 etcd (平文) etcd (暗号化)
サイズ制限 1MB 1MB
🔒 セキュリティ: SecretはBase64エンコードのみであり, 暗号化されていません。本番環境ではetcd暗号化を有効にするか, Vaultなどの外部鍵管理ソリューションを使用してください。


7. LivenessとReadinessプローブ

(1) ▶ サンプル:プローブ設定

YAML
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

出力:

TEXT
設定が反映されました。
YAML
# 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完全デプロイ

YAML
# 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 } }

❓ よくある質問

Q DeploymentとStatefulSetの違いは?
A Deploymentはステートレスアプリケーション (いつでも置き換え可能)を管理し, StatefulSetはステートフルアプリケーション (固定ネットワークアイデンティティと永続ストレージあり)を管理します。OrderFlowはステートレスサービスなのでDeploymentを使用します。MySQLはステートフルサービスなので, StatefulSetまたはOperatorを使用します。
Q ゼロダウンタイムデプロイを実現するには?
A 1) readinessProbeを設定し, 準備完了のPodのみServiceに追加; 2) ローリングアップデート戦略のmaxUnavailableを0に設定; 3) preStopフックでグレースフルシャットダウン (sleep 10でトラフィック排出を待機); 4) アプリケーションでグレースフルシャットダウンを実装 (server.shutdown=graceful)。
Q ConfigMap更新後, Podは自動的に新しい設定を取得しますか?
A 環境変数による設定は自動更新されません (Podの再起動が必要)。ボリュームマウントによる設定は自動更新されます (約60秒の遅延あり)。Spring Cloud Kubernetesはホット設定リフレッシュをサポートしています。
Q CPUとメモリの"requests"と"limits"の設定方法は?
A "requests"はスケジューリングと最小保証を決定し, "limits"は最大利用可能量を決定します。"limits"を"requests"の2倍に設定することを推奨します。低すぎるとOOM KillやCPU制限が発生し, 高すぎるとリソースの無駄になります。実際の使用量を監視してから微調整してください。
Q Helm Chartsの利点は?
A HelmはK8sのパッケージマネージャーで, すべてのYAMLをテンプレート化し, 変数置換, バージョン管理, ワンクリックデプロイ, アップグレード, ロールバックをサポートします。複数リソースの複雑なデプロイ管理に適しています。
Q Pod起動失敗のトラブルシューティング方法は?
A 1) kubectl describe pod <name> でEventsを確認; 2) kubectl logs <name> でコンテナログを確認; 3) kubectl get events --sort-by=.metadata.creationTimestamp でクラスタイベントを確認。

📖 まとめ


📝 練習問題

  1. 基本問題 (難易度:⭐): OrderFlowのDeploymentとServiceのYAMLファイルを書き, ローカルK8sクラスタ (minikubeまたはkind)にデプロイして, アプリケーションにアクセスできることを確認してください。

  2. 応用問題 (難易度:⭐⭐): ConfigMap, Secret, Ingress設定を追加し, 外部ドメインからのアクセスを有効にしてください。LivenessとReadinessプローブを設定し, Pod障害をシミュレートして自動復旧を確認してください。

  3. チャレンジ (難易度:⭐⭐⭐): Helm ChartでOrderFlowのK8sデプロイを管理し, values.yamlによる変数置換 (イメージバージョン, レプリカ数, リソース設定)をサポートし, helm upgradeのローリングアップデートとhelm rollbackのロールバックを実装してください。

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%