【図解】GKEで始めるKubernetes(k8s)の初歩の初歩（基礎知識編）

# 0.はじめに

以前からコンテナオーケストレーションツールに興味はあったものの、触る機会が無かったのでこちらの書籍を元に学習してみたので、kubernetesの仕組みを理解するための要点だけを図にまとめてみました。
[ハンズオンで分かりやすく学べる Google Cloud実践活用術 データ分析・システム基盤編 Google監修](https://www.amazon.co.jp/%E3%83%8F%E3%83%B3%E3%82%BA%E3%82%AA%E3%83%B3%E3%81%A7%E5%88%86%E3%81%8B%E3%82%8A%E3%82%84%E3%81%99%E3%81%8F%E5%AD%A6%E3%81%B9%E3%82%8B-Google-Cloud%E5%AE%9F%E8%B7%B5%E6%B4%BB%E7%94%A8%E8%A1%93-%E3%83%87%E3%83%BC%E3%82%BF%E5%88%86%E6%9E%90%E3%83%BB%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E5%9F%BA%E7%9B%A4%E7%B7%A8-Google%E7%9B%A3%E4%BF%AE/dp/429610909X/ref=asc_df_429610909X/?tag=jpgo-22&linkCode=df0&hvadid=529847636104&hvpos=&hvnetw=g&hvrand=13323383314242899595&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009457&hvtargid=pla-1351981045608&psc=1&th=1&psc=1)

本記事ではネットワーク、Docker等の前提知識は割愛します。
画像については、引用はせずdraw.ioで描いてるので、見づらい部分があればコメントいただければ幸いです。

# 1.kubernetesの特徴

kubernetesはコンテナオーケストレーションツールであり、主に以下のような特徴があります。

- コンテナを動かすホストである
- コンテナをどこに配置するか等のスケジューリングが行える
- コンテナ間のサービスディスカバリー（名前解決と通信）
- コンテナ間のロードバランシング
- オートスケーリング（コンテナ数や１台あたりの性能増減）
- ローリングアップデート（少しずつ新しいコンテナへ入れ替えていく）

# 2.kubernetesの内部アーキテクチャ

次項のネットワーキング、デプロイフローを見る前に、まずはkubernetesの内部を見ていきます。

![Kubernetes内部アーキテクチャ.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2332281/3740b553-2e49-94a3-14ef-e07b29f37b6d.png)

## ControlPlanes

上図ControlPlanes内の機能は以下の通りです。

### Control plane

後述のNodeを制御するための基盤であり、kube-apiserver、kube-controller-manager、kube-scheduler、etcdの４つのコンポーネントで構成されています。

### kubectl

kube-apiserverにリクエストを送信するためのCLIツール。
Kubernetesクラスターは、このCLIツールを使うか、マニフェストと呼ばれるyaml形式のファイルによって設定できます。

### kube-apiserver

Kubernetesの各APIを提供するコンポーネント。
kubectlからのAPIリクエストや他のコンポーネントからもアクセスされます。

KubernetesのAPIリソースは以下のようなものがあります。
- Workload Resources
- Service Resources
- Config and Storage Resources
- Authentication Resources
- Authorization Resources
- Policy Resources
- Extend Resources
- Cluster Resources
- Common Definitions
- Common Parameters

reference: https://kubernetes.io/docs/reference/kubernetes-api/

### kube-controller-manager

DeploymentコントローラーやReplicaSetコントローラーといった、APIリソースごとに実際の処理を行うコントローラーを１つのバイナリファイルにまとめたもの。

### kube-scheduler

新たに作られたPodのうち、Nodeが割り当てられてないものに対し、どのNodeを割り当てるかをkube-apiserverにリクエストしてスケジューリングする。

### etcd

キーバリューストア（KVS）となっていて、Kubernetesクラスターの全ての情報を保存している。

## Nodes

上図Nodes内の機能は以下の通りです。

### Node

Podを実行できる環境、ワーカーマシン。
クラスター内に複数配置でき、NodeごとにNICが割り当てられるため、Node間の通信も可能です。

### kube-proxy

各Node上で動作するネットワークプロキシー。
別Nodeもしくは外部からClusterIP・NodePort宛にリクエストがあった場合、各Podに転送します。

### kubelet

Dockerやcontainerdといったコンテナランタイムと連携して、Podの起動や停止を行う。

### Pod

１つ以上のコンテナで構成されるKubernetesの基本となるリソース。
1つのPod内に複数コンテナを設置する場合、ネットワークインターフェースを共有して1つのIPアドレスを持ちます。

### アドオン

Node上で動作する代表的なアドオンは次のようなものがあります。

- kube-dns： ServiceリソースのDNS名〜PodのIPアドレスの名前解決をするコンポーネント
- Reconciliation loop： マニフェストの定義と現在の状態を比較して、差分を是正するコンポーネント


# 3.kubernetesのネットワーキングを理解する

ここでは４つの図からkubernetesのネットワークを見ていきます。
但し、プロキシモードの設定によって図の構成は変わってくるのでご注意ください。
https://kubernetes.io/ja/docs/concepts/services-networking/_print/#virtual-ips-and-service-proxies

こちらのサイトも分かりやすかったので参考になると思います。
https://www.netone.co.jp/knowledge-center/netone-blog/20210715-01/

## Serviceリソース
### クラスター内部での通信（ClusterIP）

kubernetesはServiceリソースに対してIPアドレスを割り当てており、これをClusterIPと呼びます。
ClusterIPを使うことで、クラスター内部での通信を実現できます。例えばPod間の通信です。

![Kubernetes ClusterIP.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2332281/036dd7a0-e700-62c7-8f63-e43440ae6b90.png)


### クラスター外部からの通信（NodePort）

Serviceの公開タイプに`NodePort`を設定した場合の説明です。
https://kubernetes.io/ja/docs/concepts/services-networking/service/#nodeport

NodePortはクラスター外部からのアクセス向けに各NodeのIPアドレスを提供します。
トラフィックを受信すると、kube-proxyの設定に従ってPodへの転送を行います。
また、kube-proxyはパケットフィルタリング機能もあるようです。
https://kubernetes.io/ja/docs/concepts/overview/components/#kube-proxy

![Kubernetes NodePort.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2332281/abf3e6f8-2fbf-10f9-cce4-bf5a26aabb4a.png)


### LoadBalancerによるL4レベルのロードバランシング

Serviceの公開タイプに`LoadBalancer`を設定した場合の説明です。
https://kubernetes.io/ja/docs/concepts/services-networking/service/#loadbalancer

トラフィックを受信したロードバランサーは、各NodeのIPに負荷分散しながら転送します。

![Kubernetes LoadBalancer.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2332281/f33c5ff4-f674-fc15-fc37-25b7ab9839a7.png)


## Ingressリソース
### IngressによるL7レベルのロードバランシング

Ingressを使うことで、パス単位で振り分けるService・Podを設定できます。
使うにはIngressコントローラを用意します。
https://kubernetes.io/docs/concepts/services-networking/ingress/

![Kubernetes Ingress.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2332281/478e67f1-e29b-16ff-017b-026767e75cd1.png)

上図の例では、
https://example.com/video にアクセスすると、kube-proxyの設定に従って紫のPodへ転送します
https://example.com/article にアクセスすると、kube-proxyの設定に従って黄のPodへ転送します
https://example.com/shop にアクセスすると、kube-proxyの設定に従って緑のPodへ転送します

# 4.kubernetesのデプロイフローを理解する

まずは図に登場するリソースの説明です。

### ReplicaSet

Podのレプリカ（複製）を管理するリソースです。（AWSでいうAMIに近いかもしれません）
ReplicaSetはServiceリソースと組み合わせて負荷分散、水平スケーリング（HorizontalPodAutoScaler）するときによく使われます。
ReplicaSetは単体で使うことは少なく、Deploymentに内包される形でよく使われます。

### Deployment

DeploymentはReplicaSetとPodを抽象化したものです。
Deploymentを作成すると、対応するReplicaSetとPodが自動的に作成されます。
直接ReplicasetとPodを操作せずにDeploymentを利用するメリットは、
ローリングアップデート（古いReplicaSetのPod数と新しいReplicaSetのPod数を調整しながら少しずつPodを入れ替える）やロールバックが簡単にできる点です。

---
ここではPod作成を例に図にしてみます。

![Kubernetes デプロイフロー.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2332281/87b93bbb-bde1-83fb-d51f-e14e25463531.png)

次に示す順でPodの作成処理が行われます。
1. ユーザーがkubectlでDeployment作成をリクエストorマニフェストの更新
2. DeploymentControllerがDeploymentの作成を検知し、ReplicaSetを作成
3. ReplicaSetControllerがReplicaSetの作成を検知し、Podを作成
4. kube-schedulerが新規Podを検出し、Podを実行するNodeを指定
5. 指定されたNodeのkubeletが検知し、Pod（コンテナ）を起動

# 5.GKE（Google Kubernetes Engine）の特徴

KubernetesのマネージドサービスであるGKEは次のような特徴があります。

- 構築するのが難しいとされるControl planeの管理が不要
- OSSであるKubernetesは四半期に一度マイナーバージョンがリリースされるが、これを自動アップデートする機能がある
- 上記に加え、Control planeやNodeのソフトウェアを自動でアップデートする機能がある
- Node pool（同じ構成のNodeのグループ）という仕組みにより、ダウンタイムを最小限に抑えながらKubernetesのアップデートができる
- Node poolのサイズを自動スケールするCluster Autoscaler
- Node auto-repairという、GKEが修復が必要と判断したNodeを検知して、自動的にドレイン（修復が必要なNode上のPodを別の正常なNodeに追い出す）して、Nodeを再作成する機能がある。

# 6.最後に

次回はRailsアプリケーションをGKEにデプロイするところまでをまとめてみます。

Next→ Comming soon