/prometheus # wget http://vmi1229594-app:80/metrics
Connecting to vmi1229594-app:80 (172.20.0.2:80)
Connecting to [public URL] (172.67.69.84:443)
wget: note: TLS certificate validation not implemented
wget: server returned error: HTTP/1.1 404 Not Found
여기서 Discourse의 nginx 컨테이너가 자동 리다이렉트를 수행하고 있는 것 같습니다.
발생하는 상황은 내부 Cloudflare IP인 공개 도메인의 https로 포워딩을 시도하고, 당연히 모든 요청을 거부하는 것입니다.
이것은 본질적인 문제가 아닙니다. 내부 IP에서 http://yourwebsite.com/metrics 경로로 요청이 들어올 경우 이 리다이렉트는 일어나지 않아야 하며, 플러그인이 nginx conf에 이 규칙을 추가하여 이를 처리해 줄 것으로 기대했습니다. 그런데 이것이 일어나지 않는 것 같습니다.
Discourse 개발진 중 누가 이 문제에 대해 의견을 남겨주실 수 있을까요? 무작위로 사람들을 언급하고 싶지 않고, 이전에 아무도 이 문제를 보고하지 않은 것 같아 이상합니다.
수정: 컨테이너에 랜덤한 호스트네임이 할당되는 것을 확인했기 때문에 네트워크 설정에 정적 호스트네임도 지정하여 다시 빌드했습니다.
그 후에도 prometheus 잡을 metrics의 https 버전으로 접근하도록 설정해 보았지만, 문제는 첫 번째 단계로 돌아가게 됩니다:
/prometheus # wget https://discourse_app/metrics
Connecting to discourse_app (172.20.0.2:443)
wget: note: TLS certificate validation not implemented
Connecting to [public URL] (104.26.4.193:443)
wget: server returned error: HTTP/1.1 404 Not Found
@JammyDodger 감사합니다. 하지만 불행히도 해당 리소스는 도움이 되지 않았습니다.
유사한 문제를 다루고 있지만, 이 경우와 약간 다르기 때문에 적용이 되지 않습니다.
확실히 하기 위해, 해당 토픽 중 하나에서 제안한 방법(그리고 @pfaffman님의 조언도 포함하여)을 시도해 보았고, DISCOURSE_PROMETHEUS_TRUSTED_IP_ALLOWLIST_REGEX 환경 변수를 가지고 여러 가지로 테스트해 보았습니다.
다음과 같이 테스트해 보았습니다:
주석 처리
내부 IP 값으로 추가
외부 IP 값으로 추가
또한 Prometheus 스크레이프 잡을 변경하여 Discourse 설치 환경을 다음과 같이 지정해 보았습니다:
직접 내부 IP
Docker 내부 호스트명
직접 외부 IP
공개 도메인 이름
모든 경우에서 http와 https를 모두 시도해 보았습니다.
모든 경우에서 404 오류가 발생합니다.
요청이 내부 IP에서 오고 있으므로, 실제 페이지 응답이 반환되기를 기대했습니다.
좋은 발견이지만, 해당 특정 포트를 대상으로 하면 “connection refused” 메시지가 나옵니다.
Get "http://discourse_app:9405/metrics": dial tcp 172.20.0.2:9405: connect: connection refused
확실히 하기 위해 prometheus 컨테이너 내부에서 wget으로 테스트도 해보았습니다.
/prometheus # ping discourse_app
PING discourse_app (172.20.0.2): 56 data bytes
64 bytes from 172.20.0.2: seq=0 ttl=64 time=0.223 ms
64 bytes from 172.20.0.2: seq=1 ttl=64 time=0.270 ms
^C
--- discourse_app ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.223/0.246/0.270 ms
/prometheus # wget discourse_app:9405/metrics
Connecting to discourse_app:9405 (172.20.0.2:9405)
wget: can't connect to remote host (172.20.0.2): Connection refused
네, (prometheus 컨테이너는 barebone busybox라서) 대신 wget으로 테스트했지만, 어쨌든 metrics에 접근할 수 있었습니다.
즉, 말씀하시는 것은 prometheus가 실행 중인 컨테이너의 /etc/hosts에 해당 주소를 해석하도록 하는 항목을 추가하는 방법을 찾아야 한다는 뜻이죠… 거기에선 이해를 못 했네요
제가 한 일은 단순히 nginx만 실행하는 또 다른 docker 컨테이너를 추가하고, 수신하는 요청에 Host 헤더를 추가하는 포워드 프록시 구성을 제공하는 것이었습니다. 이 컨테이너는 어떤 포트도 노출하지 않으므로, 어쨌든 내부 가상 네트워크에서만 접근할 수 있습니다.
기록을 위해 말씀드리자면, 필요한 모든 것을 설정해 둔 저장소를 하나 보유하고 있습니다.
포워딩 프록시 설정 파일에 포함된 우리 웹사이트의 FQDN과 같은 일부 하드코딩된 값이 포함되어 있어, 다른 사람이 사용하려면 변경이 필요하지만, 다른 분들께 유용할 수 있을 것입니다.
Docker Compose부터 Nginx 설정, 그리고 리소스와 대시보드에 대한 Grafana 프로비저닝까지 모든 것이 포함되어 있습니다.
이 nginx 컨테이너가 이제 localhost IP를 통해 prometheus와 통신하고 있기 때문입니다.
서비스가 리스닝 중인 IP나 포트가 확실하지 않다면, ss -ltp 또는 netstat -ltp를 사용할 수 있습니다(컨테이너 내부에서! 필요한 패키지는 각각 net-tools와 iproute2입니다). 예를 들어, 저는 방금 prometheus 플러그인이 포함된 컨테이너를 다시 빌드한 후 다음과 같은 것을 확인했습니다:
root@discourse-docker-app:/# ss -ltp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 128 127.0.0.1:3000 0.0.0.0:*
LISTEN 0 128 0.0.0.0:postgresql 0.0.0.0:*
LISTEN 0 128 0.0.0.0:https 0.0.0.0:* users:(("nginx",pid=555,fd=7))
LISTEN 0 128 127.0.0.1:9405 0.0.0.0:*
LISTEN 0 128 0.0.0.0:redis 0.0.0.0:*
LISTEN 0 128 0.0.0.0:http 0.0.0.0:* users:(("nginx",pid=555,fd=6))
LISTEN 0 128 [::]:postgresql [::]:*
LISTEN 0 128 [::]:https [::]:* users:(("nginx",pid=555,fd=8))
LISTEN 0 128 [::]:redis [::]:*
root@discourse-docker-app:/# curl http://172.17.0.2:9405/metrics
curl: (7) Failed to connect to 172.17.0.2 port 9405: Connection refused
root@discourse-docker-app:/# curl http://localhost:9405/metrics
# HELP discourse_collector_working Is the master process collector able to collect metrics
# TYPE discourse_collector_working gauge
discourse_collector_working 1
# HELP discourse_collector_rss total memory used by collector process
# TYPE discourse_collector_rss gauge
discourse_collector_rss 38178816
…
vmi1187507-app에 대한 IP 조회 요청을 거부하는 네임서버입니다. 포트 53은 DNS입니다.