はじめに
前回は、Kubernetesでコンテナを動かす最小単位であるPodについて学びました。
Podの中では、RailsやSidekiqなどのコンテナが動きます。
では、そのPod自体は、どこで動いているのでしょうか。
そこで登場するのが Node(ノード) です。
この記事では、次の内容を整理します。
- Nodeとは何か
- PodとNodeの関係
- Nodeの中で動くコンポーネント
- Podを配置するNodeはどのように決まるのか
- Nodeで障害が起きた場合に何が起こるのか
- EKS・EC2・Node Groupの関係
- NodeとVPC・Subnet・AZの関係
結論
Nodeとは、Podを実際に動かすコンピューターです。
Nodeは、物理マシンの場合もあれば、仮想マシンの場合もあります。
AWSのEKSでEC2を利用する構成では、基本的に1台のEC2インスタンスが1つのNodeとしてKubernetesクラスターへ参加します。
Kubernetesクラスター
├── Node 1(EC2)
│ ├── Rails Pod
│ │ └── Railsコンテナ
│ └── Sidekiq Pod
│ └── Sidekiqコンテナ
│
└── Node 2(EC2)
└── Rails Pod
└── Railsコンテナ
最も簡単に表すと、次の関係です。
Nodeの中でPodが動く
Podの中でコンテナが動く
Nodeとは
Kubernetesは、複数のコンピューターをまとめて1つのクラスターとして管理します。
そのクラスターに参加し、Podを実行するコンピューターがNodeです。
Kubernetesクラスター
├── Node 1
├── Node 2
└── Node 3
各Nodeには、CPU・メモリ・ディスク・ネットワークなどのリソースがあります。
Kubernetesは、それらの空き状況やPodの条件を確認しながら、PodをいずれかのNodeへ配置します。
Nodeは、環境によって異なる実体を持ちます。
| 環境 | Nodeの例 |
|---|---|
| 自分のPCで学習する環境 | Docker Desktopなどが用意する仮想マシン |
| オンプレミス | 物理サーバー・仮想マシン |
| AWS EKS | EC2インスタンスなど |
| Google Kubernetes Engine | Compute EngineのVMなど |
つまり、NodeはKubernetes独自の仮想的な箱ではありません。
実際のコンピューターをKubernetesへ登録し、Podを動かせる状態にしたものがNodeです。
Cluster・Node・Pod・Containerの関係
ここまで登場した要素を入れ子で表すと、次のようになります。
Kubernetesクラスター
└── Node
└── Pod
└── Container
それぞれの役割は次のとおりです。
| 要素 | 役割 |
|---|---|
| Cluster | 複数のNodeやKubernetesの管理機能をまとめた全体 |
| Node | Podを実際に動かすコンピューター |
| Pod | コンテナをまとめて動かすKubernetesの最小単位 |
| Container | RailsやSidekiqなどのアプリケーションを実行する |
1つのNodeでは、複数のPodを動かせます。
一方、1つのPodが複数のNodeにまたがって動くことはありません。
Node 1
├── Pod A
├── Pod B
└── Pod C
Node 2
├── Pod D
└── Pod E
Pod内に複数のコンテナがある場合も、そのコンテナはすべて同じNode上で動きます。
Control PlaneとNodeの関係
Kubernetesクラスターは、大きく次の2つに分けられます。
Kubernetesクラスター
├── Control Plane
│ └── クラスター全体を管理する
│
└── Node
└── Podを実際に動かす
Control Planeは、クラスターの状態を管理する側です。
たとえば、次のような判断や管理を行います。
- Podを何個動かす必要があるか
- 新しいPodをどのNodeへ配置するか
- NodeやPodが正常な状態か
- 現在の状態を、指定された状態へ近づけるには何が必要か
Nodeは、Control Planeから伝えられた内容に基づいてPodを動かす側です。
簡単に分けると、次のように考えられます。
Control Plane:決める・管理する
Node :実際に動かす
AWS EKSでは、Control PlaneをAWSが管理します。
一方、EC2を使用するNodeは、ユーザー側のAWSアカウント内で動きます。
Nodeの中では何が動いているのか
NodeがPodを動かすためには、主に次のコンポーネントが必要です。
Node
├── kubelet
├── container runtime
├── kube-proxy
└── Pod
└── Container
kubelet
kubeletは、それぞれのNode上で動くKubernetesのエージェントです。
Control Planeから、そのNodeで動かすPodの情報を受け取り、Pod内のコンテナが指定どおり動くように管理します。
Control Plane
「このPodを、このNodeで動かしてください」
↓
kubelet
「コンテナランタイムへ起動を依頼します」
↓
container runtime
「コンテナを起動します」
kubeletは、主に次のような役割を持ちます。
- Podの定義を受け取る
- コンテナランタイムへコンテナの起動を依頼する
- コンテナが正常に動いているか確認する
- NodeやPodの状態をControl Planeへ報告する
- Liveness ProbeやReadiness Probeなどのヘルスチェックを実行する
ただし、kubelet自身がコンテナを直接実行するわけではありません。
実際のコンテナ実行は、コンテナランタイムが担当します。
container runtime
container runtimeは、コンテナイメージを取得し、コンテナを実際に起動・停止するソフトウェアです。
代表例として、containerdやCRI-Oがあります。
kubelet
↓ 起動を依頼
container runtime
├── コンテナイメージを取得
├── コンテナを作成
└── コンテナを起動
Dockerについて学んだ際に登場した「コンテナを実際に動かす部分」に近い役割です。
Kubernetesは、CRIという共通の仕組みを通じてコンテナランタイムと連携します。
kube-proxy
kube-proxyは、Node上のネットワークルールを管理し、Service宛ての通信を適切なPodへ届けるために使われるコンポーネントです。
Service宛ての通信
↓
Node上のネットワークルール
↓
対象のPod
Serviceが持つ安定した接続先と、実際に動いているPodをつなぐ役割を支えます。
ただし、利用するネットワーク構成によっては、kube-proxyを使わず別の仕組みで同等の処理を行う場合もあります。
Podを配置するNodeは誰が決めるのか
新しいPodをどのNodeへ配置するか決めるのは、Control Planeで動く kube-scheduler です。
たとえば、DeploymentによってRails Podを1個増やす場合、次のように進みます。
1. Deployment
「Rails Podを3個にしたい」
↓
2. 新しいPodが必要になる
↓
3. kube-scheduler
「どのNodeなら動かせるか確認します」
↓
4. Node 2を選択
↓
5. Node 2のkubelet
「Pod内のコンテナを起動します」
kube-schedulerは、Nodeを選ぶ際に次のような条件を確認します。
- Nodeに十分なCPU・メモリがあるか
- Podが要求する条件をNodeが満たしているか
- Nodeに設定されたtaintをPodが許容できるか
- node affinityなどの配置条件に一致するか
- 複数のNodeへPodを分散できるか
つまり、kubeletが配置先を決めるわけではありません。
kube-scheduler:配置するNodeを決める
kubelet :決められたNode上でPodを動かす
CPU・メモリとPodの配置
Nodeで動かせるPodの数は、単純に「最大10個」などと固定されているわけではありません。
NodeのCPU・メモリやネットワーク上の上限、Podが要求するリソースなどによって変わります。
Podでは、コンテナが必要とするCPUとメモリをrequestsで指定できます。
resources:
requests:
cpu: "250m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"
それぞれの意味は次のとおりです。
| 項目 | 意味 |
|---|---|
requests |
Podを配置する際に必要として扱うCPU・メモリ |
limits |
コンテナが使用できるCPU・メモリの上限 |
kube-schedulerは、主にrequestsを見て、Podを配置できるNodeを探します。
Nodeの配置可能なメモリ:1Gi
新しいPodのrequests:256Mi
↓
配置できる可能性がある
反対に、条件を満たすNodeがなければ、PodはPendingのままになります。
新しいPodに必要なメモリ:2Gi
空き条件を満たすNode:0台
↓
PodはPending
この場合は、Nodeを増やす、Nodeを大きくする、Podのリソース指定を見直すなどの対応が必要です。
Nodeの状態
NodeがPodを動かせる状態かどうかは、次のコマンドで確認できます。
kubectl get nodes
出力例は次のようになります。
NAME STATUS ROLES AGE VERSION
node-1 Ready <none> 10d v1.xx.x
node-2 Ready <none> 10d v1.xx.x
STATUSがReadyであれば、基本的にPodを受け入れられる状態です。
詳細を確認する場合は、次のコマンドを使用します。
kubectl describe node node-1
Nodeでは、次のようなConditionが管理されます。
| Condition | 意味 |
|---|---|
Ready |
Nodeが正常で、Podを受け入れられるか |
MemoryPressure |
メモリ不足の圧力があるか |
DiskPressure |
ディスク不足の圧力があるか |
PIDPressure |
プロセスIDが不足する圧力があるか |
NetworkUnavailable |
Nodeのネットワークが利用できない状態か |
たとえば、Nodeからの状態報告が途絶えると、NotReadyなどの状態になります。
Nodeで障害が起きたらどうなるのか
Nodeが停止すると、そのNode上で動いていたPodも動けなくなります。
障害発生前
Node 1
├── Rails Pod A
└── Sidekiq Pod B
Node 1で障害
↓
Pod A・Pod Bも利用できなくなる
Deploymentなどのコントローラーに管理されているPodであれば、Control Planeは必要なPod数が不足していることを検知し、利用可能な別のNodeへ代わりのPodを作成します。
Node 1で障害
↓
Rails Pod Aが利用できない
↓
指定されたPod数を満たしていない
↓
Node 2に新しいRails Pod Cを作成
ここで重要なのは、停止したPodそのものがNode 2へ移動するわけではないことです。
別のNodeで、代わりとなる新しいPodが作成されます。
また、1台のNodeしかなければ、そのNodeが停止した際に代わりのPodを動かす場所がありません。
複数Nodeや複数AZを使う構成は、障害時にもアプリケーションを継続しやすくするために重要です。
Nodeを安全にメンテナンスする
Nodeを更新・停止する際、いきなり終了すると、そのNode上のPodも突然停止してしまいます。
そこで、KubernetesにはNodeからPodを安全に退避させるための操作があります。
cordon
cordonは、そのNodeへ新しいPodが配置されない状態にします。
kubectl cordon node-1
すでに動いているPodは、そのまま動き続けます。
drain
drainは、新しいPodの配置を止めたうえで、対象Node上のPodを退避させます。
kubectl drain node-1 --ignore-daemonsets
コントローラーに管理されているPodは、必要に応じて別のNodeに作り直されます。
uncordon
メンテナンス後、再びPodを配置できるようにします。
kubectl uncordon node-1
流れをまとめると、次のようになります。
cordon
新しいPodの配置を止める
↓
drain
既存のPodを退避させる
↓
Nodeをメンテナンスする
↓
uncordon
再びPodを配置できるようにする
EKSではNodeは何に当たるのか
AWSのEKSで一般的なEC2ベースの構成を使う場合、NodeはEC2インスタンスに当たります。
Amazon EKSクラスター
├── Control Plane
│ └── AWSが管理
│
└── Node
└── EC2インスタンス
└── Pod
└── Container
ただし、EKSとEC2が同じものという意味ではありません。
| 要素 | 役割 |
|---|---|
| EKS | Kubernetesクラスターを提供・管理するAWSサービス |
| EC2 | Podを動かすための計算リソースとして使える仮想マシン |
| Node | EC2などをKubernetesへ参加させたときの呼び方 |
つまり、EC2インスタンスがEKSクラスターへ参加し、Podを実行できる状態になると、KubernetesからはNodeとして見えます。
Node Groupとは
EKSでは、複数のNodeをまとめて管理するために Node Group を使用できます。
EKSクラスター
└── Node Group
├── Node 1(EC2)
├── Node 2(EC2)
└── Node 3(EC2)
NodeとNode Groupの違いは次のとおりです。
| 用語 | 意味 |
|---|---|
| Node | Podを動かす1台のコンピューター |
| Node Group | 同じような設定を持つ複数のNodeをまとめたグループ |
EKSのManaged Node Groupを使うと、EC2 Nodeの作成・更新・終了などのライフサイクル管理をEKSに任せやすくなります。
Managed Node Groupでは、EC2 Auto Scaling Groupを利用してNode数を管理します。
Managed Node Group
└── EC2 Auto Scaling Group
├── Node 1(EC2)
├── Node 2(EC2)
└── Node 3(EC2)
たとえば、次のような設定を持てます。
- 最小Node数
- 希望するNode数
- 最大Node数
- EC2のインスタンスタイプ
- 使用するAMI
- On-DemandまたはSpotのキャパシティタイプ
NodeとVPC・Subnet・AZの関係
EKSでEC2 Nodeを使う場合、そのEC2はVPC内のSubnetへ配置されます。
AWSアカウント
└── VPC
├── Private Subnet(AZ-a)
│ └── Node 1(EC2)
│ ├── Rails Pod
│ └── Sidekiq Pod
│
└── Private Subnet(AZ-c)
└── Node 2(EC2)
└── Rails Pod
ここでの関係は次のとおりです。
| 要素 | 意味 |
|---|---|
| VPC | AWSアカウント内に作るプライベートネットワーク |
| Subnet | VPCをIPアドレス範囲とAZごとに分割した区画 |
| AZ | 互いに物理的・設備的に分離されたデータセンター群 |
| EC2 Node | Subnet内に配置され、Podを動かす仮想マシン |
VPCは複数のAZにまたがれますが、1つのSubnetは1つのAZに属します。
また、EC2 Nodeも、配置されたSubnetが属する1つのAZで動きます。
複数AZにNodeを分けておけば、1つのAZで障害が起きても、別のAZにあるNodeでPodを動かせる可能性があります。
Podを増やすこととNodeを増やすことの違い
PodのスケーリングとNodeのスケーリングは、別の操作です。
Podを増やす
= アプリケーションの実行単位を増やす
Nodeを増やす
= Podを載せるコンピューターを増やす
たとえば、アクセス増加に合わせてRails Podを3個から10個へ増やそうとしても、Nodeに空きがなければ新しいPodを配置できません。
Rails Podを10個にしたい
↓
Nodeの空きが足りない
↓
一部のPodがPendingになる
↓
Nodeを追加する
↓
新しいNodeへPodを配置できる
一般的には、次のような仕組みを組み合わせます。
| 仕組み | 増減させる対象 |
|---|---|
| Horizontal Pod Autoscaler | Pod数 |
| Cluster Autoscalerなど | Node数 |
Podを増やす仕組みと、そのPodを載せるNodeを増やす仕組みは、役割が異なります。
よくある勘違い
NodeはPodのこと?
違います。
NodeはPodを動かすコンピューターで、PodはNode上でコンテナを動かす単位です。
Node
└── Pod
└── Container
NodeはKubernetesが作る仮想マシン?
必ずしもそうではありません。
Nodeの実体は物理マシンや仮想マシンです。EKSでEC2を使う場合は、EC2をクラスターへ参加させることでNodeになります。
1つのPodは複数のNodeで動く?
動きません。
1つのPodは必ず1つのNodeへ配置されます。Pod内のコンテナもすべて同じNode上で動きます。
Nodeが停止するとPodが別のNodeへ移動する?
停止したPodそのものが移動するわけではありません。
Deploymentなどで管理されていれば、別のNodeに代わりの新しいPodが作成されます。
Nodeを増やせばPodも自動的に増える?
増えません。
Nodeを増やすとPodを配置できる容量は増えますが、DeploymentのreplicasやHorizontal Pod AutoscalerなどでPod数を増やさない限り、必要なPod数は変わりません。
NodeとNode Groupは同じもの?
違います。
Nodeは1台のコンピューターで、Node Groupは複数のNodeをまとめて管理する単位です。
まとめ
Nodeについて、重要な点をまとめます。
- Nodeは、Podを実際に動かすコンピューター
- Nodeの実体は、物理マシンまたは仮想マシン
- EKSでEC2を使う場合、基本的に1台のEC2が1つのNodeになる
- 1つのNodeでは複数のPodを動かせる
- 1つのPodが複数のNodeにまたがることはない
- kube-schedulerがPodを配置するNodeを決める
- kubeletがNode上でPodの状態を管理する
- container runtimeがコンテナを実際に起動・停止する
- NodeのCPUやメモリが不足すると、Podを配置できず
Pendingになる場合がある - Node障害時は、別のNodeで代わりのPodが新しく作られる
- Node Groupは複数のNodeをまとめて管理する単位
- EKSのEC2 Nodeは、VPC内のSubnetへ配置される
- 可用性を高めるには、複数のNodeやAZへPodを分散することが重要
最も簡単に覚えるなら、次の関係です。
Control Planeが管理する
↓
NodeがPodを動かす
↓
PodがContainerを動かす
EKSまで含めると、次のようになります。
EKSクラスター
└── Node Group
└── Node(EC2)
└── Pod
└── Container
Podを理解したあとにNodeを学ぶと、Kubernetesが「コンテナをどのコンピューターへ配置し、どのように動かしているのか」が見えやすくなります。