Kubernetes PodとNodeの核心的な違いを理解する
Kubernetesアーキテクチャの基礎をマスターするために、PodとNodeの役割を明確に定義します。このガイドでは、Nodeがリソースを提供する基盤となるコンピュートマシンであり、Podがアプリケーションコンテナをホストする最小のデプロイ可能ユニットであることを説明します。スケジューラを介したこれらのコンポーネントの相互作用、リソース要求に関する重要な考慮事項、およびアプリケーションの安定性を確保するための実践的なトラブルシューティング手順について学びます。
Kubernetes PodとNodeの核心的な違いを理解する
Kubernetesを初めて使う場合、PodとNodeの区別は、システム全体を理解するための最初の重要なポイントです。Nodeはマシンです。PodはKubernetesがそのマシンに配置するワークロードです。コンテナはPod内で実行され、PodはNode上で実行されます。
これは単純に聞こえますが、日常的なトラブルシューティングの多くを説明します。PodがPending状態の場合、Kubernetesが適切なNodeを見つけられなかった可能性があります。NodeがNotReady状態の場合、その上のすべてのPodがリスクにさらされます。アプリケーションに高可用性が必要な場合、コンテナの数を増やすだけでは不十分です。異なるNodeに分散されたレプリカが必要です。
Kubernetesクラスターアーキテクチャの概要
Kubernetesクラスターは、連携して動作する一連のマシン(物理または仮想)で構成されています。これらのマシンは、コントロールプレーン(クラスター状態を管理する頭脳)とワーカーノード(実際のワークロードを実行する筋肉)に大別されます。PodとNodeはこの構造内で相互作用します。
- Node: CPU、メモリ、ディスク、ネットワークを提供する物理または仮想マシン。
- Pod: Kubernetesがスケジュールする最小のデプロイ可能ユニット。1つ以上のコンテナをホストします。
NodeがPodをホストし、Podがコンテナをホストするというこの階層を理解することが、Kubernetesを習得するための出発点です。
Kubernetes Node: コンピュートパワーの基盤
KubernetesのNode(ワーカーマシンとも呼ばれる)は、アプリケーションを実行するために必要な計算リソース(CPU、RAM、ネットワーク)を提供するマシンです。クラスターには少なくとも1つのNodeが必要ですが、本番環境では通常、冗長性とスケーラビリティのために複数のNodeを使用します。
Nodeの主な責務
各Nodeは、コントロールプレーンと通信し、アプリケーションワークロードをホストするために必要なコンポーネントを実行します。
- Kubelet: 各Nodeで実行されるエージェントで、コントロールプレーンとの通信を担当します。コンテナランタイムと連携して、PodSpecで記述されたコンテナがそのNode上で実行され、正常であることを確認します。
- コンテナランタイム: イメージをプルしてコンテナを実行するソフトウェアで、最近のクラスターでは一般的にcontainerdやCRI-Oが使用されます。
- Kube-proxy: Node上のネットワークルールを維持し、Podとの内部および外部の通信を可能にします。
実践例: Nodeの表示
クラスター内のNodeを検査すると、Kubernetesが利用している基盤となるインフラストラクチャを確認できます。
kubectl get nodes
NAME STATUS ROLES AGE VERSION
worker-node-01 Ready <none> 2d1h v1.27.4
worker-node-02 Ready <none> 2d1h v1.27.4
重要なポイント: Nodeは実行が行われるマシンレイヤーです。
Kubernetes Pod: 最小のデプロイ可能ユニット
Podは、Kubernetesにおけるデプロイメントの原子単位です。それ自体はコンテナではなく、同じNode上に配置され、リソースを共有することが保証された1つ以上のコンテナをラップするものです。
なぜ直接コンテナではなくPodなのか?
Kubernetesが個々のコンテナではなくPodを管理する理由は、いくつかの重要な理由があります。
- 共有コンテキスト: 単一のPod内のすべてのコンテナは、同じネットワーク名前空間(IPアドレスとポート範囲)を共有し、
localhostを介して簡単に通信できます。 - 共有ストレージ: 同じPod内のコンテナは、同じマウントされたストレージボリュームにアクセスできます。
- ライフサイクル管理: KubernetesはPodを単一のエンティティとして扱います。Pod内のいずれかのコンテナが失敗した場合、KubernetesはPod構造全体の再起動または再作成を処理します。
Podの構造
ほとんどの場合、Podには1つのプライマリアプリケーションコンテナが含まれます。ただし、サイドカーパターンで頻繁に使用され、セカンダリコンテナがプライマリコンテナを支援します(例:ログエージェント、サービスメッシュプロキシ)。
Pod定義の例(簡略化されたYAML)
次のYAMLは、単一のNginxコンテナをラップするPodを定義しています。
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
spec:
containers:
- name: nginx-container
image: nginx:latest
ports:
- containerPort: 80
重要なポイント: Podはアプリケーションコンテナの論理的なホストであり、Nodeにスケジュールされる単位です。
核心的な関係: スケジューリングと配置
PodとNodeの基本的な相互作用は、コントロールプレーンに存在するKubernetesスケジューラによって管理されます。
PodがNodeに配置される仕組み
- Podの作成: ユーザーがPod(またはDeploymentなどのPodを作成する高レベルオブジェクト)のYAML定義をAPIサーバーに送信します。
- スケジューリングの決定: スケジューラは、リソース要求、制約、および利用可能な容量に基づいて、そのPodを実行するのに最適なNodeを特定します。
- バインディング: Nodeが選択されると、Podはその特定のNodeにバインドされます。
- 実行: 割り当てられたNode上のKubeletが新しいPodの割り当てを検出し、必要なイメージをプルしてコンテナを起動します。
重要なポイント: PodがNodeにスケジュールされると、終了されるか、永続的にクラッシュするか、Nodeが故障するまで、そのNodeに留まります。Kubernetesは通常、実行中のPodをNode間で移行しません。
| 特徴 | Kubernetes Node | Kubernetes Pod |
|---|---|---|
| 役割 | 物理/仮想コンピューティングリソースを提供する。 | 1つ以上のアプリケーションコンテナを実行する。 |
| 範囲 | クラスターインフラストラクチャレベル。 | アプリケーションワークロードレベル。 |
| スケジューリングの単位 | スケジューラからPodを受け取る。 | Nodeにスケジュールされる単位。 |
| コンポーネント | Kubelet、コンテナランタイム、Kube-proxy。 | アプリケーションコンテナ、共有ボリューム、共有IP。 |
| 数量 | 通常、クラスターあたり数個から多数。 | ワークロードによっては数百から数千になる可能性がある。 |
実際のデプロイメント例
次のDeploymentを持つWebアプリケーションを想像してください。
apiVersion: apps/v1
kind: Deployment
metadata:
name: storefront
spec:
replicas: 3
selector:
matchLabels:
app: storefront
template:
metadata:
labels:
app: storefront
spec:
containers:
- name: web
image: example/storefront:v1
ports:
- containerPort: 8080
これは3つのNodeを作成するわけではありません。3つのPodレプリカを作成します。スケジューラは、どの既存のNodeがそれらのPodを実行するかを決定します。小規模なクラスターでは、次のように表示される場合があります。
kubectl get pods -o wide
NAME READY STATUS NODE
storefront-6d8f8c7f9b-2xk9p 1/1 Running worker-node-01
storefront-6d8f8c7f9b-7hxm4 1/1 Running worker-node-02
storefront-6d8f8c7f9b-q4zpt 1/1 Running worker-node-02
3つのPodがありますが、関係するNodeは2つだけです。worker-node-02が故障すると、2つのレプリカが同時に失われます。Deploymentはそれらを置き換えようとしますが、そのためには正常なNodeの容量が必要です。これが、Deploymentに複数のレプリカがある場合でも、Nodeの配置が重要である理由です。
KuberneteにレプリカをNode間で分散させたい場合は、トポロジー分散制約またはPod間アンチアフィニティを使用します。すべての小さな内部ツールにこれが必要なわけではありませんが、1つのNode障害で容量の大部分が失われてはならない顧客向けサービスでは検討する必要があります。
Podは使い捨て可能、Nodeは管理された容量
健全なKubernetesの考え方として、Podは交換可能です。Deployment、ReplicaSet、StatefulSet、Job、DaemonSetは常にPodを作成および置き換えます。ランダムなサフィックスが付いたPod名に永続的に依存すべきではありません。
Nodeも適切に管理されたクラスターでは交換可能ですが、それらは容量の単位です。オペレーティングシステムのパッチ、kubeletの健全性、十分なディスク容量、動作するコンテナランタイム、ネットワーク接続が必要です。Nodeに問題が発生すると、多くのPodが同時に影響を受ける可能性があります。
この違いは、デバッグの方法に現れます。
- 1つのPodが失敗し、同じNode上の他のPodが正常な場合、Podのログ、設定、プローブ、イメージ、リソース制限から調査を開始します。
- 同じNode上の無関係なPodが複数失敗した場合、Nodeから調査を開始します。ディスク圧力、メモリ圧力、kubeletステータス、CNIの健全性、コンテナランタイムのログを確認します。
- 新しいPodがどこでも起動できない場合、クラスター全体の容量、クォータ、スケジューリングルール、コントロールプレーンの健全性を確認します。
よくある誤解
最初の誤解は、Podはコンテナと同じものだと思うことです。ほとんどのPodには1つのメインコンテナが含まれているため、このショートカットは無害に感じられます。しかし、サイドカーがあると、この区別が重要になります。サービスメッシュプロキシ、ログシッパー、ヘルパーコンテナは、アプリケーションと同じPod内で実行できます。それらはPodのネットワーク名前空間を共有するため、そのPod内ではそれらのコンテナ間でlocalhostが機能します。
2番目の誤解は、Kubernetesが実行中のPodをライブVMマイグレーションのように別のNodeに移動すると思うことです。一般的にはそうではありません。Nodeがドレインされたり故障したりすると、Kubernetesは古いPodを終了または喪失し、別の場所に新しいPodを作成します。その新しいPodは異なるPod IDを持ち、古いPodのローカルコンテナファイルシステムの変更は、永続ストレージに書き込まれていない限り失われます。
3番目の誤解は、ServiceがNode上で実行されると仮定することです。Serviceは、Podの前にある安定したネットワーキング抽象化です。ラベルでPodを選択し、トラフィックをそれらのIPにルーティングします。NodeはそれらのPodが実行される場所を提供しますが、Service自体はPodと同じように特定のワーカーノード上にあるわけではありません。
これが日常的な設計に与える影響
レプリカ数を選択するとき、Kubernetesが実行し続けようとするPodのコピー数を選択しています。存在するNodeの数を選択しているわけではありません。10個のレプリカを持つDeploymentでも、分散ルールを追加せず、クラスターに十分なNode容量がない場合、複数のPodが同じNodeに配置される可能性があります。
Nodeサイズを選択するとき、容量プールの形状を選択しています。少数の大きなNodeは効率的ですが、1つのNode障害で実行中のPodのより大きな割合が失われます。より多くの小さなNodeは障害の分離を改善できますが、オーバーヘッドが追加され、ビンパッキングの効率が低下する可能性があります。普遍的な答えはありません。適切な選択は、ワークロードのサイズ、可用性のニーズ、コストによって異なります。
ステートフルワークロードはさらに複雑さを増します。StatefulSetもPodを作成し、それらのPodもNode上で実行されますが、各Podは安定したIDと永続ボリュームを持つ場合があります。Nodeが停止した場合、Kubernetesは別の場所にPodを再作成できますが、ストレージレイヤーは新しい場所からのボリュームのアタッチまたはアクセスをサポートする必要があります。
ベストプラクティスとトラブルシューティングの洞察
このアーキテクチャを理解することは、実践的なクラスター管理に役立ちます。
リソース管理
- リソース要求/制限: Pod仕様で常にリソース
requestsとlimitsを定義します。これにより、スケジューラはPodを十分な容量を持つNodeに正確に一致させ、リソースの競合を防ぐことができます。 - Node圧力: Nodeが過負荷になった場合(ディスク容量またはメモリ不足)、Kubeletはこの状態を報告します。Kubernetesは安定性を維持するために、そのNodeからPodを退避させる場合があります。
高可用性(HA)
- 冗長性: HAを実現するには、DeploymentまたはStatefulSetで管理されるPodの複数のコピー(レプリカ)を実行する必要があります。スケジューラは、これらのレプリカを異なるNodeに配置しようと試み、1つのNodeの障害がアプリケーション全体をダウンさせないようにします。
トラブルシューティング
アプリケーションが起動しない場合:
- Podのステータスを確認する:
kubectl describe pod <pod-name>を使用します。'Events'セクションを確認して、PodがどのNodeにスケジュールされたかを確認します。 - Nodeのステータスを確認する: Podが
Pendingでスタックしている場合、問題は通常スケジューリング関連です(例:必要な制約を満たすNodeがない)。Podが実行中だが失敗している場合、そのPodが配置された特定のNodeのKubeletログを確認します。
便利なコマンド:
kubectl get pods -o wide
kubectl describe pod <pod-name>
kubectl get nodes
kubectl describe node <node-name>
-o wide出力は過小評価されています。各PodがどのNodeに配置されたかを表示し、アプリケーションの問題とインフラストラクチャの問題を区別する手がかりとなることがよくあります。
短いバージョン
Nodeは「これはどこで実行できるか?」に答えます。Podは「何を一緒に実行すべきか?」に答えます。スケジューラは、PodをNodeに配置することで、これら2つの概念を結び付けます。この関係がわかれば、Kubernetesのエラーは読みやすくなります。保留中のPodは多くの場合配置の問題であり、失敗しているPodは多くの場合ワークロードの問題であり、正常でないNodeは同時に多くのPodの問題を引き起こす可能性があります。