Kubernetes is 何

実務でAmazon EKSを設計するタスクを任されたため、そもそもKubernetesがよくわかっていないのでそれぞれコンポーネントなどを理解するために本記事を執筆します。

前提としてコンテナとは何か？ということはお話しません。


## Kubernetes is 何
すごく簡単にいうと複数コンテナを作って、監視して、何か障害が発生したら自動でコンテナを停止させて、新しいコンテナを作って運用されるため、運用を自動化してくれるという優れものです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379725/da652322-0101-278a-9db4-59f75b8f7be5.png)

Kubernetesは「宣言型」と言われるツールでmanifestファイルと呼ばれるjsonまたはyml形式でコードを記述することで<font color="DeepPink">望ましい状態を定義する</font>ことができます。
望ましい状態を定義することで、指定した数のコンテナ数を維持することができたり、ネットワークの設定を行ったりすることができます。


## 宣言型と手続き型の違い
Kubernetesは宣言型のツールであるとご説明しましたが、手続き型と呼ばれる従来の方式も存在します。
宣言型の特徴は「望ましい状態を維持」することができますが、手続き型は明示的に命令を指示しないと望ましい状態を維持してくれません。

例えば、宣言型の場合、常にコンテナの数は3つに維持してください、manifestファイルに指示すれば1つのコンテナが障害等で壊れたとしても、新たに1つコンテナを起動します。
しかし、手続き型の場合は1つのコンテナが障害で壊れた場合には、自動では起動してくれません。
「壊れた場合には〇〇してください」という指示をしない限り復旧をしてくれません。

これが「宣言型」と「手続き型」の大きな違いになります。

## Kubernetesクラスターのアーキテクチャ
まず全体像を把握しましょう。
わかりやすかったので[アーキテクチャから読み解くKubernetes Controllerの仕組み](https://codezine.jp/article/detail/19131)の図を引用します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379725/fb315c35-22e7-b11a-c800-2f9c58d3c869.png)


以下Kubernetesに関するコンポーネントの名前が出てきたときにこの図に戻って説明と付け合わせしながら読むと良いでしょう。
Kubernetesでは大まかに分けるとControl PlaneとNodeという2つの役割を持ったコンポーネントに分かれています。

Clusterの上にControl PlaneとNodeが乗っかる形となります。

Control PlaneとNodeの中にさらに以下のようなコンポーネントが存在します。

**Control Plane**
- kube-apiserver
- etcd
- kube-scheduler
- kube-controller-manager

**Node**
- kubelet
- kube-proxy
- コンテナランタイム


## コントロールプレーン is 何
いわばクラスター全体の管理を担う脳全体です。
状態を監視、管理し、各コンポーネントが連携してクラスターの望ましい状態を保ちます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379725/89f9b1f0-2754-1a29-03e9-6ed687c09651.png)


### kube-apiserver is 何
Control Planeの中でも最も重要でクラスターへのすべての操作を受け付け、処理します。
APIリクエストの処理とクラスターの状態管理を専門に担当します。
ユーザやKubernetes クラスターとやり取りするためのインターフェースとも言えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379725/9b2899a3-c071-5045-686d-cff4a2842763.png)


### etcd is 何
分散Key-Value Storeで、全てのクラスターの構成情報のデータを保存します。
Key-Value Store = 要するにデータを「キー」と「値」のペアで格納するDBです。
このキーと値のペアでKubernetesクラスターの設定情報や状態を管理しています。
Kubernetesはkubectlというコマンドでリソースを操作することになりますが、そのコマンド操作をして構成情報が変更、更新された場合にはその情報をetcdに保存する、ということです。



### kube-scheduler is 何
Kubernetesクラスター内でPodをNodeに割り当てる役割を担っています。
Pod？と思った方、ドラゴンボールでサイヤ人が乗っているあの宇宙船ポッドを想像したのではないでしょうか？


はい、想像としてはかなり似たようなものと思っていただいて大丈夫です。
Podとはコンテナとストレージボリュームの集合体です。
「Pod = コンテナ」はほぼ同義です。
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379725/6f8d1ca5-a41b-575f-8e05-afaf705e6525.png)
> 引用元: https://kubernetes.io/ja/docs/tutorials/kubernetes-basics/explore/explore-intro/

kube-schedulerに話を戻しましょう。
kube-schedulerはPodをNodeに割り当てる役割を担っているとお話しました。
新しいPodが作成されたときに、どのNodeに割り当てるかを選択します。

scheduler(スケジューラ)なので、「ある何かしらのイベントを検知して動作するもの」です。
以下の図のようなイメージです。
1. kube-apiserverがClusterを監視している
2. ClusterにPodが作成されるとkube-apiserverが検知する
3. kube-apiserverはkube-schedulerへ通知する
4. kube-schedulerはPodを最適なNodeへ割り当てる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379725/44235f8a-d75f-3543-0cea-9142a02e6c1b.png)

### kube-controller-manager is 何
Controll Plane上には複数のコントローラープロセスが実行されています。
例えばコントローラがPodをデプロイする際には以下のようなコントローラーが特定のタスクを実行してクラスタの状態を管理します。
- ReplicaSet: 
    - 指定されたmanifestファイルを監視し、指定された数のPodが常に稼働していることを確認する
    - Pod数が指定された数よりも少ない場合、新しいPodを作成する
    - Pod数が多すぎる場合は、余分なPodを削除する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379725/df45156f-bc11-ee76-4a99-cc328d7d62b1.png)

- Deployment:
    - 指定されたmanifestファイルに基づいてReplicaSetを作成しReplicaSetがPodを作成する
    - 新しいバージョンのアプリケーションをデプロイする際に、新しいReplicaSetを作成する
    - 新しいPodを徐々にデプロイし、古いPodを順次削除することでローリングアップデートを実現する

DeploymentとReplicaSetは親子関係にあり、Deploymento がReplicaSetの親リソースであり、ReplicaSetはPodの親リソースとなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379725/f5604ed7-1fda-a2d4-246b-3f94fc7b0c9f.png)

上記の各コントローラの実行を管理するのがkube-controller-managerの役割です。



ここまでがControll Planeに関する内容について解説してきました。
次にNodeの話をしましょう。

## Node is 何
Kubernetesクラスタ内の物理または仮想マシンです。
NodeはPodを実行するためのホストです。
例えばAWSを例にするとEC2のような仮想マシンがあり、その上でPodが稼働している、と言えばわかりやすいでしょうか。

## kubelet is 何
Node上で実行されるエージェントです。
ユーザがkube-ctlというコマンドを使用して指示すると、kube-apiserverがそのリクエストを受け取り、kube-apiserverからNodeに割り当てられたPodの定義情報を取得します。
その定義情報には実行するコンテナイメージ、必要なリソース、環境変数、ボリュームのマウント情報などが含まれており、kubeletはコンテナランタイムというものを使用してコンテナを作成します。

## コンテナランタイム is 何
コンテナランタイムはコンテナを実行する役割のソフトウェアです。

## kube-proxy is 何
kube-proxyはServiceリソースを介して、クラスタ内のPodへのトラフィックをロードバランシングする役割を持ちます。
またiptablesやIPVS(IP Virtual Server)などのネットワークルーティングを使用してルーティング設定をします。
これによりServiceの仮想IP(ClusterIP)に送信されたトラフィックが適切なPodにルーティングされます。

kube-proxyはノード上で実行されるServiceの仮想IPアドレスへのトラフィックを受信し、それを適切なPodに転送します。
これによりServiceの仮想IPへのトラフィックがPodに適切に分散されます。


## まとめ
Kubernetesの各コンポーネントについてまとめてみました。
[つくって、壊して、直して学ぶKubernetes入門](https://amzn.to/3VOA1xE)を読んでいて非常にわかりやすい例があったのですが、
> kube-apiserverはRESTで通信可能なAPIサーバであり、etcdは分散型のキーバリューストアであり、いわゆるデータベースの一種です。
Controll PlaneはAPIサーバとデータベースでできている、と思うと一般的なWebサービスのような親近感が湧きませんか？

非常に湧きました。
ユーザがからのリクエストを受けてetcdにデータを保存または取得などをしている、などと考えるとSQLを使ってデータそInsert, Selectしている、と置き換えると非常に理解しやすいですね。

```
$ kubectl get pod
```
上記のコマンドを実行することで、etcdに保存してあるデータをkube-apiserverを通じて取得できるということです。


## 参考
[つくって、壊して、直して学ぶKubernetes入門](https://amzn.to/3VOA1xE)
[Kubernetesをだいたい理解するまで](https://zenn.dev/gege/articles/80b55c345cc1cb)