Coursera の "Architecting with Google Kubernetes Engine: Foundations" を受講したメモ

面白かったところ、勉強になったところだけメモる。


## GKE のすごいところ

自前でkuberntes使うよりすごいところは、


- GKE uses a container optimized operating system. These operating systems are maintained by Google, they are optimized to scale quickly and with a minimal resource footprint.
- GKE's auto upgrade feature can be enabled to ensure that your clusters are automatically upgraded with the latest and greatest version of kubernetes. 
-  If you enable GKE's auto repair feature, the service will automatically repair unhealthy notes for you. 
- GKE supports scaling the cluster itself.
- GKE seamlessly integrates with Google clouds build and container registry. This allows you to automate deployment using private container images that you've securely stored in container registry.



## Kubernetes のコンセプト

###  Object モデルを採用

- kubernetes の管理するものは　Object によって表現される。Objectは、attributes, stateを持ち、これらを見たり変更したりできる。例えば、

    - the resources that are available to them
    - the policies that affect their behavior


### Declarative Managementの原則
- 内部的には、watch-loop を利用してこれを実現している

- Object specは、そのobjectのあるべき姿を現し、Object statusは現在のstate(これはcontrol planeから提供されるもの)。
    - control planeがこれらのgapを埋めるために働いてくれる。

---

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534442/e436f9be-28e5-1da3-5827-69314a3435df.png)

- 最小単位のobjectは(コンテナではなく)pod。
- podごとに、(IPアドレス, ポート)が提供される。同一pod内のコンテナ同士は、localhost(127.0.0.1)指定でやり取りできる。
- podごとに、コンテナ間でshareされるshared volumeを指定できる。

## Kubernetes Plane's Component

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534442/b7a740cc-5936-7ecb-a8ea-fad7b15e0cf3.png)

- etcd は、clusters database。持っているデータとしては、
    - clusterのcurrent state
    - cluster configuration data
    - dynamic information, such as what nodes are part of the cluster, what pods should be running and where they should be running

-  Kube-scheduler は、scheduling pods onto nodes ことに責任を持つ。
    -  pod の必要条件を評価し、podを立てるのに最適なpodを選択する。
    -  nodeにpodを立てる作業そのものは行わない。代わりに、新しく作りたいpod objectに、それを立てたいnodeの名前を書き込む。
    -  kube-schedulerは、全てのnodeのstateを知っている。これにより、podを立てるのにふさわしい&条件を満たすnodeを決めている。条件とは例えば
        -  「nodeに最低どれだけのメモリが必要だ」
        -  affinity specifications (podのグループが同一のnodeに立つことを指定)
        -  aiti-affinity specifications　(あるpodとあるpodは同一のpod上に立ってはいけない)

- kube-controller-managerは、各objectを制御している
    - kube-api-serverを通して、clusterのstateを監視する
    - もしclusterがdesired stateではなかった場合、変更を試みる。
    - objectは、controllerと呼ばれる制御ループによって管理されており、kube-controller-managerは、シングルプロセスで複数のcontrollerを走らせている。controller による制御が発動するonjectは例えば以下が存在する。
        - `deployment` `StatefulSet`, `DaemonSet`, `Job`, `ReplicaSet`, `Replication Controller`
        - See: https://www.coursera.org/learn/foundations-google-kubernetes-engine-gke/supplement/Scs0m/controller-objects-to-know-about

- Kube-cloud-manager は、underlying cloud providersと相互作用するcontrollersを管理する。
    - For example, if you manually launched a Kubernetes cluster on Google compute engine, kube-cloud manager would be responsible for bringing in Google cloud features like load balancers and storage volumes when you needed them. 

- kubeletは、Kubernetes agent。
    - kube-APIserverがあるnodeでpodを立てたい場合には、そのnodeのkubeletと接続する。
    - container runtime(イメージからコンテナを起動させることのできるソフトウェア)を使い、コンテナを起動したり、そのライフサイクルを管理したりできる。
        - Linux distribution that GKEは、Containerd (=runtime component of Docker)を使用している。

- Kube-proxy'は、 network connectivity among the pods in the clusterを管理する。
    - In open source Kubernetes, it does so using the firewall capabilities of IP tables, which are built into the Linux kernel. 

### GKEのkubernetes

GKEの嬉しいところ。

- control planeには課金されない
- GKEなら、nodeを自分で立てなくてよくなる
- nodeはhour単位で課金される。
- Node poolを指定できる。
    -  automatic nodal creates, automatic node repairs, and cluster auto-scaling をnode poolレベルで指定できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534442/b0ced1f8-6c37-c0cc-6aa4-0b373733f7b8.png)
regional clutserでも、外部とやり取りするAPIエンドポイントは一つ。
なお、regionalにすると、各zone内のpodsの数は同一になる。
(zonal cluster<-> regional cluster の設定切り替えは後からできない)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534442/9c2bfb0b-535b-a86d-6d68-dad6dba37352.png)

### KubernetesでのObjectの管理方法

- manifest file(yaml形式かjson形式)で指定する
    - 一つのmanifest file内に複数のobjectを定義しても良い。
    - nameを持つ同一kindのobjectを複数定義することはできない。ただしnamespaceが違えば同一cluster内でも同一nameを複数定義できる。
    - labelはkey-value形式で宣言できる。「ラベルのあるキーが特定のvalueを持つobjectだけを取得する」といったユースケースが存在する。
        - 例えば、`kubectl get pods -selector=app=nginx`とか
#### uid
kubernetesは、clusterのlifecycleを通してユニークなid(UID)をそれぞれのobjectに割り当てる。

#### namespace

cluster内で複数のnamespace(スコープ)を定義できる。(例えばtest, stage, prodとかね)
namespaceが違えば同一cluster内でも同一nameを複数定義できる。また、namespaceごとにresouceの上限quotasを定義することもできる。

デフォルトでcluster内には、3つのnamespaceが用意されている。


- `Default`
    - 明示的にnamespaceが指定されていないworkload resouceはデフォでこのスコープ内に作られる
- `Kube-system`
    - kubernetesのシステム自身によって作られたオブジェクトはこのスコープ内に入っている
    - kubectlコマンドを使う際にこのnamespaceを含めるには明示的に指定しないといけない
- `Kube-public`
    - 全てのuser(namespaceもまたぐ??)からread可能なobjectが入る
    - cluster内で走る全てに共通のinformationを伝搬するために使用するツール(?)である


manifestファイル内にnamespaceをembedするのは賢い方法ではない(異なるnamespaceに同一のobjectを作るためにnamespaceの数だけmanifest fileを作成しなければならなくなる)。
それよりかは、manifestファイル内にはnamespaceを指定せず、kubectlコマンドを使ったオブジェクト作成時に`kubectl -n your_namespace apply -f mypod.yaml`の様な形でnamespaceを指定する方がより柔軟である。

---

以下、主要なobjectを紹介する。
階層構造は、`type has many kinds`


#### Pod Kind

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534442/29a833b5-1de2-0890-76a3-ef158b583fd6.png)

#### Deployment Kind

controllerの一種。long-lived software componentの定義にぴったり。(=webサーバみたいにずっと起動しているもの)
タスク実行のためのコンテナを立てる場合にはJob controller を、定期的なタスク実行のためには CronJob controllerを使用しましょう。
(podの中でコンテナを指定するのではなく)deploymentにおいて、pod名とreplica数と**podの中で立てるコンテナ**を指定することで、冗長で水平スケール可能な構成を作ることができる。

順序としては、
1. cube scheduler schedules pods for a deployment
2. cube scheduler notifies it to cube AP server.
3. These changes are constantly monitored by deployment controller. (The deployment controller monitors and maintains the current state.) If one of those Pods fails, the deployment controller will recognize the difference between the current state and the desired state and try to fix it by launching a new Pod. 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534442/be209e64-d0ca-efa8-e340-bd7dd2b5b11c.png)

(⏫replicasはpodのレプリカ数。specで指定されるcontainersは、**一つのpodの中で走らせられるコンテナ**を指定している。podの指定とpodの中で走るコンテナの指定を両方しているのだ)

ちなみに、実はDeploymentオブジェクトは`ReplicaSet`オブジェクトを作成しており、実質はこれがpodsを管理している。

#### Service Kind

An abstract way to expose an application running on a set of Pods as a network service. 特定のpodsへのload-balanced accessを提供する。

以下の3つの主要なtypesが存在する。

- `ClusterIP`
    - Exposes the service on an IP address that is only accessible from within this cluster. This is the default type.
- NodePort
    - Exposes the service on the IP address of each node in the cluster, at a specific port number.
- LoadBalancer
    - Exposes the service externally, using a load balancing service provided by a cloud provider. 
    - GKE では、regional　Network Load Balancingの設定を提供する。global HTTPS load balancing へのaccessの設定を得るためには、Ingress Objectを使用する。