Fedora CoreOS + Podman + Prometheus + Blackbox Exporter + GrafanaでWebサーバ(IPv6)を監視してみた。(その1) Web Server(IPv6)を監視するために、Fedora CoreOS に Podman で監視コンテナ(Prometheus+Blackbox Exporter+Grafana)を作成してみました。
自宅サーバと Netlify に構築した Web Server を外形監視したいと思います。外形監視は Prometheus+Blackbox Exporter で行います。Web Server に対して IPv6 で HTTPS 通信してその応答時間を監視していきます。環境は自宅サーバの Fedora CoreOS に Podman でコンテナを構築していきます。
監視コンテナの環境
コンテナは自宅サーバの Fedora CoreOS 上に Podman で構築していきます。またデプロイは gitLab.com(CI/CD)から自宅サーバでリモートシェルを使って行います。こちらの環境については別途備忘録を残していきたいと思います。監視コンテナは、backend ポッドに作成していきたいと思います。
Podman は Fedora CoreOS をセットアップすると標準で入っていますので新たにインストールする必要はありません。残念ながらPodman 3.0 ではまだないよです。
追記 2021.03.13
Testing Streamは、Mar 03, 2021にpodman3.0.1にアップデートされているようです。まもなくStable Streamもアップデートされると思います。
Release Date: Mar 03, 2021:ignition2.9.0 kernel5.10.19 moby-engine19.03.13 podman3.0.1 rpm-ostree2021.2 systemd246.7
version $ cat /etc/os-release
NAME = Fedora
VERSION = "33.20210201.3.0 (CoreOS)"
ID = fedora
VERSION_ID = 33
:
$ podman --version
podman version 2.2.1
今回は、以下のコンテナを構築していきます。
No ID 用途 Docker イメージ ポート番号[外部:内部] 備考 1 backend Pod - 52100-52110:52100-52110 後で利用するかもしれないので取り敢えず 11Port 外部と開けてます。 2 pr2 proxy alpine + (nginx) 52100:52100 nginx の Docke イメージではなく Alpine に個別インストール 2 prothemeus イベント監視 prom/prometheus 52101:52101 3 balckbox-exporter 外形監視 prom/blackbox-exporter 9115 ポート番号 9115 は Default 値で Pod 内のみの通信、外形監視は https 4 grafana 監視結果のグラフ grafana/grafana 52102:52102
backend ポッドの作成
ポッドは、以下のコマンドで作成します。
podman pod create --name backend --net=slirp4netns:enable_ipv6=true -p 52100-52110:52100-52110
rootless コンテナとしたいのでコンテナから外部のサーバと IPv6 で通信するために net オプションでslirp4netns:enable_ipv6=true を指定しています。ポッド内のコンテナ間通信はこの設定をしなくても IPv6 通信ができると思いますが、外との通信にはこの指定をすると良さそうです。なお外からコンテナと IPv6 通信するためにはこの指定ではなく、rootfull で IPv6 のアドレス指定するやり方でやるしかないと思います。おそらく。こちらの方法はコンテナ用サーバを Fedora Core OS で構築してみました。 の Tip podman で IPv6 コンテナ通信(ULA)を参照してください。
この指定をしないで Grafana でみると Status が DOWN となっていました。試しに google.com をデバッグモードでみてみると ip_protocol=ip6 となっていましたが Probe failed とエラーを吐いていました。ip_protocol=ip4 にして IPv4 で外形監視する方法もあるようですが私はコンテナを IPv6 に対応して回避しました。
$ podman exec -it pr1 sh
curl 'localhost:9115/probe?target=google.com&debug=true' ← pr1 ( proxyコンテナ ) からcurlでprobeしてみる。
Logs for the probe:
ts = 2021-02-24T12:22:39.035707468Z caller = main.go:304 module = http_2xx target = google.com level = info msg = "Beginning probe" probe = http timeout_seconds = 119.5
ts = 2021-02-24T12:22:39.03586488Z caller = http.go:342 module = http_2xx target = google.com level = info msg = "Resolving target address" ip_protocol = ip6
ts = 2021-02-24T12:22:39.037457859Z caller = http.go:342 module = http_2xx target = google.com level = info msg = "Resolved target address" ip = 2404:6800:4004:81b::200e
ts = 2021-02-24T12:22:39.037551564Z caller = client.go:252 module = http_2xx target = google.com level = info msg = "Making HTTP request" url = http://[2404:6800:4004:81b::200e] host = google.com
ts = 2021-02-24T12:22:39.037716724Z caller = main.go:119 module = http_2xx target = google.com level = error msg = "Error for HTTP request" err = "Get \" http://[2404:6800:4004:81b::200e] \" : dial tcp [2404:6800:4004:81b::200e]:80: connect: network is unreachable"
ts = 2021-02-24T12:22:39.037760284Z caller = main.go:119 module = http_2xx target = google.com level = info msg = "Response timings for roundtrip" roundtrip = 0 start = 2021-02-24T12:22:39.037636095Z dnsDone = 2021-02-24T12:22:39.037636095Z connectDone = 2021-02-24T12:22:39.037684075Z gotConn = 0001-01-01T00:00:00Z responseStart = 0001-01-01T00:00:00Z end = 0001-01-01T00:00:00Z
ts = 2021-02-24T12:22:39.037797644Z caller = main.go:304 module = http_2xx target = google.com level = error msg = "Probe failed" duration_seconds = 0.002054087
Tip
【Blackbox ExporterでHTTPS IPv6通信】
コンテナを外との通信にIPv6通信を許可する。
podman pod create —nameポット名—net=slirp4netns:enable_ipv6=true・・・
ポッドは、gitLab.com(CI/CD)からリモートシェルを使って自宅サーバでコンテナをデプロイします。自宅サーバに gitLab-runner のコンテナをたて自宅サーバ側で実行するようにしています。
自宅 Mac(VSC)-git→gitLab.com(CI/CD)-rshell→ 自宅サーバ(dev-pod:gitLab-runner)-rshell→ 自宅サーバ(ホスト Podman:deploy)のような流れです。
用途別に.gitlab-ci-yml を作成したいので、メインの.gitlab-ci-yml は以下のように記述しました。
.gitlab-ci-yml ## v2.1 akibo.I
include :
- 'backend/.gitlab-ci.yml'
variables :
GIT_SSL_NO_VERIFY : '1'
stages :
- buildPod
- buildContainer
before_script :
- set -x
- pwd
after_script :
こちらが実際のポッド構築のスクリプトとなります。podman を使って shell でデプロイしています。
backend/.gitlab-ci.yml ## v2.1 akibo.I
## backend
variables :
backend-pod :
stage : buildPod
only :
changes :
- backend/pod
script :
- HOST="xxxx@yyyy"
- POD="backend"
- ssh $HOST podman pod stop -i $POD
- ssh $HOST podman pod rm -i $POD
- ssh $HOST podman pod create --name $POD --net=slirp4netns:enable_ipv6=true -p 52100-52110:52100-52110
proxy コンテナの作成
自宅サーバは、別サーバで frontEnd Server が動作していますので、そちらから転送されたものを各コンテナに転送する proxy コンテナを作成します。
fronend-Pod(pr1)→backend-Pod(pr2,balckbox-exporter,prometheus,grafana)
フォルダ構成
backend
├──.gitlab-ci.yml
├──pr2
│ ├──Dockerfile
│ ├──build
│ ├──conf.d
│ │ ├──default.conf
│ │ ├──header.conf
│ │ └──log.conf
│ ├──nginx.conf
│ └──vhost.d
│ ├──01_ap-Server.conf
│ └──99_default.conf
Dockerfile
nginx の設定ファイルを作成しそのままコピーするようにしています。
FROM alpine
LABEL version= "1.0" "akiboi.net" = "akiboI"
RUN apk add --update --no-cache nginx
COPY build/ /etc/nginx/
CMD [ "/usr/sbin/nginx" , "-g" , "daemon off;" ]
nginx の起動は-g オプションで daemon off としています。
podman のデプロイ
ホスト側で Dockefile を元にビルドしますが、gitLab-runner のコンテナ内にある builds ディレクトは動的に変わるのでこの対応をします。
gitlab-runner コンテナのボリュームマップは -v /vol/gitlab-runner/data:/home/gitlab-runner:Z としています。
Docker ファイルを例にするとコンテナ側は、/home/gitlab-runner/builds/動的フォルダ/0/・・・/backend/pr2/Dockerfile となります。このファイルはホスト側では/vol/gitlab-runner/data/builds//動的フォルダ/0/・・・/backend/pr2/Dockerfile となります。ホスト側の Podman でビルドしていきますので、sed コマンドでコンテナ側のカレントディレクトを元に取得しています。以前は gitlab-runner をホスト側で動かしていましたのでこのようなことをする必要はありませんでしたが、Fedora CoreOS に変更してからは gitlab-runner 自身もコンテナに変更しましたのでこのような対応が必要でした。なお pr2 コンテナのボリュームマップは、-v /vol/pr2/data:/usr/share/nginx:Z と -v /vol/pr2/log:/var/log/nginx:Z としました。
pr1 :
stage : buildContainer
only :
changes :
- backend/pr2/**/*
script :
- HOST="xxxx@yyyy"
- POD="backend"
- BASEDIR="/vol"
- HOMEDIR=`pwd`
- WORKDIR=`echo ${HOMEDIR} | sed -e "s/^\/home\/gitlab-runner/\/vol\/gitlab-runner\/data/g"`
- CONTAINER=pr2
- VOLUME="-v $BASEDIR/$CONTAINER/data:/usr/share/nginx:Z -v $BASEDIR/$CONTAINER/log:/var/log/nginx:Z "
- REGISTRY="registry.akiboi.net:5000"
- ssh $HOST mkdir -p $BASEDIR/$CONTAINER/data $BASEDIR/$CONTAINER/log
- ssh $HOST podman build -t $REGISTRY/$CONTAINER $WORKDIR/$POD/$CONTAINER
- ssh $HOST podman push $REGISTRY/$CONTAINER
- ssh $HOST podman stop -i $CONTAINER
- ssh $HOST podman rm -i $CONTAINER
- ssh $HOST podman run -dt --pod $POD --restart=always --name $CONTAINER $VOLUME $REGISTRY/$CONTAINER
Balckbox Exporter と Prometheus コンテナの作成
Balckbox Exporter と Prometheus コンテナを作成していきます。
ビルド用フォルダ
backend
:
├──blackbox-exporter
│ └──Dockerfile
├──prometheus
│ ├──Dockerfile
│ └──build
│ └──prometheus.yml
Blackbox exporter Dockerfile
prom/blackbox-exporter イメージを利用します。設定ファイルはディフォルトのものをそのまま利用しますので Dockerfile のみで OK です。
backend/blackbox-exporter/Dockerfile FROM prom/blackbox-exporter
LABEL version= "1.0" "akiboi.net" = "akiboI"
prometheu Dockerfile
prom/prometheus イメージを利用しています。config ファイルやポート番号は CMD で指定しています。
FROM prom/ prometheus
LABEL version= "1.0" "akiboi.net" = "akiboI"
USER 0
COPY build/ prometheus .yml /etc/ prometheus
CMD [ "--config.file=/etc/ prometheus / prometheus .yml" , "--web.listen-address=:52103" , "--web.console.libraries=/usr/share/ prometheus /console_libraries" , "--web.console.templates=/usr/share/ prometheus /consoles" , "--web.enable-admin-api" ]
USER 0(root)を設定しています。この指定をしないと nobody となりホスト側のボリュームマッピングしたフォルダにアクセスできないためです。
root ユーザ名前空間にマッピングされていない UID が所有するファイルオブジェクトは「nobody」(65534、kernel.overflowuid)が所有するものとして扱われます。
今回は、rootless ユーザ ID 1001 で実行しています。この時の名前空間を見てみると以下のようになっています。グループ ID も同様ですが、要はコンテナ側のユーザ ID 0(root)の場合は、ホスト側 rootless の実行ユーザー ID とマッピングされてます。このおかげで、ホスト側の rootless ユーザ ID で作成した Voluem マッピングのフォルダにアクセスできるのだと思います。通常の Docker イメージは root ID で作成されていることが多いので意識する必要ありませんが別 ID で作成されている場合などは注意が必要と思います。
$ podman unshare id
uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:system_r:container_runtime_t:s0-s0:c0.c1023
$ podman unshare cat /proc/self/uid_map
0 1001 1
1 165536 65536
$ podman unshare cat /proc/self/gid_map
0 1001 1
1 165536 65536
prometheus.yml の設定
prometheus.yml は、監視する web サーバを指定してその他はディフォルトのままとしました。テストのために監視サーバは、google.com と Netlify、自宅サーバとしてみました。
global :
scrape_interval : 15s
evaluation_interval : 15s
alerting :
alertmanagers :
- static_configs :
- targets :
rule_files :
scrape_configs :
- job_name : 'blackbox_http'
metrics_path : /probe
params :
module : [ http_2xx ]
static_configs :
- targets :
- https://google.com/
- https://www.akiboi.net/ ← 自宅サーバ
- https://www.akiboi.info/ ← Netlify
relabel_configs :
- source_labels : [ __address__ ]
target_label : __param_target
- source_labels : [ __param_target ]
target_label : instance
- target_label : __address__
replacement : localhost:9115
Blackbox Exporter と Prometheus の.gitlab-ci.yml
proxy コンテナとほとんど同じで、ビルド判断するフォルダとコンテナ名、ボリュームマッピングが違うのみです。
blackbox-exporter :
stage : buildContainer
only :
changes :
- backend/blackbox-exporter/**/*
script :
- HOST="xxxx@yyyy"
- POD="backend"
- BASEDIR="/vol"
- HOMEDIR=`pwd`
- WORKDIR=`echo ${HOMEDIR} | sed -e "s/^\/home\/gitlab-runner/\/vol\/gitlab-runner\/data/g"`
- CONTAINER=blackbox-exporter
- VOLUME=""
- REGISTRY="registry.akiboi.net:5000"
- ssh $HOST mkdir -p $BASEDIR/$CONTAINER/data
- ssh $HOST podman build -t $REGISTRY/$CONTAINER $WORKDIR/$POD/$CONTAINER
- ssh $HOST podman push $REGISTRY/$CONTAINER
- ssh $HOST podman stop -i $CONTAINER
- ssh $HOST podman rm -i $CONTAINER
- ssh $HOST podman run -dt --pod $POD --restart=always --name $CONTAINER $VOLUME $REGISTRY/$CONTAINER
prometheus :
stage : buildContainer
only :
changes :
- backend/prometheus/**/*
script :
- HOST="xxxx@yyyy"
- POD="backend"
- BASEDIR="/vol"
- HOMEDIR=`pwd`
- WORKDIR=`echo ${HOMEDIR} | sed -e "s/^\/home\/gitlab-runner/\/vol\/gitlab-runner\/data/g"`
- CONTAINER=prometheus
- VOLUME="-v $BASEDIR/$CONTAINER/data:/prometheus/data:Z "
- REGISTRY="registry.akiboi.net:5000"
- ssh $HOST mkdir -p $BASEDIR/$CONTAINER/data
- ssh $HOST podman build -t $REGISTRY/$CONTAINER $WORKDIR/$POD/$CONTAINER
- ssh $HOST podman push $REGISTRY/$CONTAINER
- ssh $HOST podman stop -i $CONTAINER
- ssh $HOST podman rm -i $CONTAINER
- ssh $HOST podman run -dt --pod $POD --restart=always --name $CONTAINER $VOLUME $REGISTRY/$CONTAINER
Black Exporter と Prometheus の動作確認
Prometheus で Web サーバを監視できているか確認してみます。標準であれば http://prometheus サーバ:9090/でアクセスすると Prometheus の初期画面が表示できると思います。私の環境は FrontEnd Server の Proxy1 の設定も行い https://●●●●.akiboi.net/でアクセスしてみます。ヘッダーメニューから Status-Targets を選ぶと Black Exporter と接続されていることが確認できました。
メトリックスも確認していきます。ヘッダーメニューから Graph を選択します。probe_http_duration_seconds と入力して Execute ボタンをクリックするとメトリックスが表示されます。Graph に切り替えてみましょう。
自宅から Netlify は流石に遠いので Duration は 400ms、Google が 200ms、自宅サーバは同じ LAN 上ですので 20ms といったぐらいでしょうか。次回はこれを Grafana を使ってダッシュボードを作っていきたいと思います。