Motivation
Prometheus には Service Discovery という機能があり、監視対象のノードを自動的に補足し対象に追加する事が可能です。
(https://prometheus.io/docs/prometheus/latest/configuration/configuration/ の **_sd_config がそれらの設定になります。)
最近は Kubernetes などの Docker orchestration tool の普及により監視対象が動的に変化する環境が多く、Auto Scaling / Self Healing に自動的に追随して監視を行ってくれるツールの必須度が高くなっています。
個人的には Datadog が好きなので、同様な機能が Datadog にもあると良いな、と思っていたのですが、 Datadog でも AutoDiscovery という機能が提供されておりこちらを用いることで似たような事が実現可能です。
ここでは kubernetes 環境で動作させることを前提に、Docker の AutoDiscovery の設定方法について書きます。
構成
kubernetes についての説明は端折りますが、kubernetes では daemonset という機能を用いることで一つのホストインスタンス上に特定の docker image を一つだけ配置することができます。
datadog のような、一つのホストインスタンスに一つだけあれば良いような管理系の docker image については、daemonset として構成するのが一般的です。
(他に、fluentd なども同様な構成を取ることが多いです)
今回の例では
- daemonset: datadog
- deployment: nginx
という構成で kubernetes 上に配置し、datadog から各 nginx の監視を行います。
設定
namespace
とくに必然性はないのですが、ここでは sada4j とします。
apiVersion: v1
kind: Namespace
metadata:
name: sada4j
daemonset
datadog の設定を行います。
あらかじめ docker に最適化された docker-dd-agent というイメージがあるので、そちらをそのまま使います。
env にて、API Key や、Kubernetes 上で動作させる際に必要となる設定を入れていきます。
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: dd-agent
namespace: sada4j
spec:
template:
metadata:
labels:
app: dd-agent
name: dd-agent
spec:
containers:
- image: datadog/docker-dd-agent:latest
imagePullPolicy: Always
name: dd-agent
ports:
- containerPort: 8125
name: dogstatsdport
protocol: UDP
env:
- name: API_KEY
value: "<your api key>"
- name: KUBERNETES
value: "yes"
- name: SD_BACKEND
value: "docker"
- name: KUBERNETES_KUBELET_HOST
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: SD_CONFIG_BACKEND
value: "etcd"
- name: SD_BACKEND_HOST
value: "127.0.0.1"
- name: SD_BACKEND_PORT
value: "4001"
volumeMounts:
- name: dockersocket
mountPath: /var/run/docker.sock
- name: procdir
mountPath: /host/proc
readOnly: true
- name: cgroups
mountPath: /host/sys/fs/cgroup
readOnly: true
volumes:
- hostPath:
path: /var/run/docker.sock
name: dockersocket
- hostPath:
path: /proc
name: procdir
- hostPath:
path: /sys/fs/cgroup
name: cgroups
deployment
ここでは nginx を起動し、/nginx_status を有効にすることのみを目的としています。
それ以外の各種設定値はサービス運用を前提としたものではないいい加減なものです。
apiVersion: v1
kind: ConfigMap
metadata:
name: sada4j-nginx
namespace: sada4j
data:
nginx.conf: |-
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
location /nginx_status {
stub_status on;
access_log off;
}
}
}
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: sada4j-nginx
namespace: sada4j
spec:
replicas: 2
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
type: RollingUpdate
template:
metadata:
labels:
cluster_name: dev-sada4j-nginx
env: dev
project: sada4j
tier: app
annotations:
service-discovery.datadoghq.com/frontend.check_names: '["nginx"]'
service-discovery.datadoghq.com/frontend.init_configs: '[{}]'
service-discovery.datadoghq.com/frontend.instances: '[{"nginx_status_url": "http://%%host%%:%%port%%/nginx_status"}]'
spec:
containers:
- name: frontend
image: nginx:alpine
ports:
- containerPort: 80
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
volumes:
- name: nginx-config
configMap:
name: sada4j-with-nginx
---
apiVersion: v1
kind: Service
metadata:
name: sada4j-nginx
namespace: sada4j
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
selector:
cluster_name: dev-sada4j-nginx
設定ファイルが長くなっていますが、ここでの要点は以下の部分です。
annotations:
service-discovery.datadoghq.com/frontend.check_names: '["nginx"]'
service-discovery.datadoghq.com/frontend.init_configs: '[{}]'
service-discovery.datadoghq.com/frontend.instances: '[{"nginx_status_url": "http://%%host%%:%%port%%/nginx_status"}]'
kubernetes の annotations 情報として、当該 pod の監視設定を記述しています。
こうすることで、datadog の agent が監視対象の container image と、何を監視するかについて知ることができる、という仕組みになっています。
各設定値については、以下のように設定する必要があります。
-
service-discovery.datadoghq.com/.check_names
- 監視対象のスクリプトの名前です。datadog-dd-agent に同梱されているか、 datadog の docker image 内の /etc/dd-agent/checks.d/ 配下に設置されている checks スクリプトで同名のものがあれば、ここで指定された名前の監視スクリプトを実行します。
-
service-discovery.datadoghq.com/.init_configs
- 監視処理を行うスクリプトの init_config に渡すパラメータを設定します。何を渡せるかは監視スクリプトの作り次第になります。
- https://docs.datadoghq.com/ja/guides/agent_checks/#init-config
- nginx の監視スクリプトには特に init_config に渡せる値はないので空の連想配列を渡しています。
-
service-discovery.datadoghq.com/.instances
- 監視処理を行うスクリプトの instances に渡すパラメータを設定します。何を渡せるかは監視スクリプトの作り次第になります。
- https://docs.datadoghq.com/ja/guides/agent_checks/#instances
- nginx の監視スクリプトでは、監視対象の nginx のURL を指定できる ( nginx_status_url ) ので、上記例ではそちらを設定しています。
設定をする際に、以下がハマりやすいので注意が必要です。
-
container_name の部分は、 containers に記述している name の値と一致している必要があります。
- 上記例だと frontend
- 一つの annotation 記述で、複数の監視スクリプトを指定することが出来ます。
- ex. service-discovery.datadoghq.com/frontend.check_names: '["nginx", "jmx"]'
- etcd にこちらの情報が書き込まれるのですが、左辺の値が key 文字列として用いられるので、複数の監視スクリプトを設定する場合は上記のようにしないとうまく動きません。
上記のような設定をすることで、container image を apply したタイミング、もしくは container image の数を増やしたタイミングで、自動的に追加された container が監視対象になります。
動作確認
ただしく AutoDiscovery の設定を反映して監視スクリプトが動いているかどうか、結構判別が面倒くさいのですが、以下の2つの視点で確認をします。
1. Datadog に値が送られているかどうか確認する
意図した値が Datadog に送られているか、metrics explorer などで確認をします。
2. datadog-agent info コマンドの結果を確認する
daemonset として起動している dd-agent の docker container の中に入り、datadog-agent info というコマンドを叩くと、現在 dd-agent が収集を行っているメトリクスの一覧が確認できます。
上記の設定例だと、ここで nginx のスクリプトが含まれていれば、OK です。
$ /etc/init.d/datadog-agent info
====================
Collector (v 5.21.1)
====================
(snip.)
Checks
======
nginx (5.21.1)
--------------
- instance #0 [OK]
- Collected 7 metrics, 0 events & 1 service check
network (5.21.1)
----------------
- instance #0 [OK]
- Collected 20 metrics, 0 events & 0 service checks
kubernetes (5.21.1)
-------------------
- instance #0 [OK]
- Collected 108 metrics, 0 events & 3 service checks
(snip.)
Checks に nginx が含まれているので、正しく監視対象となっている、と判断できます。
エラーになっている際は、 /var/log/dd-agent/collector.log などを確認するとその状況が把握できるかもしれません。
まとめにかえて
datadog の autodiscovery 周りは極めてドキュメントもなく動きを把握するのが結構たいへんだったので、個人的な備忘録的にまとめました。