😀

Kubernetes完全ガイド 雑多メモ

2024/06/18に公開

3. リソース

  • Kubernetes Master と Kubernetes Node の2種類
  • $ kubectl だけでなく、APIを呼び出すことでも操作可
  • リソース
    Workloads: コンテナ実行
    8種類
    Discovery&LB: 外部公開するようなエンドポイントを提供
    7種類のServiceとIngress
    Config&Strage: 設定・機密情報・永続化ボリューム
    3種類
    Cluster: セキュリティやクォータ
    10種類
    Metadata: クラスタ内の他リソースを操作する
    4種類

4. APIリソースとkubectl

  • Namespaceの利用により、1つのKubernetesクラスタを複数チームで運用したり、プロダクション環境・ステージング環境・開発環境に分けたりする。
    例) kube-system, kube-public, default namespace
  • "--grace-period 0", "--force" でリソースを即座に強制的に削除する
  • "kubectl apply" では、前回のマニフェスト・登録されているリソース・今回のマニフェストから差分が算出される → "kubectl create"よりもおすすめ
    ↓マージの挙動
    https://kubernetes.io/docs/tasks/manage-kubernetes-objects/declarative-config/
  • マニフェストの設定指針
    1. 全てのマイクロサービスのマニフェストを1つのディレクトリにまとめる(規模が小さいとき)
    2. 特定のサブシステムに分割する(まあまあ大きくなった時)
    3. マイクロサービスごとにディレクトリを切る(大規模システム)
  • アノテーションとラベルの違い[どちらもメタデータ]
    アノテーション→システムコンポーネントが利用する
    ラベル→リソース管理に利用する
    "-l" でフィルタリングする
    "-l label1" であれば、存在するか
    "-l label1=val1" であれば、ラベルが一致するか
  • "--prune" で削除されたリソースを検知して、自動的に削除する
  • set でリソースの一部情報を更新する[マニフェストと一致しなくなるため、乱用しないこと]
    env, image, resources, selector, serviceaccount, subject が対象
  • get でJSON or YAMLで出力した時、より詳細な情報を確認できる
    エイリアスでcustom-columnsを登録すると、ほしい情報だけ獲得できる
  • cp でローカルマシン-コンテナ間でファイルコピーする
  • ログレベルを変更することで、デバッグを行う
    HTTPリクエスト・レスポンスの概要→"-v=6"
    HTTPリクエスト・レスポンスボディまで確認→"-v=8"

5. Workloadsリソース

  • デザインパターン
    サイドカーパターン:メインコンテナに機能を追加
    アンバサダパターン:外部システムとのやりとりを代理で行う
    アダプタパターン:外部からのアクセスのインタフェースとなる
  • Podはネットワークの名前空間を共有→Pod内でコンテナが同一ポートを指定すると起動できない
  • spec.containers[].commandspec.containers[].args でコンテナイメージのENTRYPOINTとCMDを上書きする
  • dnsPolicyでクラスタ内DNSではなく、外部DNSを指定する
  • spec.hostAliasで/etc/hosts内のファイルを書き換える
  • レプリカ数が不足している時は、templateからPodを作成する
  • scale でPodをスケールする
  • spec.templateの構造体ハッシュ値でDeploymentのアップデートとロールバックを行う
  • DeamonSetはReplicaSetの特殊形で、各ノードに1つづつ配置するリソース
  • StatefulSetもReplicaSetの特殊形で、ステートフルなワークロードに対応するためのリソース
    スケールアウト 0→1→2の順、スケールイン 2→1→0の順
    故に、0番目のPodをマスターノードとするような冗長化構成を持つアプリに最適
  • Jobでバッチ処理を行い、spec.completionを指定しない場合に、ワークキューとして動作する
  • spec.startingDeadlineSecondsで実行開始期限を制御する
  • spec.successfulJobsHistoryLimit, spec.failedJobsHistoryLimitで保存する履歴の数を指定する

6. Discovery & LBリソース

  • Serviceはサービスディスカバリの機能を提供する
  • spec.ports.portにはサービスのポート番号、spec.ports.targetPortにはコンテナのポート番号
  • ClusterIPでExternalIPサービスを使えば、指定ノードからはアクセスできる
    ↑ NodePortサービスを使えば、全てのノードからアクセスできる
  • spec.externalTrafficPolicyでClusterIPロードバランスを行うか指定できる(未検証
  • Headlessサービスは個々のIPアドレスが直接返ってくる
    ↑ 通常は、Cluster IPが返ってくる

7. Config & Storageリソース

  • コンテナのデフォルトタイムゾーンはUTCである
    spec.containers.envTZ=Asia/Tokyo を環境変数として設定しておくといい
  • Pod情報はfieldRefで取得できる
    コンテナ情報はresourceFieldRefで取得できる
  • GenericタイプのSecret作成方法は4通り
    --from-file, --from-env-file, --from-literal, -f
  • Secretのデータはetcdに保存されており、Secretを利用するPodがあるときのみ、Nodeにデータを送る(データはtmpfs領域に保持される)
  • Volumeはマニフェストで直接指定することで、利用可能なリソースであり、Persistent Volumeは永続化領域として確保されるリソースのこと
  • VolumeはToDo

8. Cluster & Metadataリソース

  • status.capacityはノードが所有しているCPUやメモリの量、status.allocatableはKubernetesが実際にPodに割り当て可能なリソースの量を指す

9. リソース管理とオートスケーリング

  • requestsでリソースの下限、Limitsでリソースの上限を指定する
  • Pending状態のPodができたタイミングでCluster Autoscalerが発動する
    → requestsとlimitsを適切に設定していないといけない
  • LimitRangeによって、PodやContainerに対して、リソースを制限する
  • QoS Classの値によって、Podの優先度をつける
    ↑ requestsとlimitsの設定によって決まる
  • ResourceQuotaでNamespaceごとにリソース制限をする
  • Cluster Autoscalerはクラスタノードをスケールさせる
  • HorizontalPodAutoscaler(HPA)とは負荷に応じて、レプリカ数をスケールさせる(未検証
  • VerticalPodAutoscaler(VPA)とはコンテナに割り当てるリソースをスケールさせる(未検証

10. ヘルスチェックとコンテナライフサイクル

  • Liveness ProveはPodが正常動作するかチェックする
    失敗時→Podを再起動する
  • Readiness ProveはPodがサービスインする準備ができているかチェックする
    失敗時→トラフィックを流さない
  • ヘルスチェック方法は3つ
    exec, httpGet, tcpSocket
  • ヘルスチェックの間隔は適切に指定する
  • restartPolicyはAlways, OnFailure, Neverの3つ
  • spec.InitContainersでメインコンテナを起動する前に、別コンテナで処理を行うことができる
  • spec.containers.lifecycleでコンテナ起動後と停止直前に任意のコマンドを実行できる
  • "preStop+SIGTERM"と"Serviceからの除外"は非同期で行われるため、"Serviceから除外"が終わるまでの数秒を待機すると安全に終了できる

11. メンテナンスとノードの停止

  • $ kubectl cordon でノードのステータスを変更できる
  • $ kubectl drain で全てのPodを退避させる
    処理としては、ノードをSchedulingDisabledにし、各Podに対してSIGTERMシグナルを送信する→Deploymentのセルフヒーリング機能により、別ノードでPodが作られる

12. 高度なスケジューリング

  • スケジューリングの指定方法は5通り
    nodeSelector, Node Affinity, Node Anti-Affinity, Inter-Pod Affinity, Inter-Pod Anti-Affinity
  • spec.nodeSelector でラベルをもとにノードを指定してPodを動かせる
    ↑ ノードを直接指定することもできるが、これは望ましくないため、ラベルなどをもとに間接的にスケジューリングを行う
  • spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecutionで必須のスケジューリングポリシー
  • spec.affinity.nodeAffinity.preferredDuringSchedulingIgnoredDuringExecutionで優先するスケジューリングポリシー
  • Inter-Pod Affinityは、特定のPodが実行されているノードやゾーンを指定してPodをスケジューリングする → Pod間通信のレイテンシを下げる
  • Taints/Tolerationsでは、指定しない限りNodeでPodを動かさない
  • Taintsの条件を全て満たすTolerationsがなければ、そのノードへはスケジューリングされない

13. セキュリティ

  • ServiceAccountはNamespaceに紐づいており、これをもとに認証・認可を行う。
  • SecurityContextで、コンテナに対するセキュリティ設定を行う。
    privileged, capabilities, readOnlyRootFilesystem
  • PodSecurityContextで、Podに対するセキュリティ設定を行う。
  • PodSecurityPolicyで、クラスタに対してポリシーによる制限を行う。
    「PocSecurityAdmissionを使え」となっている。
  • クラスタ内で通信制御を行うならpodSelectorかnamespaceSelector、クラスタ外の制御を行うならipBlockを利用する。
  • AdmissionControlで、Kubernetes APIサーバへのリクエスト制御を行う。
    PodPresetを使うことで、設定をInjectionできる。

14. マニフェストの汎用化

  • Helmとは、Kubernetesのパッケージマネージャである。
    → RedisやWordpressのクラスタ環境を1コマンドで作成する。

15. モニタリング

  • DatadogやPrometheusを利用する。

16. ログの集約

  • 基本的にログは標準出力・標準エラー出力に書き込む。
    ↑ アプリケーション側でファイル書き込みや外部への転送しないこと
  • Fluentdで/var/log/containers/の出力を読み出して、ログを転送する。

17. Kubernetes環境でのCI/CD

  • CDツールとして、Spinnaker, Skaffold, Jenkins Xがある。
    ↑ 今なら、GitOpsでArgo CD使うのが多い?
  • 実運用では、kubectlでKubernetes環境を操作しないようにする。

18. マイクロサービスアーキテクチャとサービスメッシュ

  • マイクロサービスではシステム全体(依存関係やトラフィックのレイテンシ)のモニタリングが難しい → Pod間の通信経路にプロキシを挟み、トラフィックのモニタリング・コントロールを行う(サービスメッシュ)
  • できること
    Circuit Breaker:転送先のマイクロサービスに問題がある場合に、アクセスを即座に遮断する
    Fault Injection:意図的にリクエストを遅延させたり、失敗させたりする
    レート制限
    リクエスト失敗時のリトライ処理

19. Kubernetesのアーキテクチャ

  • kubectlはkube-apiserverにリクエストを送り、DeploymentやServiceの作成・削除を行う。
  • $ kubectl apply -f sample.yamlkube-apiserverにリクエスト
    etcdにspec.nodeName:""を登録→kube-schedularがkube-apiserverに書き換えリクエスト→kubeletがkube-apiserverにリクエストを送り、データを取得

20. Kubernetesとこれから

  • OCI(Open Container Initiative): コンテナの標準仕様を策定する団体
  • CRI(Container Runtime Interface): kubeletとコンテナランタイムをつなぐインタフェース
  • CSI(Container Storage Interface): コンテナオーケストレーションエンジンとストレージをつなくためのインタフェース
  • CNI(Container Network Interface): コンテナオーケストレーションエンジンとネットワークをつなぐためのインタフェース

Discussion