ReDO 운영 환경의 애플리케이션·EC2·Redis 메트릭과 컨테이너 로그를 수집하고, Grafana 대시보드와 Discord 알림으로 관찰하기 위한 구성입니다.
이 문서의 서버 실행, SSH 터널과 Prometheus 관리 절차는 Monitoring EC2 접근 권한이 있는 인프라 담당자를 대상으로 합니다. 팀원은 별도로 발급받은 Grafana Viewer 계정으로 대시보드를 조회하며, SSH 키나 Grafana Admin 계정은 공유하지 않습니다.
Service EC2
├─ Spring Boot Actuator :9101 ─┐
├─ Node Exporter :9100 ─┼─> Monitoring EC2의 Prometheus
├─ Redis Exporter :9121 ─┘
└─ Docker Socket Proxy -> Alloy -> TLS + Basic Auth -> Loki Proxy :3100
Monitoring EC2
├─ Prometheus :9090 ─┐
├─ Loki ├─> Grafana :3000 -> Discord 장애·복구 알림
└─ Loki Proxy :3100 ──┘
k6 실행 환경 -> Prometheus Remote Write :9090/api/v1/write
| 구성 요소 | 역할 | 보관 정책 |
|---|---|---|
| Prometheus | 애플리케이션·EC2·Redis·k6 메트릭 저장 | 최대 7일 또는 2GB |
| Loki | Service EC2의 Docker 로그 저장 | 72시간 |
| Grafana | 메트릭·로그 조회, 대시보드, Discord 알림 | Grafana 볼륨에 저장 |
| Alloy | Service EC2 컨테이너 로그 수집 및 Loki 전송 | 로컬 상태만 저장 |
| Docker Socket Proxy | Alloy에 Docker 조회 권한만 제한적으로 제공 | 해당 없음 |
monitoring/
├─ compose.yaml
├─ .env.example
├─ prometheus/prometheus.yml
├─ loki/loki.yaml
├─ loki-proxy/nginx.conf
├─ alloy/config.alloy
└─ grafana/
├─ dashboards/
└─ provisioning/
├─ alerting/
├─ dashboards/
└─ datasources/
- 루트
compose.yaml: Service EC2의 애플리케이션, Redis, Exporter, Alloy를 실행합니다. monitoring/compose.yaml: Monitoring EC2의 Prometheus, Loki, Loki Proxy, Grafana를 실행합니다.- 인증서,
.htpasswd, 실제.env는 Git에서 제외됩니다.
두 EC2가 같은 VPC의 사설 IP로 통신할 수 있어야 합니다.
| 방향 | 포트 | 용도 |
|---|---|---|
| Monitoring EC2 → Service EC2 | TCP 9100 | EC2 메트릭 수집 |
| Monitoring EC2 → Service EC2 | TCP 9101 | Spring Boot 메트릭 수집 |
| Monitoring EC2 → Service EC2 | TCP 9121 | Redis 메트릭 수집 |
| Service EC2 → Monitoring EC2 | TCP 3100 | Alloy 로그 전송 |
| 인프라 담당자 → Monitoring EC2 | TCP 22 | SSH 및 Grafana·Prometheus 터널 |
보안 그룹의 소스는 가능하면 상대 EC2의 보안 그룹으로 제한합니다. 3000, 9090, 3100, 9100, 9101, 9121을 인터넷 전체에 공개하지 않습니다.
Loki Proxy는 TLS와 Basic Auth를 모두 확인합니다. 다음 파일은 저장소에 커밋하지 않습니다.
monitoring/loki-proxy/secrets/server.crt
monitoring/loki-proxy/secrets/server.key
monitoring/loki-proxy/secrets/.htpasswd
monitoring/alloy/certs/loki-ca.crt
Monitoring EC2에서 사설 IP가 SAN에 포함된 인증서를 준비합니다. 아래 명령은 자체 서명 인증서를 만드는 예시입니다.
mkdir -p monitoring/loki-proxy/secrets
openssl req -x509 -nodes -newkey rsa:2048 -days 365 \
-keyout monitoring/loki-proxy/secrets/server.key \
-out monitoring/loki-proxy/secrets/server.crt \
-subj "/CN=<MONITORING_PRIVATE_IP>" \
-addext "subjectAltName=IP:<MONITORING_PRIVATE_IP>"Basic Auth 파일도 생성합니다. 사용자명과 비밀번호는 이후 Service EC2의 .env 값과 같아야 합니다.
docker run --rm --entrypoint htpasswd httpd:2.4-alpine \
-Bbn '<LOKI_USERNAME>' '<LOKI_PASSWORD>' \
> monitoring/loki-proxy/secrets/.htpasswd생성한 server.crt를 Service EC2의 다음 경로로 안전하게 복사합니다.
monitoring/alloy/certs/loki-ca.crt
인증서를 갱신하면 Monitoring EC2의 server.crt, server.key와 Service EC2의 loki-ca.crt를 함께 교체해야 합니다.
cp monitoring/.env.example monitoring/.envMONITORING_PRIVATE_IP=<모니터링 EC2 사설 IP>
SERVICE_PRIVATE_IP=<서비스 EC2 사설 IP>
GRAFANA_ADMIN_USER=admin
GRAFANA_ADMIN_PASSWORD=<강한 비밀번호>
GRAFANA_ALERT_DISCORD_WEBHOOK_URL=<Discord Webhook URL>루트 .env에 다음 값을 설정합니다.
SERVICE_PRIVATE_IP=<서비스 EC2 사설 IP>
MONITORING_PRIVATE_IP=<모니터링 EC2 사설 IP>
LOKI_TENANT_ID=redo
LOKI_BASIC_AUTH_USERNAME=<htpasswd 생성 시 사용한 사용자명>
LOKI_BASIC_AUTH_PASSWORD=<htpasswd 생성 시 사용한 비밀번호>실제 비밀번호와 Webhook URL은 .env.example에 작성하지 않습니다.
Monitoring EC2를 먼저 실행한 뒤 Service EC2를 실행합니다.
docker compose \
--env-file monitoring/.env \
-f monitoring/compose.yaml \
config
docker compose \
--env-file monitoring/.env \
-f monitoring/compose.yaml \
up -ddocker compose config
docker compose up -d환경변수나 설정 파일을 변경한 경우 해당 서비스를 다시 생성합니다.
docker compose up -d --force-recreate alloy
docker compose \
--env-file monitoring/.env \
-f monitoring/compose.yaml \
up -d --force-recreate prometheus loki loki-proxy grafana볼륨에는 메트릭, 로그, Grafana 설정이 저장되므로 장애 대응 과정에서 down -v를 실행하지 않습니다.
docker compose ps
docker compose \
--env-file monitoring/.env \
-f monitoring/compose.yaml \
psMonitoring EC2에서 Service EC2의 Exporter에 접근되는지 확인합니다.
curl http://<SERVICE_PRIVATE_IP>:9101/actuator/health
curl http://<SERVICE_PRIVATE_IP>:9100/metrics
curl http://<SERVICE_PRIVATE_IP>:9121/metricsPrometheus의 Status > Target health 화면에서 다음 작업이 모두 UP인지 확인합니다.
prometheusredo-springredo-noderedo-redis
Service EC2와 Monitoring EC2에서 오류 로그를 확인합니다.
docker compose logs --tail=100 alloy docker-socket-proxy
docker compose \
--env-file monitoring/.env \
-f monitoring/compose.yaml \
logs --tail=100 loki loki-proxyGrafana의 Explore에서 Loki를 선택한 뒤 다음 쿼리로 로그 유입을 확인합니다.
{environment="production"}
인프라 담당자는 로컬 PC에서 Monitoring EC2로 SSH 터널을 연결합니다.
ssh -N \
-L 3000:127.0.0.1:3000 \
-L 9090:127.0.0.1:9090 \
ubuntu@<MONITORING_EC2_PUBLIC_IP>- Grafana:
http://localhost:3000 - Prometheus:
http://localhost:9090
Grafana에는 다음 항목이 자동 프로비저닝됩니다.
- Prometheus·Loki 데이터 소스
ReDO Operations Overview운영 대시보드ReDO k6 Load Test부하 테스트 대시보드- 애플리케이션·EC2·Redis 장애 및 자원 알림
- Discord 장애·복구 알림
대시보드나 알림 설정 파일을 변경했는데 반영되지 않으면 Grafana를 재시작합니다.
docker compose \
--env-file monitoring/.env \
-f monitoring/compose.yaml \
restart grafana팀용 HTTPS 접속 경로가 구성된 환경에서 인프라 담당자가 팀원별 Grafana 계정을 생성하고 조직 역할을 Viewer로 지정합니다.
- 접속 주소:
https://<GRAFANA_DOMAIN> - 계정은 팀원별로 발급하며 공용 계정을 사용하지 않습니다.
- Viewer 계정으로 대시보드와 부하 테스트 결과를 조회합니다.
- Grafana Admin 계정, Monitoring EC2 SSH 키와 Prometheus 접근 권한은 공유하지 않습니다.
- 회원가입은 비활성화하고 계정 생성과 회수는 인프라 담당자가 수행합니다.
Prometheus는 인프라 담당자가 실행한 k6의 Remote Write 결과를 받을 수 있도록 구성되어 있습니다. 인프라 담당자는 로컬 PC에서 Monitoring EC2의 9090 포트로 SSH 터널을 연결한 뒤 k6/.env를 설정합니다.
K6_OUTPUT=prometheus
K6_PROMETHEUS_RW_SERVER_URL=http://host.docker.internal:9090/api/v1/write테스트를 실행하면 자동 생성된 testid가 모든 k6 메트릭에 추가됩니다.
./k6/run.sh scenarios/examples/authenticated-read.js일반 팀원은 k6의 local 출력으로 기본 결과를 확인하고, 인프라 담당자가 공유한 TEST_ID로 Grafana의 ReDO k6 Load Test 대시보드를 조회합니다. Viewer 계정은 Prometheus나 Monitoring EC2 접근 권한을 요구하지 않습니다.
Grafana의 ReDO k6 Load Test 대시보드에서 testid, domain, scenario, endpoint를 선택해 결과와 애플리케이션·EC2·Redis 자원 사용량을 함께 확인합니다. 자세한 실행 방법과 안전장치는 k6 부하 테스트 운영 가이드를 참고합니다.
- 두 EC2의 사설 IP가 환경변수와 일치하는지 확인합니다.
- Service EC2의
9100,9101,9121포트가 사설 IP에 바인딩됐는지 확인합니다. - 보안 그룹이 Monitoring EC2에서 오는 요청을 허용하는지 확인합니다.
docker compose ps와 Exporter 로그를 확인합니다.
loki-ca.crt가 현재 Loki Proxy의server.crt와 대응하는지 확인합니다.- 인증서 SAN에 Monitoring EC2의 사설 IP가 포함됐는지 확인합니다.
- 인증서 갱신 후 Alloy와 Loki Proxy를 모두 재생성합니다.
.htpasswd의 사용자명·비밀번호와 Service EC2.env값을 확인합니다.- 비밀번호 변경 후
.htpasswd와.env를 함께 변경하고 두 서비스를 재생성합니다.
- SSH 터널의
9090연결이 유지되는지 확인합니다. K6_OUTPUT=prometheus인지 확인합니다.- k6 출력에 Prometheus Remote Write 오류가 없는지 확인합니다.
- Prometheus 컨테이너에
--web.enable-remote-write-receiver가 적용됐는지 확인합니다.
GRAFANA_ALERT_DISCORD_WEBHOOK_URL값을 확인합니다.- Grafana의
Alerting > Contact points에서 테스트 알림을 보냅니다. - Grafana 로그에서 provisioning 또는 webhook 오류를 확인합니다.
docker compose \
--env-file monitoring/.env \
-f monitoring/compose.yaml \
logs --tail=100 grafana.env, 인증서, 개인키,.htpasswd, Discord Webhook을 Git에 커밋하지 않습니다.- 모니터링 포트는 사설망과 SSH 터널을 통해서만 접근합니다.
- Prometheus·Loki·Grafana 볼륨 삭제 전에는 데이터 유실 범위를 반드시 확인합니다.
- 부하 테스트 전 Grafana에서 기존 자원 사용량과 모든 Target의
UP상태를 확인합니다. - 운영 환경의
stress또는 쓰기 부하 테스트는 팀 합의와 전용 테스트 데이터 준비 후 실행합니다.