tjinjin's blog

インフラ要素多めの個人メモ

prometheusの設定ファイルに環境変数を埋め込みたい

About

最近prometheus導入を頑張っていたときの気付きです。もっとよい方法がありそうなのでご存知のかたいたら教えてほしいです。。結構雑目に書いています。

課題

prometheusやalertmanagerは私が知る限り設定ファイルベースとなっていて、一部の設定値を除きコマンドラインで設定を埋め込むということができません。

コンテナ環境で動かそうと思っていて、例えば下記の点が不便だなと思っています。

  • alertmanagerのreceiverの設定ファイルに秘匿情報(slackのWebhookとか)を入れないといけない。
  • regionが違う場合にregionごとにimageを作成する必要がある

imageを作成した時点で設定を固めないといけないため柔軟に設定を変えるのが難しいなーと感じていました。何かいい方法ないかなといろいろ考えていたときにenvsubstというものを見つけました。

qiita.com

envsubstとは

軽量なテンプレートエンジンのようです。gettext utilitiesに含まれています。環境変数を展開してくれるようです。

GNU gettext utilities

使ってみる

既存のprometheusのimageでpackageを入れる方法がわからなかったので、alpineベースでimageを作り直しenvsubstを導入します。

# 参考にしたDockerfileへのリンクが見つからない…
FROM alpine:latest

ARG ARCH=amd64
ARG VERSION=1.8.1

RUN apk --no-cache add gettext

RUN apk --no-cache add --virtual build-dependencies wget ca-certificates \
    && mkdir -p /tmp/install /tmp/dist \
    && wget -O /tmp/install/prometheus.tar.gz https://github.com/prometheus/prometheus/releases/download/v$VERSION/prometheus-$VERSION.linux-$ARCH.tar.gz \
    && apk del build-dependencies \
    && cd /tmp/install \
    && tar --strip-components=1 -xzf prometheus.tar.gz \
    && mkdir -p /etc/prometheus /usr/share/prometheus \
    && mv prometheus promtool   /bin/ \
    && mv prometheus.yml        /etc/prometheus/prometheus.yml \
    && mv consoles console_libraries NOTICE LICENSE /usr/share/prometheus/ \
    && ln -s /usr/share/prometheus/console_libraries /usr/share/prometheus/consoles/ /etc/prometheus/ \
    && rm -rf /tmp/install


EXPOSE     9090
VOLUME     [ "/prometheus" ]
WORKDIR    /prometheus
COPY  prometheus.yml.template /etc/prometheus/prometheus.yml.template

prometheus本体のimageだとcommandやEntrypointがありますがわかりにくくなりそうだったので一旦削除しました。最後にCOPYでtemplateをimageに入れています。

template自体はサンプルなので、下記のようにしました。

$ cat prometheus.yml.template
# my global config
global:
  scrape_interval:     15s # By default, scrape targets every 15 seconds.
  evaluation_interval: 15s # By default, scrape targets every 15 seconds.
  # scrape_timeout is set to the global default (10s).

  # Attach these labels to any time series or alerts when communicating with
  # external systems (federation, remote storage, Alertmanager).
  external_labels:
      monitor: ${PROJECT_NAME}

...

${PROJECT_NAME} という部分が環境変数で置き換える部分ですね。

docker-compose.ymlは下記のようにします。

version: '3'
services:
  prometheus:
    build: .
    command:
      - /bin/sh
      - -c
      - |
        envsubst '$$PROJECT_NAME'< /etc/prometheus/prometheus.yml.template> /etc/prometheus/prometheus.yml
        /bin/prometheus \
        --config.file=/etc/prometheus/prometheus.yml \
        --storage.local.path=/prometheus \
        --alertmanager.url=http://alertmanager:9093/alertmanager \
        --web.console.libraries=/usr/share/prometheus/console_libraries \
        --web.console.templates=/usr/share/prometheus/consoles
    ports:
      - 9090:9090
    environment:
      PROJECT_NAME: 'test'

commandの部分でenvsubstで設定ファイルを置き換えたのちにprometheusを起動させています。

commandを複数実行する際の参考 Running multiple commands in entrypoint · Issue #52 · docker-library/redmine · GitHub

起動後にコンテナに入ってみると

# cat /etc/prometheus/prometheus.yml
# my global config
global:
  scrape_interval:     15s # By default, scrape targets every 15 seconds.
  evaluation_interval: 15s # By default, scrape targets every 15 seconds.
  # scrape_timeout is set to the global default (10s).

  # Attach these labels to any time series or alerts when communicating with
  # external systems (federation, remote storage, Alertmanager).
  external_labels:
      monitor: test
...

というように起動時に環境変数を挿入できるようになりました。