harukin721

主に学習記録 🔗 wantedly.com/id/harukin721

Kubernetes完全ガイド 【第2版】 読書会2 Part2

これの続き。Part2

第5章 Workload APIs カテゴリの概要

Pod : デバッグや確認用途などに利用

  • リソースの最小単位
  • Pod は1つ以上のコンテナから構成される
  • 2つ以上のコンテナが入った Pod を作成すると、コンテナは同一のIP
  • Pod 内のコンテナはお互いに localhost 宛で通信が可能

デザインパターン

  • サイドカーパターン : メインコンテナに機能を追加
    • 補助的な機能を追加するコンテナを内包
  • アンバサダーパターン : 外部システムとのやりとりの代理行う
    • メインコンテナが外部のシステムとの接続する際に代理で中継
  • アダプタパターン : 外部からのアクセスのインターフェース
    • 外部からのリクエストに対して差分を吸収するコンテナを内包
    • 例) Prometheus などの監視ソフトウェア

ネットワーク

  • Pod はネットワークの名前空間を共有している
  • 通常 VM 上で 80/TCP ポートを bind するサービスを2つ起動できないのと同じ
  • Kubernetes で起動する Pod に割り当てられる IP は Kubernetes Node のホストの IP とはレンジが異なり、外部から疎通性がない IP が払い出される

ENTRYPOINT 命令 / CMD 命令と command / args

  • Kubernetes では、Dockerfile の ENTRYPOINT -> command
  • Kubernetes では、Dockerfile の CMD -> args
  • ※ CMD が command ではない

Pod の DNS設定(dnsPolicy)とサービスディスカバリ

  • ClusterFirst : クラスタ内の DNS に問い合わせを行い、解決できなかった場合はアップストリームに問い合わせを行う
  • None : Pod 定義内で静的に設定を行う(クラスタ外の DNSサーバ 参照)
  • Default : Pod が起動する Kubernetes Node の /etc/resolv.conf を引き継ぐ
  • ClusterFirstWithHostNet : ClusterFirst の挙動と同様(HostNetwork 利用時)

ReplicaSet : Pod をスケールさせて管理(基本的には Deployment 経由)

  • Pod のレプリカを作成し、指定した数の Pod を維持し続けるリソース
  • ノードや Pod 障害時は Pod 数が指定された数を満たすように別のノードで Pod を起動することでレプリカ数を維持(セルフヒーリング)
  • 特定のラベルが付けられた Pod の数をカウントすることで監視を行うことで Pod の数を調整する

Deployment : スケールさせるワークロードに利用

  • 複数の ReplicaSet を管理し、ローリングアップデート(maxUnavailable と maxSurge が設定可能)ロールバックなどを実現するリソース
    • Deployment が ReplicaSet を管理し、ReplicaSet が Pod を管理する関係性
      1. 新しい ReplicaSet を作成
      2. 新しい ReplicaSet の Pod を徐々に増やす
      3. 古い ReplicaSet の Pod を徐々に減らす
      4. (2,3を繰り返す)
      5. 古い ReplicaSet はレプリカ数0で保持する
  • Recreate : 1度に全ての Pod を削除してから再度 Pod を作成する
    • ダウンタイムが発生するが、余剰なリソースを使わないことや、切り替え完了が早いというメリットがある
    • 実運用では kubectl rollout はなるべく利用しないのが望ましい
    • CI/CD のパイプラインからロールバックする場合、古いマニフェストを再度  kubectl apply を実行して適用するほうが相性がよい

DeamonSet : 各ノードに1つずつ Pod を配置したい時に利用

  • レプリカ数は指定できない、1ノードに2 Pod ずつ配置するといったことはできないが、Pod を配置したくないノードがある場合にはスケジューリングで除外することができる

harukin721.hatenablog.com

ユースケース

  • 各 Pod が出力するログをホスト単位で収集する Fluentd
  • 各 Pod のリソース使用状況や Node の状態をモニタリングする Datadog

DaemonSet のアップデート戦略

  • OnDelete
    • DaemonSet はマニフェストを変更しても、死活監視やログ転送といった用途で利用されることが多いため、アップデートを次回作成時や手動による任意のタイミングで行えるようになっている
    • 任意のタイミングで Pod のアップデートを行いたいときは DaemonSet に紐づく Pod を kubectl delete で Pod を停止し、セルフヒーリングの機能によって、新しい Pod を作成するとよい
  • RollingUpdate 

StatefulSet : データの永続化などステートを持つワークロードに利用

  • データベースなどステートフルなワークロードに対応させるためのリソース
  • 作成される Pod名のサフィックスは数字のインデックスが付与されたものになる
  • データを永続化するための仕組みを持っている

StatefulSet によって作成される各Pod に対して

  • PersistentVolumeClaim(PersistentVolume 要求)を設定できる
  • PersistentVolumeClaim を利用することでクラスタ外のネットワーク越しに提供される PersistentVolume(永続化領域)を Pod にアタッチできるため Pod の再起動や別ノードへの移動時にも同じデータを保持した状態でコンテナが再作成される
  • PersistentVolume は1つの Pod が専有することも PersistentVolume の種類によっては複数の Pod で共有することも可能

StatefulSet のアップデート戦略

  • OnDelete
  • RollingUpdate

StatefulSet の削除と PersistentVolume の削除

  • StatefulSet が削除されても同時に PersistentVolume は解放されないのは、ボリュームからデータをバックアップする猶予を与えるため
  • StatefulSet 削除後 PersistentVolumeClaim で確保した PersistentVolume を解放せずに再度 StatefulSet を作成すると永続化領域のデータはそのまま Pod が起動
  • ※ StatefulSet 削除しても永続化領域が確保されたままだとコストがかかる

Job : ワークキューやタスクなどコンテナの終了が必要なワークロードに利用

  • コンテナを利用して1度限りの処理を実行させるリソース

ReplicaSet との大きな違いは起動する Pod が停止することを前提にして作られているか

  • ReplicaSet の Pod 停止は予期せぬエラー
  • Job の Pod 停止は正常終了が期待される用途

restartPolicy による挙動の違い

  • Never を指定した場合、Pod の障害時には新規の Pod が作成される
  • OnFailure を指定した場合、再度同一の Pod を利用して Job を再開する

その他

  • 並列で実行することも可能
  • ワークキュー型を使用することも可能
  • 一定期間後の Job の削除設定をすることも可能

CronJob : 定期的に Job を作成したい時に利用する

  • Cron のようにスケジュールされた時間に Job を作成するリソース
  • CronJob が Job を管理し、Job が Pod を管理する関係性
  • 指定した時間に Job を作成し続けたり、メンテナンス等で Job が作成されてほしくない場合には一時停止したりすることも可能

第6章 Service APIs カテゴリ

L4 ロードバランシングの Service(クラスタDNSによる名前解決:ラベルを利用した Pod のサービスディスカバリ) と L7 ロードバランシングの Ingress(HTTPS 終端:パスベースでのルーティング) のリソースがある

Pod は Service を利用せずに Pod 間通信を行うことも可能であるが、Service を利用することによって得られるメリットが 2つある

  • Pod 宛トラフィックのロードバランス
    • Service は受信トラフィックを複数 Pod にロードバランシングする
    • 1つの Service に複数 Port を割り当てることも可能
    • 名前による Port 参照も可能
    • 例) http,https で ClusterIP が異なると不便なので 1つの Service で複数Port を持たせる
  • サービスディスカバリークラスタDNS
    • 環境変数を利用したサービスディスカバリ
      • Pod 内からは、同じ Namaspace のサービスが確認できる
      • Pod 作成後に Service の作成や削除に伴って変更された環境変数は、先に起動していた Pod 境には自動的に再登録されない
    • DNS Aレコードを利用したサービスディスカバリ
    • DNS SRVレコードを利用したサービスディスカバリ
      • Port 名と Protocol を利用することで、サービスを提供している Port 番号を含めたエンドポイントを DNS で解決する仕組み

クラスタDNSクラスタDNS

  • dnsPolicy を使って Pod の DNSサーバーの設定を明示的に行わない限り、起動する全ての Pod はクラスタDNS を利用して名前解決を行う

ClusterIP Service : Kubernetes Cluster 内でのみ疎通可能な仮想 IP

  • Kubernetesクラスタ内からのみ疎通性がある Internal Network に作り出される仮想IPを割り当てる
  • ClusterIP 宛ての通信は、各Nodeで実行しているシステムコンポーネントの kube-proxy が Pod 向けに転送を行う
  • 静的に設定することも可能

ExternalIP Service : 特定の Kubernetes Node の IPアドレス

  • 特定の Kubernetes Node のIPアドレス:Port で受信したトラフィックをコンテナに転送する形で外部疎通性を確立
  • ※ 特別な事情がない場合は、NodePort Service を利用するとよい

NodePort Service : 全 Kubernetes Node の全IPアドレス(0.0.0.0)

  • すべての Kubernetes Node のIPアドレス:Port で受信したトラフィックをコンテナに転送する形で外部疎通性を確立
  • Kubernetes Node のIPアドレスで指定したポートを Listen するため Port のバッティングを起こさないように注意が必要
  • NodePort Service を確認すると、コンテナ内からの通信には ClusterIP を利用するために自動的に確保されている
  • NodePort で利用できるポート範囲は Kubernetes 環境では範囲が決まっている

LoadBalancer Service : クラスタ外で提供されている LoadBalancer の仮想IP

  • プロダクション環境でクラスタ外からトラフィックを受ける場合に、一番実用的で使い勝手が良いのが LoadBalancer Service
  • Kubernetes クラスタ外のロードバランサに外部疎通性のある仮想IPを払い出すことが可能
  • ファイアウォール機能を利用してアクセス制限を設定できる
  • セッションアフィニティを有効化できる(Node 上の iptables で実現)
  • ノード間通信の排除と送信元IPアドレスの保持などの設定が可能

Headless Service(None) : Pod の IPアドレスを用いた DNSラウンドロビン

ExternalName Service : CNAME を用いた疎結合性の確保

  • Service名の名前解決に対して外部のドメイン宛のCNAMEを返す
    • 別の名前を設定したいとき
    • クラスタ内からのエンドポイントを切り替えやすくしたいとき
  • 例) hoge.default.svc.cluster.local. → external.example.com
  • 外部サービスとの疎結合性の確保や内部サービス間の切り替え
  • 外部サービスと内部サービス間の切り替え

Ingrass

マニフェストで定義したリソースを Kubernetes に登録するだけでは何も処理は行われないので、実際に処理を行うコントローラーが必要となる。

  • クラスタ外のロードバランサのを利用した Ingrass
  • クラスタ内の Ingrass 用の Pod をデプロイする Ingrass
    • 代表的なのものが Nginx Ingrass
    • Nginx の設定を変更してリロードを実施など

github.com

第7章 Config & StorageAPIsカテゴリ

コンテナに対して設定ファイル、パスワードなどの機密情報なをインジェクトしたらい、永続化ボリュームを提供したりするためのリソース

個別のコンテナに対する設定の内容は、環境変数やファイルが置かれた領域をマウントして渡すことが一般的であり、以下の5つから環境変数を埋め込むことが可能

  • 静的設定
    • spec.containers[].env に静的な値として定義
  • Podの情報
    • Pod自身のIPアドレスや起動時間などの情報は fieldRef を使って参照
  • コンテナの情報
    • Podの情報と同様、resourceFieldRef を使って参照
    • ※ 各コンテナに関する情報については fieldRef では参照できないので注意
  • Secret リソースの機密情報
  • ConfigMap リソースの設定値

Secret

ConfigMap

  • Key - Value 値を保存できるリソース
    • kubectl でファイルから値を参照して作成する(--from-file)
    • kubectl で直接値を渡して作成する(--from-literal)
    • マニフェストから作成する(-f)

Volume と PersisitentVolume と PersisitentVolumeClaim(PVC) の違い

  • Volume はあらかじめ用意された利用可能なボリューム(ホスト領域など)をマニフェストに直接指定する
  • PersisitentVolume は外部の永続ボリュームを提供するシステムと連携し、新規ボリュームの作成や、既存ボリュームの削除などを行う
    • クラスタにボリュームを登録するのみ。
    • PersisitentVolumeClaim(PVC) 経由で利用する
  • PersisitentVolumeClaim(PVC) は PersisitentVolume リソースの中からアサインするためのリソース

Volume

  • Pod に対して静的に領域を指定するような形になる
  • emptyDir
    • Pod が Terminate されると消える一時的なディスク領域として使う
    • ホスト上の任意の領域をマウントすることはできない
    • 複数のコンテナ間でのやり取りで使われる
  • hostPath
    • Kubernetes Node 上の領域をコンテナにマッピングする
    • ホスト上の任意の領域をマウントする
    • セキュリティの観点から少しでも信頼できないコンテナがある場合は利用を控える
  • downwardAPI
    • Pod の情報などをファイルとして配置する
    • fieldRef や resourceFieldRef のファイルマウント版
  • projected
    • Volume プラグインでマウントしたものを一箇所にまとめるもの

PersisitentVolume(PV)

  • 永続化領域として確保される Volume
  • PersisitentVolume はリソースとして個別に作成してから利用する

PersisitentVolumeClaim(PVC)

  • 永続化領域の要求を行うリソース
  • PersisitentVolumeClaim 経由で指定された容量やラベルなどの条件を元に、永続化領域の要求が発行されると、スケジューラーは現在保持している PersisitentVolume から適した Volume を割り当てる
  • PersisitentVolume が3GBの要求に対して10GBのものしかなければそれが割り当てられるので7GB無駄になる

第8章 ClusterAPIsカテゴリとMetadataAPIsカテゴリ

ClusterAPI は全部で10種類(利用者が直接利用するもの)

  • Node 
  • Namespace
  • PersistentVolume
  • ResourceQuota
  • ServiceAccount
  • Role
  • ClusterRole
  • RoleBinding
  • ClusterRoleBinding
  • NetworkPolicy

MetadataAPI は全部で4種類(利用者が直接利用するもの)

  • LimitRange
  • HorizontalPodAutoscaler
  • PodDisruptionBudget
  • CustomResourceDefinition

Node

  • Node の IPアドレスとホスト名は、status.addresses に保持
    • 環境によっては InternalIP, ExternalIP のいずれかしか表示されない場合も.
  • Node のリソースは、status.allocatable と status.capacity で確認可能
    • Capacity : Node が所有している CPU やメモリの実際の量
    • Allocatable : Kubernetes がシステムリソースとして割り当てている分を引いた、実際に Pod に割り当て可能なリソースの量になる
  • Node の Status が Ready でなければ status.conditions を確認すると良い
  • Docker イメージや、Node のバージョン情報なども確認できる

Namespace

  • 初期状態では4種類が作成されている
    • default
    • kube-system
    • kube-public
    • kube-node-lease
  • リソースのクォータを設定範囲をしているするのに利用可能
    • ResourceQuota
    • Role Based Access Control

コラム

(Part3 に続く...)

参考

book.impress.co.jp