以前のブログ記事「Elastic StackをPrometheusとFluentdと組み合わせてKubernetesを監視する」で、PrometheusとFluentdをElastic Stackと組み合わせて使用して、Kubernetesを監視する方法をご紹介しました。既に利用しているオープンソースベースの監視ツールが組織内にある場合は、このような方法も有効ですが、これから新規でKubernetesを監視したい場合や、あるいはElastic Observabilityをフル活用したい場合は、もっと簡単で包括的な方法があります。本ブログでは、FilebeatとMetricbeatを使ったElastic流の方法で、Kubernetesを監視する方法を解説します。
FilebeatとMetricbeatを使う
Beatsは、ご存知の通り、データシッピングに特化した無料かつオープンなプラットフォームです。Beatsを活用することで、何百、何千ものマシンからLogstashやElasticsearchにデータを転送できます。
Filebeatは、軽量なログシッパーとして知られていますが、コンテナを多く使うアーキテクチャーにも対応しています。FilebeatはDockerやKubernetes、クラウド環境にもデプロイ可能で、全てのログストリーム収集に加え、コンテナ、ポッド、ノード、仮想環境、ホストやその他のメタデータも取得し、自動でログイベントと関連付けします。また、Metricbeatは、軽量なメトリックシッパーで、Filebat同様、コンテナにも対応しています。 Kubernetes環境では、コンテナは利用可能なワーカーノードにポッドとして、動的にデプロイされます。この「動的」というのが肝心ですが、FilebeatとMetricbeatには、Autodiscoverという便利な機能が備わっています。コンテナでアプリケーションを実行すると、それらは監視システムにとって移動する対象になります。Filebeat、MetricbeatのKubernetes Autodiscover Providerは、Kubernetesノード、ポッド、サービスの開始、更新、および停止を監視します。Filebeat、Metricbeatはこれらのイベントを検知すると、それぞれのイベントに適切なメタデータを利用可能にします。また、起動されたKubernetesポッドのアノテーションに応じて、処理対象のログ、メトリックに対して、適切な設定を適用します。 ヒントベースのAutodiscoverについては、Beatsを使用したDockerおよびKubernetesのヒントベースの自動探知機能(Autodiscover)で詳細について説明されていますので、参考にしてみてください。
モニタリングアーキテクチャ
前回同様、Cloud-Voting-Appというシンプルな、マルチコンテナアプリケーションをKubernetesクラスター上にデプロイし、そのアプリケーションを含めたKubernetes環境を監視します。今回は、Filebeatを使ってログを収集し、Metricbeatを使ってメトリックを収集し、直接Elasticsearchに投入し、Kibanaを使って監視する手順を説明していきます。また、Elastic APMを活用した、Promethuesカスタムメトリックの取得についても解説します。大まかなアーキテクチャは以下の図のようになります。また、ここでご紹介するコードは、GitHubレポに掲載していますので、完全な手順はそちらを参照してください。
それでは、各手順を見ていきましょう。
FilebeatをDaemonSetとしてデプロイする
Filebeatのインスタンスは、Kubernetesノード1つにつき1つデプロイします。DaemonSetのManifestは、elastic/filebeat-kubernetes.yaml
に定義されていますが、キーとなる設定を見ていきましょう。
まず、Kubernetes Autodiscover Providerを利用して、アプリケーションポッドのアノテーション設定を使ってログを処理できるように構成します。Autodiscoverの設定については、filebeat.autodiscover
セクションに定義しますが、ヒントを有効にして、コンテナログのデフォルトパスを設定しているだけです。FilebeatのAutodiscoverの設定の詳細については、Filebeatドキュメントを参照してください。
...
# To enable hints based autodiscover, remove `filebeat.inputs` configuration and uncomment this:
filebeat.autodiscover:
providers:
- type: kubernetes
node: ${NODE_NAME}
hints.enabled: true
hints.default_config:
type: container
paths:
- /var/log/containers/*${data.kubernetes.container.id}.log
...
それ以外では、基本的に出力先のElasticsearchのクラスターURLとクレデンシャル情報を追加するだけでOKです。
...
containers:
- name: filebeat
image: docker.elastic.co/beats/filebeat:7.13.0
args: [
"-c", "/etc/filebeat.yml",
"-e",
]
env:
- name: ELASTICSEARCH_HOST
value: elasticsearch
- name: ELASTICSEARCH_PORT
value: "9200"
- name: ELASTICSEARCH_USERNAME
value: elastic
- name: ELASTICSEARCH_PASSWORD
value: changeme
- name: ELASTIC_CLOUD_ID
value:
- name: ELASTIC_CLOUD_AUTH
value:
...
kube-state-metricsをデプロイする
kube-state-metricsは、Kubernetesにストアされているオブジェクトを監視するためのアドオンです。kube-state-metricsは、Kubernetesクラスター上のオブジェクトの状態を識別することに焦点を当てています。例えば、ある時点において、いくつポッドがクラスターにデプロイされているのか、割り当て可能なCPUコアはいくつあるのか、いくつジョブが失敗しているのか、などです。kube-state-metricsは、デフォルトではKubernetesクラスタにデプロイされていないので、自身でデプロイする必要があります。kube-state-metricsのサンプルManifestは、examples/standard
配下に定義されていますので、これを使ってデプロイすることができます。kube-state-metricsの詳細については、こちらのGitHubレポを参照ください。
MetricbeatをDaemonSetとしてデプロイする
Metricbeatのインスタンスは、Filebeatと同様に、Kubernetesノード1つにつき1つデプロイします。DaemonSetのManifestは、elastic/metricbeat-kubernetes.yaml
に定義されていますが、Filebeatに較べて少しトリッキーです。キーとなる設定を見ていきましょう。
Autodiscoverについての設定は、metricbeat.autodiscover
セクションに定義します。最初の- type: kubernetes
の設定は、Kubernetesクラスター全体に対するものです。ここでは、MetricbeatのKubernetesモジュールを使って、Kubernetesクラスター全体にかかるメトリックについて設定しています。最初の- module: kubernetes
の構成は、前述のkube-state-metricsから取得するメトリックについて設定しています。二番目の- module: kubernetes
の構成は、Kubernetes APIを公開する、Kubernetesコントロールプレーンの中心となるKubernetes APIサーバー(kube-apiserver)を監視するための設定です。MetricbeatのKubernetesモジュールについての詳細は、Metricbeatドキュメントを参照ください。
metricbeat.autodiscover:
providers:
- type: kubernetes
scope: cluster
node: ${NODE_NAME}
unique: true
templates:
- config:
- module: kubernetes
hosts: ["kube-state-metrics:8080"]
period: 10s
add_metadata: true
metricsets:
- state_node
- state_deployment
- state_daemonset
- state_replicaset
- state_pod
- state_container
- state_cronjob
- state_resourcequota
- state_statefulset
- state_service
- module: kubernetes
metricsets:
- apiserver
hosts: ["https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT}"]
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
ssl.certificate_authorities:
- /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
period: 30s
さらに、ヒントを有効にして、Kubernetes Autodiscover Providerを利用して、アプリケーションポッドのアノテーション設定を使ってメトリックを処理できるように設定します。MetricbeatのAutodiscoverの設定の詳細については、Metricbeatドキュメントを参照してください。
# To enable hints based autodiscover uncomment this:
- type: kubernetes
node: ${NODE_NAME}
hints.enabled: true
以下のConfigMapの設定は、MetricbeatのKubernetesモジュールのデフォルトのMetricsetである、node/system/pod/container/volumeについてのものです。これらのメトリックは、各ノードのkubelet endpointから取得されます。
kubernetes.yml: |-
- module: kubernetes
metricsets:
- node
- system
- pod
- container
- volume
period: 10s
host: ${NODE_NAME}
hosts: ["https://${NODE_NAME}:10250"]
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
ssl.verification_mode: "none"
あとは、Filebeat同様、基本的に出力先のElasticsearchのクラスターURLとクレデンシャル情報を追加するだけでOKです。
アプリケーションのデプロイ
前回ブログと同様、Cloud Votingアプリケーションをデプロイします。Cloud Votingアプリケーションは、ユーザーインターフェースをPython/Flask、データ層にRedisを使った、マルチコンテナの非常にシンプルなアプリケーションです。アプリケーションは、Prometheusのカスタムメトリックを公開するようにPrometheus Python Clientでインストゥルメントされていたことを思い出してください。今回、Prometheusをデプロイしていないのに、どうやってPromehteusのカスタムメトリックを収集するのでしょう?7.12から、Elastic APM Agentを使ってPrometheusのカスタムメトリックが取得できるようになったのです!
まず、アプリケーションコードでは、ElasticAPM
をインポートし、Elasitc APM Agentに必要な設定を環境変数からセットしています。SERVICE_NAME
は、アプリケーションを識別するための任意の文字列、ENVIRONMENT
は、アプリケーション環境を識別するための任意の文字列、SECRET_TOKEN
とSERVER_URL
は、APM Serverと通信するためのものです。最後のPROMETHEUS_METRICS
は、prometheus_clientからメトリックを取得するか否かを指示するパラメータです。
from elasticapm.contrib.flask import ElasticAPM
...
app = Flask(__name__)
...
# Elastic APM Configurations
app.config['ELASTIC_APM'] = {
# Set required service name. Allowed characters:
# a-z, A-Z, 0-9, -, _, and space
'SERVICE_NAME': os.environ['SERVICE_NAME'],
#
# Use if APM Server requires a token
'SECRET_TOKEN': os.environ['SECRET_TOKEN'],
#
# Set custom APM Server URL (default: http://localhost:8200)
'SERVER_URL': os.environ['SERVER_URL'],
#
# Set environment
'ENVIRONMENT': os.environ['ENVIRONMENT'],
#
# Set prometheus_metrics
'PROMETHEUS_METRICS': os.environ['PROMETHEUS_METRICS'],
}
apm = ElasticAPM(app)
次に示すのは、Cloud VotingアプリケーションをKubernetesクラスタにデプロイするためのManifestです。ファイルは、elastic/cloud-vote-all-in-one-redis-aks.yaml
に定義されています。まず、ユーザーインターフェースのcloud-vote-front
ですが、container specで環境変数として、前述のAPM Agentに必要な変数を設定しています。ここでは、ポッド固有のアノテーションは指定せず、ログ、メトリック共にデフォルトの設定で取得します。
apiVersion: apps/v1
kind: Deployment
metadata:
name: cloud-vote-front
spec:
replicas: 1
selector:
matchLabels:
app: cloud-vote-front
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
minReadySeconds: 5
template:
metadata:
labels:
app: cloud-vote-front
spec:
nodeSelector:
"beta.kubernetes.io/os": linux
containers:
- name: cloud-vote-front
image: your image name
ports:
- containerPort: 80
resources:
requests:
cpu: 250m
limits:
cpu: 500m
env:
- name: REDIS
value: "cloud-vote-back"
- name: SERVICE_NAME
value: "cloud-voting"
- name: SECRET_TOKEN
value: "APM Server secret token"
- name: SERVER_URL
value: "APM Server URL"
- name: ENVIRONMENT
value: "Production"
- name: PROMETHEUS_METRICS
value: "True"
一方、バックエンドのcloud-vote-redis
ですが、ポッドのannotations
により、ログについてはFilebeatのredisモジュールを、メトリックについてはMetricbeatのredisモジュールをそれぞれ有効にして、必要な設定をしています。この設定により、cloute-vote-frontがデフォルト設定のまま、ログやメトリックをBeatsで収集するのに対して、cloud-vote-backについては、Beatsのredisモジュールを使って、ログやメトリックを収集することが可能になります。また、このようにBeats側のManifestではなく、アプリケーション側のManifestで、どのようにログやメトリックを収集するかを設定することで、結果として、アプリケーションのDevチームとObservabilityプラットフォームのチームで責任を分離するという効果も得られます。
apiVersion: apps/v1
kind: Deployment
metadata:
name: cloud-vote-back
spec:
replicas: 1
selector:
matchLabels:
app: cloud-vote-back
template:
metadata:
labels:
app: cloud-vote-back
annotations:
co.elastic.logs/enabled: "true"
co.elastic.logs/module: redis
co.elastic.logs/fileset.stdout: log
co.elastic.metrics/enabled: "true"
co.elastic.metrics/module: redis
co.elastic.metrics/hosts: "${data.host}:6379"
spec:
nodeSelector:
"beta.kubernetes.io/os": linux
containers:
- name: cloud-vote-back
image: redis
ports:
- containerPort: 6379
name: redis
Kibanaから見てみよう
さて、これで必要なコンポーネントが全てデプロイできました。早速、Cloud Votingアプリで何度かVoteしてから、Kibanaにアクセスしてみましょう。
オブザーバビリティオーバービュー
まずは、KibanaからObservabilityを開いてみると、Filebeatから投入されたログのログレートや、Metricbeatから投入されたメトリックのサマリが、何もせずとも表示されています。これは、FilebeatやMetricbeatが、データをデフォルトでECSフォーマットで投入しているからこそなせる技です。
ログ
Filebeatから投入されたログは、filebeat-*というインデックスに書き込まれます。通常は、KibanaのLogsアプリを使って、Elasticsearchに収集した全てのログの検索、絞り込み、tailを実行できます。ご覧の通りに、特定の文字列、以下の例ではcloud-vote-front
でハイライト表示したりすることもできます。
メトリック
Metricbeatから投入されたメトリックは、metricbeat-*というインデックスに書き込まれます。KibanaのMetricsアプリを使って、Elasticsearchに収集したメトリックをわかりやすく、直感的に表示することができます。Kubernetes Pods
ビューで表示すれば、ご覧の通りKubernetesのノードとポッドをマッピングして、各リソースの利用状況を表示してくれます。
さらに特定のポッドをクリックすると、コンテキストを保持しながら、ポッドのログやAPMトレースなど、他のアプリにジャンプすることができます。View details for kubernetes.pod.uid a47d81b1-02d7-481a-91d4-1db9fe82d7a7
と画面に表示されていることに着目してください。
Kubernetes Pod logs
をクリックすると、このポッドのログにジャンプすることができます。Logsアプリのサーチバーにkubernetes.pod.uid: a47d81b1-02d7-481a-91d4-1db9fe82d7a7
と入力済みであることに気づきましたか?このように、Kibanaアプリ間でコンテキストとなる情報を引き継ぐことで、KibanaはElasticsearchで瞬時に検索をして、画面を切り替えているのです。
さて、Promethuesのカスタムメトリックは、どうなったでしょうか?Prometheus Python Clientで保持しているカスタムメトリックは、Elastic APM Agentを介して、apm-*というインデックスに書き込まれます。Kibana Discoverで確認すると、prometheus.metrics.cloud_votes
というフィールドで収集されていることがわかります。POST時の変数もlabels.vote
として取得できています。Elastic APM Python AgentによるPromethuesカスタムメトリックの収集についての詳細は、APMドキュメントを参照ください。
Kibana Lensでapm-*インデックスを可視化すれば、この通りです。
事前定義済みのダッシュボード
Redisを使っているcloud-vote-back
ポッドについては、Filebeat、Metricbeat共にredisモジュールを有効にしていました。これにより、すぐに使えるKibanaダッシュボードも事前作成されます。他に特別な設定をしなくても、すぐにRedisのログやメトリックを可視化できます。
さらに、Kubernetesに関するダッシュボードもこの通り、何もしなくても可視化されます。これは、MetricbeatのKubernetesモジュールのお陰です。
まとめ
今回は、FilebeatとMetricbeatを使って、Elastic Stackにログとメトリックを投入し、Kubernetesを監視する、よりElastic流の方法をご紹介しました。Elastic APM Agentを使って、Promethuesカスタムメトリックを取得する方法についても、見てきました。Elastic CloudのElasticsearch Service無料トライアルに登録したり、自前の環境にElastic Stackをダウンロードすれば、今日からお使いのKuberntes環境の監視を始めることができます。Elastic Observabilityを使えば、より効率的かつ効果的な監視が可能であることが、ご理解いただけたかと思います。また、Elasticの機械学習やKibana Alertingと組み合わせて、高度に自動化された、アクションに直結する包括的なオブザーバビリティを確立することも可能になります。お困りのことや、ご質問がおありの場合はディスカッションフォーラムをご活用ください。活発なコミュニティが待っています。
本ブログに続く将来の投稿では、Kubernetes環境の監視にElasticを活用した別の方法に引き続きご注目ください。