Kubernetesとは ― Podとコントロールプレーン
Kubernetesは、
Kubernetesとは、多数のコンテナを自動で動かし続ける仕組み
コンテナの数が増えると、どのサーバに置き、止まったらどう起動し直し、いくつ動かすかを人の手で管理しきれなくなります。Kubernetesは、この3つを自動で行う仕組みです。利用者があるべき状態を宣言しておくと、Kubernetesがいまの状態をそこへ近づけ続けます。
公式ドキュメントは、Kubernetesを、コンテナ化したアプリを管理するためのオープンソースのプラットフォームと説明しています。2014年にGoogleがオープンソースとして公開し、2016年からはCNCFのプロジェクトになっています。CNCFは、クラウド向けのオープンソースを支える団体です。Kubernetesは2018年に、CNCFの成熟度の段階でGraduatedに上がりました。
KとSの間に8文字あることから、K8sと略して書かれることもあります。
宣言型で動く:あるべき状態といまの状態を比べて近づける
Kubernetesには、「このPodを3つ動かす」のように、最終的にどうなっていてほしいかを書いて渡します。Podは、コンテナをまとめて動かす単位です。どの順に何を起動するかの手順は書きません。この書き方は、IaCでいう宣言型と同じ考え方です。
公式ドキュメントは、この仕組みを部屋のエアコンの温度設定にたとえています。設定した温度があるべき状態で、いまの室温がいまの状態です。エアコンは、室温を設定に近づけるように動き続けます。
Kubernetesで同じ役をするのが、コントローラーです。コントローラーは、クラスターの状態を見続け、あるべき状態との差があれば直します。状態を見て直す動きを止まらずに繰り返すことを、公式ドキュメントは制御ループと呼んでいます。差を埋めて状態を合わせる動きなので、調整ループとも呼ばれます。
Kubernetesは、コンテナのオーケストレーションの代表例として挙げられます。ただし公式ドキュメントは、決めた手順をAからCへ順に実行するのとは違うと説明しています。独立した複数の制御の仕組みが、いまの状態をあるべき状態へ近づけ続けるからです。
クラスターの構成は、コントロールプレーンとワーカーノード
Kubernetesで管理するサーバの集まりを、クラスターと呼びます。クラスターは、全体を管理するコントロールプレーンと、コンテナを実際に動かすワーカーノードに分かれます。ワーカーノードは単にノードとも呼ばれ、物理サーバでも仮想マシンでもかまいません。
コントロールプレーンの構成要素どうしは、APIサーバを窓口にしてつながります。コントローラーやスケジューラーは、APIサーバを通して状態を読み、変更を書き込みます。APIサーバは、受け付けた内容をetcdに保存します。
ワーカーノードには、kubelet、kube-proxy、コンテナランタイムが入ります。kubeletは、自分のノードに割り当てられたPodのコンテナが動いているように保ちます。コンテナランタイムは、containerdやCRI-Oのように、コンテナを実際に起動するソフトウェアです。
| 構成要素 | 置く | 役目 |
|---|---|---|
| kube-apiserver | コントロールプレーン | KubernetesのAPIを受け付ける窓口。ほかの構成要素はここを通して状態を読み書きする |
| etcd | コントロールプレーン | クラスターのデータをすべて保存するキーバリュー型の保存先 |
| kube-scheduler | コントロールプレーン | ノードが決まっていないPodを見つけ、置くノードを選ぶ |
| kube-controller-manager | コントロールプレーン | Deploymentなどのコントローラーを動かし、いまの状態をあるべき状態に近づける |
| kubelet | ワーカーノード | 割り当てられたPodのコンテナが動いているように保つ |
| kube-proxy | ワーカーノード | Serviceあての通信をPodへ届ける規則をノードに作る |
| コンテナランタイム | ワーカーノード | コンテナを実際に起動して動かす。containerdやCRI-Oなど |
本番の環境では、ふつうコントロールプレーンを複数のサーバに分けて動かし、ノードも複数台にします。どれか1台が止まっても、クラスター全体が止まらないようにするためです。クラウドの事業者と連携する構成要素として、cloud-controller-managerを加えることもあります。
Podとは、コンテナをまとめて動かす最小の単位
Podとは、1つ以上のコンテナをまとめた、Kubernetesで作って管理できる最小の単位です。Kubernetesはコンテナを直接ではなく、Podとして置き場所を決め、起動し、止めます。
同じPodの中のコンテナは、同じノードで動き、ネットワークと保存領域を分け合います。Podには1つずつIPアドレスが割り当てられ、中のコンテナどうしはlocalhostで通信できます。公式ドキュメントによると、1つのPodに1つのコンテナを入れる形がいちばん多い使い方です。
Podは、使い捨てる前提で作られています。ノードの故障や資源の不足で消えることがあり、消えたPodがそのまま戻ることはありません。そのためPodはふつう直接作らず、次の節で説明するDeploymentなどに作らせます。
Deploymentとは、Podの数を保ち、順に入れ替えて更新する仕組み
Deploymentとは、Podのひな形と、同じ作りのPodをいくつ動かすかを書いておくものです。Deploymentは、指定した数のPodを保つReplicaSetを作り、ReplicaSetが実際のPodを作ります。
次の例は、公式ドキュメントにあるDeploymentの定義です。nginxのイメージを使うPodを3つ動かすように宣言しています。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80replicasが、保ちたいPodの数です。templateの中が、Podのひな形にあたります。selectorは、このDeploymentが受け持つPodを、app: nginxというラベルで見分ける指定です。
ひな形のイメージを新しい版に書き換えると、Deploymentは新しいReplicaSetを作ります。そして新しいPodを少しずつ増やし、古いPodを少しずつ減らします。この入れ替え方をローリングアップデートと呼び、更新の途中も動いているPodで処理を続けられます。
初期設定では、入れ替えの途中に使えるPodがあるべき数の75%を下回らないようにします。Podの合計は、あるべき数の125%までに抑えます。更新後のPodがうまく動かないときは、前の版に戻すこともできます。ローリングアップデートとほかの切り替え方の違いは、ブルーグリーンデプロイとカナリアリリースの記事で比べています。
Podが止まったとき・数を変えたときに、Kubernetesの中で起きること
Podが1つ消えると、あるべき数といまの数に差が生まれます。その差をコントローラー・スケジューラー・kubeletが順に埋めていきます。次の図で場面を選び、段を進めると、どの構成要素が何をするかを1段ずつ確かめられます。
- 起きた
こと ノード2で動いていた Podが 1つ 消えました。 あるべき数は 3の ままで、 いま動いているのは 2つです。 - ReplicaSetコントローラー
(kube-controller-managerの 中) あるべき数との差に 気づき、 足りない 1つ分の Podを APIサーバを 通して 作ります。 この Podは、 まだ 置き先の ノードが 決まっていません。 - kube-scheduler置き先の
決まっていない Podを 見つけ、 空きの ある ノードを 選びます。 この 例では ノード2を 選び、 その 結果を APIサーバに 伝えます。 - ノード2の
kubelet 自分のノードに 割り当てられた Podに 気づき、 コンテナランタイムに コンテナを 起動させます。 いま動いている Podが 3つに 戻りました。 - Service新しい
Podが 応答できる 状態に なると、 Serviceの 振り分け先に 加わります。 利用者は、 Podが 入れ替わった ことを 意識せずに 使い続けられます。
- 利用者と
APIサーバ 利用者がDeploymentの replicasを 3から 5に 書き換えます。 APIサーバが この 変更を 受け付け、 etcdに 記録します。 - DeploymentコントローラーDeploymentの
変更に 気づき、 配下の ReplicaSetが 保つ数を 5に 書き換えます。 Podは まだ 増えていません。 - ReplicaSetコントローラー5に
対していまは 3つなので、 2つ 足りないと 判断します。 足りない 2つの Podを、 APIサーバを 通して 作ります。 - kube-scheduler2つの
Podの 置き先を、 ノードの 空きを 比べて 選びます。 この 例では、 ノード1と ノード2に 1つずつ 置きます。 - 各ノードの
kubelet 割り当てられたPodの コンテナを 起動します。 いま動いている Podが 5つに なり、 あるべき数に そろいました。
- 利用者と
Deploymentコントローラー 利用者がPodの ひな形の イメージを 書き換えます。 Deploymentは、 新しい ひな形の Podを 保つReplicaSetを 作ります。 - Deploymentコントローラー新しい
ReplicaSetの 数を 1に 増やし、 新しい Podを 1つ作らせます。 初期設定では、 Podの 合計は あるべき数より 1つ 多い 4つまで 許されます。 - Deploymentコントローラー新しい
Podが 使える 状態に なってから、 古い Podを 1つ 減らします。 使える Podは、 つねに 3つ以上に 保たれます。 - Deploymentコントローラー合計が
3つに 戻ったので、 新しい Podを もう 1つ作らせます。 合計は また 4つに なります。 - Deploymentコントローラー新しい
Podが 使える 状態に なってから、 古い Podを もう 1つ 減らします。 - Deploymentコントローラー最後の
1つも 同じ順で 入れ替わり、 新しい Podが 3つに なります。 古い ReplicaSetが 保つ数は 0に なります。
どの場面でも、コントローラーはPodを直接起動しません。APIサーバに書き込み、スケジューラーとkubeletがその内容を見て動きます。公式ドキュメントは、この自動で元に戻す働きを自己修復と呼んでいます。
Podの中のコンテナが落ちただけのときは、Podは作り直されません。そのノードのkubeletが、設定に従ってコンテナを再起動します。ただし公式ドキュメントは、アプリそのものの不具合は再起動では直らないと注意しています。
replicasは手で変えるほか、CPUの使用率などに応じて自動で変えることもできます。この仕組みをHorizontalPodAutoscalerと呼び、Podの数を増やして負荷に応えます。台数を増やして処理を分ける考え方は、スケールアップとスケールアウトの記事で説明しています。
Serviceとは、入れ替わるPodの前に置く変わらない接続先
Podは作り直されるとIPアドレスが変わり、置かれるノードも変わることがあります。Serviceとは、条件に合うPodの集まりの前に置き、変わらない接続先を与える仕組みです。利用者や別のアプリは、Serviceに向けて通信すれば、いま動いているPodのどれかに届きます。
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80この例は、公式ドキュメントのServiceの例と同じ書き方で、selectorを前の節のDeploymentに合わせたものです。Serviceは、app: nginxのラベルを持つPodを見つけ、80番ポートへの通信をPodの80番ポートへ送ります。Podが入れ替わると、振り分け先の一覧も自動で書き換わります。
typeを書かないと、Serviceはクラスターの中だけで使えるIPアドレスを持ちます。外から使えるようにするには、ノードのポートで受けるNodePortや、外部のロードバランサを使うLoadBalancerを選びます。振り分けの考え方は、ロードバランサの記事が詳しいです。
図ではServiceを1つの箱で描きましたが、Serviceは専用の機械ではありません。各ノードのkube-proxyなどが、Serviceあての通信をPodへ届ける規則を作っています。
Kubernetesが受け持たないこと
Kubernetesの仕事はコンテナを動かし続けることで、アプリを作る仕組みまでは持ちません。公式ドキュメントは、Kubernetesが行わないこととして次のものを挙げています。
- ソースコードのビルドとデプロイ。この流れはCI/CDの仕組みで別に用意します
- ログの収集・監視・通知の仕組みの決定。連携のための仕組みだけを用意しています
- データベースやメッセージの仲介などの、アプリが使うサービスそのもの
これらは、Kubernetesの上で動かすか、外のサービスを組み合わせて用意します。どの道具を選ぶかは、利用者に任されています。
マネージドのKubernetesは、コントロールプレーンの運用を事業者に任せる形
コントロールプレーンを自分で組み、止まらないように運用するのは手間がかかります。そこで、クラウドの事業者がコントロールプレーンを運用するサービスがあります。Amazon EKS・Google Kubernetes Engine・Azure Kubernetes Serviceが、その例です。
これらのサービスでも、Pod・Deployment・Serviceの考え方は変わりません。ワーカーノードの管理まで事業者に任せる方式を用意しているサービスもあります。AWSでEKSがどの層の選択肢になるかは、ECSの記事でAmazon ECSと比べています。
参考にした資料
- Kubernetes Docs「Overview」(定義、提供する機能、Kubernetesに含まれないもの)
- Kubernetes Docs「Cluster Architecture」(コントロールプレーンとノードの構成要素)
- Kubernetes Docs「Controllers」(調整ループ、温度設定のたとえ)
- Kubernetes Docs「Kubernetes Self-Healing」(コンテナの再起動とPodの置き換え)
- Kubernetes Docs「Pods」(Podの定義とネットワーク)
- Kubernetes Docs「Deployments」(定義の例、ローリングアップデートの初期設定)
- Kubernetes Docs「Service」(定義の例、Serviceの種類)
- Kubernetes Docs「Horizontal Pod Autoscaling」(Podの数の自動調整)
- CNCF「Kubernetes」(CNCFでの成熟度)
- AWS「What is Amazon EKS?」(コントロールプレーンの運用)
- Google Cloud「GKE overview」(マネージドのKubernetes)
- Microsoft「What is Azure Kubernetes Service (AKS)?」(マネージドのKubernetes)
練習問題(全5問)
正解:Pod
公式ドキュメントは、
正解:コントローラーが
あるべき数は
正解:kube-scheduler
kube-schedulerは、
正解:入れ替わる
Podは
正解:ソースコードの
公式ドキュメントは、
選んでから「採点する」を押すと、解説つきで答え合わせができます。