MuninをFastCGIで表示するときにおこるDynazoomページのURLがおかしくなるバグ

Muninを高速に表示するためには、グラフとHTMLの生成をFastCGI化するのがいい。しかしDynazoomページのURLが一定の確率でおかしくなるバグがある。

通常https://FQDN/muninの直後は/static/dynazoom.htmlとなるはずである。しかし時々https://FQDN/munin/static/dynazoom.htmlの間に/Munin-nodeのグループ名が入ることがある。

正 https://example.com/munin/static/dynazoom.html?cgiurl_graph=/munin-cgi/munin-cgi-graph&plugin_name=production/api/api0001/memory&size_x=800&size_y=400&start_epoch=1546831257&stop_epoch=1546939257
誤 https://example.com/munin/production/api/static/dynazoom.html?cgiurl_graph=/munin-cgi/munin-cgi-graph&plugin_name=production/api/api0001/memory&size_x=800&size_y=400&start_epoch=1546831257&stop_epoch=1546939257

おかしくなったURLでは遷移しても正常にページを表示できないため、Nginxのrewrite機能を使って正常なURLに変換してあげる必要がある。

検証したMuninのバージョン: 2.0.43

Muninのinstall方法

まずはMuninのinstall方法を簡単に記載する。

グラフ生成とHTML生成をFastCGIにするためにmunin.confgraph_strategyhtml_strategycgiに設定する必要がある。

sudo su -
yum install munin munin-nginx spawn-fcgi --enablerepo epel

cat << EOF > /etc/munin/munin.conf
includedir /etc/munin/munin-conf.d
graph_strategy cgi
html_strategy cgi
EOF

mkdir /etc/munin/munin-conf.d

systemctl enable munin-cgi-graph.socket
systemctl enable munin-cgi-html.socket

systemctl start munin-cgi-graph.socket
systemctl start munin-cgi-html.socket

systemctl status munin-cgi-graph.socket
systemctl status munin-cgi-html.socket

systemctl status munin-cgi-graph.service
systemctl status munin-cgi-html.service

munin-cgi-graph.socketmunin-cgi-html.socketはyum installで自動で入る。Unixドメインソケットによる起動になっている。

$ systemctl cat munin-cgi-graph.socket
# /usr/lib/systemd/system/munin-cgi-graph.socket
[Unit]
Description=Munin FastCGI Graphs Socket

[Socket]
ListenStream=/run/munin/munin-cgi-graph.sock
SocketMode=0660
SocketUser=nginx
SocketGroup=munin

[Install]
WantedBy=sockets.target

Nginxのconf

FastCGIを呼び出すためのNginxのconfの抜粋を記載する。

location /munin-cgi/munin-cgi-graph/ {
    fastcgi_split_path_info ^(/munin-cgi/munin-cgi-graph)(.*);
    fastcgi_param PATH_INFO $fastcgi_path_info;
    fastcgi_pass unix:/var/run/munin/munin-cgi-graph.sock;
    include fastcgi_params;
}

location /munin/static/ {
    alias /etc/munin/static/;
}

location /munin/ {
    fastcgi_split_path_info ^(/munin)(.*);
    fastcgi_param PATH_INFO $fastcgi_path_info;
    fastcgi_pass unix:/var/run/munin/munin-cgi-html.sock;
    include fastcgi_params;
}

本来であればこれだけで問題ない。

グラフ生成のために、URLが/munin-cgi/munin-cgi-graph/であるときはUnixドメインソケットのunix:/var/run/munin/munin-cgi-graph.sockへつなぐ。

HTML生成のために、URLが/munin/であるときはUnixドメインソケットのunix:/var/run/munin/munin-cgi-html.sockへつなぐ。ただしURLが/munin/static/のときは静的ファイルであるため、/etc/munin/staticディレクトリにあるファイルをそのまま配信する。

Nginxによるバグ対処法

冒頭で説明した通り、MuninのFastCGIにはバグがあり、URLが/munin/staticの時にURLがおかしくなることがある。Nginxのrewriteを使っておかしくなったURLを正常なURLに戻す設定を入れる必要がある。

location ~ ^/munin/(.*)/static/dynazoom.html {
     rewrite ^/munin/(.*)/static/dynazoom.html(.*)$ /munin/static/dynazoom.html$2 permanent;
}

/munin//static/dynazoom.htmlの間に文字列が入ってしまった場合、その文字列を削除し、/munin/static/dynazoom.htmlへURLを書き換えている。

バグ対処後のNginxのconf

バグ対処の理由コメントも入れて、Nginxのconfを再掲する。

location /munin-cgi/munin-cgi-graph/ {
    fastcgi_split_path_info ^(/munin-cgi/munin-cgi-graph)(.*);
    fastcgi_param PATH_INFO $fastcgi_path_info;
    fastcgi_pass unix:/var/run/munin/munin-cgi-graph.sock;
    include fastcgi_params;
}

location /munin/static/ {
    alias /etc/munin/static/;
}

# for dynazoom bug
# Dynazoom url should be like below.
#   https://example.com/munin/static/dynazoom.html?cgiurl_graph=/munin-cgi/munin-cgi-graph&plugin_name=production/api/api0001/memory&size_x=800&size_y=400&start_epoch=1546831257&stop_epoch=1546939257
# Dynazoom url sometimes become invalid. Munin-node groups appear between 'munin' and 'static'.
#   https://example.com/munin/production/api/static/dynazoom.html?cgiurl_graph=/munin-cgi/munin-cgi-graph&plugin_name=production/api/api0001/memory&size_x=800&size_y=400&start_epoch=1546831257&stop_epoch=1546939257
# Should rewrite url to fix problem.
location ~ ^/munin/(.*)/static/dynazoom.html {
     rewrite ^/munin/(.*)/static/dynazoom.html(.*)$ /munin/static/dynazoom.html$2 permanent;
}

location /munin/ {
    fastcgi_split_path_info ^(/munin)(.*);
    fastcgi_param PATH_INFO $fastcgi_path_info;
    fastcgi_pass unix:/var/run/munin/munin-cgi-html.sock;
    include fastcgi_params;
}