GKEに入門する

# はじめに
* GKEに入門した時に確認したことのメモです。

# Kubernetes構成概要
![gke.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92368/e508f813-825d-4f10-5649-b13a34317811.png)

# Kubernetes基礎
* Cluster = ControlPlane+Node
* Pod: 1つ以上のコンテナを含み、１つの機能を実現する論理的な単位
    * ex.nginx が動作するPod
    * Pod内のコンテナは、ネットワークやストレージを共有する（localhostでアクセス可能）
* Deployment: ReplicaSetとPodを管理するオブジェクト。指定されたPodの数を保つように動くReplicaSetに加えて、ローリングアップデートやロールバック機能を提供
* Job: Deploymentと同様に複数のPodを実行。JobはPodの正常な終了を追跡することが目的。並列化やリトライ回数の設定が可能
* Service: Deployment に対して外部からアクセス可能な IP アドレスを付与し、外部からアクセスできるようにしたもの
* Podへのアクセス
    * ClusterIP
        * クラスタ内部の通信に利用する
        * 複数のPodに対してClusterIPと呼ばれる一つのIPと一つのDNS名を付与して抽象化することで負荷分散を実現する。一つのClusterIPに複数のPodIPが紐付く
        * DNS名はk8sの内部DNSに自動的に登録される（core-dns） -> ここでClusterIPを取得する
    * NodePort
        * NodeのIPとポートを利用する
    * LoadBalancer
        * クラウドプロバイダーが提供するロードバランサーを利用する
* Ingress: 
    * 外部からのHTTP/HTTPSアクセスを `Service` にルーティングする。NodePortまたはLoadBalancer
    * グローバル展開、パスでルーティングしたい場合に利用する
    * リクエスト元のユーザの地理的近接性に基づいて、トラフィックが流れるtargetPoolを最も近いリージョンのものに自動的に設定する
    * SSL証明書をインストール可能
* サービスメッシュ: 
    * サービスディスカバリ、サーキットブレイカー、オブザーバビリティ、セキュリティ
    * 変化を自動的に検知し、アプリケーションから見た場合にシームレスなサービスディスカバリを提供する
* ディスク
    * Pod内のコンテナのファイルシステムは揮発性
    * ストレージ機能を抽象化したVolume
        * Nodeのローカルストレージ、EBS、GCPのPersistent Disk、etc
    * Persistent Volume: Volumeと異なりPodと切り離して作成可能
* Secret: base64でNodeに登録。Gitで管理しない、RBACを設定する
* namespace: リソース使用量のハードリミットとして、namespaceでクォータを設定可能。LimitRange
* オートスケール
    * NodeとPodの2つのスケーリングを考える
    * Pod: HPAとVPA
        * HPAの計算式: 必要なレプリカ数 = 現在のレプリカ数×（現在のメトリクス値÷指定したメトリクス値）
    * Node: Cluster Autoscaler、水平スケーリング
    * ex. CPUの使用量が定めた値を超えるとPodがオートスケールする
* ResourceRequest/LimitsとQosクラス
    * ResourceRequest: PodのコンテナごとにCPUやメモリ・エフェメラルストレージなどのリソース要求を行う
        * → Podのスケジューリングの計算の際に利用。足りなければPendingになる。 → 過剰なRequest値を設定するべきではない
    * ResourceLimits: コンテナランタイムはPod内のコンテナに設定されたLimitを超えないようにする。メモリの場合はOOM KillerによりプロセスをKillする
    * QoSクラス: ResourceRequest/Limitsの設定内容から決まる。Nodeのリソースが枯渇した際にOOM KillerによってKillされるPodを選定する際の優先順位などに利用される
        * きちんと設定されているかなど
        * Priorityと違って、スケジューリングの優先順位に影響を与えない
* Priority: Podがスケジューリングされる際やNodeから退避させられる場合に考慮される
    * Nodeのリソース不足の時は、PriorityとQoSとの組み合わせで決まる
* Probeによるコンテナ監視
    * Liveness Probe, Readiness Probe, Startup Probe
        * Pod内で障害が発生しても、Liveness Probeにより自動で再起動される、etc
    * コマンド実行、HTTPリクエスト、TCPコネクション
* ログ収集
    * Fluentdなどのログ収集ツールをDaemonSetとして各ノードで起動する
* アップグレード
    * Data Plane: AMI更新、Kubernetesアドオン・カスタムコントローラー・マニュフェストのアップグレード
    * インプレースだが基本ダウンタイムなし
    * Control Plane -> Data Plane
    * Managed NodeGroupの場合、アップグレードコマンドを実行することで自動的にPodを安全に避難させてインプレースでNodeが更新される
* Kustomize: マニュフェスト管理ツール。開発・テスト・本番環境など複数環境を管理。ディレクトリを分けて、baseとoverlays/develop, production。-kオプション。
* Helm: パッケージマネージャ。aptのk8s版。リソースの作成・更新・削除・ロールバック。パッケージ=Chart。　`helm install aws-load-balancer-controller ...`
    * Terraformでも管理可能
* Flux: GitのソースとCluster上のリソースを定期的に監視、Cluster上で動作、kustomization.yamlの変更を検知してClusterへリリース、Gitのパスや監視間隔を設定
* Argo CD: FluxはCUIベースだが、Argo CDはGUIベース

# GKE基礎
* ControlPlaneの管理不要
* ネットワーク
    * クラスタ作成時に--networkで指定しないとdefaultネットワークに作成され、そこのファイアーウォールが適用されるので注意
    * ControlPlaneは専用VPCに作成される、自動でピアリングされる
    * ワーカーノードのIPアドレスに、サブネットのプライマリIP範囲を使用
    * PodのIPアドレスに、セカンダリIP範囲を使用
    * ServiceのCluster IPアドレスに、別のセカンダリIP範囲を使用
    * ワーカーノードがホストされたVPC内からkubectlコマンドを実行
    * 限定公開クラスターには、内部IPアドレスと外部IPアドレスの2つのエンドポイントが存在し、--internal-ipオプションを付けることで、外部IPアドレスではなく、内部IPアドレスのエンドポイントへ接続するように設定される
* GCRにアクセスするにはGCSの権限が必要
* GCRの脆弱性スキャン: メモとオカレンス
* `gcloud init`: 自身が正常にGCPを触れるように専用のサービスアカウントを発行しローカルに保存する
* ローカルで `gcloud components install kubectlでkubectl` をインストールしておく
* Autopilot
    * ノードの管理が不用
    * Podに関する課金のみ
    * カーネルのチューニングはできない

# GKE設計ポイント
* ワークロードの分散、課金管理、クォータ、料金コスト、運用コスト、拡張性
* ベースイメージ: マネージドベースイメージを使うか
* Public Cluster or Private Cluster
    * 1. No client access to the public endpoint
    * 2. Limited access to the public endpoint
    * 3. Unrestricted access to the public endpoint
* CIDR設計
    * [IP アドレス割り振りの最適化](https://cloud.google.com/kubernetes-engine/docs/how-to/flexible-pod-cidr?hl=ja)
    * ノード、Pod、サービス、コントロールプレーン
    * ノード以外はセカンダリ
    * サービスは/24、コントロールプレーンは/28など
    * ノードあたりのPod数なども考慮して決める
    * IPマスカレード
* IAM権限付与
    * Secretのマウント, Workload Identity, nodeに付与
    * Workload Identity
        * クラスタでWorkload Identity有効化
        * GSAを作成し、KSAとのIAM policy Bindingを作成
        * KSAを作成し、GSAへのアノテーションを追加
        * PodでKSAを指定
* AutoScale
    * NodeGroupの最大数に達してスケールできない場合のログ監視
* リージョン or ゾーン
* PodのAnti-Affinity
    * ゾーン間でWorkloadを均等に配置するか
* リトライ設計
    * [Running a Job](https://cloud.google.com/kubernetes-engine/docs/how-to/jobs)
* ノードプール
    * 学習と推論、GPU有無
    * nodeselectorを利用するなど
* NameSpace, label
    * environment: dev, など
* リソースクォータ制限
    * ResourceQuota
* メンテナンスウィンドウ
* バージョンアップ
    * マイナーバージョンアップデート
    * 自動アップデート
    * サージアップグレード
* バージョン情報の隠蔽
* ログ
    * Node（Data Plane）, Node(ホストOS), コンテナ
* Kustomize, KPT, namespace
* リソースをPodで指定させる、それを把握できるようにする。ノードのスペックを下げたがPodを下げ忘れて起動しない、とかが内容に
* JobとPodの使い分け
    * Composerを使うときはリトライを寄せるからPodで良いのでは、とか
* Podが終了してもSuccessで残る、とかがある。削除してから新しいものを作る？
* モニタリング
    * CPU利用率は注意。ノードかPodか。確保か利用か。
    * ダッシュボードで取得できるCPU使用率はnamespaceごとのリクエストに対するCPU使用率
    * 使用しているPodごとのCPU使用率を監視する場合にはLimitの設定が必要か
    * Request: Podのスケジューリングなどで利用される、全体のリソースに余裕があればオーバーコミットされていても使用される
    * 個別にLimitとRequestが設定されていないコンテナはRequestのみ設定される。0.1cores

# コマンド

```
$ kubectl exec -n <namespace> -it pod1 -- bash

$ kubectl get node -n <namespace>

$ kubectl get pod
$ kubectl describe pod pod1

# port確認
$ kubectl get svc -n <namespace>

$ kubectl get deployment -n <namespace>
$ kubectl get deployment metrics-server -n kube-system

# Allocated resourceでNodeのリソースが予約されているか確認できる
$ kubectl describe nodes

# メトリクス確認
$ kubectl top node

# hpaによるPodのスケーリングを確認
$ kubectl get hpa -w
```

# 参考
* [GCPの教科書2 コンテナ開発編](https://www.ric.co.jp/book/development/detail/269)
* [完全マネージドな k8s ! GKE Autopilot を解説する](https://medium.com/google-cloud-jp/gke-autopilot-87f8458ccf74)
* [ネットワークまわりを確認&勉強しながら、Kubernetesの環境構築をしてみた](https://qiita.com/nokoxxx1212/items/204f70dbd66bfda118b7)
* [3パターンあるGKE Private Cluster構成の違い](https://qiita.com/atsumjp/items/8e2bbb0066d3acab4938)
* [GKEクラスタに割り当てるCIDRを設計する](https://future-architect.github.io/articles/20191017/)
* [現場で使えるKubernetes](https://www.c-r.com/book/detail/1468)