๐ ์ํฌ๋ก๋

1) docker-compse ์ค์
services:
prometheus:
image: prom/prometheus:latest # Prometheus ์ต์ ์ด๋ฏธ์ง ์ฌ์ฉ
container_name: prometheus # ์ปจํ
์ด๋ ์ด๋ฆ ์ง์
ports:
- "9090:9090" # ํธ์คํธ ํฌํธ 9090 โ ์ปจํ
์ด๋ ํฌํธ 9090
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml # ํธ์คํธ์ ์ค์ ํ์ผ์ ์ปจํ
์ด๋๋ก ๋ง์ดํธ
command:
- --config.file=/etc/prometheus/prometheus.yml # ์ค์ ํ์ผ ๊ฒฝ๋ก ์ง์ (์ต์
)
networks:
- prometheus # prometheus ๋คํธ์ํฌ์ ์ฐ๊ฒฐ
loki:
image: loki:latest # Loki ์ต์ ์ด๋ฏธ์ง ์ฌ์ฉ (๊ณต์ ์ด๋ฏธ์ง๋ grafana/loki ์ฌ์ฉ ๊ถ์ฅ)
container_name: loki # ์ปจํ
์ด๋ ์ด๋ฆ ์ง์
user: "$UID:$GID" # ํ์ฌ ์ฌ์ฉ์ ๊ถํ์ผ๋ก ์คํ (๊ถํ ๋ฌธ์ ๋ฐฉ์ง)
ports:
- "3100:3100" # Loki ํฌํธ ๋งคํ (๊ธฐ๋ณธ ํฌํธ 3100)
volumes:
- ./loki/loki.yml:/etc/loki/local-config.yaml # Loki ์ค์ ํ์ผ ๋ง์ดํธ
- ./loki:/var/loki # ๋ก๊ทธ ๋ฐ์ดํฐ ์ ์ฅ ๋๋ ํ ๋ฆฌ ๋ง์ดํธ
command: -config.file=/etc/loki/local-config.yaml # ์ค์ ํ์ผ ์ง์
networks:
- loki # loki ๋คํธ์ํฌ์ ์ฐ๊ฒฐ
grafana:
image: grafana:latest # Grafana ์ต์ ์ด๋ฏธ์ง
container_name: grafana # ์ปจํ
์ด๋ ์ด๋ฆ ์ง์
user: "$UID:$GID" # ํ์ฌ ์ฌ์ฉ์ ๊ถํ์ผ๋ก ์คํ
ports:
- "3000:3000" # Grafana ์น ํฌํธ (๊ธฐ๋ณธ 3000)
volumes:
- ./grafana:/var/lib/grafana # Grafana ๋ฐ์ดํฐ ๋๋ ํ ๋ฆฌ ๋ง์ดํธ (๋์๋ณด๋, ์ค์ ๋ฑ ์ ์ฅ)
depends_on:
- prometheus # Prometheus ์๋น์ค๊ฐ ๋จผ์ ์์๋๋๋ก ์ค์
- loki # Loki ์๋น์ค๊ฐ ๋จผ์ ์์๋๋๋ก ์ค์
networks:
- prometheus # Prometheus ๋คํธ์ํฌ์ ์ฐ๊ฒฐ (๋ฉํธ๋ฆญ ์์ง์ฉ)
- loki # Loki ๋คํธ์ํฌ์ ์ฐ๊ฒฐ (๋ก๊ทธ ์์ง์ฉ)
networks: # ์ฌ์ฉ์ ์ ์ ๋คํธ์ํฌ ์ค์
prometheus:
driver: bridge # ๊ธฐ๋ณธ ๋ธ๋ฆฌ์ง ๋คํธ์ํฌ ์ฌ์ฉ
loki:
driver: bridge # ๋ก๊ทธ ๊ด๋ จ ์ปจํ
์ด๋์ฉ ๋คํธ์ํฌ
โ
docker-compose down
- ํ์ฌ ์คํ ์ค์ธ ๋ชจ๋ ์ปจํ
์ด๋, ๋คํธ์ํฌ, ๋ณผ๋ฅจ ๋ฑ์ ์ข
๋ฃ ๋ฐ ์ญ์ ํฉ๋๋ค.
- ๊ธฐ๋ณธ์ ์ผ๋ก ๋คํธ์ํฌ์ ์ปจํ
์ด๋๋ฅผ ์ญ์ ํ๊ณ , ๋ณผ๋ฅจ์ ์ ์ง๋ฉ๋๋ค. (--volumes ์ต์
์ ์ฃผ๋ฉด ๋ณผ๋ฅจ๋ ์ญ์ ๋จ)
โ
docker-compose up -d
- docker-compose.yml์ ์ ์๋ ์๋น์ค๋ฅผ ๋ฐฑ๊ทธ๋ผ์ด๋(-d)๋ก ์คํํฉ๋๋ค.
- ๋ณ๊ฒฝ๋ ๋ถ๋ถ๋ง ๋ค์ ๋น๋ํ๊ณ ์คํํฉ๋๋ค.
2) Spring Application ์์ ํ๋ก๋ฉํ
์ฐ์ค ์๋ฒ๋ก ๋ฉํธ๋ฆญ ๋ฐ์ดํฐ๋ฅผ Export
1. build.gradle ์์กด์ฑ ์ถ๊ฐ
implementation 'io.micrometer:micrometer-registry-prometheus'
2. yml ํ์ผ ์ค์
management:
endpoints:
web:
exposure:
include: prometheus
endpoint:
prometheus:
enabled: true
3) Spring Application ์์ Loki ์๋ฒ๋ก ๋ก๊ทธ๋ฅผ ์ ๋ฌํ๋ Appender ์ค์
1. build.gradle ์์กด์ฑ ์ถ๊ฐ
implementation 'com.github.loki4j:loki-logback-appender:1.5.1'
2. logback ์ค์
<appender name="LOKI" class="com.github.loki4j.logback.Loki4jAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>WARN</level>
</filter>
<http>
<url>http://{Loki ์๋ฒ URL}:3100/loki/api/v1/push</url>
</http>
<format>
<label>
<pattern>appName=weather-v2-dev,host=${HOSTNAME},level=%level</pattern>
</label>
<message>
<pattern> [%thread] %-5level %logger{36} - %msg%n</pattern>
</message>
</format>
</appender>
4) preometheus.yml ์ค์
๐จECS + FARGATE ์๋น์ค ๋์ค์ปค๋ฒ๋ฆฌ ์ฐ๋ ์ : dns_sd_config + Cloud Map ์ฌ์ฉ
global:
scrape_interval: 1s # ๋ฉํธ๋ฆญ ์์ง ์ฃผ๊ธฐ (๊ธฐ๋ณธ: 1์ด)
evaluation_interval: 1s # ์๋ฆผ ๋ฃฐ ํ๊ฐ ์ฃผ๊ธฐ (๊ธฐ๋ณธ: 1์ด)
- job_name: "test-one"
metrics_path: "/actuator/prometheus"
static_configs:
- targets: ["test.application.com"]
relabel_configs:
- source_labels: ['__address__']
target_label: 'instance'
replacement: '์ํํ
์คํธ(์ฒซ๋ฒ์งธ)'
scheme: https
- job_name: "test-two"
metrics_path: "/actuator/prometheus"
dns_sd_configs: # DNS ๊ธฐ๋ฐ ์๋น์ค ๋์ค์ปค๋ฒ๋ฆฌ ์ฌ์ฉ
- names:
- 'test-two-api.test-two.dev' # ์๋น์ค ๋๋ฉ์ธ {
type: 'A' # A ๋ ์ฝ๋ ์กฐํ
port: 80 # HTTP ํฌํธ
relabel_configs:
- source_labels: ['__address__']
target_label: 'instance'
scheme: https
โ
static_configs
์ ์ ์ธ ํ๊ฒ ์ค์ โ IP๋ ๋๋ฉ์ธ ์ฃผ์๋ฅผ ์ง์ ๋ช
์
- ํ๊ฒ์ ์๋์ผ๋ก ์
๋ ฅ
- IP ๋๋ ๋๋ฉ์ธ ์ฃผ์๊ฐ ๊ณ ์ ๋์ด ์์ ๋ ์ฌ์ฉ
- ๊ฐ๋จํ ๊ตฌ์กฐ, ํ
์คํธ/๊ฐ๋ฐ ํ๊ฒฝ์์ ๋ง์ด ์ฌ์ฉ
์ฌ์ฉ ์
- EC2, ECS, ๋ก๋๋ฐธ๋ฐ์ ๋ฑ์ ๋๋ฉ์ธ์ด๋ IP๋ก ์ ๊ทผ ๊ฐ๋ฅํ ๋
- ์๊ฐ ๋ง์ง ์๊ณ ๋ณ๊ฒฝ๋์ง ์๋ ์๋น์ค๋ค
โ
dns_sd_configs
DNS ๊ธฐ๋ฐ์ ์๋น์ค ๋์ค์ปค๋ฒ๋ฆฌ โ DNS ์ฟผ๋ฆฌ๋ฅผ ํตํด ๋์ ์ผ๋ก ํ๊ฒ์ ์ฐพ์
- ์๋น์ค๊ฐ ๋ฑ๋ก๋ ๋๋ฉ์ธ์ ๊ธฐ์ค์ผ๋ก DNS A/AAAA ๋ ์ฝ๋๋ฅผ ์กฐํ
- ํด๋ฌ์คํฐ ๋ด๋ถ ์๋น์ค(DNS๊ฐ ์๋ ๊ด๋ฆฌ๋๋ ํ๊ฒฝ, ์: Kubernetes, ECS ์๋น์ค ๋์ค์ปค๋ฒ๋ฆฌ ๋ฑ)์ ์ ํฉ
- ๋์์ด ๋์ด๋๊ฑฐ๋ ์ค์ด๋๋ ๊ฒฝ์ฐ ์๋ ๋ฐ์ ๊ฐ๋ฅ ( โปํต์ฌ )
์ฌ์ฉ ์
- AWS ECS, Kubernetes ๋ฑ ๋์ ์ผ๋ก ์์ฑ๋๋ ์๋น์ค
- DNS๋ฅผ ํตํด ํด๋ฌ์คํฐ ์๋น์ค ์๋ํฌ์ธํธ๋ฅผ ๋
ธ์ถํ ๋
5) Loki ์ค์
auth_enabled: false # ์ธ์ฆ ๊ธฐ๋ฅ ๋นํ์ฑํ (๊ธฐ๋ณธ์ ์ผ๋ก ๋ด๋ถ ๋คํธ์ํฌ์์ ์ฌ์ฉ ์ ์ธ์ฆ ์๋ต ๊ฐ๋ฅ)
server:
http_listen_port: 3100 # Loki ์๋ฒ๊ฐ HTTP ์์ฒญ์ ์์ ํ ํฌํธ ์ค์
common:
instance_addr: 127.0.0.1 # Loki ์ธ์คํด์ค์ ์ฃผ์ (gossip ring์ ์ฌ์ฉ)
path_prefix: /var/loki # Loki๊ฐ ๋ด๋ถ์ ์ผ๋ก ํ์ผ์ ์ ์ฅํ ๊ธฐ๋ณธ ๊ฒฝ๋ก
storage:
filesystem: # ๋ก์ปฌ ํ์ผ ์์คํ
๊ธฐ๋ฐ ์ ์ฅ์ ์ฌ์ฉ
chunks_directory: /var/loki/chunks # ๋ก๊ทธ ์ฒญํฌ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ ๋๋ ํ ๋ฆฌ
rules_directory: /var/loki/rules # ๋ฃฐ ํ์ผ ์ ์ฅ ๊ฒฝ๋ก (์๋ฆผ ๋ฃฐ ๋ฑ)
replication_factor: 1 # ๋ณต์ ๊ฐ์ ์ค์ , 1์ ๋จ์ผ ๋
ธ๋์์ ์ฌ์ฉ
ring:
kvstore:
store: inmemory # ํค-๊ฐ ์ ์ฅ์๋ก ์ธ๋ฉ๋ชจ๋ฆฌ ๋ฐฉ์ ์ฌ์ฉ (๋จ์ผ ๋
ธ๋์ ์ ํฉ)
query_range:
results_cache:
cache:
embedded_cache:
enabled: true # ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ์ ๋ํ ์บ์ ๊ธฐ๋ฅ ํ์ฑํ
max_size_mb: 100 # ์บ์ ์ต๋ ํฌ๊ธฐ (MB ๋จ์)
schema_config:
configs:
- from: 2020-10-24 # ์ด ๋ ์ง๋ถํฐ ์ ์ฉํ ์คํค๋ง ์ค์
store: tsdb # ์ ์ฅ ๋ฐฉ์์ผ๋ก TSDB(Time Series Database) ์ฌ์ฉ
object_store: s3 # ์ฒญํฌ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ ์ค๋ธ์ ํธ ์คํ ์ด ํ์
schema: v12 # Loki ์คํค๋ง ๋ฒ์ (์ต์ ๋ฒ์ ์ค ํ๋)
index:
prefix: index_ # ์ธ๋ฑ์ค ํ๋ฆฌํฝ์ค (S3์ ์ ์ฅ๋ ํค ์ด๋ฆ์ ์ ๋์ด)
period: 24h # ์ธ๋ฑ์ค๋ฅผ ํ๋ฃจ ๋จ์๋ก ์์ฑ
storage_config:
aws:
s3: tnear-loki-log # ์ฌ์ฉํ S3 ๋ฒํท ์ด๋ฆ
region: ap-northeast-2 # S3 ๋ฆฌ์ (์์ธ)
access_key_id: {AWS_ACCESS_KEY} # AWS ์ ๊ทผ ํค (๋ณด์์ ์ฃผ์ ํ์)
secret_access_key: {AWS_SECRET_ACCESS_KEY} # AWS ๋น๋ฐ ์ ๊ทผ ํค (๋ณด์์ ์ฃผ์ ํ์)
6) Grafana ์ ์

๐น ๊ฒฐ๋ก
โญ Prometheus ๋ฉํธ๋ฆญ ๋ฐ์ดํฐ + Loki ๋ก๊ทธ๋ฅผ ์ฐ๋ํ์ฌ ์๊ฐํ
โญ Loki๋ ๋ ์ด๋ธ ๊ธฐ๋ฐ์ ์ต์ ์ธ๋ฑ์ฑ ๊ตฌ์กฐ ์ฌ์ฉ,
โญ Prometheus๋ ์์ฒด DB์ ์์ถ ๊ตฌ์กฐ๋ก ๊ณ ์ฑ๋ฅ ๊ณ ํจ์จ์ ์
โญ Loki์ Prometheus ์ค์ ํ์ผ ๊ธฐ๋ฐ ์ด์์ด ์ฌ์
โญ ์คํ์์ค ๊ธฐ๋ฐ์ผ๋ก ๋ณ๋ ๋ผ์ด์ ์ค ๋น์ฉ์ด ์๋ค.
์๊ฐํ ๋์๋ณด๋ ๊ตฌ์ฑ์ ๊ดํด์๋ ๋ค์ ๊ธ์์ ์งํํ๋๋ก ํ๊ฒ ๋ค. ๐๐๐๐๐๐๐๐