一般的なサーバ構築においては、エンジニアがコマンドを叩いてサーバのOSやミドルウェアを設定・構築していきます。監視サーバからの監視結果がNGの場合、エンジニアが原因を確認し改修します。

一方で、Kubernetesにおいては、初期の環境構築時に、ToBeとなる設定値を投入します。後述するControllerなどのコンポーネントが監視し、ToBeとAsIsのギャップを検知したら、自動改修します。

今回は、こうした仕組みをKubernetesのアーキテクチャの側面から紐解いていきます。

API Serverを用いたアーキテクチャ

前回まで、PodやReplicaSetなどのKubernetesのリソースを体系的に紹介しましたが、皆さんはkubectlコマンドを叩いてからリソースがどのように作られるかご存知でしょうか。

KubernetesではAPI Serverを通して全ての処理が実行されます。

API Serverを中心としたKubernetesのアーキテクチャを、具体的な手順を交えて5ステップで紹介します。

API Serverを中心とした5ステップの処理 

上図(1)にて、[kubectl apply -f sample.yaml]といった形でコマンドを打ったあと、(4)で特定のNodeにおいてコンテナ(busyboxなど)を起動します。

kubectlコマンドが直接的にコンテナを起動するのではなくController・Scheduler・kubeletの3つのコンポーネントを媒介して動作します。

(1) kubectlによりReplicaSetを定義(Desired Stateの定義)
  ※ 以降、Desired Stateとのギャップ解消のための処理
(2) ControllerがPodを作成
(3) SchedulerがNodeを割当
(4) kubeletがコンテナを作成
(5) kubeletがPodステータスを起動に変更

(1)~(5)いずれの操作も高信頼分散KVSであるetcdに永続化されます。etcdに定義されたDesired State(あるべき状態)に対して各コンポーネントがポーリングし、(2)~(5)の動作を実行しているのです。これをReconciliation Loopと言います。

Reconciliation Loop

Reconciliation Loopについて深掘りしてみましょう。

ControllerやSchedulerやkubeletはそれぞれ自律的に以下の3ステップを踏むことで、相互に直接的な連携なく、全体的な調和を保っています。

  1. Observe : API Serverに問い合わせ、kubectlによって定義されたDesired Stateを確認する
  2. Analyze : Desired StateとCurrent Stateとの差分をチェックする
  3. Act : Desired StateとCurrent Stateとの差分をなくすよう、リソースの作成やノードの割当やコンテナの作成などを実行する

続いて、残りのコンポーネントを紹介していきましょう。

kube-proxyとDNS

kube-proxyはServiceに紐づけられた仮想IPを、iptablesを用いて管理し、仮想IPへのアクセスをPodにラウンドロビンで負荷分散します。なお、デフォルトではiptablesが選択されますが、-proxy-modeオプションを用いることで、ユーザスペースで管理するuserspaceモードや最小接続数ベースでの振り分けが可能なIPVS(IP Virtual Server)を選択することもできます。

kube-dnsやCoreDNSを用いてServiceの名前解決し、解決されたIPアドレスにアクセスできます。DNSの設定はPod内の/etc/resolv.confに記載されます。Podのspec.dnsPolicyを設定することで 、NodeやClusterのDNS設定を選択可能です

CoreDNSはkube-dnsの後継としての位置付けで、Kubernetes v1.11にGAになりました。

ダッシュボード

第三回で紹介したKubernetes Dashboardを用いると、k8sクラスタの構築や、クラスタの情報の確認をGUIで行えます。YAMLやJSONファイルのアップロードによる構築も可能です。

メトリクス収集とロギング

metrics-serverはPodやNodeのメトリクスの収集やfluentdを用いてログ収集と管理が可能です。Kubernetes v1.10まではHeapsterが使われていましたが、現在は非推奨となっています。kubectl top を用いてCPUやメモリの状況を確認したり、kubectl autoscaleを用いるためにはmetrics-serverが必要になります。minikube v1.4.0ではデフォルトで有効になっています。

$minikube addons list|grep metrics-server
-   metrics-server: enabled
$kubectl top node
NAME       CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
minikube   454m         22%    1408Mi          76%

標準出力・標準エラー出力の内容はkubectl logsを使って出力可能です。デフォルトでは10MBを超えた場合はlogrotateによりローテーションされます。

$kubectl logs counter
0: Thu Oct 31 16:59:31 UTC 2019
1: Thu Oct 31 16:59:32 UTC 2019
2: Thu Oct 31 16:59:33 UTC 2019
3: Thu Oct 31 16:59:34 UTC 2019

Nodeレベルでの簡易なロギングを行う場合は上記で十分ですが、クラスタレベルでのロギングを行う場合には、StackDriver(GCPの場合)やElasticSearchを用います。

*  *  *

今回はKubernetesのアーキテクチャについて紹介しました。API Serverを中心としたアーキテクチャをとっており、Desired Stateを維持するために各コンポーネントが自律的に動作します。これまでの基盤構築の考え方と一線を画すものと言えるでしょう。

kube-proxyやCoreDNSといったネットワークの設定や、ダッシュボード・ロギングのコンポーネントも併せて理解しておくとよいでしょう。

著者紹介


正野 勇嗣 (SHONO Yuji ) - NTTデータ 課長

2011年まで開発自動化技術のR&Dに従事。その後、開発プロジェクト支援やトラブルシューティング等に主戦場を移す。「ソースコード自動生成」に加えて、JenkinsやMaven等の「ビルド自動化」、JsTestDriverやSelenium等の「テスト自動化」を扱うようになり、多様化する開発自動化技術動向に興味。

最近は第四の自動化であるInfrastructure as Code等の「基盤自動化」の魅力に惹かれている。開発自動化技術に関する雑誌・記事執筆も行う。3児のパパ。