kibana
grafana
kubernetes
DashBoard

k8sメトリックスのモニタリングとログ分析について調べたメモ

KubernetesのCNCFプロジェクトのドキュメントは、古いもの、新しいもの、意気込み表明のもの、などなど色々なもの混合になっていて、何を取り入れたら適切なのか解りづらいところが苦しい。 もちろん、クラウドベンダーのドキュメントと合わせて見るのが良いが、それでも、基本的なことは、OSSプロジェクトの資料で勉強してから来てね… という立場を取られる事も少なくないから、Kubernetesの技術を習得し難いと感じる。

今回は、Kubernetesの Task, Moniror, Log and Debugのモニタリングツールやロギングツールの一部について、調べて解ったことを書き残しておきます。

今回も、実際にソフトウェアを実際に動かして、ドキュメントと実装を確認しながら書いていきます。 vagrantでのKubernetesクラスタの構築、そして、適用したYAMLファイル等は、https://github.com/takara9/vagrant-k8s においてあります。


コアメトリックス・パイプライン Core metrics pipeline

Heapsterをインストールしていれば、kubectl topコマンドを利用することができる。ウェブブラウザを操作しなくても、CPUとメモリの使用量を絶対値と相対値で知ることが便利で便利なコマンドである。 これは、k8sのAPIサーバーのエンドポイント以下のパスで/apis/metrics.k8s.io/でアクセスでき、セキュリティ、スケーラビリティ、信頼性を提供するとされています。

しかし、注意書きが有り、"Metrics Server"がデプロイされていないと使えいないとある。 しかし、インストールのガイドの通りに実行しても、"kubectl topの実行例"からも判る通り、インストールされていません。

kubectl top の実行例

vagrant@node-1:~$ kubectl top node
NAME      CPU(cores)   CPU%      MEMORY(bytes)   MEMORY%   
node-1    85m          8%        931Mi           49%       
node-2    37m          3%        846Mi           44%       
node-3    32m          3%        1342Mi          70%       

vagrant@node-1:~$ kubectl top pod
NAME                     CPU(cores)   MEMORY(bytes)   
nginx-6f596bfb6d-dc5l6   0m           2Mi             

vagrant@node-1:~$ kubectl top pod --all-namespaces
NAMESPACE     NAME                                    CPU(cores)   MEMORY(bytes)   
default       nginx-6f596bfb6d-dc5l6                  0m           2Mi             
kube-system   elasticsearch-59d89bf8d-wlp4h           6m           793Mi           
kube-system   etcd-node-1                             8m           53Mi            
kube-system   fluentd-9rbz6                           2m           72Mi            
kube-system   fluentd-9wnp9                           2m           77Mi            
kube-system   heapster-69b5d4974d-84d9n               0m           28Mi            
kube-system   kibana-7959c48fd-8glxv                  3m           235Mi           
kube-system   kube-apiserver-node-1                   16m          239Mi           
kube-system   kube-controller-manager-node-1          23m          39Mi            
kube-system   kube-dns-86f4d74b45-plmnd               0m           23Mi            
kube-system   kube-flannel-ds-8g82w                   1m           9Mi             
kube-system   kube-flannel-ds-bfj67                   1m           9Mi             
kube-system   kube-flannel-ds-tz9nj                   1m           10Mi            
kube-system   kube-proxy-5lcb5                        1m           10Mi            
kube-system   kube-proxy-g75c9                        1m           10Mi            
kube-system   kube-proxy-vjph7                        2m           10Mi            
kube-system   kube-scheduler-node-1                   7m           11Mi            
kube-system   kubernetes-dashboard-7d5dcdb6d9-lzl86   0m           16Mi     

Metrics Serverは、どこに行ったのかと、ソースコード https://github.com/kubernetes-incubator/metrics-server を参照すると、"kubernetes-incubator" となっており、https://github.com/kubernetes/community/blob/master/contributors/design-proposals/instrumentation/metrics-server.md では、Kubernetesの設計として受理された提案というレベルの様に伺えます。

この様な情報から、k8sのインストーラーから普通に導入されるレベルにならないと、ここに依存するには、早すぎるという印象を受けました。


計算、ストレージ、そして、ネットワークの資源監視ツール

(Tools for Monitoring Compute, Storage, and Network Resources)

この章では、Kubernetesのモニタリングのアーキテクチャとして引用される事も多い下図があります。 この図から、Heapsterは、Nodeの一つに常駐して、自己が存在するノード、および、他のすべてのノードの kubelet と連携して、Storage Backendで何かを送り出す役割であることが理解できます。

スクリーンショット 2018-05-06 10.18.18.png

Kubelt

Kubeletは、Kubernetesマスターと各ノードの間の橋渡しとして機能します。Kubeletは、各ポッドを構成コンテナに変換し、cAdvisorから個々のコンテナ使用統計をフェッチします。 次に、集約されたポッドリソース使用統計をREST APIを介して公開します。

cAdvisorについて

Advisorは、オープンソースコンテナリソースの使用状況とパフォーマンス分析エージェントです。コンテナ用に専用に設計されたもので、ネイティブにDockerコンテナをサポートしています。Kubernetesでは、cAdvisorはKubeletバイナリに統合されています。cAdvisorは、マシン内のすべてのコンテナを自動検出し、CPU、メモリ、ファイルシステム、およびネットワーク使用状況の統計情報を収集します。つまり、cAdvisorは、kubeletの一部として動作しているとの事です。 ここで、ポート4194でウェブUIを提供しているとなっていますが、しかし、現在(1.10)、k8sのインストーラのパッケージでは、次の様にセキュリティの観点から 4194ポートは閉じられているので、ドキュメントを鵜呑みにしない様に注意が必要です。 後述するPrometheusは、プル型のメトリックス収集をおこなう時系列データベースであるが、ポート番号を10255に変更しなければ、メトリックスを収集できません。

vagrant@node-1:~$ cat /etc/systemd/system/kubelet.service.d/10-kubeadm.conf |grep cadvisor
Environment="KUBELET_CADVISOR_ARGS=--cadvisor-port=0"

Heapster

現在の公式のKubernetesダッシュボードでは、CPU /メモリー使用率メト​​リックを表示するためにHeapsterが使用されています。ダッシュボードがPrometheusと他のプラグイン可能な監視ソリューションをサポートするというオープンな機能要求が存在しますが、今のところ、Heapsterはどのプロダクション・クラスタにとっても欠かせないコンポーネントです。

Heapsterの機能要約

  • モニターおよびイベント・データをKubernetesクラスター全体から集約する
  • ネイティブにサポートされ, すべてのバージョンで動作
  • クラスタ内でポッドとして動作、アプリケーション実行と同様
  • クラスタ内のすべてのノードを検出し、各ノードのKubeletから情報を収集、Kubeletは、cAdvisorからデータを取得
  • 関連するラベルとともにポッドで情報をグループ化、ストレージとビジュアライゼーションのために構成可能なバックエンドにプッシュ
  • 現在サポートされているバックエンドには、InfluxDB(視覚化のためのGrafana)

ストレージバックエンド (Storage Backends)

InfluxDB と Grafana が紹介されている。 現在、主流のPrometheusとGrafanaの組み合わせと比べると、この組み合わせ専用のコンテナが提供されており、ただちに、使い始められる点で、とても便利である。

Heapster-InfluxDB-Grafana 実行例

以下の利用しているyamlファイルは、https://github.com/kubernetes/heapster/tree/master/deploy/kube-config/influxdb を k8s 1.10 の vagarantの環境に合わせて、動作する様に修正したものです。 heapsterは、'kubectl top'を実行するために、予め動かしていたので、unchanged になっています。 4つのYAMLファイルを適用するだけで、前述の図の構成を作り、Grafanaのウェブ画面でモニタすることができる様になります。

vagrant@node-1:~$ kubectl apply -f https://raw.githubusercontent.com/takara9/vagrant-k8s/master/mon-influxdb/heapster-rbac.yaml
clusterrolebinding.rbac.authorization.k8s.io "heapster" configured

vagrant@node-1:~$ kubectl apply -f https://raw.githubusercontent.com/takara9/vagrant-k8s/master/mon-influxdb/heapster.yaml
serviceaccount "heapster" unchanged
deployment.extensions "heapster" unchanged
service "heapster" unchanged

vagrant@node-1:~$ kubectl apply -f https://raw.githubusercontent.com/takara9/vagrant-k8s/master/mon-influxdb/influxdb.yaml
deployment.extensions "monitoring-influxdb" created
service "monitoring-influxdb" created

vagrant@node-1:~$ kubectl apply -f https://raw.githubusercontent.com/takara9/vagrant-k8s/master/mon-influxdb/grafana.yaml
deployment.extensions "monitoring-grafana" created
service "monitoring-grafana" created

vagrant@node-1:~$ kubectl get svc -n kube-system
NAME                   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                         AGE
heapster               ClusterIP   10.244.216.216   <none>        80/TCP                          1h
monitoring-grafana     NodePort    10.244.20.94     <none>        80:31500/TCP                    24s
monitoring-influxdb    ClusterIP   10.244.163.105   <none>        8086/TCP                        48s

InfluxDB - Grafana モニタリング画面

前述のYAMLの適用結果で、vagrant仮想サーバーをブラウザから、http://(ip-address-of-node-1):31500/ としてアクセスすることで、Grafanaの画面を閲覧することができます。カッコ内は、IPアドレスに置き換えてください。 GitHub Vagrantfileの設定を使ったとすれば、192.168.1.91になります。

スクリーンショット 2018-05-06 11.15.15.png

ダッシュボードのテンプレートと普及状況

こんなに便利で手軽ならば、広く多く使われ、主流のツールになっていると考えたくなるのですが、そうなっていません。 コミュニティで作成されたダッシュボードを、データソース:InfuxDB の条件で検索すると、わずか5件だけで、ダウンロード数も1000未満となっています。

スクリーンショット 2018-05-06 11.26.14.png


Kubenetes ダッシュボード

せっかく、Heapsterを動かしたので、ダッシュボードのグラフを見てみたいと思います。 ダッシュボードの設定方法は、K8s on Vagrant, ダッシュボードのセットアップ を参照してください。 Heapsterが動作していない場合は、円グラフの上のCPU Usage と Memory Usageのグラフは表示されません。

スクリーンショット 2018-05-06 11.31.52.png

次のポッドのサマリー画面では、Heapsterが動作していないと、CPU(コア数)とメモリ(バイト)列が表示されません。

スクリーンショット 2018-05-06 11.32.12.png


プロメテウス Prometheus

僕は、プロメテウスという音を聞くと、何故か銀河鉄道999の優しくて美しいメーテルの怖ーいおっかさん、プロメシュームが連想してしまいます。プロメシューム(プロメチウム)は、元素(Pm)の名前でもあり、天然に存在するものは確認されず,1945年に核分裂生成物から初めて存在が確認されたため、ギリシャ神話に出て来る英雄プロメテウスが天上から火を盗んだかどで岩山に鎖で縛られた話にちなんで、元素に付けられた名前です。

どうでも良い話は、ここまでにして、

プロメテウスは、もともとSoundCloudで構築されたオープンソースのシステム監視と警報のツールキット です。2012年の創業以来、多くの企業や組織がプロメテウスを採用しており、このプロジェクトは非常に活発な開発者とユーザーコミュニティを持っています。これは現在、スタンドアロンのオープンソースプロジェクトであり、どの企業からも独立して管理されています。これを強調し、プロジェクトのガバナンス構造を明確にするために、プロメテウスはKubernetesの後の第2のホストプロジェクトとして2016年にCloud Native Computing Foundationに参加しました。 https://prometheus.io/docs/introduction/overview/ には、プロメテウスの特徴や得意とするユースケースが記載されています。

プロメテウスは、cAdvisor, node-expoter, kube-state-metrics などのメトリックス・コレクタと呼ばれるCPU,メモリ、ネットワークなどの使用量をノード、コンテナ、ポッドなどの単位で収集するソフトウェアです。

プロメテウスの設定として、prometheus.yamlファイルに、メトリックス・コレクタのジョブを定義しておくことで、例えば 10秒 間隔で情報を収集して、蓄積していってくれます。 k8sでプロメテウスを利用する場合には、prometheus.yamlを ConfigMapとして名前空間下のクラスタ環境に統督して、プロメテウスのポッドから、ConfigMapをボリュームとしてマウントして利用します。

次のプロメテウスの実行例は、vagrantのk8sクラスタ用にカスタマイズしたもので、https://github.com/takara9/vagrant-k8s/tree/master/mon-prometheus に置いてある YAMLファイルを適用したものです。

vagrant@node-1:/vagrant$ kubectl top node
NAME      CPU(cores)   CPU%      MEMORY(bytes)   MEMORY%   
node-1    83m          8%        968Mi           50%       
node-2    37m          3%        848Mi           44%       
node-3    34m          3%        1418Mi          74% 

vagrant@node-1:/vagrant/prometheus$ kubectl apply -f https://raw.githubusercontent.com/takara9/vagrant-k8s/master/mon-prometheus/rbac.yaml 
clusterrolebinding.rbac.authorization.k8s.io "kube-state-metrics" created
clusterrole.rbac.authorization.k8s.io "kube-state-metrics" created
serviceaccount "kube-state-metrics" created
clusterrolebinding.rbac.authorization.k8s.io "prometheus" created
clusterrole.rbac.authorization.k8s.io "prometheus" created
serviceaccount "prometheus-k8s" created

vagrant@node-1:/vagrant/prometheus$ kubectl apply -f https://raw.githubusercontent.com/takara9/vagrant-k8s/master/mon-prometheus/node-exporter.yaml 
daemonset.extensions "node-exporter" created

vagrant@node-1:/vagrant/prometheus$ kubectl apply -f https://raw.githubusercontent.com/takara9/vagrant-k8s/master/mon-prometheus/kube-state-metrics.yaml 
deployment.extensions "kube-state-metrics" created

vagrant@node-1:/vagrant/prometheus$ kubectl apply -f https://raw.githubusercontent.com/takara9/vagrant-k8s/master/mon-prometheus/prometheus-configmap.yaml 
configmap "prometheus-core" created
configmap "prometheus-rules" created

vagrant@node-1:/vagrant/prometheus$ kubectl apply -f https://raw.githubusercontent.com/takara9/vagrant-k8s/master/mon-prometheus/prometheus.yaml 
deployment.extensions "prometheus-core" created
service "prometheus" created

vagrant@node-1:/vagrant/prometheus$ kubectl apply -f https://raw.githubusercontent.com/takara9/vagrant-k8s/master/mon-prometheus/grafana.yaml 
deployment.extensions "grafana-prometheus" created
service "grafana-prometheus" created

vagrant@node-1:/vagrant/prometheus$ kubectl top node
NAME      CPU(cores)   CPU%      MEMORY(bytes)   MEMORY%   
node-1    126m         12%       992Mi           52%       
node-2    171m         17%       874Mi           46%       
node-3    189m         18%       1525Mi          80%     

Grafanaセットアップ

上記の設定を変更していなければ、http://192.168.1.91:31510/ でGrafanaへのログイン画面が表示されます。 Grafanaへは、admin/adminでログインできます。

スクリーンショット 2018-05-06 13.21.28.png

データソースの設定

先ほどは、InfuxDB用に作られたコンテナのGrafanaでしたから設定が不要でしたが、こちらは設定操作が必要です。 次の画面から add data sourceをクリックします。

スクリーンショット 2018-05-06 13.21.45.png

設定画面で入力するには、3箇所です。 Nameにデータソースが識別できる名前をセットします。Typeは選択リストになっているので、Prometheusを選択します。 そして、最後にHTTP URLのフィールドに、http://prometheus:9090 をセットして、「Save & Test」をクリックして "Data source is working" が表示されたら完了です。

スクリーンショット 2018-05-06 13.22.35.png

ダッシュボードの選択

サイドメニューのダッシュボードのアイコンをクリックして、画面上のHOMEの表示をクリックすると、次の画面が出ます。 右側のメニューの一番下 "Find dashboard on Grafana.com" をクリックします。

スクリーンショット 2018-05-06 13.23.49.png

別のタブに、Grafana.comのダッシュボードの検索画面があらわれます。そこで、"Filter by:"のフィールドに、次の様にセットして、ダッシュボードを絞り込みます。 Data Source に、"Prometheus", Search within this list に "kubernetes" とすると、プロメテウスでKubernetesに関するダッシュボードが表示されます。 この中で、最もダウンロード数が多い下から2番目をクリックします。

スクリーンショット 2018-05-06 13.25.39.png

ダッシュボードの番号が表示されるので、クリップボードにコピーしておくか、番号を暗記します。 インポートの画面に戻って、番号をインプットして "Load" をクリックします。

スクリーンショット 2018-05-06 13.26.16.png

データソースに、Prometheusに設定した名前を選択します。これで、k8sクラスタを監視するダッシュボードが表示される様になりました。簡単ですね。それに、ダッシュボードはコミュニテーで作られたた沢山のアセットがありますから、Grafanaを知らなくても、色々なビューで見ることができます。

スクリーンショット 2018-05-06 13.26.51.png

メトリックスコレクタの設定

プロメテウスが、メトリクス・コレクタへポーリングして、収集する状況を見ることができるのが、次の画面です。これは、PrometheusのサービスをNodePortで外部へ開いて、ブラウザからアクセスする事で参照できます。 ここでは、http://192.168.1.91:31600/target で参照できます。 これは、prometheus.yamlファイルによって定義されたジョブの実行結果を表しており、不適切な設定があると、Sateの列にDOWNとして表示されます。

スクリーンショット 2018-05-06 13.55.07.png

このPrometheusの設定は、ConfigMapとして環境にデプロイしていますから、configmapをリストして、名前を確認して、エディットすることができます。 または、元のYAMLファイル prometheus-configmap.yaml で編集します。

vagrant@node-1:~$ kubectl get configmap -n kube-system
NAME                                 DATA      AGE
prometheus-core                      1         1h

vagrant@node-1:~$ kubectl edit configmap prometheus-core -n kube-system

ファイルを編集させた後は、該当のポッドを削除する事で先起動させて、設定を反映させます。

$ kubectl get po -n kube-system |grep prometheus-core
prometheus-core-7c5bfbb4d4-sf79n        1/1       Running   0          1h

$ kubectl delete po prometheus-core-7c5bfbb4d4-sf79n -n kube-system 
pod "prometheus-core-7c5bfbb4d4-sf79n" deleted

$ kubectl get po -n kube-system |grep prometheus-core
prometheus-core-7c5bfbb4d4-9zjr7        0/1       ContainerCreating   0          18s

$ kubectl get po -n kube-system |grep prometheus-core
prometheus-core-7c5bfbb4d4-9zjr7        1/1       Running   0          26s

プロメテウス・オペレータ

Kubernetes AddOn の プロメテウス には、このコードはE2Eテスト用であり、本番利用には、Kubernetes Operator または Kube-Prometheusなどの成熟したセットアップを確認する様にとのコメントもある。 KubeCon2018 の RedHat社のキーノートセッションでも、オペレータフレームワークを紹介していた事もあり、今後、注目しておくべき、プロジェクトの一つではないかと思う。


ログ分析 ElassticSearch

並列分散クラスタの実行環境で、クラスタを構成するサーバーの中で、それぞれログが出力されていると、ログの分析や問題判別が、とても大変な作業になります。 この課題を解決するために、クラスタ環境では、ログ転送ツール fluentd を使用して、全文検索データベース ElassticSearchへ蓄積して、 ブラウザUI Kibana で視覚化と分析が、一般的になっています。 Kubernetesのクラスタ環境でも同じ状況にあります。

ElassticSearch, Kibana, Fluentdは、コンテナとして、DockerHubでも公開さてており、Kubernetes上でも利用することができます。また、本番環境を想定した構成のYAMLファイルなどもあります。

しかし、ElassticSearchは、大規模なログ分析を想定したツールなので、本番環境用の設定では、小さな小さなvagrant上で手軽に動かすことができません。 そこで、デベロパー用モードのElassticSearch環境を構築して、検証してみます。

以下の3本のYAMLファイルは、標準的なRBAC下用の Fluentd, vagrant環境用にカスタマイズした、ElasstiecSearch, Kibanaです。

$ kubectl apply -f https://raw.githubusercontent.com/takara9/vagrant-k8s/master/mon-elasticsearch/elasticsearch.yaml

$ kubectl apply -f https://raw.githubusercontent.com/takara9/vagrant-k8s/master/mon-elasticsearch/kibana.yaml

$ kubectl apply -f https://raw.githubusercontent.com/takara9/vagrant-k8s/master/mon-elasticsearch/fluentd-daemonset-elasticsearch-rbac.yaml

このファイルを適用することで、http://192.168.1.91:31601/ でKibanaの画面を参照できる様になります。
スクリーンショット 2018-05-06 14.52.15.png

NGINXを使用したお試しのログ分析

以下のYMALを提供して、NGINXのサーバーを作り、curlで連続してアクセスして、アクセスログを出力させ、ElassticSearchで収集して、Kibanaでグラフ化してみます。

$ kubectl apply -f https://raw.githubusercontent.com/takara9/vagrant-k8s/master/mon-elasticsearch/nginx.yaml

$ imac:~ maho$ while true; do curl http://192.168.1.91:32000/;sleep 1; done
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
...continue...

収集したログデータに、タイムスタンプでインデックスを付与することで、次の様なリクエスト数の推移を出すことができます。
スクリーンショット 2018-05-06 15.32.55.png

まとめ

今回、解ったことを列挙します。 ドキュメントを読んだだけでは正しい理解はできず、実際に動作させてみて、判る事も多いと再実感した。

  • CNCFプロジェクトTask, Moniror, Log and Debugの幾つかの文書は古かったり、早すぎるものがあり、読者自身が吟味しなければならない。
  • Metrics_server は、インキュベーションレベルであり、インストーラによるセットアップでは導入されない。
  • Heapsterは、ダッシュボードやkubectl topコマンドで、CPUやメモリの使用量を表示するために必須なコンポーネントである。
  • Heapster - InfluxDB - Grafana は簡単に設定できて便利であるが、利用者は少数であり、コミュニティも活発ではない。
  • Prometheus - Grafana の組み合わせは、活発で、メトリックス・コレクタ、Grafanaダッシューボードなども活発な活動が続いている。
  • Prometheusオペレータ、kube-Prometheusは、注目しておくべき、プロジェクトであろうと思う。
  • Fluentd - ElassticSeach - Kibana は、k8sでもログ分析の主流である、しかし、Javaで開発されている事もあり、大量のメモリを消費するため、本番運用時には注意が必要である。

k8s on Vagrant の他記事

この記事は、自分のMacOS上のVagrant環境で、小さなKubernetesクラスタを構築して、検証した記録の一部です。これまでに、Vagrantの仮想サーバーのk8sクラスタで、以下の検証を進めてきましたので、参考までにリンクを挙げておきます。

  1. Kubenetes v1.10 クラスタをVagrantで構築したメモ
  2. K8s on Vagrant, Node障害時の振る舞いについての検証記録
  3. K8s on Vagrant, ダッシュボードのセットアップ
  4. K8s on Vagrant, NFS 永続ボリュームの利用メモ
  5. K8s on Vagrant, NGINX Ingress Controller の利用
  6. K8s on Vagrant, Workerノードの追加と削除
  7. K8s on Vagrant, kube-keepalived-vip を利用したサービスIP設定
  8. K8s on Vagrant, MetalLB BGP ECMP を利用したロードバランサーの検証