Ritolabo
  1. Home
  2. Kubernetes
  3. Kubernetes の Pod とは?コンテナを動かす最小単位を整理する

Kubernetes の Pod とは?コンテナを動かす最小単位を整理する

  • 公開日
  • カテゴリ:Kubernetes
  • タグ:Kubernetes,学習メモ
Kubernetes の Pod とは?コンテナを動かす最小単位を整理する

Kubernetes では、コンテナを Pod という単位に入れて動かす。Docker で docker run nginx としていたところを、Kubernetes では「nginx のコンテナを入れた Pod を作る」という形にする。

この記事では、その Pod をローカルのクラスタで実際に作り、状態を見て、消すところまでを整理する。クラスタの構成要素(Control Plane、Node、kubelet など)については「Kubernetes のアーキテクチャを整理する:Control Plane と Node の構成要素」を参照。

この記事でやること:

  • kind でローカルのクラスタを作る
  • Pod の YAML を読む
  • kubectl apply で Pod を作る
  • kubectl get / describe / logs / port-forward で Pod を見る
  • kubectl delete で Pod を消す
  • コンテナを2つ入れた Pod で、コンテナ同士が localhost でつながることを確かめる

Pod の中身を図にしたものは「Kubernetes の仕組みを図で整理する」にまとめている。

contents

  1. 環境:kind でクラスタを作る
  2. Pod とは
  3. Pod の YAML
  4. Pod を作る
  5. Pod を見る
    1. kubectl get pods
    2. kubectl describe pod
    3. kubectl logs
    4. kubectl port-forward
  6. Pod を消す
  7. コンテナを2つ入れた Pod
  8. 用語メモ
  9. 参考 URL

環境:kind でクラスタを作る

Kubernetes を触るにはクラスタが必要で、本来は複数台のマシンで構成する。手元の Mac 1台でそれを再現するために kind(Kubernetes IN Docker)を使う。kind は、Docker コンテナ1つを Node(マシン1台)に見立ててクラスタを作るツール。

Mac
└── Docker Desktop
    ├── コンテナ「k8s-study-control-plane」 ← Node 1台のふり(クラスタを管理する側)
    ├── コンテナ「k8s-study-worker」        ← Node 1台のふり(Pod を載せる側)
    └── コンテナ「k8s-study-worker2」       ← Node 1台のふり(Pod を載せる側)

kind の役目はクラスタを作る・消すことだけで、作ったあとの操作は kubectl で行う。

インストールは Homebrew。

brew install kind

Control Plane 1台 + Worker 2台の構成にするため、設定ファイルを用意する。

# kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
  - role: control-plane
  - role: worker
  - role: worker
kind create cluster --name k8s-study --config kind-config.yaml

Node が3つ Ready になっていれば準備完了。

kubectl get nodes
NAME                      STATUS   ROLES           AGE   VERSION
k8s-study-control-plane   Ready    control-plane   1m    v1.37.0
k8s-study-worker          Ready    <none>          1m    v1.37.0
k8s-study-worker2         Ready    <none>          1m    v1.37.0
  • 環境: macOS(Apple Silicon)、Docker Desktop 29.8.0、kind v0.33.0、Kubernetes v1.37.0、kubectl v1.36.1
  • kubectl は kube-apiserver の ±1 マイナーバージョンまでサポートされるので、v1.36 の kubectl で v1.37 のクラスタを操作できる
  • クラスタを消すときは kind delete cluster --name k8s-study

Pod とは

公式ドキュメントでは、Pod は「Kubernetes 内で作成・管理できるコンピューティングの最小のデプロイ可能なユニット」と定義されている。

  • Pod は 1つ以上のコンテナをまとめたもので、ストレージとネットワークを共有する
  • Kubernetes が管理するのはコンテナではなく Pod。コンテナ単体を作る操作はなく、コンテナは必ず Pod の中に書く
  • 最も一般的なのは「1 Pod 1 コンテナ」の構成。この場合、Pod はコンテナ1つを包む薄いラッパーと考えられる
Docker:      docker run ──▶ コンテナ
Kubernetes:  kubectl apply ──▶ Pod ──▶ コンテナ(Pod の中に入っている)

Pod の YAML

nginx のコンテナを1つ入れた Pod の定義。公式ドキュメントの例と同じ内容。

# nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
    - name: nginx
      image: nginx:1.14.2
      ports:
        - containerPort: 80
フィールド意味
apiVersion / kind何を作るか。Pod なら v1 と Pod の組み合わせで固定
metadata名前などの識別情報。name は kubectl get や delete で指定するときに使う
specどんな Pod にしたいか。自分で決めるのはここ
spec.containersPod に入れるコンテナの一覧(1つ以上)。image が docker run に渡すイメージ名にあたる
spec.containers[].portsコンテナが待ち受けるポートの情報。書かなくても通信はできる

Kubernetes のリソースは、Pod 以外もすべて apiVersion / kind / metadata / spec の4つの塊でできている。

Pod を作る

kubectl apply -f nginx-pod.yaml
pod/nginx created

kubectl apply -f <ファイル> は、ファイルの内容を Kubernetes に渡すコマンド。ここから先は Kubernetes が、Pod を置く Node を決め、その Node でイメージを取得してコンテナを起動する。

Pod を見る

kubectl get pods

kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          30s
列意味
READY動いているコンテナ数 / Pod に入っているコンテナ数
STATUSPod の状態。作った直後は ContainerCreating、動き出すと Running
RESTARTSコンテナが再起動された回数
AGE作ってからの経過時間

-o wide を付けると、どの Node に置かれたかと、Pod に付いた IP が見える。

kubectl get pods -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP           NODE                NOMINATED NODE   READINESS GATES
nginx   1/1     Running   0          15s   10.244.2.5   k8s-study-worker2   <none>           <none>
  • NODE は k8s-study-worker2。Pod を置く Node は Kubernetes が決めるもので、YAML には書いていない。Control Plane の Node には kubeadm の既定で普通の Pod が置かれないため、Worker のどちらかになる
  • IP は Pod に1つ付く。コンテナではなく Pod が IP を持つ

kubectl describe pod

kubectl describe pod nginx

出力は長いが、見るのは Node: / IP:、Containers: の下の State:、一番下の Events: の3か所。Events: には、この Pod に何が起きたかが時系列で記録されている。

Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  114s  default-scheduler  Successfully assigned default/nginx to k8s-study-worker2
  Normal  Pulling    114s  kubelet            spec.containers{nginx}: Pulling image "nginx:1.14.2"
  Normal  Pulled     109s  kubelet            spec.containers{nginx}: Successfully pulled image "nginx:1.14.2" in 4.531s (4.531s including waiting). Image size: 41901077 bytes.
  Normal  Created    109s  kubelet            spec.containers{nginx}: Container created
  Normal  Started    109s  kubelet            spec.containers{nginx}: Container started

上から順に「Node が決まった → イメージを取りに行った → 取れた → コンテナを作った → 起動した」。kubectl apply のあとに Kubernetes が裏で行っていたことが、ここに並ぶ。

  • From 列は、それを行った担当。Scheduled だけが default-scheduler(Node を決める係)で、Pulling 以降はその Node の kubelet(Node 上でコンテナを動かす係)
  • Pulling と Pulled の間の 5 秒が、イメージ(約 42MB)のダウンロードにかかった時間
  • Pod がうまく動かないときも、まずここを見る。イメージ名を間違えると Failed to pull image のような行が出る

同じ Node でもう一度 Pod を作ると、イメージはすでに Node にあるため Pulling の行がなくなり、Pulled の内容が「already present on machine」に変わる。

  Normal  Scheduled  38s   default-scheduler  Successfully assigned default/nginx to k8s-study-worker2
  Normal  Pulled     38s   kubelet            spec.containers{nginx}: Container image "nginx:1.14.2" already present on machine and can be accessed by the pod
  Normal  Created    38s   kubelet            spec.containers{nginx}: Container created
  Normal  Started    38s   kubelet            spec.containers{nginx}: Container started

イメージは Node ごとに保存されるので、次にもう一方の Worker に置かれたときは、また Pulling から始まる。

kubectl logs

kubectl logs nginx

コンテナが標準出力に書いたものが出る。docker logs にあたる。

kubectl port-forward

Pod の IP はクラスタの中のものなので、Mac から直接はつながらない。port-forward で Mac のポートを Pod のポートにつなぐ。

kubectl port-forward pod/nginx 8080:80

別のターミナルから curl http://localhost:8080 を実行すると nginx のトップページの HTML が返り、kubectl logs nginx にアクセスログが1行増える。確認したら Ctrl+C で port-forward を止める。

port-forward を止めないままにすると、Pod を消したあとも Mac のポート 8080 は kubectl が握ったままになる。ブラウザのキャッシュで nginx の画面が表示され続けることもあるので、Pod が消えたかどうかは kubectl get pods で確認する。

Pod を消す

kubectl delete pod nginx

# => pod "nginx" deleted
kubectl get pods

# => No resources found in default namespace.

Pod を単体で作った場合、消したら終わりで、誰も作り直さない。「消えたら自動で作り直してほしい」「同じ Pod を3つ動かしたい」を実現するのは Pod ではなく、Pod を見張って数を保つ担当である Deployment という別のリソースになる。

コンテナが落ちた場合とは動きが違う。コンテナが落ちたときは、同じ Pod の中で kubelet がコンテナを再起動する(RESTARTS が増える)。Pod は残ったまま、中のコンテナだけが入れ替わる。

起きたこと何が起きるか誰がやるか
コンテナが落ちた同じ Pod の中でコンテナを再起動するkubelet
Pod が削除された何も起きない。単体で作った Pod は作り直されない担当がいない

コンテナを2つ入れた Pod

Pod にはコンテナを2つ以上入れられる。同じ Pod のコンテナは 同じ IP とポート空間を共有し、localhost でお互いに届く。これを確かめるため、nginx(web)と、5 秒ごとに localhost:80 にアクセスして結果を出力するだけのコンテナ(checker)を1つの Pod に入れる。

# multi-container-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: web-and-checker
spec:
  containers:
    - name: web
      image: nginx:1.14.2
      ports:
        - containerPort: 80
    - name: checker
      image: busybox:1.28
      command:
        - sh
        - -c
        - |
          while true; do
            if wget -q -O /dev/null http://localhost:80; then
              echo "ok  $(date)"
            else
              echo "ng  $(date)"
            fi
            sleep 5
          done
kubectl apply -f multi-container-pod.yaml
kubectl get pods

READY が 2/2 になる。コンテナが複数ある Pod では、kubectl logs に -c <コンテナ名> を付けてどのコンテナのログかを指定する。

kubectl logs web-and-checker -c checker   # ok <日時> が 5 秒ごとに並ぶ
kubectl logs web-and-checker -c web       # 127.0.0.1 からのアクセスが記録されている

web のアクセスログに 127.0.0.1 からのリクエストが並ぶのは、checker が同じ Pod の中から localhost でアクセスしているため。Pod の IP は1つで、待ち受けているのは web だけ。

この Pod の中身を図にすると次のようになる。

図を描画しています…
  • 同じ Pod に nginx を2つ入れることはできない。ポートも共有しているので、2つ目がポート 80 を取れずに起動に失敗する
  • nginx を2つ動かしたい場合は Pod を2つ作る。それを行うのが Deployment
  • 2つ目のコンテナを入れる実際の用途は、ログの転送や通信の中継のように、アプリ本体を手伝う役目のもの。checker は動作を確かめるためだけのもの
kubectl delete pod web-and-checker

用語メモ

用語読み方意味
Podポッドコンテナを入れて動かす箱。Kubernetes が扱う最小の単位
kindカインドDocker の上に学習用のクラスタを作るツール
NodeノードPod を載せるマシン。kind では Docker コンテナ1つ
EventsイベンツPod に何が起きたかの記録。kubectl describe pod の一番下に出る

まとめ

  • Kubernetes では、コンテナは Pod という箱に入れて動かす。人間が作るのは Pod で、コンテナ単体を作る操作はない
  • Pod の YAML は apiVersion / kind / metadata / spec の4つの塊。自分で決めるのは spec(何のコンテナを入れるか)
  • 作る: kubectl apply -f、見る: kubectl get pods(-o wide で Node と IP)、kubectl describe pod(Events: に経緯)、kubectl logs、消す: kubectl delete pod
  • Pod を置く Node は Kubernetes が決める。IP はコンテナではなく Pod に付く
  • 単体で作った Pod は、消したら作り直されない。作り直す担当を付けるのが Deployment

参考 URL

Author

rito

rito

  • Backend Engineer
  • Tokyo, Japan
  • PHP 5 技術者認定上級試験 認定者
  • 統計検定 3 級