Kubenetes 登場人物が分からない...

# 目的
Kubernetes の登場人物をもう少し理解する。

[公式ドキュメント](https://kubernetes.io/ja/docs/home/)を読んでも Pod など分かり易い登場人物はなんとなく理解できましたが、Controller manager? etcd? 的な感じでしたので、もう少しかみ砕いたドキュメントで理解を深める。

# 手段
どこかのテック記事を参照

#### 第一回
- PDCAを回そう(全体の荒い学習→テスト→詳細の再学習)


#### 第二回
サンプル環境は以下の通り。

- サーバ台数：3台(コントロールプレーンx1, ワーカー x2)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474478/c6188826-da16-cef6-5310-1f225927bdef.png)
[引用](https://thinkit.co.jp/article/18188)

登場人物を整理する。大きく２つ。
- コントロールプレーン
    - kube-api-server : リソースの管理。設定変更もこの人が受ける。
    - kubectl コマンド : k8s の CLI コマンド
    - kube-controller-manager : リソースの登録、操作。(この人は kube-api-server と連動して良い感じに動いてくれるのか？)
    - etcd : 全情報のデータストア
    - kube-scheduler : Podのノード割り当て。(この人はなんとなくイメージ湧きますね)
    - containerd : コンテナランタイム。docker サポート終了するらしいので、containerd に切り替える必要がありそうですね。
- ワーカー
    - kubelet : Podの起動と停止。(kube-api-server と通信する)
    - kube-proxy : コンテナ環境のネットワーク管理
    - containerd : コンテナランタイム

規模が大きくなれば、ワーカー増加は想像できる。コントロールプレーンは HA 構成を取れる。

kubeadm は Kubernetes コミュニティが公式に提供する簡易な構築ツール。Kubernetes を構成するコンポーネントや証明書、各種設定ファイルを自動で生成し、素早く Kubernetes クラスタを作成できる。

kubelet は Kubernetes の CLI ツール。

インストールの流れは以下の通り。
1. コンテナランタイムのインストール(コントロールプレーン及びワーカー)
1. kubeadm, kubelet, kubectl のインストール(コントロールプレーン)
1. コントロールプレーン起動(最後のワーカー登録するコマンドが表示される)
1. kubeadm, kubelet, kubectl のインストール(ワーカー)
1. ワーカのコントロールプレーンへの接続
1. ネットワークプラグインのインストールと接続確認
1. Pod を作成してコンテナを動かす

ネットワークプラグインは複数種類ありそう。メジャー所の採用で良さそうですね。



#### 第三回
- Kubernetes で Pod を起動するためには、多くの場合で Deployment リソースを作成し、間接的に Pod を作成する
- Deployment リソースは Pod とアップデートを管理してくれるリソースになる。従い、Pold を複数並べたり、Pod 障害時に新規 Pod 新規作成が可能になる。 

```yaml
apiVersion: apps/v1 # apiバージョン指定
kind: Deployment # リソース種類指定
metadata: # リソースの名前等を指定
    name: nginx-deployment
spec:
  replicas: 3 # Pod 数を指定
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec: # コンテナを指定
      containers:
        - name: nginx
          image: nginx:1.17
```


- Service リソース
    - Service リソースを使用することで、Pod の IP アドレスを指定しなくても、Deployment で管理されている Pod に自動で通信を振り分けできる
    - Service リソースは複数種類存在し、サンプルでは ClusterIP Service を利用している

```yaml
apiVersion: v1
kind: Service #サービスの種類を指定
metadata:
  name: nginx-service
spec:
  ports:
    - port: 80
  selector: # 振り分け先の Pod は selector でラベル指定。
            # このラベルは、Kubernetes 上で扱う全てのリソースに付与可能
    app: nginx
```

- Kubernetes 上でサービスをクラスタ外部に公開する方法
    - NodePort Service : Service の一種。Cluster IP に加えて NodePort と呼ばれるポート番号がアサインされ、Kubernetes の各ノード上でリッスンされる。同一クラスタ内でポート重複できないため、30000番台などのハイポートが利用される
    - LoadBalancer Service : サービスごとに外部からアクセス可能な External IP アドレスがアサインされる。LoadBalancerサービス利用には外部の LB と連携用プラグインが必要
        - Ingress : Ingress はサービスではなく別のリソース。Ingress はアプリケーション層のロードバランサ―のようなイメージ。




#### 第四回
- 複数のマニフェストをまとめてデプロイ/管理するツールとして kustomize が存在する。kubectl にも組み込まれている。
- Secret や Configmap はアプリケーション設定を保持するリソース。コンテナ外部から環境変数や設定ファイルとしてアプリケーションを読み込み可能。Secret は機密情報格納を想定して取り扱われる。



#### 第五回
- kustomize は kubernetes のマニュフェスト管理ツール。Deployment や Service など、実際に kubernetes にデプロイされるマニュフェストファイルとは別に、kustomization.yaml という差分を管理し、マニフェストを統合するためのファイルを喜寿ｔうすることでマニフェストを管理可能



#### 第六回
Volume としてホスト上の領域を Pod/コンテナにマウントするマニフェスト例

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: postgres
spec:
  containers:
  - name: db
    image: postgres:latest
    volumeMounts: # volume 指定
    - name: data 
      mountPath: /mnt/data/ # マウントパス指定
  volumes: # volume 作成
  - name: data
    emptyDir: {}
```

- volume は共有するファイルのライフタイムを Pod のタイムタイムまで延長する
- volume は基本的にライムタイムを Pod と共有している
- 永続ストレージをコンテナに提供する PersistentVolume/PersistentVolumeClaim

```yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  labels:
    release: stable #リソースのグループイングのためのラベル
  name: pv0003
spec:
  capacity:
    storage: 5Gi # 利用したいストレージ容量
  volumeMode: Filesystem # ボリュームの利用方法
  accessModes: # PV をマウントできるアクセスモード
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle # PVC にバインドされ、その後 PVC が削除された後の取り扱いを指定
  storageClassName: slow ボリュームが所属する StorageClass の名前を指定
  mountOptions: # ストレージ種類によって必要なオプションを指定
    - hard
    - nfsvers=4.1
  nfs:
    path: /tmp
    server: 172.17.0.2
```

- PVC はどのような PV を必要とするかのためのリソースのこと
- Kubernetes は PVC が要求した内容に対して最終的に PV をバインド(割り当て)することにより、Pod で PV を利用可能になる
- PVC のサンプルは以下の通り

```yaml
apiVersion: v1
kind: PersistentVolumeClaim # リソースの種類を指定
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources: # バインドする PV が提供するべきストレージ容量を設定。
    requests:
      storage: 8Gi
  storageClassName: slow
  selector: # PV のラベルに関する条件指定で、より柔軟に PV を絞り込む
    matchLabels:
      release: "stable"
```


- 永続ストレージのプロビジョニングを自動化する Provisioner と StorageClass
- プロビジョニング分類
    - 静的プロビジョニング：クラスタ管理者が事前に必要な PV を設定し、利用時は PVC を通じて Pod に割り当てる
    - 動的プロビジョニング：クラスタ管理者はプロビジョニングに必要な情報だけを事前に設定して利用時に PVC に応じて必要な PV を作成し、PVC に割り当てる
- Provisoner
    - 要求に対して自動的にストレージのプロビジョニングを行う Kubernetes のコントローラ
- StorageClass
    - クラスタにおいて自動プロビジョニングによって提供できるストレージを表すリソース
    - 動的プロビジョニングを利用するためクラスタ管理者が作成する
  

- StatefulSet : Deployment に似たワークロード API
    - 管理下の Pod の再スケジューリング(再作成)をまたがって同一のストレージをマウント可能


#### 第七回
- Deployment によるローリングアップデート
    - 古いバージョンの Pod 削除と、新しいバージョンの Podc 作成が順次行われることで、Service を通してアプリケーションにアクセスできる状態を保ちながらアップデートされる
- CI/CD と GitOps
    - Git 更新をトリガーに対象 Kubernetes クラスタへ外部からアクセスし、Kubectl apply コマンド等でクラスタを更新する push 型の方式
    - kubernetes クラスタ内部から Git レポジトリを監視し、更新を検知した場合に適用する pull 型の方式


#### 第八回
- モニタリングとオブザーバビリティ
    - 近年ではモニタリングに加えて、アプリケーションの内部動作に踏み込んで可視化する「オブザーバビリティ」に取り組む必要がある、と言われている
- Kubernetes メトリクスのモニタリング
    - Metrics API はプラグインにより実装されるものなので、kubeadm を使用してクラスタを構築した場合、別途 metrics Server をクラスタにインストールする必要がある
    - Metrics API はあくまで Pod、Node のメトリクスを取得するための仕組み。Pod をまたいだ Deployment、Service 単位でモニタリングする機能もなければ、アプリケーション固有のメトリクスをモニタリングするのにも適していません。
    - Metrics API はあくまでオートスケールのために利用する
    - 運用のためのモニタリングは Prometheus を利用する



#### 第九回
- 分散トレーシングの仕組み
    - スパン(Span)：アプリケーションの論理的な作業単位
    - トレース(Trace)：一覧の処理にかかわるスパン全体のあつまり



#### 第十回
- Linux Foundation による Kubernetes 認定試験
    - CKA(Certified Kubernetes Administartor): 認定 Kubernetes 管理者
    - CKS(Certified Kubernetes Security Specialist): 認定 Kubernetes セキュリティスペシャリスト
- サービスとネットワーキング
    - NetworkPolicy は Pod 間の通信を制御するための Kubernetes リソース
    - デフォルトでは Kubernetes の Pod 間の通信はすべて許可されている

```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          role: frontend
    ports: # TCP 6379 のみ通信許可
    - protocol: TCP
      port: 6379
```



# まとめ
- 登場人物は大体理解できました
- Ingress Controller とプラグインは何を利用するか事前に決めないと駄目そうですね
- 次は公式ドキュメントに戻って kubeadm で検証していきたいと思います
    



# 参考文献
- [今からでも遅くない! Kubernetesを最速で学ぶための学習法とは](https://thinkit.co.jp/article/18079)