先日のOperatorを使ったK8sクラスタへのデプロイは全自動だったので一体何が動いたのか!?という感じだったので、Prometheusのコンポーネントや動きを理解するために、素のPrometheusを使いGetting Startedの内容に沿って動かしてみる。
環境はCentOS 7
$ cat /etc/redhat-release CentOS Linux release 7.8.2003 (Core)
Prometheus本体を動かす
Prometheusの入手
2020.10.14時点で2.20のRC版がリリースされてるが、とりあえず2.21.0で。
$ curl -LO https://github.com/prometheus/prometheus/releases/download/v2.21.0/prometheus-2.21.0.linux-amd64.tar.gz $ tar xf prometheus-2.21.0.linux-amd64.tar.gz
設定サンプル
アーカイブ内には、設定サンプル込みのpromehteus.yml
が含まれている。
サンプルの内容は、Prometheusサーバー自身のデータを収集する内容になっている。
# my global config global: scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute. evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute. # scrape_timeout is set to the global default (10s). # Alertmanager configuration alerting: alertmanagers: - static_configs: - targets: # - alertmanager:9093 # Load rules once and periodically evaluate them according to the global 'evaluation_interval'. rule_files: # - "first_rules.yml" # - "second_rules.yml" # A scrape configuration containing exactly one endpoint to scrape: # Here it's Prometheus itself. scrape_configs: # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config. - job_name: 'prometheus' # metrics_path defaults to '/metrics' # scheme defaults to 'http'. static_configs: - targets: ['localhost:9090']
実行
prometheus
実行バイナリを直接実行する。
実行時には設定ファイルを引数で指定。
[zaki@cloud-dev prometheus-2.21.0.linux-amd64]$ ls -F LICENSE NOTICE console_libraries/ consoles/ prometheus* prometheus.yml promtool* [zaki@cloud-dev prometheus-2.21.0.linux-amd64]$ ./prometheus --config.file=prometheus.yml level=info ts=2020-10-14T12:07:52.694Z caller=main.go:310 msg="No time or size retention was set so using the default time retention" duration=15d level=info ts=2020-10-14T12:07:52.694Z caller=main.go:346 msg="Starting Prometheus" version="(version=2.21.0, branch=HEAD, revision=e83ef207b6c2398919b69cd87d2693cfc2fb4127)" level=info ts=2020-10-14T12:07:52.694Z caller=main.go:347 build_context="(go=go1.15.2, user=root@a4d9bea8479e, date=20200911-11:35:02)" level=info ts=2020-10-14T12:07:52.696Z caller=main.go:348 host_details="(Linux 3.10.0-1127.19.1.el7.x86_64 #1 SMP Tue Aug 25 17:23:54 UTC 2020 x86_64 cloud-dev (none))" level=info ts=2020-10-14T12:07:52.696Z caller=main.go:349 fd_limits="(soft=4096, hard=4096)" level=info ts=2020-10-14T12:07:52.696Z caller=main.go:350 vm_limits="(soft=unlimited, hard=unlimited)" level=info ts=2020-10-14T12:07:52.707Z caller=main.go:701 msg="Starting TSDB ..." level=info ts=2020-10-14T12:07:52.709Z caller=web.go:523 component=web msg="Start listening for connections" address=0.0.0.0:9090 level=info ts=2020-10-14T12:07:52.715Z caller=head.go:644 component=tsdb msg="Replaying on-disk memory mappable chunks if any" level=info ts=2020-10-14T12:07:52.715Z caller=head.go:658 component=tsdb msg="On-disk memory mappable chunks replay completed" duration=7.065µs level=info ts=2020-10-14T12:07:52.715Z caller=head.go:664 component=tsdb msg="Replaying WAL, this may take a while" level=info ts=2020-10-14T12:07:52.715Z caller=head.go:716 component=tsdb msg="WAL segment loaded" segment=0 maxSegment=0 level=info ts=2020-10-14T12:07:52.715Z caller=head.go:719 component=tsdb msg="WAL replay completed" checkpoint_replay_duration=22.965µs wal_replay_duration=313.668µs total_replay_duration=378.051µs level=info ts=2020-10-14T12:07:52.717Z caller=main.go:721 fs_type=XFS_SUPER_MAGIC level=info ts=2020-10-14T12:07:52.717Z caller=main.go:724 msg="TSDB started" level=info ts=2020-10-14T12:07:52.717Z caller=main.go:850 msg="Loading configuration file" filename=prometheus.yml level=info ts=2020-10-14T12:07:52.720Z caller=main.go:881 msg="Completed loading of configuration file" filename=prometheus.yml totalDuration=3.638807ms remote_storage=4.799µs web_handler=447ns query_engine=939ns scrape=3.217009ms scrape_sd=67.157µs notify=25.552µs notify_sd=19.669µs rules=1.612µs level=info ts=2020-10-14T12:07:52.720Z caller=main.go:673 msg="Server is ready to receive web requests."
これで、ブラウザで9090/tcpにアクセスすればPrometheusのweb UIが表示される。
※ firewalldが動いているなら9090/tcpを空ける
[zaki@cloud-dev ~]$ sudo firewall-cmd --add-port=9090/tcp success
自身のメトリクス値
ここにアクセスすると、実行したPrometheus自身の、Prometheusが値を取得しに来た時に返すメトリクス値の一覧が表示される。(ややこしいな)
言い換えると、Prometheusはターゲット(この場合は自分自身)の/metrics
にアクセスしてメトリクスを収集する。
値のクエリー
例としてprometheus_target_interval_length_seconds
の値を出してみる。
まずは「- insert metric at cursor」のドロップダウンメニューからprometheus_target_interval_length_seconds
を選択する。
選択したら"Execute"を押下。すると下部にqueryの結果が表示される。
ちなみに http://localhost:9090/metrics にアクセスして表示されるメトリクス値は以下の通りなので、queryにヒットして表示された値と一致していることがわかる。
: : # HELP prometheus_target_interval_length_seconds Actual intervals between scrapes. # TYPE prometheus_target_interval_length_seconds summary prometheus_target_interval_length_seconds{interval="15s",quantile="0.01"} 14.99985301 prometheus_target_interval_length_seconds{interval="15s",quantile="0.05"} 14.999877942 prometheus_target_interval_length_seconds{interval="15s",quantile="0.5"} 15.000014192 prometheus_target_interval_length_seconds{interval="15s",quantile="0.9"} 15.00010798 prometheus_target_interval_length_seconds{interval="15s",quantile="0.99"} 15.000207268 prometheus_target_interval_length_seconds_sum{interval="15s"} 990.0011557570001 prometheus_target_interval_length_seconds_count{interval="15s"} 66 : :
値の絞り込み
クエリーのprometheus_target_interval_length_seconds
に条件を追加してみる。
具体的にはprometheus_target_interval_length_seconds{quantile="0.99"}
と入力してExecute押下
すると、結果が絞り込まれる。
※ ちょっとよくわかっていない。ざっくり検索した感じだと、PromQLを使って、ラベルの絞り込みをやってる…ぽい
グラフを表示
Graphタブを押下すれば、表示が切り替わる。
Node Exporterでターゲットを追加する
ここまでは、Prometheus自身のメトリクスを表示していたが、Node Exporterを動かすことで、ターゲットを追加できる。
Starting up some sample targets
Node Exporterの入手
Prometheus本体には含まれていないので、別途ダウンロードする。
https://prometheus.io/download/#node_exporter
$ curl -LO https://github.com/prometheus/node_exporter/releases/download/v1.0.1/node_exporter-1.0.1.linux-amd64.tar.gz $ tar xf node_exporter-1.0.1.linux-amd64.tar.gz
Node Exporterを実行する
[zaki@cloud-dev node_exporter-1.0.1.linux-amd64]$ ls -F LICENSE NOTICE node_exporter*
foregroundで動くので、ターミナル3つ起動して、3つのコマンドそれぞれ実行する。
(あと、リモートから見たいので、Listenのアドレスを0.0.0.0
に変更してる)
[zaki@cloud-dev node_exporter-1.0.1.linux-amd64]$ ./node_exporter --web.listen-address 0.0.0.0:8080 level=info ts=2020-10-14T13:01:02.719Z caller=node_exporter.go:177 msg="Starting node_exporter" version="(version=1.0.1, branch=HEAD, revision=3715be6ae899f2a9b9dbfd9c39f3e09a7bd4559f)" level=info ts=2020-10-14T13:01:02.719Z caller=node_exporter.go:178 msg="Build context" build_context="(go=go1.14.4, user=root@1f76dbbcfa55, date=20200616-12:44:12)" level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:105 msg="Enabled collectors" level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=arp level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=bcache level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=bonding level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=btrfs level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=conntrack level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=cpu level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=cpufreq level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=diskstats level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=edac level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=entropy level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=filefd level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=filesystem level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=hwmon level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=infiniband level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=ipvs level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=loadavg level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=mdadm level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=meminfo level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=netclass level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=netdev level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=netstat level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=nfs level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=nfsd level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=powersupplyclass level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=pressure level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=rapl level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=schedstat level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=sockstat level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=softnet level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=stat level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=textfile level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=thermal_zone level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=time level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=timex level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=udp_queues level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=uname level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=vmstat level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=xfs level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:112 collector=zfs level=info ts=2020-10-14T13:01:02.720Z caller=node_exporter.go:191 msg="Listening on" address=0.0.0.0:8080 level=info ts=2020-10-14T13:01:02.720Z caller=tls_config.go:170 msg="TLS is disabled and it cannot be enabled on the fly." http2=false
同様に、8081/tcp, 8082/tcpでも別ターミナルで起動する。
これで、Prometheus本体のときと同じように、http://localhost:8080/metrics にアクセスすると、今起動したNode Exporterが提供するメトリクス値を確認できる。
Node Exporter追加分の設定を変更しPrometheus再起動
3つのメトリクスのエンドポイントを用意したので、prometheus.yml
に項目追加する。
既存のlocalhost:9090
一つのリストに単純に追加してもいいが、Getting Startedの設定例にならって、グループ名も設定してみる。
- job_name: 'node' scrape_interval: 5s static_configs: - targets: ['localhost:8080', 'localhost:8081'] labels: group: 'production' - targets: ['localhost:8082'] labels: group: 'canary'
PrometheusはCtrl-c
で停止し、上記の内容に変更してPrometheusを再度起動。
メトリクス取得対象となっているターゲットは、web画面の「Targets」ページから確認できる。
現在、デフォルトのPrometheus本体と、Node Exporterを使った3つのターゲットになっており、job_name
で設定した名前単位でリストされる。
値のクエリー
この状態でnode_cpu_seconds_total
だけの値を出してみると、3つのNode Exporter全ての値(さらに環境によるがCPUコアごと…手元の環境だと4コアなのでcpu="0"
からcpu="3"
まで)が出力される。
prometheus.yml
で定義したグループの「production」だけに絞る場合はnode_cpu_seconds_total{group="production"}
でクエリーすれば項目を絞れる。
ルールの作成
Configure rules for aggregating scraped data into new time series
複雑なルールや時系列の集約を都度実行すると負荷が高いため(←解釈間違ってるかもしれないけど)、Prometheusでは予め作成した式を用いて値を記録しておくことができる。(と書いてあるように読み取った)
5分間の平均CPU時間(でいい?)であれば
avg by (job, instance, mode) (rate(node_cpu_seconds_total[5m]))
というクエリーになる。
※ 実際にExecuteしてグラフ表示するとこうなった
この結果の値をクエリーでなくメトリクス値として記録するには、ルールファイルを別途作成する。
作成するルールファイルprometheus.rules.yml
は以下の通り
groups: - name: cpu-node rules: - record: job_instance_mode:node_cpu_seconds:avg_rate5m expr: avg by (job, instance, mode) (rate(node_cpu_seconds_total[5m]))
そして、メインの設定ファイルprometheus.yml
から、このルールファイルをincludeするように記述を追加する。
初期のサンプル設定ファイルだと、以下のコメントアウトされている部分。
# Load rules once and periodically evaluate them according to the global 'evaluation_interval'. rule_files: # - "first_rules.yml" # - "second_rules.yml"
これをこうじゃ
# Load rules once and periodically evaluate them according to the global 'evaluation_interval'. rule_files: - "prometheus-rule.yml"
この設定変更を行い、Prometheusを再起動する。
すると、ドロップダウンメニューで選べるメトリクス種別の中にjob_instance_mode:node_cpu_seconds:avg_rate5m
が追加され、これを選ぶだけで(式を評価した結果の)メトリクスを表示できる。
収集したメトリクス値
ちなみにPrometheusのバイナリのあるディレクトリはこの通り。
[zaki@cloud-dev prometheus-2.21.0.linux-amd64]$ ls -lF 合計 161132 -rw-r--r--. 1 zaki zaki 11357 9月 11 22:29 LICENSE -rw-r--r--. 1 zaki zaki 3420 9月 11 22:29 NOTICE drwxr-xr-x. 2 zaki zaki 38 9月 11 22:29 console_libraries/ drwxr-xr-x. 2 zaki zaki 173 9月 11 22:29 consoles/ drwxrwxr-x. 4 zaki zaki 70 10月 14 21:07 data/ -rwxr-xr-x. 1 zaki zaki 88471209 9月 11 20:37 prometheus* -rw-rw-r--. 1 zaki zaki 166 10月 14 22:41 prometheus-rule.yml -rw-r--r--. 1 zaki zaki 1184 10月 14 22:43 prometheus.yml -rw-r--r--. 1 zaki zaki 926 10月 14 22:13 prometheus.yml.org -rwxr-xr-x. 1 zaki zaki 76493104 9月 11 20:39 promtool*
data/
以下にデータが出力される。
前述のように、収集済みメトリクス値からクエリーで出した値でなく、ルールを作成して新しいメトリクス値を作った場合は、作成した時点からの収集となるので、それ以前のデータは(メトリクス値としては)見えない (同じ式でクエリーを実行すればクエリーの結果としては見える)
参考: Dockerイメージ
ちなみにDockerイメージもあるので、簡単に試すこともできた。
prometheus.yml
を用意するようになってるけど、とりあえず空ファイルでも動作する。
$ touch /tmp/prometheus.yml $ docker run \ -p 9090:9090 \ -v /tmp/prometheus.yml:/etc/prometheus/prometheus.yml \ --rm \ --name prometheus \ prom/prometheus
実行例
zaki@cloud-dev ~]$ docker run \ > -p 9090:9090 \ > -v /tmp/prometheus.yml:/etc/prometheus/prometheus.yml \ > --rm \ > --name prometheus \ > prom/prometheus level=info ts=2020-10-14T11:44:44.529Z caller=main.go:310 msg="No time or size retention was set so using the default time retention" duration=15d level=info ts=2020-10-14T11:44:44.529Z caller=main.go:346 msg="Starting Prometheus" version="(version=2.21.0, branch=HEAD, revision=e83ef207b6c2398919b69cd87d2693cfc2fb4127)" level=info ts=2020-10-14T11:44:44.529Z caller=main.go:347 build_context="(go=go1.15.2, user=root@a4d9bea8479e, date=20200911-11:35:02)" level=info ts=2020-10-14T11:44:44.529Z caller=main.go:348 host_details="(Linux 3.10.0-1127.19.1.el7.x86_64 #1 SMP Tue Aug 25 17:23:54 UTC 2020 x86_64 1951c31b3707 (none))" level=info ts=2020-10-14T11:44:44.529Z caller=main.go:349 fd_limits="(soft=1048576, hard=1048576)" level=info ts=2020-10-14T11:44:44.529Z caller=main.go:350 vm_limits="(soft=unlimited, hard=unlimited)" level=info ts=2020-10-14T11:44:44.530Z caller=web.go:523 component=web msg="Start listening for connections" address=0.0.0.0:9090 level=info ts=2020-10-14T11:44:44.530Z caller=main.go:701 msg="Starting TSDB ..." level=info ts=2020-10-14T11:44:44.535Z caller=head.go:644 component=tsdb msg="Replaying on-disk memory mappable chunks if any" level=info ts=2020-10-14T11:44:44.535Z caller=head.go:658 component=tsdb msg="On-disk memory mappable chunks replay completed" duration=5.044µs level=info ts=2020-10-14T11:44:44.535Z caller=head.go:664 component=tsdb msg="Replaying WAL, this may take a while" level=info ts=2020-10-14T11:44:44.535Z caller=head.go:716 component=tsdb msg="WAL segment loaded" segment=0 maxSegment=0 level=info ts=2020-10-14T11:44:44.535Z caller=head.go:719 component=tsdb msg="WAL replay completed" checkpoint_replay_duration=31.707µs wal_replay_duration=184.249µs total_replay_duration=234.576µs level=info ts=2020-10-14T11:44:44.536Z caller=main.go:721 fs_type=XFS_SUPER_MAGIC level=info ts=2020-10-14T11:44:44.536Z caller=main.go:724 msg="TSDB started" level=info ts=2020-10-14T11:44:44.536Z caller=main.go:850 msg="Loading configuration file" filename=/etc/prometheus/prometheus.yml level=info ts=2020-10-14T11:44:44.536Z caller=main.go:881 msg="Completed loading of configuration file" filename=/etc/prometheus/prometheus.yml totalDuration=557.508µs remote_storage=3.834µs web_handler=392ns query_engine=939ns scrape=503.038µs scrape_sd=5.5µs notify=442ns notify_sd=953ns rules=741ns level=info ts=2020-10-14T11:44:44.537Z caller=main.go:673 msg="Server is ready to receive web requests."
空設定だと動かないと思ってたのでちょっとビックリ笑
[zaki@cloud-dev ~]$ docker ps | head -2 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1951c31b3707 prom/prometheus "/bin/prometheus --c…" About a minute ago Up About a minute 0.0.0.0:9090->9090/tcp prometheus
今回はNode Exporterを使う時にlocalhostでやろうとするとコンテナ間通信とか出てきて、コンテナネットワークの設定の要素も出てくるので、解説視点的にややこしくなるので一旦保留した。
まとめ
ここまでで確認した内容は以下の通り。
(ここで書いたのが全て、というわけじゃないです)
- Prometheus本体
- 対象のメトリクスの収集
- メトリクスの保存
- クエリーによるメトリクスの抽出
- Node Exporter
- 代表的なExporterの一つ (Node以外にいろいろある)
- ノードのCPUやメモリ、ネットワークやストレージなどのメトリクスを収集
- Exporter
- Prometheusからのリクエストに対して収集したメトリクスを返す