kubernetes徹底入門



# はじめに
kubernetesは一般常識になってきているこのご時世なのでざっとまとめてみました。
個人的メモです。


# 4分類10種類のリソース


まず、よく出てくる以下の用語を覚えましょう

| 分類 | リソース |
|:-:|:-:|
|  ワークロード | Pod, ReplicaSet, Deployment, StatefulSet  |
| サービス  |  Service, Ingress |
| 設定  |  ConfigMap, Secret |
| ストレージ  | PersistentVolume, PersisentVolumeClaim  |


# (0) minikube

- まず、kubernetesを勉強していく上で環境が必要になります
- minikubeは１台のPC上で仮想的にk8s環境を構築することができる
- k8sはLinux上でコンテナクラスタを構築するためのソフトウェアなので基本的にLinuxでしか動作しない

minikubeのインストール(on Mac)

```
$ brew install minikube
```

minikube起動

```
$ minikube start
```


# (1) Pod (Point of Delivery)

- Podは内部IPアドレスを持つ1つの仮想マシンのような存在
- Pod単位で起動と破棄され、永続データは保持できない一時的な存在
- k8sはコンテナを直接管理するのではなくPodを管理する
- コンテナを直接 WorkerNode にはデプロイできない→ 「必ずPodで抽象化する」

```pod.yml
apiVersion : v1
kind : Pod
metadata :
   name : nginx
   nanmespace : default
   labels :
        app : nginx
        env : study
spec : 
    containers :
    - name : nginx
      image : nginx:1.17.2-alpine
```


- `apiVersion` : Podの場合は`v1`
- `kind` : Pod
- `metadata.labels` : key / valueのペア。グルーピングするために使うことができる 
- `spec.containers.name` : 名前
- `image` : イメージ名 


---

api versionの全て表示

```
$ kubectl api-versions
```

Podの作成

```
$ kubectl apply -f pod.yaml
```

PodのIPアドレスを調べる

```
$ kubectl get pod -o wide
```

コンテナに入る

```
$ kubectl exec -it Pod名 sh

#コンテナから出る
$ exit
```

Podの削除

```
$ kubectl delete -f pod.yml
```

雛形を作る

```
$ kubectl run mydeploy --image nginx --dry_run=client -o yaml > pod.yaml
```

# (2) ReplicaSet(RS)


- 指定したPodを起動し、その数を維持し続けるリソース
- アプリケーションのバージョン毎にRSを生成
- Podの雛形を定義し、Label Selectorという方法で管理対象を選択してRSに制御してもらう
- RSは`spec` に`replicas`, `selector`, `template`の3つを指定 (⭐️)
- replicas : Podの複製数
- selector : label selector (`matchLabels`, `matchExpressions`)
- template : Pod templateを指定


```replicas.yml
apiVersion : apps/v1
kind : ReplicaSet
metadata :
    name : sample
spec :
    replicas : 3
    selector :
        matchLabels :
            app : web
            env : study
    template :
        metadata :
            name : nginx
            labels :
                app : web
                env : sudy
            spec :
                containers :
                - name : nginx
                  image : nginx:1.17.2-alpine
```

- `spec.selecor.matchLabels` : 指定したLabelと全て一致したものが対象になる。他には`machExpressions`


```
#RSの取得
$ kubecctl get rs

replica数を減らす
$ kubectl scale --replicas=1 -f replicas.yml
```


#### DaemonSet

- ReplicaSetの特殊形
- 全ノードに1Podずつ配置→レピリカ数などは指定できない
- ユースケース
    - 各Podが出すログを収集するfluentdや各Podのリソース使用状況やノードの状態をモニタリングするDatadogなど、全Node上で必ず動作している必要のあるプロセスで利用

# (3) Deployment

- replicasetを生成・管理(こやつはPodを直接管理していない)
- ローリングアップデート
- ロールバック
- `replicas`, `selector`, `revisionHistoryLimit`, `strategy`, `template`
- deploymentを変更した際は、新しいRSを作成してPodを置き換えていく

```deploy.yml
apiVersion : apps/v1
kind : Deployment
metadata : 
    name : nginx
spec :
    replicas : 2
    selector :
        matchLabels:
            app : web
            env : study
    revisionHistoryLimit : 10
    strategy :
        type : RollingUpdate
        rollingUpdate :
            maxSurge : 1
            maxUnavailable : 1
    template :
        metadata :
            name : nginx
            labels :
                app : web
                env : sudy
        spec :
            containers :
            - name : nginx
              image : nginx:1.17.2-alpine
```


- `minReadySeconds` : Podが作成されてから使用可能な状態になるまでの待ち時間を指定、デフォは0s
- `paused` : Deploymentの変更をポーズさせるかを指定。通常は指定する必要はない
- `progressDeadlineSeconds` : Deploymentの処理の最大処理時間を指定する、デフォは600s
- `revisionHistoryLimit` : リビジョンの履歴の保持を指定する、デフォ10
- `strategy` : Podを置き換える際の戦略,デフォはRollingUpdate
- `maxSurge` : replicasで指定した数よりも増やしていいPodの最大数
- `maxUnavailable` : replicasで指定した数よりも減らしていいPodの最大数



RollingUpdate

```yaml
strategy:
    type : RollingUpdate
    rollingUpdate :
        maxSurge : 50%
        maxUnavailable : 10%
```

*Deploymentはこの`maxSurge`と`maxUnavailable`を元にRolling Updateを行う

```
$ kubectl apply -f deploy.yml

$ kubectl get all

$ kubectl rollout history deploy/nginx

#直前に戻す
$ kubectl rollout undo deploy/nginx

#確認
$ kubectl rollout history deploy/nginx

#削除
$ kubectl delete -f deploy.yml

#ロールアウト履歴確認
$ kubectl rollout history TYPE/NAME

#ロールバック
$ kubectl rollout undo TYPE/NAME --to-revision=N
```


# (4) Service

- IPアドレスが変動するPodに対してクライアントがアクセスするために作成するオブジェクト
- 外部に公開
- L4ロードバランサ
- エンドポイントとポートを指定してあげれば通信をPodに流してくれる
- Serviceを動かすには、転送先となるコンテナ(Pod,RS, Deployment)が必要

**①ClusterIP**

- クラスタ内からのみアクセス可能な仮想IPが割り振られる
-　 デフォルトはこれ

**②NodePort**

- k8sクラスタに所属していない端末からPodに通信することができる
- 公開用ポートはデフォルトで30000-32767から採番
- クライアントがノードのIPアドレスと公開用ポートに送った番号はPodのポート番号に変換されてPodにリクエストが送信される
- マニュフェストでは、spec.ports.nodePortで記述
- NodePortは外部のネットワークへポッドを公開できるが可用性が十分ではないため本番環境には適さない

**③LoadBlancer**

- NodePortのアクセス範囲に加えクラスタ外からも代表IPアドレスとプロトコルのデフォルトポート番号でアクセスできる
- LoadBalancerは可用性であり、HTTPやHTTPSのデフォルトportが利用できるので本番環境に適している

**④ExternalName**

- クラスタ内から外部のIPアドレスを名前でアクセスできる



```service.yml
apiVersion : v1
kind : Pod
metadata :
    name : nginx
    labels :
        app : web
        env : sudy
spec :
    containers :
    - name : nginx
      image : nginx:1.17.2-alpine

---
apiVersion : v1
kind : Service
metadata : 
    name : web-svc
spec :
    type : NodePort
    selector : 
        app : web
        env : sudy
    ports :
    - port : 80
      targetPort : 80
      nodePort : 30000
```

- `nodePort` : ノードが待ち受けるポート (クラスタ外からの通信)
- `port` : Serviceが待ち受けるポート (クラスタ内からの通信)
- `targetPort` : Podが待ち受けるポート(他のPodからの通信)

*k8sでは「30000」に来た通信を「80」に変換してPodに届ける

```
$ kubectl apply -f service.yml

#ブラウザからアクセス
http://<IP>:30000
```


# (5) StatefulSet

- DBなどのステートフルなアプリケーションのためのリソース
- Deploymenでレプリカされた場合にPodはランダムのIDが付与されるのに対してstatefulSetはPodは順序づけされる
- Podが同名でレプリカされるので永続ボリュームを引き継ぐ


**いつ使用するか？**

- 安定した永続ストレージが必要な時
- 安定した一意のネットワーク識別子が求められた時
- 規則的で自動化されたローリングアップデートが必要な時
- StatefulSetはvolumechaimTemplateで指定されたchaimそれぞれに1つずつPVが作成され、Podにマウントされる
- StatefulSetが削除されてもPVCは削除されない
- 例えば、DBサーバーとしてPodを立てる際には、StatefulSetを使用(データが消失してはダメだから)
- 逆にAPIサーバーを立てるなら。永続ストレージは必要ない→ Deploymen

```
apiVersion : apps/v1
kind : StatefulSet

spec : (ほぼDeployment)
    updateStrategy :
        type : RollingUpdate
    serviceName :frontend 
    template :
    volumeChaimTemplates :(PVCテンプレート)

```

# (6) Ingress

- 外部公開
- パスベースのLB
- SSLターミネーション

```ingress.yml

apiVersion : networking.k8s.io/v1beta1
kind : Ingress
metadata :
    name : frontend
spec :
    rules :
    - http
      paths :
      - path : /
        backend :
            serviceName : web-svc
            servicePort : 80
```


```
$ kubectl apply -f ingress.yml
$ kubectl get ing, svc, deploy
```

# (7) PersisentVolume

- 永続データの実体
- 永続化ボリューム
- クラスタにボリュームを登録するだけのオブジェクトなので、Podから利用するにはPVCを定義する

```pv.yml
apiVersion : v1
kind : PersistentVolume
metadata :
    name : storage
spec :
    storageClassName : host (ストレージの種類)
    accessModes : ["ReadWriteMany"]
    capacity :
        storage : 1Gi
    persistentVolumeReclaimPolicy : Retain (削除時動作を定義)
    hostPath : :
        host : "/data/storage"
        type : Directory
```


- accessModes : `ReadWriteOnly`, `ReadOnlyMany`, `ReadWriteMany`
- persistentVolumeReclaimPolicy : `retain`, `delete`, `recycle`


# (8) PersistentVolumeClaim

- 必要なPVがどんなものかを定義
- データ保存先はPVで抽象化して隠蔽


```pvc.yml
apiVersion : v1
kind : PersistentVolumeClaim
metadata :
    name : volume-claim
spec:
    storageClassName : slow
    accessModes : ["ReadWriteMany"]
    resources :
        requests :
            storage : 1Gi
```

# その他

### Taint

- Node Affinityと逆の機能でNodeへPodをスケジュールさせないための機能
- PodをNodeにスケジュールさせない / 実行させない仕組み

### Toleration

- PodがNodeについているTaintを容認するかを指定する機能

### cordon / uncordon

- 指定したNodeにスケジュールさせないようにするための処理

### drain

- Nodeを停止させる前準備として動作しているPodを別Nodeへ退去させるコマンド

### PodDisruptionBudget

- Podの最小の有効状態や最大の無効状態の数を指定する
- Podの管理対象はLabelSelectorで指定する


◆ spec.maxUnavailable : Eviction実行時にPodを無効状態にしていい最大数を指定する、絶対値か百分率で指定する
◆ spec.minAvailable : Eviction実行時にPodを無効状態にしていい最小数を指定する、絶対値か百分率で指定する
◆ spec.selector : このBudgetを適用する対象のPodを選択するLabelSelectorを指定

### Service Account

- 作成や削除、権限の付与などをkubectlを通して行う


### RBAC

### Affinity

- Podのスケジュールについて条件を指定

①NodeAffinity : NodeにあるLabelを元にPodのスケジュール
②PodAffinity / Anti-Affinity
③Topology Key

### Annotation

- オブジェクトに対してKey / valueの形式でmetadataを登録できる仕組み
- labelとほぼ同じ機能だが、selectorなどで使用されない

# kubernetesコンポーネント

### etcd

- クラスタ情報の保管庫
- Key-Valueストア


### kube-scheduler

- Podの要求しているリソースやNodeのリソースの使用率などをみて適切なNodeを１つ選択し、PodをNodeに紐付ける
- Podに配置決めのみ行う
- `scheduling Framework` : Filter（割り当て可能な場所を見つける）とScore()が主にNodeの決定に影響している

### kube-apiserver (C-planeの親玉)

- (1)ユーザー認証 
- (2)Validate Request 
- (3)Retrieve data 
- (4)Update etcd 
- (5)scheduler 
- (6)kubelet

### kube-conroller-manager

- k8sのオブジェクトを処理するコントローラーを実行
- ノード監視が主な仕事
- deployment, replicasett, cronjob, service(オブジェクトに対して１つのコントローラー)



### kubelet (各NodeにあるAgent的なもの)

- Podの起動や停止処理を行う、Worker Nodeで稼働するデーモン
- Podを起動・管理するエージェントとも言える
- kube-schedulerによって紐づけられたPodをkubeletが認識して、そのPodを自身のNodeで起動させる
- Podやノードの状態を監視して「apiserver」にレポートを送信
- Node上にあるCNIプラグインを実行
- Static PodをMIrrorPodとしてAPI Serverに登録

#### ※CNIプラグイン

- Podをcluster Networkに参加させるために必要な処理を実行
- (PodにNICをINSERT, NICにIPを割り当てる)

#### ※ Static Pods

- kubeletによって直接管理されるPod
- XXXX

### kube-proxy

- コンテナのネットワーク管理
- 実体はiptablesのルールを発行し、パケットの制御している
- Pod間通信、ルーティング