前回、前々回でConsulとNomadのHTTP APIのTLSを有効化しました。
今回はNomad上にPrometheusを配置しつつ、ConsulとNomadのメトリクスを収集してみたいと思います。
概要
PrometheusをNomadのジョブとして投入します。
Prometheusの設定ファイルはあえてdockerイメージの内部に配置せず、Consul KVに登録してNomadジョブ投入と同時にコンテナ内に配置していきます。
さらにPrometheusでConsulとNomadのメトリクスを収集しますが、前回まででConsulとNomadをTLS化したため、PrometheusからもHTTPSでメトリクス取得のリクエストを発行します。
そのあたりの設定ファイルの書き方を見ていきましょう。
ちなみに、Nomadのジョブはなるべくステートレス(状態を持たない、永続化もしない)に作るべきものですが、Prometheusのメトリクス情報については何かしら永続化の方法を考えたいところです。
これについては次回以降で扱っていく予定です。
では進めていきましょう。
Prometheusの設定ファイル
まず、ConsulとNomadのメトリクスを収集するためのPromethuesの設定ファイルを作ります。
PrometheusはPull型でデータを収集するため、監視エンドポイントをPrometheusに設定する必要があります。
今回は、ConsulのService Discoveryを使ってConsulとNomadが起動しているIPアドレスとポートを取得します。
「consul_sd_configs」がConsul経由で監視エンドポイントのIPアドレスとポートを取得する設定です。
HTTPSでConsulにアクセスするため、「scheme: https」を指定し、「tls_config」で各種証明書・鍵を指定しています。
ここではDockerコンテナ内の/opt/certに証明書・鍵を配置することにしています。
global:
scrape_interval: 5s
evaluation_interval: 5s
scrape_configs:
- job_name: 'consul_metrics'
scheme: https
tls_config:
ca_file: /opt/cert/consul-agent-ca.pem
cert_file: /opt/cert/dc1-cli-consul-0.pem
key_file: /opt/cert/dc1-cli-consul-0-key.pem
insecure_skip_verify: true
consul_sd_configs:
- server: 'consul.service.consul:8501'
services: ['consul']
scheme: https
tls_config:
ca_file: /opt/cert/consul-agent-ca.pem
cert_file: /opt/cert/dc1-cli-consul-0.pem
key_file: /opt/cert/dc1-cli-consul-0-key.pem
insecure_skip_verify: false
relabel_configs:
- source_labels: [__address__]
replacement: ${1}:8501
regex: ([^:]+):(\d+)
target_label: __address__
- source_labels: [__meta_consul_node]
target_label: node_name
scrape_interval: 5s
metrics_path: /v1/agent/metrics
params:
format: ['prometheus']
- job_name: 'nomad_metrics'
scheme: https
tls_config:
ca_file: /opt/cert/nomad-ca.pem
cert_file: /opt/cert/nomad-cli.pem
key_file: /opt/cert/nomad-cli-key.pem
insecure_skip_verify: true
consul_sd_configs:
- server: 'consul.service.consul:8501'
services: ['nomad-client', 'nomad']
scheme: https
tls_config:
ca_file: /opt/cert/consul-agent-ca.pem
cert_file: /opt/cert/dc1-cli-consul-0.pem
key_file: /opt/cert/dc1-cli-consul-0-key.pem
insecure_skip_verify: false
relabel_configs:
- source_labels: ['__meta_consul_tags']
regex: '(.*)http(.*)'
action: keep
- source_labels: [__meta_consul_node]
target_label: node_name
scrape_interval: 5s
metrics_path: /v1/metrics
params:
format: ['prometheus']
前提として、PrometheusのDockerコンテナから「consul.service.consul」の名前でConsulにアクセスできるように、DNSの調整をする必要があります。
私の環境では、Nomadクライアントを起動しているホストでdnsmasqを使ってConsul DNSを参照できるようにし、その上でDockerコンテナからhost_network経由でホスト上のDNSを参照しています。
Nomadの公式ドキュメントを参考にしてください。
Consulから得られるNomadのIPアドレスがNomadのサーバ証明書内のCNやSANと一致しないため、サーバホスト名の検証をスキップしてTLSエラーを回避しています。
(nomad_metricsのinsecure_skip_verify:true)
consul_metricsの insecure_skip_verify: trueも同様です。
Nomadの設定ファイル
Nomadの設定フィルにメトリクス公開の設定を追加します。
項目についてはドキュメントを参照ください。
...
telemetry {
publish_allocation_metrics = true
publish_node_metrics = true
prometheus_metrics = true
}
...
Nomadジョブファイル
Prometheus向けのNomadジョブファイルを作ります。
再下部のtemplateブロックでConsul KVからprometheus.yml、証明書・鍵を読み出し、Nomadジョブ用のlocalディレクトリに配置します。
mountブロックでlocalディレクトリをコンテナ内にマウントしています。
証明書・鍵ファイルをばらばらと置いていますが、このあたりはzip化してWebサーバやS3に上げるほうがすっきりするかと思います。
update,migrate,resourcesあたりは仮の設定ですので、運用設計や環境に合わせて設定が必要です。
job "prometheus" {
datacenters = ["dc1"]
type = "service"
update {
max_parallel = 1
min_healthy_time = "10s"
healthy_deadline = "3m"
progress_deadline = "10m"
auto_revert = false
canary = 0
}
migrate {
max_parallel = 1
health_check = "checks"
min_healthy_time = "10s"
healthy_deadline = "5m"
}
group "prometheus" {
count = 1
restart {
attempts = 2
interval = "30m"
delay = "15s"
mode = "fail"
}
network {
mode = "host"
port "prometheus" {
static = 9090
}
}
service {
name = "prometheus"
port = "prometheus"
tags = ["opt"]
check {
type = "http"
protocol = "http"
path = "/-/healthy"
interval = "30s"
timeout = "2s"
}
}
task "prometheus" {
driver = "docker"
config {
logging {
type = "journald"
}
image = "prom/prometheus:v2.24.1"
ports = ["prometheus"]
network_mode = "host"
args = [
"--config.file=/srv/prometheus/prometheus.yml",
"--storage.tsdb.path=/prometheus",
"--web.enable-lifecycle"
]
mounts = [
{
type = "bind"
source = "local/prometheus.yml"
target = "/srv/prometheus/prometheus.yml"
},
{
type = "bind"
source = "local/cert"
target = "/opt/cert"
}
]
}
env {
}
template {
change_mode = "restart"
destination = "local/prometheus.yml"
data = "{{ key \"prometheus/config/prometheus.yml\" }}"
}
template {
change_mode = "noop"
destination = "local/cert/consul-agent-ca.pem"
data = "{{ key \"cert/consul/consul-agent-ca.pem\" }}"
}
template {
change_mode = "noop"
destination = "local/cert/dc1-cli-consul-0.pem"
data = "{{ key \"cert/consul/dc1-cli-consul-0.pem\" }}"
}
template {
change_mode = "noop"
destination = "local/cert/dc1-cli-consul-0-key.pem"
data = "{{ key \"cert/consul/dc1-cli-consul-0-key.pem\" }}"
}
template {
change_mode = "noop"
destination = "local/cert/nomad-ca.pem"
data = "{{ key \"cert/nomad/nomad-ca.pem\" }}"
}
template {
change_mode = "noop"
destination = "local/cert/nomad-cli.pem"
data = "{{ key \"cert/nomad/nomad-cli.pem\" }}"
}
template {
change_mode = "noop"
destination = "local/cert/nomad-cli-key.pem"
data = "{{ key \"cert/nomad/nomad-cli-key.pem\" }}"
}
resources {
cpu = 500 # MHz
memory = 1024 # MB
}
}
}
}
Consul KVとNomadジョブファイルの投入
それではいよいよローカルにあるファイルをConsul KVやNomadに投入していきましょう。
以下のファイルを用意します。ドメイン名やパスは調整してください。
export CONSUL_HTTP_ADDR=https://consul.mydomain.tk:8501
export CONSUL_CACERT=./consul-agent-ca.pem
export CONSUL_CLIENT_CERT=./dc1-cli-consul-0.pem
export CONSUL_CLIENT_KEY=./dc1-cli-consul-0-key.pem
export NOMAD_ADDR=https://nomad.mydomain.tk:4646
export NOMAD_CACERT=./nomad-ca.pem
export NOMAD_CLIENT_CERT=./nomad-cli.pem
export NOMAD_CLIENT_KEY=./nomad-cli-key.pem
#!/bin/bash
source ./env.sh
consul kv put prometheus/config/prometheus.yml @./prometheus.yml
consul kv put cert/consul/consul-agent-ca.pem @./consul-agent-ca.pem
consul kv put cert/consul/dc1-cli-consul-0.pem @./dc1-cli-consul-0.pem
consul kv put cert/consul/dc1-cli-consul-0-key.pem @./dc1-cli-consul-0-key.pem
consul kv put cert/nomad/nomad-ca.pem @./nomad-ca.pem
consul kv put cert/nomad/nomad-cli.pem @./nomad-cli.pem
consul kv put cert/nomad/nomad-cli-key.pem @./nomad-cli-key.pem
#!/bin/bash
source ./env.sh
nomad job run prometheus.nomad
シェルスクリプトを実行して投入します。
$ chmod +x *.sh
$ ./register_setting.sh
Success! Data written to: prometheus/config/prometheus.yml
Success! Data written to: cert/consul/consul-agent-ca.pem
Success! Data written to: cert/consul/dc1-cli-consul-0.pem
Success! Data written to: cert/consul/dc1-cli-consul-0-key.pem
Success! Data written to: cert/nomad/nomad-ca.pem
Success! Data written to: cert/nomad/nomad-cli.pem
Success! Data written to: cert/nomad/nomad-cli-key.pem
$
$ ./register_job.sh
==> Monitoring evaluation "8e6e815c"
Evaluation triggered by job "prometheus"
Evaluation within deployment: "679353d4"
Allocation "50ef43a1" created: node "ef1cba89", group "prometheus"
Evaluation status changed: "pending" -> "complete"
==> Evaluation "8e6e815c" finished with status "complete"
ConsulやNomadの管理UI画面でPrometheusのジョブが起動しているのを確認します。
以下のようにNomad CLIでNomadジョブのステータスを確認することもできます。
$ source ./env.sh
$ nomad job status prometheus
ID = prometheus
Name = prometheus
Submit Date = 2021-03-31T02:26:49Z
Type = service
Priority = 50
Datacenters = dc1
Namespace = default
Status = running
Periodic = false
Parameterized = false
Summary
Task Group Queued Starting Running Failed Complete Lost
prometheus 0 0 1 0 0 0
Latest Deployment
ID = 679353d4
Status = successful
Description = Deployment completed successfully
Deployed
Task Group Desired Placed Healthy Unhealthy Progress Deadline
prometheus 1 1 1 0 2021-03-31T02:39:09Z
Allocations
ID Node ID Task Group Version Desired Status Created Modified
50ef43a1 ef1cba89 prometheus 0 run running 2m29s ago 10s ago
Statusがrunningになり、Healthyが1になっています。
まとめ
今回はPrometheusをNomadジョブで起動してみました。
また、ConsulのService Discoveryから監視エンドポイントを取得する設定も確認しました。
今回の設定では、Prometheusが収集したメトリクス情報は、Nomadジョブ内の起動オプション「--storage.tsdb.path」でしたとおり、Dockerコンテナ内の/prometheusに保存されます。
これではNomadジョブが停止した際にDockerコンテナと同時にロストしてしますので、次回は適切に永続化するように構成を変更してみましょう。
<参考>