블로그 ELK 스택 도입 -2-
2025년 03월 02일
서론
지난 편에서 예고했듯, 난 Kibana와 NGINX의 리버스 프록시와의 전쟁을 치뤘는데 이건 지금부터 약 일주일 전의 이야기이다. 근데 그걸 왜 지금 포스팅 하냐고 묻는다면 그 전쟁에서 승리한 뒤에 시험들과 면접들 때문에 시간이 나질 않아서 어제에서야 ELK 스택의 기본적인 설정을 완료했기 때문이다. 오늘은 그 두 가지 중 리버스 프록시에 대한 경험을 이야기 해보려 한다.
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/로 자동 리다이렉트 되면서 키바나 화면을 볼 수 있었다. 여기서부터 끝도 없는 설정과의 싸움이 시작됐는데 일단 기억나는 시도들은 이렇다.
(A) Kibana basePath 관련 설정
- server.basePath, server.rewriteBasePath, server.publicBaseUrl 등의 키바나 설정을 조정해서 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 등으로 리다이렉트하도록 시도해봤지만 내가 사용중인 키바나 버전에서는 이런 라우트들이 서버 측에 존재하지 않는 이유로 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 prefix를 제거하고 올바른 경로로 매핑하도록 설정했다. 이를 통해 Kibana가 내부 API 요청 시 불필요한 basePath가 포함되지 않도록 방지할 수 있다.
- server.publicBaseUrl도 동일하게 지정해서, 응답 Location 헤더가 올바른 절대 URL을 사용하도록 설정했다. 또한, 키바나 내부에서 정적 리소스를 올바른 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 없이 그대로 키바나에 전달한다.
2. Kibana의 설정이 rewriteBasePath: true로 설정되어 있으므로, 전달받은 요청 URL에 대해 /kibana prefix를 자동으로 처리하고 올바른 내부 라우팅(예를 들어 /spaces/enter -> /app/home 등)을 수행함.
3. proxy_redirect off;로 응답 Location 헤더가 변경되지 않도록 함으로써, 키바나가 설정한 URL이 그대로 유지됨. 이는 키바나가 자체적으로 basePath를 처리하도록 하고, NGINX에서 불필요한 리다이렉트를 추가하지 않도록 하기 위한 설정이다.
결론적으로 실패했던 이유는 최초에 NGINX와 Kibana 양쪽에서 동시에 basePath를 재작성하려고 시도해서 URL이 잘못 변형되었고, 그 결과 키바나가 기대하는 내부 라우팅과 실제 전달된 URL 간의 불일치로 404가 발생하거나 무한 리다이렉트가 발생한 것이었다.
지금 이렇게 써놓고 보니 엄청 간단한 해결방법인 거 같지만, 사실 이 문제를 해결하는 데는 2일 정도가 걸렸다. 그리고 내 Cursor IDE의 토큰과, ChatGPT의 토큰을 거의 다 사용할 정도였다. 공식 문서도 참조했지만 rewriteBasePath는 기본적으로 False라는 글을 보고 오히려 더 혼란이 온 적도 있었다.
정말 농담이 아니고 그 이틀 동안 sudo nginx -t
와 sudo systemctl restart nginx
를 몇백번도 넘게 친 거 같다. 꿈에서도 나올 것만 같았다. 이 문제를 해결하고 나서 진이 다 빠졌지만 기쁜 마음으로 키바나에 접속해봤는데, 이번엔 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를 말아보겠다고 염병을 했는지, 그냥 이대로 사는 것도 나쁘지 않을 것 같다는 잡생각이 들기 시작했지만 이미 강을 건너버린 난 다시 싸움을 준비했다. 그 이야기는 다음 편에서 풀어보도록 하겠다.