💻

【4-2】Kubernetes実践編:PodとDeploymentを操り「自己修復」と「更新」を体感する

に公開

Kubernetes実践編:PodとDeploymentを操り「自己修復」と「更新」を体感する

はじめに

前回の記事では、k3sを使って自分専用のKubernetesクラスターを構築し、kubectlk)コマンドでその内部を覗き見る「鍵」を手に入れました。私たちの手元には、アプリを動かすための広大な「都市(クラスター)」が用意されています。
https://zenn.dev/koikoi_infra/articles/7eb8bccdfa74cf

いよいよ今回から、この都市にアプリケーション(コンテナ)を配備(デプロイ) していきます。

この記事では、Kubernetesでアプリを動かす最小単位であるPodの作成・操作方法から始まり、本番運用の核となるDeploymentを使って、Kubernetesの代名詞とも言える 「自己修復」「ローリングアップデート」 を実践します。

Part 1: 最小実行単位「Pod」を直接操作する

Podは、Kubernetesにおけるアプリケーションの最小実行単位です。1つ以上のコンテナをまとめたグループ(カプセル)のようなものだと考えてください。

まずは、このPodを直接作成し、Dockerコンテナを起動する感覚で操作してみましょう。

# 作業ディレクトリを作成して移動
mkdir ~/k8s-practice
cd ~/k8s-practice

Step 1: Podマニフェスト(設計図)の作成と適用

Kubernetesでは、「何をしたいか」をYAMLファイル(マニフェスト) に記述し、それをkubectlでクラスターに「適用(apply)」するのが基本です。

# nginx-pod.yaml を作成
cat > nginx-pod.yaml << 'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:alpine
    ports:
    - containerPort: 80
EOF
  • kind: Pod: リソースの種類(Pod)を定義します
  • metadata.name: nginx-podという名前を付けます。
  • spec.containers: このPodが内包するコンテナのリスト(今回はnginx:alpine 1つ)を定義します

この設計図をクラスターに適用します。

# YAMLを適用してPodを作成
k apply -f nginx-pod.yaml

# Podの一覧を表示(STATUSが Running になるのを待つ)
k get pods

# IPアドレスや起動ノードなど、より詳細な情報を表示
k get pods -o wide
【補足】Podはどのサーバー(ノード)で動くの? ランダム?

今回はサーバー1台構成ですが、本番環境では複数のワーカーノードでクラスターが構成されます。その場合、Podはどのノードに配置されるのでしょうか?

答えは「ランダムではなく、Schedulerが賢く決定する」です。

Kubernetesの司令塔(コントロールプレーン)には、**「Scheduler(スケジューラ)」**という専門のコンポーネントがいます。Schedulerは、新しいPodの配置先を以下の2段階で決定します。

  1. フィルタリング (Filtering):
    まず、Podを実行できないノードを候補から除外します。(例:「Podが必要なCPU/メモリが足りないノードは除外」)

  2. スコアリング (Scoring):
    残った候補ノードに点数を付けます。(例:「リソースに一番余裕があるノードは高得点」「同じアプリのPodがまだ少ないノードは高得点(=分散配置)」)

Schedulerは、この合計点が最も高かったノードにPodを配置するよう指示を出します。

▼ 物理サーバーを意識する必要は?
Kubernetesの理想は、クラスター全体を1つの巨大なリソースプールとして扱い、開発者は物理サーバーを意識しないことです。

しかし、現実の運用では「このAI用PodはGPU搭載ノードに配置したい」「DB用PodとWeb用Podは別のサーバー群に分けたい」といった制御が必要になります。そのために、KubernetesにはnodeSelectorAffinityといった、Podの配置ルールを細かく制御する仕組みも用意されています。

Step 2: Podの調査とデバッグ

Podが起動したら、中を覗いてみましょう。

# Podの詳細情報(イベントログや設定内容)を表示
k describe pod nginx-pod

# Podが出力するログを確認
k logs nginx-pod

# Pod内部のシェルに入る (docker exec と同じ)
k exec -it nginx-pod -- /bin/sh
# (コンテナ内で ps aux や hostname を実行して exit で抜ける)

# 【一時的な動作確認】ローカルPCとPodを直接つなぐ
# 自分のPCの8080番ポートを、Podの80番ポートに転送
k port-forward nginx-pod 8080:80

port-forwardを実行した状態で別のターミナルを開き、curl http://localhost:8080を叩くと、Nginxの画面が表示されるはずです。

Step 3: Podの削除

確認が終わったらPodを削除します。

k delete pod nginx-pod

Part 2: 宣言的管理「Deployment」で本番運用へ

Podを直接作成する方法を学びましたが、これには致命的な弱点があります。もし、今作成したPodがエラーで停止したり、ノード(サーバー)ごとダウンしたら、Podは二度と起動しません。これでは本番運用は不可能です。

そこで登場するのがDeploymentです。

Deploymentは、「このPodの設計図(template)を使って、常に3個(replicas)起動した状態を維持せよ」と命令するための、Podの管理者です。

Step 1: Deploymentマニフェストの作成

replicas: 3(3個起動)のDeploymentを作成します。

cat > nginx-deployment.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.25-alpine # バージョンを 1.25 に指定
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: "64Mi"
            cpu: "100m"
          limits:
            memory: "128Mi"
            cpu: "200m"
EOF
  • kind: Deployment: リソースの種類がDeploymentになりました
  • spec.replicas: 3: 常に3個のPodを起動・維持します。これが「自己修復」の核です
  • spec.selector: このDeploymentが管理するPod(app: nginxのラベルを持つPod)を定義します
  • spec.template: Deploymentが新しくPodを作るときの設計図です。内容は先ほどのPodマニフェストとほぼ同じです
  • resources: コンテナが最低限必要とするリソース(requests)と、最大で使用できる上限(limits)を指定します

このDeploymentを適用します。

# Deploymentを適用
k apply -f nginx-deployment.yaml

# Deploymentの状態を確認(READYが 3/3 になるのを待つ)
k get deployments

# Deploymentによって作成されたPodが3つあることを確認
k get pods -l app=nginx

Step 2: Kubernetesの真価:「自己修復」と「スケーリング」

Deploymentの力を体験してみましょう。

自己修復(セルフヒーリング)

k get podsで表示されたPod名を1つ選び、強制的に削除してみます。

# Podを1つ強制削除(Pod名は自分の環境に合わせてください)
k delete pod nginx-deployment-xxxxxxxxx

# すぐにPod一覧を監視モードで表示
k get pods -l app=nginx -w

Terminating(削除中)になったPodと入れ替わるように、新しいPodがContainerCreatingされ、すぐにRunningになるのが観測できるはずです。

Deploymentが「replicas: 3」というあるべき姿を維持するために、不足したPodを自動で補充したのです。これが自己修復です。

【補足】Podの名前はなぜ自動生成されるの?

記事の中でk delete pod nginx-deployment-xxxxxxxxxというコマンドが出てきますが、DeploymentのYAMLにはPod名を指定する場所はありませんでした。

その通りで、DeploymentがPodを作成するとき、Pod名は自動的に生成されます
命名規則は**[Deployment名]-[ランダムな英数字]となります。
▼ なぜ自動生成なのか?
これがKubernetesの
「自己修復」「スケーリング」**の核となる仕組みだからです。

もしnginx-deployment-7b5b7c9c7f-x9lkvというPodがクラッシュして消滅しても、Deploymentは「Podが1つ足りない!」と検知し、まったく新しいPodを(例:nginx-deployment-7b5b7c9c7f-abcde)のように自動で作成します。

Kubernetesでは、Podは「使い捨て」であり、いつでも消えて新しいものに置き換えられる前提で設計されているため、名前は固定せず、自動でユニークなものが割り当てられるのです。

スケーリング(スケールアウト)

次に、Podの数を3個から5個に増やしてみましょう。

# replicasの数を5に変更
k scale deployment nginx-deployment --replicas=5

# Podが2個追加され、合計5個になるのを確認
k get pods -l app=nginx

コマンド一つで、アプリケーションの処理能力を即座に向上させることができました。

Step 3: ゼロダウンタイム更新:「ローリングアップデート」

最後に、アプリケーションをサービスを停止せずに更新します。Nginxのバージョンを1.25-alpineから1.26-alpineに上げてみましょう。

# Deploymentのnginxコンテナのイメージを 1.26-alpine に変更
k set image deployment/nginx-deployment nginx=nginx:1.26-alpine

# アップデート(ロールアウト)の状況をリアルタイムで監視
k rollout status deployment/nginx-deployment

k get pods -l app=nginx -w を別ターミナルで実行しながら見ていると、古いPod(1.25)が1つ削除され、新しいPod(1.26)が1つ起動し、それがRunningになるのを待ってから次の古いPodが削除される…という動きを繰り返します。

このように、新しいコンテナを古いコンテナと少しずつ入れ替えることで、ユーザーからのリクエストを一度も止めることなく更新が完了します。これがローリングアップデートです。

ロールバック(取り消し)

もし新しいバージョンに問題があれば、コマンド一つで即座に元に戻せます。

# 1つ前のリビジョン(バージョン)に戻す
k rollout undo deployment/nginx-deployment

# ロールバックが完了するのを待つ
k rollout status deployment/nginx-deployment

Step 4: 後片付け

Deploymentを削除すると、それが管理していた5つのPodもすべて自動で削除されます。

k delete deployment nginx-deployment

まとめ

PodとDeploymentの関係を理解したことで、Kubernetesがなぜ本番環境で圧倒的に支持されているのか、その理由の半分以上を理解できたと言っても過言ではありません。

次の記事では、これらのPodに**「外部からアクセスする」ための仕組みであるService**について学んでいきます。

Discussion