序論:Kubernetesの三大核心リソース

Kubernetesでアプリケーションを運用する際、最も頻繁に接するリソースはPodDeploymentServiceです。PodはKubernetesで作成できる最小のコンピューティング単位であり、Deploymentはこれらのデプロイと管理を自動化し、Serviceはネットワークを通じてPodへのアクセス方法を提供します。

この第8編では、これら3つのリソースを深く掘り下げ、実務で活用できるレベルまで理解を深めます。

1. Pod深掘り

1.1 Podとは?

PodはKubernetesで作成・管理できる最小のデプロイ可能な単位です。1つ以上のコンテナを含み、ストレージとネットワークリソースを共有します。

  • 同じPod内のコンテナは同じIPアドレスを共有します
  • localhostを通じて相互に通信できます
  • 同じボリュームをマウントできます
  • Podは一時的(ephemeral)です - いつでも削除され再作成される可能性があります

1.2 PodのYAML構造

# pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  labels:
    app: my-app
    environment: production
  annotations:
    description: "メインアプリケーションPod"
spec:
  containers:
  - name: main-container
    image: nginx:1.24
    ports:
    - containerPort: 80
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
    env:
    - name: APP_ENV
      value: "production"
    volumeMounts:
    - name: config-volume
      mountPath: /etc/config
  volumes:
  - name: config-volume
    configMap:
      name: app-config
  restartPolicy: Always

1.3 Podのライフサイクル

Podは以下のフェーズを経ます:

フェーズ 説明
Pending Podが作成されましたが、まだコンテナが実行されていません
Running Podがノードにバインドされ、すべてのコンテナが作成されました
Succeeded すべてのコンテナが正常に終了しました(再起動なし)
Failed 1つ以上のコンテナが失敗状態で終了しました
Unknown Podの状態を取得できません

1.4 マルチコンテナPodパターン

1つのPodに複数のコンテナを含める一般的なパターンがあります:

1. サイドカーパターン(Sidecar)

メインコンテナの機能を拡張または補助します。

apiVersion: v1
kind: Pod
metadata:
  name: sidecar-example
spec:
  containers:
  - name: main-app
    image: my-app:latest
    ports:
    - containerPort: 8080
  - name: log-collector
    image: fluentd:latest
    volumeMounts:
    - name: log-volume
      mountPath: /var/log/app
  volumes:
  - name: log-volume
    emptyDir: {}

2. アンバサダーパターン(Ambassador)

外部サービスへの接続をプロキシします。

apiVersion: v1
kind: Pod
metadata:
  name: ambassador-example
spec:
  containers:
  - name: main-app
    image: my-app:latest
    env:
    - name: DB_HOST
      value: "localhost"
    - name: DB_PORT
      value: "5432"
  - name: db-ambassador
    image: ambassador-proxy:latest
    ports:
    - containerPort: 5432

3. アダプターパターン(Adapter)

メインコンテナの出力を標準化します。

1.5 ProbeによるヘルスチェックC

Kubernetesはコンテナの状態を確認するための3種類のProbeを提供します:

apiVersion: v1
kind: Pod
metadata:
  name: probe-example
spec:
  containers:
  - name: app
    image: my-app:latest
    ports:
    - containerPort: 8080

    # livenessProbe: コンテナが正常かどうかを確認
    # 失敗時コンテナを再起動
    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
      initialDelaySeconds: 15
      periodSeconds: 10
      failureThreshold: 3

    # readinessProbe: トラフィックを受け入れる準備ができているかを確認
    # 失敗時Serviceのエンドポイントから除外
    readinessProbe:
      httpGet:
        path: /ready
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 5

    # startupProbe: アプリケーションが起動したかを確認
    # 成功するまで他のProbeは実行されない
    startupProbe:
      httpGet:
        path: /startup
        port: 8080
      failureThreshold: 30
      periodSeconds: 10

2. ReplicaSetの理解

2.1 ReplicaSetとは?

ReplicaSetは指定された数のPodレプリカが常に実行されるように保証します。Podが削除されたりノードに障害が発生した場合、新しいPodを作成して希望するレプリカ数を維持します。

直接ReplicaSetを作成することはほとんどありません。Deploymentが内部的にReplicaSetを管理するためです。

2.2 ReplicaSetの構造

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: my-replicaset
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-container
        image: nginx:1.24
        ports:
        - containerPort: 80

3. Deployment深掘り

3.1 Deploymentとは?

DeploymentはPodとReplicaSetに対する宣言的更新を提供します。希望する状態(desired state)を記述すると、Deployment Controllerが実際の状態を希望する状態に変更します。

Deploymentの主な機能:

  • Pod数(replicas)の維持
  • ローリングアップデート
  • ロールバック
  • スケーリング
  • 一時停止と再開

3.2 DeploymentのYAML構造

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
  labels:
    app: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-container
        image: nginx:1.24
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: "64Mi"
            cpu: "250m"
          limits:
            memory: "128Mi"
            cpu: "500m"
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
  revisionHistoryLimit: 10
  progressDeadlineSeconds: 600

3.3 ローリングアップデート

ローリングアップデートはダウンタイムなしでアプリケーションを更新する方式です。

# イメージを更新
kubectl set image deployment/my-deployment my-container=nginx:1.25

# またはYAMLを編集
kubectl edit deployment my-deployment

# ロールアウト状態を確認
kubectl rollout status deployment/my-deployment

# ロールアウト履歴を確認
kubectl rollout history deployment/my-deployment

# 特定のリビジョンの詳細を確認
kubectl rollout history deployment/my-deployment --revision=2

# ロールバック(直前のリビジョンに)
kubectl rollout undo deployment/my-deployment

# 特定のリビジョンにロールバック
kubectl rollout undo deployment/my-deployment --to-revision=2

3.4 アップデート戦略

RollingUpdate(デフォルト)

spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 25%        # 更新中に追加で作成可能なPod数
      maxUnavailable: 25%  # 更新中に使用不可のPod数

Recreate

spec:
  strategy:
    type: Recreate  # すべてのPodを削除してから新しいPodを作成

3.5 スケーリング

# 手動スケーリング
kubectl scale deployment my-deployment --replicas=5

# HPAによる自動スケーリング
kubectl autoscale deployment my-deployment --min=2 --max=10 --cpu-percent=80

4. Service深掘り

4.1 Serviceとは?

ServiceはPod集合に対する安定したネットワークエンドポイントを提供します。PodのIPアドレスは変わる可能性がありますが、ServiceのIP(ClusterIP)と名前は固定されます。

4.2 Serviceタイプ

タイプ 説明 用途
ClusterIP クラスター内部IPを割り当て(デフォルト) 内部通信
NodePort 各ノードの固定ポートで公開 外部アクセス(開発/テスト)
LoadBalancer クラウドLBを通じて公開 プロダクション外部アクセス
ExternalName 外部DNS名をマッピング 外部サービス接続

4.3 ClusterIP Service

# clusterip-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-clusterip-service
spec:
  type: ClusterIP  # デフォルト
  selector:
    app: my-app
  ports:
  - protocol: TCP
    port: 80        # Serviceポート
    targetPort: 8080  # Podのコンテナポート

4.4 NodePort Service

# nodeport-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-nodeport-service
spec:
  type: NodePort
  selector:
    app: my-app
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
    nodePort: 30080  # 30000-32767範囲(省略時自動割り当て)

4.5 LoadBalancer Service

# loadbalancer-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-loadbalancer-service
  annotations:
    # クラウドプロバイダー固有の設定
    service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
spec:
  type: LoadBalancer
  selector:
    app: my-app
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

4.6 ExternalName Service

# externalname-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: external-database
spec:
  type: ExternalName
  externalName: database.example.com

4.7 ヘッドレスService

ClusterIPを「None」に設定すると、ServiceのIPは割り当てられず、DNS経由で直接PodのIPを取得できます。StatefulSetと共に使用されることが多いです。

# headless-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-headless-service
spec:
  clusterIP: None
  selector:
    app: my-app
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

5. ラベルとセレクター

5.1 ラベル(Labels)

ラベルはKubernetesオブジェクトに付けるキー/値のペアです。オブジェクトを識別し、グループ化するために使用されます。

metadata:
  labels:
    app: my-app
    environment: production
    tier: frontend
    version: v1.0.0

5.2 セレクター(Selectors)

セレクターはラベルに基づいてリソースを選択します。

等価ベースセレクター:

selector:
  matchLabels:
    app: my-app
    environment: production

集合ベースセレクター:

selector:
  matchExpressions:
  - key: environment
    operator: In
    values:
    - production
    - staging
  - key: tier
    operator: NotIn
    values:
    - test

6. 実践例:完全なアプリケーションデプロイ

# complete-deployment.yaml
---
apiVersion: v1
kind: Namespace
metadata:
  name: my-app
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: my-app
data:
  APP_ENV: "production"
  LOG_LEVEL: "info"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
  namespace: my-app
  labels:
    app: web-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-app
  template:
    metadata:
      labels:
        app: web-app
    spec:
      containers:
      - name: web
        image: nginx:1.24
        ports:
        - containerPort: 80
        envFrom:
        - configMapRef:
            name: app-config
        resources:
          requests:
            memory: "64Mi"
            cpu: "250m"
          limits:
            memory: "128Mi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 10
          periodSeconds: 5
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 3
---
apiVersion: v1
kind: Service
metadata:
  name: web-app-service
  namespace: my-app
spec:
  type: ClusterIP
  selector:
    app: web-app
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
# デプロイ
kubectl apply -f complete-deployment.yaml

# 確認
kubectl get all -n my-app

# ポートフォワーディングでテスト
kubectl port-forward service/web-app-service 8080:80 -n my-app

結論

この第8編では、KubernetesのコアリソースであるPod、Deployment、Serviceを詳しく学びました。

  • Pod:Kubernetesの最小デプロイ単位で、1つ以上のコンテナを含みます
  • Deployment:Podのデプロイと管理を自動化し、ローリングアップデートとロールバックを提供します
  • Service:Podに安定したネットワークアクセスを提供し、さまざまなタイプ(ClusterIP、NodePort、LoadBalancer)をサポートします

これらのリソースの理解は、Kubernetesを効果的に活用するための基礎となります。次の第9編では、ConfigMap、Secret、Ingressについて詳しく学んでいきます。