Featured image of post Prometheusとかをnginxでリバースプロキシした

Prometheusとかをnginxでリバースプロキシした

リバースプロキシ

最近監視用にラズパイ上でいろいろ動かしてるけど, だんだんポート番号を覚えきれなくなってきたのでいい感じにリバースプロキシした.


やったことのまとめ

  • ラズパイにnginxを突っ込んでリバースプロキシにした
  • リクエストパスを使った監視関係へのリバースプロキシの設定がちょっと面倒だった

つかうもの

構成

component
Icons made by Smashicons from www.flaticon.com

現在ラズパイ上のPrometheus等のUIにアクセスする場合, 192.168.3.200:9090 のように
各アプリが起動しているポート番号を指定してアクセスしているが,
アプリのポート番号なんてすぐ忘れちゃう(バカ)のでラズパイ側でnginxを立ててリバースプロキシをかけることにする.
リバースプロキシは8080番ポートでリクエストを受けて, パス(/prometheus)によってアクセスするアプリを変えるようにする.
(例: 192.168.3.200:8080/prometheus 宛のリクエストに 192.168.3.200:9090 で動くアプリのレスポンスを返す)
ポート番号よりはパスのほうが覚えやすいので便利になる. はず…
Node exporterはUIがないので今回は対象外.

やったこと

nginxのインストール

nginxのインストール自体は簡単. aptで入れるだけ.

# nginxのインストール
$ sudo apt update
$ sudo apt install nginx

# service起動
$ sudo systemctl start nginx
$ systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
   Active: active (running) since Tue 2020-01-28 22:12:54 JST; 7min ago
     Docs: man:nginx(8)
  Process: 23808 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
  Process: 23809 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
 Main PID: 23810 (nginx)
    Tasks: 5 (limit: 2200)
   Memory: 3.5M
   CGroup: /system.slice/nginx.service
           ├─23810 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
           ├─23811 nginx: worker process
           ├─23812 nginx: worker process
           ├─23813 nginx: worker process
           └─23814 nginx: worker process

Jan 28 22:12:54 raspberrypi systemd[1]: Starting A high performance web server and a reverse proxy server...
Jan 28 22:12:54 raspberrypi systemd[1]: Started A high performance web server and a reverse proxy server.

試しに<ラズパイのIP>:80にアクセスするとnginxの初期画面のhtmlが表示される. かんたん.

nginx

リバースプロキシの設定

このnginxをリバースプロキシとして使うための設定をする.
デフォルトで作成されているnginxの設定ファイル/etc/nginx/nginx.conf
/etc/nginx/conf.d/*.confを読み込むようになっているので,
新たに/etc/nginx/conf.d/default.conf(名前は何でも良い)を作成する.
今回は8080番ポートで受けてパス(location)により各アプリのポートに割り振るリバースプロキシを設定する.

# nginxの設定ファイルを確認する
# 編集はしない  
$ cat /etc/nginx/nginx.conf

# リバースプロキシ設定を作成
$ sudo vim /etc/nginx/conf.d/default.conf
nginx.conf(初期設定のまま)
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
	worker_connections 768;
	# multi_accept on;
}

http {

	##
	# Basic Settings
	##

	sendfile on;
	tcp_nopush on;
	tcp_nodelay on;
	keepalive_timeout 65;
	types_hash_max_size 2048;
	# server_tokens off;

	# server_names_hash_bucket_size 64;
	# server_name_in_redirect off;

	include /etc/nginx/mime.types;
	default_type application/octet-stream;

	##
	# SSL Settings
	##

	ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
	ssl_prefer_server_ciphers on;

	##
	# Logging Settings
	##

	access_log /var/log/nginx/access.log;
	error_log /var/log/nginx/error.log;

	##
	# Gzip Settings
	##

	gzip on;

	# gzip_vary on;
	# gzip_proxied any;
	# gzip_comp_level 6;
	# gzip_buffers 16 8k;
	# gzip_http_version 1.1;
	# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

	##
	# Virtual Host Configs
	##

	# ここでdefault.confを参照する
	include /etc/nginx/conf.d/*.conf;
	include /etc/nginx/sites-enabled/*;
}
default.conf
server {

	listen	8080;

	location /prometheus/ {
		proxy_pass	http://localhost:9090/;
	}

	location /alertmanager/ {
		proxy_pass	http://localhost:9093/;
	}

	location /grafana/ {
		proxy_pass	http://localhost:3000/;
	}

}

また, このリバースプロキシが効くように各アプリの外部URL(nginxが見るやつ)を変える必要がある.
どれも起動時に読み込むオプションで指定できるので, 設定ファイルを編集する.

# 各アプリのserviceファイルを修正する
# Prometheus
$ sudo vim /etc/systemd/system/prometheus.service
# Alertmanager
$ sudo vim /etc/systemd/system/alertmanager.service

# Grafanaだけはパッケージインストールしたので別の設定ファイルを編集する
$ sudo vim /etc/grafana/grafana.ini
prometheus.service
[Unit]
Description=Prometheus Server

[Service]
User=prometheus
ExecStart=/usr/local/prometheus/prometheus \
  --config.file=/usr/local/prometheus/prometheus.yml \
  --storage.tsdb.path=/var/lib/prometheus/data \
  --web.external-url=http://localhost:8080/prometheus/ \
  --web.route-prefix=/

[Install]
WantedBy=multi-user.target
alertmanager.service
[Unit]
Description=Alertmanager

[Service]
User=alertmanager
ExecStart=/usr/local/alertmanager/alertmanager \
  --config.file=/usr/local/alertmanager/alertmanager.yml \
  --storage.path=/var/lib/alertmanager/data \
  --web.external-url=http://localhost:8080/alertmanager/ \
  --web.route-prefix=/

[Install]
WantedBy=multi-user.target
grafana.ini(一部抜粋)
...
[server]
# The public facing domain name used to access grafana from a browser
domain = localhost
...
# The full public facing url you use in browser, used for redirects and emails
# If you use reverse proxy and sub path specify full url (with sub path)
root_url = %(protocol)s://%(domain)s/grafana/
...

PrometheusとAlertmanagerの設定はほぼ同じ.
重要なのはnginxから見える外部URLのフラグ--web.external-urlの設定で
実際に起動している場所(localhost:9090, localhost:9093)とは違うパス(localhost:8080/prometheus, localhost:8080/alertmanager)からアクセスできるようにしていることと,
Prometheus(Alertmanager)がリクエストを処理するルートパスのフラグ--web.route-prefix/ のみにすることで
リバースプロキシを経由する場合としない場合で同じルートパスを扱えるようにしていることである.

--web.route-prefixを指定しない例(Prometheus):
--web.route-prefixはデフォルトだと--web.external-urlのパス(/prometheus/)と同じになってしまうため,
リバースプロキシを経由しない場合のリクエストが処理できない.
nginxを経由せずlocalhost内のアプリ同士で通信する場合などに不便.

リクエスト                                 処理
localhost:8080/prometheus/metrics   -> /metrics(リバースプロキシ)
localhost:9090/metrics              -> ルートパスが/prometheus/でないため解釈できずBad Request
localhost:9090/prometheus/metrics   -> /metrics(リバースプロキシなし), しかし不便

Grafanaの設定も似たようなことをやっていて,
こちらは localhost:8080/grafana でアクセスできるようになっているが,
リバースプロキシをかけない場合(localhost:3000)はエラーになる.
(ただしGrafanaに人間以外がアクセスすることはほとんど無いのでPrometheusの場合と違って困ることはない)

このあたりはかなり難しかったので以下の記事を参考にした.
https://www.robustperception.io/external-urls-and-path-prefixes
https://grafana.com/docs/grafana/latest/installation/behind_proxy/

ここまで設定できたら, 各サービスを再起動する.

# serviceファイルが書き換わっているのでリロード
$ sudo systemctl daemon-reload

# 全部まとめて再起動
$ sudo systemctl restart prometheus alertmanager grafana-server nginx

試しに<ラズパイのIP>:8080/prometheus, <ラズパイのIP>:8080/alertmanager, <ラズパイのIP>:8080/grafanaにそれぞれアクセスするとそれぞれのUIが開く.

prometheus
alertmanager
grafana

やったぜ.

おわり

これでリバースプロキシの8080番だけ覚えればあとは名前だけで各アプリにたどり着けるようになったのでとても便利.
リバースプロキシの練習にもなったのでよかった.

おまけ

パソコンの邪魔して怒られて暇なそとちゃん