これの続き。Part4
第14章 マニフェストの汎用化を行うオープンソースソフトウェア
マニフェストの汎用化
Kubernetes では YMAL形式で書かれたマニフェストを作成し kubectl を使って適用するのが一般的。
システムが大規模になってくると類似したマニフェストを大量に作らなければならず、再利用や一括変更といったことが困難になってくるので汎用化の考え方が必要。
Helm
Kubernetes のパッケージマネージャー
Helm が管理している公式 Chart はそれぞれの成熟度に合わせて stable と incubator に分かれている。
- `helm test` コマンドで Helm Chart が適切に動作しているか確認できる
- `helm template` コマンドで Helm のテンプレートから YMAL形式のマニフェストを生成することができる
- 生成するマニフェストの出力のみで Kubernetes クラスタへの適用はされない
- CI/CD パイプラインを GitOps で組んだ場合にアプリケーションを直接インストールせずに、テンプレートエンジンとして Helm を使うことができる
- Helm クライアントは Chart と values の組み合わせを Releaseとして管理し Secrets としてデータを扱うので別途DBを用意しなくてよい。
Kustomize
Kubernetes コミュニティの sig-cli が提供しているマニフェストテンプレーティングツール
Kustomize の設定は `kustomization.yaml` ファイルを利用する。
複数マニフェストの結合(resources-sample/kustomization.yaml)
resources:
- sample-deployment.yaml
- sample-lb.yaml
`kubectl kustomize resources-sample/ `コマンドを実行するとマニフェスト生成
Namespace の上書き(namespace-sample/kustomization.yaml)
namespace: sample-namespace
resources:
- sample-deployment.yaml
- sample-lb.yaml
`kubectl kustomize namespace-sample/ `コマンドを実行すると metadata.namespace が指定された状態で生成
Prefix と Suffix の付与(name-sample/kustomization.yaml)
namePrefix: prefix-
nameSuffix: -suffix
resources:
- sample-deployment.yaml
- sample-lb.yaml
`kubectl kustomize name-sample/ `コマンドを実行すると `prefix-<NAME>suffix` にそれぞれ置換される。
他にも commoLabels と commonAnnotations を利用して、すべてのリソースに対して共通のメタデータ(ラベル、アノテーション)を付与することもできる。
images によるイメージの上書き(image-sample/kustomization.yaml)
images:
- name: nginx
newName: samplpe-nginx
newTag: v2.0
resources:
- sample-deployment.yaml
- sample-lb.yaml
リソースで使われるイメージを置換することができる。
name にマッチするイメージはすべて置換されるので複数の Deployment などがある場合はすべてに影響することもある。
Overlayによる値の上書き(production/kustomization.yaml)
メタデータ系のフィールド以外、その他の細かな設定に関しては Overlay 機能を使ってリソースに対してパッチを当てて変更することが可能。
production や staging ごとにレプリカ数や CPU やメモリの値を変えることができる。
bases:
- ../resources-sample/
patchesStrategicMerge:
- ./patch-replicas.yaml
images:
- name: nginx
newTag: production
下記 Deployment のレプリカ数をのパッチを当てるマニフェスト
apiVersion: apps/v1
kind: Deployment
metadata:
name: sample-deployment
spec:
replicas: 100
Kustomize に関連する kubectl サブコマンド
$ kubectl <apply|get|describe|diff> -k resources-sample/
第15章 モニタリング
Kubernetes における監視
Kubernetes では複数の Node で大量コンテナが起動しており `kubectl top` コマンドを使って、メトリクスを見るだけで Kubernetes クラスタを運用していくのは困難なので監視ツールを導入することになる。
DataDog(SaaS)
様々なミドルウェア、SaaS、パブリッククラウドとの連携機能などが用意されていて、時系列で様々なメトリクスを収集 / 可視化 / モニタリングすることが可能。
Kubernetes 上にデプロイする際は DaemonSet を利用してDatadog Agent を各Node 上で起動する(環境によってサイドカーパターンも)。
デプロイされた Agent は各ホストの CPU 使用率やディスク使用率といったメトリクスや、各Node 上のコンテナのメトリクスも取得する。
Prometheus(OSS)
Datadog とは違い、利用するための課金要素はないが運用コストやサーバー側のマシンリソースが必要となる。Datadog と同様に時系列で様々なメトリクスを収集 / 可視化 / モニタリングすることが可能。
Prometheus Server を中心に Alert Manager / Exporter / Push Gateway から構成されている。
- Prometheus Server : メトリクスの収集と保存などを行う
- データソースから収集する Pull 型のアーキテクチャ
- Exporter : 各種ミドルウェアから監視項目のデータ抽出を行う
- Push Gateway : Push 型のアーキテクチャで Prometheus にメトリクス送信を行う
- バッチ系システムのメトリクスは Pull 型と相性が悪い
- 各プログラムからメトリクスを送信(Push)されて Prometheus がメトリクスを収集(Pull)する。
- Alert Manager : Prometheus Server がモニタリング閾値を超えたと判断するとアラートのリクエストを送る
- メール通知や Slack通知、PagerDuty 通知などへ通知する
- 通知の無効化や、類似したアラートが連続した際の重複排除も可能
- これらの可視化には Grafana がよく利用される
第16章 コンテナログの集約
コンテナ上で起動するアプリケーションは、基本的に標準出力と標準エラー出力にログを出力するようにしておく。Kubernetes では `kubectl logs` コマンドで表示できる。
クラスタ上で起動しているすべてのコンテナのログをクラスタ外部のサービスに転送する仕組みを利用することができる。中長期的にログを安定保存するには、ログを集約してクラスタ外部に転送することで、後からいつでも利用できるようにしておく。
Fluentd によるログ集約
Kubernetes に組み込んで利用するには DaemonSet を利用して各Nodeに Fluentd の Pod を 1つずつ起動する。DaemonSet が作成する各Node の Fluentd Pod は同じ Node 上に起動している全コンテナのログを取得して転送する。
Docker コンテナの標準出力に出力されたログが Node 上の `/var/log/containers` に出力されて、配下のログファイルを Fluentd Pod が tail プラグインを使って読み出して転送している。
Fluentd の他にも Datadog Logs や Grafana Loki によるログ集約
- Datadog Logs : Datadog Agent が直接コンテナの標準出力から出力されたログを収集し、Datadog の SaaS サーバーに対して転送を行う
- Grafana Loki : Prometheus ライクなログ集約を行う OSS
- DaemonSet で展開される promtail と呼ばれるエージェントがログを収集し、Deployment で展開される Loki にデータを集約する仕組み
- Loki ではデータの集約以外にもクエリの実行も担当する
- Loki に集約されたログデータは Grafana を経由して可視化できる
第17章 Kubernetes環境での CI/CD
実際に運用を行う際には手動で kubectl コマンドを実行するのは避けるべきであり、ヒューマンエラーの発生やスケールしないといった課題がある。
そのため自動で CI/CD パイプラインを構築するのが推奨される。
GitOps(Git を用いた CI/CD)
アプリケーションのアップデート、Deployment などのリソースが使用する Docker イメージの変更のような Kubernetes クラスタの操作を Git リポジトリを介して行うことで、手動でのマニフェスト変更や `kubectl apply` コマンドの実行をなくすことが可能。
- アプリケーションのソースコード用のリポジトリと、Kubernetes マニフェスト管理用のリポジトリの 2つの Git リポジトリが用意される
- アプリケーション開発者がアプリケーションのソースコードが置かれている Git リポジトリに変更をコミットすると、自動的にアプリケーションのテスト / コンテナイメージの作成 / コンテナレジストリへのイメージのプッシュなどの CI を行う
- マニフェスト管理者用の Git リポジトリに対して自動的にイメージタグを変更する Pull Request が送られ、アプリケーション開発者は送られた Pull Request を元に Kubernetes マニフェストの変更分を確認
- 問題が無ければマージし、マニフェストの変更がマージされると Kubernetes 上で動作している Deploy Agent がリポジトリのマニフェストを取得してきて適用
ArgoCD(Git を実現するための CD ツール)
あらかじめ指定したリポジトリを監視し Kubernetes クラスタに対してマニフェストを適用する。
Application リソースを作成することで特定のリポジトリの特定のパスにあるファイルを Kubernetes クラスタに適用する仕組みとなっている。
この本も読む。
第18章 マイクロサービスアーキテクチャとサービスメッシュ
マイクロサービスアーキテクチャは、システム個々の機能をサービスとして切り出し、サービス同士を gRPC や RESTful API などで連携することでシステム全体を構成する、疎結合なアーキテクチャ。これに対して、システム全体を 1つのサービスで実現する構成をモノリシックアーキテクチャ。
メリット
- サービス同士をつなぐ gRPC や RESTful API のインターフェースの仕様が決まっていれば、それに従う以外は各サービスのプログラム言語やFWなどの技術を自由に選定可能
- サービス同士が疎結合に保たれていれば、サービスごとの開発規模や性能をスケールさせることができる
- サービスごとに独立してアップデートできるので、リリースサイクルを短縮することが可能
- 障害の影響範囲をそのサービスにとどめることができる
デメリット
- システムを複数マイクロサービスに適切に分割することが困難
- マイクロサービス間の依存関係などの把握、マイクロサービス間のトラフィックのレイテンシやエラーレートのモニタリングが困難
サービスメッシュ
マイクロサービス間に張り巡らされたメッシュ状の通信やその経路を制御する考え方
代表的なものに Istio がある。AWS だと App Mesh
基本的な仕組みは Pod 間の通信経路にプロキシを挟むことでトラフィックのモニタリングやトラフィックコントロールを行うもの。(既存のアプリケーションに手を加える必要がない)
第19章 Kubernetesのアーキテクチャを知る
Kubernetes クラスタは 8つのコンポーネント(+1 つのオプション)から構成され kube-apiserver を中心とした分散システムとなっている。
- etcd
- 分散 Key-Value Store(KVS)
- 冗長性を担保するためにクラスタを組み込むことが可能
- Kubernetes クラスタに登録されるすべての情報が保存されている
- `etcdctl snapshot` コマンドで etcd クラスタの状態をバックアップ
- kube-apiserver
- Kubernetes API を提供するコンポーネント
- kubectl は kube-apiserver にリクエストして、リリースの操作を行う
- ロードバランサ配下に複数台並べることで冗長化することが可能
- kube-scheduler
- 起動する Node 情報(spec.nodeName)が未割り当ての Pod を検知し kube-apiserver にリクエストして更新することでスケジューリングを行う
- 各 Kubernetes Node のステータスや Node Affinity などの条件に合致するかを判断して起動する Node を選定する
- リーダー選出の仕組みを持ち、1台だけがリーダーとなり書き込むを行うことによって冗長化が可能
- kube-controller-manager
- kubelet
- 各 Kubernetes Node 上で動作するコンポーネント
- コンテナランタイムと連携し、コンテナの起動や停止などの管理を行う
- kube-apiserver 経由で Pod が登録
- kube-scheduler によって Pod が起動される Node が決定
- kubelet が検知して、自身の Node で起動すべきコンテナを起動
- 自身 Node に静的に起動させたいコンテナがある場合は kube-scheduler 依存せずに起動が可能 > static pod
- kube-proxy
- 各 Kubernetes Node 上で動作するコンポーネント
- Service リソースが作られた際に ClusterIP や NodePort 宛のトラフィックが Pod に正常に転送されるようにする
- 3種の転送方式
- CNI(Container Network Interface) Plugin
- 複数の Kubernetes Node で構成された Kubernetes クラスタ内に分散配置された Pod が相互に疎通可能なネットワークを構築する Plugin
- 代表的な Plugin に Flannel などがある
- kube-dns(CoreDNS)
- Kubernetes クラスタ内部の名前解決やサービスディスカバリに利用されているクラスタ内 DNS サーバー
- 内部では CoreDNS が利用されている
- cloud-controller-manager
- Kubernetes クラスタが各種クラウドプロバイダと連携するためのコンポーネント
- 従来は kube-controller-manager 内にハードコードされていたが、現在はコンポーネントとして分けられている
- マネージド Kubernetes サービスであれば意識する必要はないが OpenStack などでは環境にあった cloud-controller-manager を利用する
- CRD(CustomResourceDefinition)とOperator
- 独自のリソースを追加して、Kubernetes を拡張することが可能
第20章 Kubernetesとこれから
Kubernetes は CNCF によりオープンな開発が行われており、並行して標準化も進められている。
主にコンテナイメージフォーマット / コンテナランタイム / コンテナストレージ / コンテナネットワークに関する標準化が進められている。
おわり
業務時間内に読書会の時間をいただいたのでその時のメモを出した。
この書籍はこれからも辞書的に使わせていただきます。ありがとうございました。