ブログELKスタック導入-2-
2025年03月02日
はじめに
前回の記事で予告したように,私はKibanaとNGINXのリバースプロキシとの戦争をしましたが,これは1週間ほど前の話です。なぜ今更記事にするかというと,その戦争に勝利した後,試験と面接のために時間が取れず,ELKスタックの基本的な設定を完了したのが昨日だったからです。今日はその2つのうち,リバースプロキシについての経験を話そうと思います。
KibanaとNGINX Reverse Proxy
基本的なDockerとNGINXの設定を終えて,喜びの気持ちでexample.url/kibana/にアクセスすると,NGINXの404 Not Foundが表示されました。
基本的にリバースプロキシの設定をexample.url/kibanaに来たリクエストをexample.url/kibana/にリダイレクトするように設定しましたが,ここまでは普通に301 Moved Permanentlyが表示されてリダイレクトされました。しかし,問題はリダイレクトされた /kibana/ で,そこで404だけを返していました。
その理由がわからなかった私は,とりあえずローカルでポートへ直接アクセスしてみました。
curl -iL localhost:5601/kibana
面白いことに,ここではlocalhost:5601/kibana/app/home/に自動リダイレクトされ,Kibanaの画面を見ることができました。ここから無限の設定との戦いが始まりましたが,とりあえず覚えている試みはこんな感じです。
(A) Kibana basePathに関する設定
- server.basePath,server.rewriteBasePath,server.publicBaseUrlなどのKibanaの設定を調整して,NGINXとのパス処理を合わせようとしました。
(B)NGINXでのrewrite処理
- NGINXで/kibana/パスに対してrewrite ^/kibana/(.)$ /$1 break;を適用してKibanaに渡そうとしました。
- proxy_redirect / /kibana/; などで応答のLocationヘッダーを調整しようとしましたが,二重のrewriteによってKibanaが意図したパスと不一致が発生し,無限リダイレクトの問題が発生しました。
(C)さまざまなリダイレクトルートの試行
- kibanaにアクセスする際に,/kibana/spaces/enterや/kibana/app/homeなどに強制的にリダイレクトしようとしましたが,私が使用しているKibanaのバージョンでは,これらのルートがサーバー側に存在しないため,404が返されました。
最終的に成功した設定は以下の通りです。
Kibanaの設定
server.host: 0.0.0.0
server.port: 5601
server.basePath: "/kibana"
server.rewriteBasePath: true
server.publicBaseUrl: "https://example.url/kibana"
- server.basePathを/kibanaに指定し,rewriteBasePathをtrueに設定することで,Kibanaが内部的に/kibana prefixを削除して正しいパスにマップするように設定しました。これにより,Kibanaが内部APIリクエストに不要なbasePathを含まないようにすることができます。
- server.publicBaseUrlも同じように指定し,応答のLocationヘッダーが正しい絶対URLを使用するように設定します。 これは,Kibana内部で静的リソースが正しいURLでロードされることを保証する役割も果たします。
NGINX設定
location = /kibana{
return 301 /kibana/;
}
location = /kibana/ {
proxy_pass http://localhost:5601;
proxy_redirect off;
}
- kibanaへのリクエストを/kibanaにリダイレクトする(スラッシュなし)。
- 既存のrewrite設定を削除し,trailing slashなしで渡し,リダイレクト処理を行わないように設定しました。
この設定は
1.NGINXが/kibanaへのリクエストを/kibana/にリダイレクトした後,/kibana/以下のパスをrewriteなしでそのままKibanaに転送する。
2.Kibanaの設定がrewriteBasePath: trueに設定されているため,転送されたリクエストURLに対して/kibana prefixを自動的に処理し,正しい内部ルーティング(例:/spaces/enter -> /app/homeなど)を行います。
3. proxy_redirect off;でレスポンスのLocationヘッダを変更しないようにすることで,Kibanaが設定したURLを維持します。これは,Kivanaが独自にbasePathを処理し,NGINXが不要なリダイレクトを追加しないようにするための設定です。
結果として,NGINXとKibanaの両方で同時にbasePathを書き換えようとした結果,URLが誤って変換され,Kibanaが期待する内部ルーティングと実際に渡されたURLの不一致により404が発生したり,無限リダイレクトが発生したりすることがありました。
今こうして書いてみると,とても簡単な解決方法のように見えますが,実はこの問題を解決するのに2日ほどかかりました。 そして,私のCursor IDEのトークンと,ChatGPTのトークンをほぼ使い切るほどでした。公式ドキュメントも参照しましたが,rewriteBasePathは基本的にFalseという文章を見て,むしろもっと混乱したこともありました。
本当に冗談ではなく,その2日間で sudo nginx -t と sudo systemctl restart nginx を何百回以上打ったと思います。夢に出てきそうでした。この問題を解決した後,ジンもなくなりましたが,嬉しい気持ちでKibanaにアクセスしてみたら,今度はLogstashが壊れていて,FastAPIから正常にログを受け取れない状態でした。
JSON parse error, original data now in message field {:message=>"Unexpected character ('\\' (code 92)): expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false')\n at [Source: (String)\"\\u0003\\u0004\\u0003\\u0003\\u0003\\u0002\\u0003\\u0001\\u0003\\u0000\\u00003\\u0000&\\u0000$\\u0000\\u001D\\u0000 \\xB2\\xFE\\xD1'\\xDE\\rt\\xB2-:\\x889\\xAB\\xA0\\xFD\\x9A@\\u001C\\u0018\"; line: 1, column: 2]",
なぜ私がELKを巻こうとしたのか,このまま生きるのも悪くはないだろうという雑念が頭をよぎりましたが,すでに川を渡った私は再び戦いの準備をしました。 その話は次回の記事で紹介したいと思います。
カカオ
グーグル
ネイバー