728x90
λ°μν
9μ₯ 컨ν μ΄λ λͺ¨λν°λ§μΌλ‘ ν¬λͺ μ± μλ μ ν리μΌμ΄μ λ§λ€κΈ°
- 컨ν μ΄λμμ μ€νλλ μ ν리μΌμ΄μ μ ν¬λͺ μ±μ λ§€μ° μ€μν μμλ€.
- ν¬λͺ μ±μ ν보ν΄μΌ μ ν리μΌμ΄μ μ λμ λ° μν, λ¬Έμ μ μμΈμ μ νν νμ ν μ μλ€.
9.1 컨ν μ΄λνλ μ ν리μΌμ΄μ μμ μ¬μ©λλ λͺ¨λν°λ§ κΈ°μ μ€ν
- νλ‘λ©ν μ°μ€λ₯Ό μ¬μ©νλ©΄ λͺ¨λν°λ§μ μ€μν μΈ‘λ©΄μΈ μΌκ΄μ±μ΄ ν보λλ€.
- λͺ¨λ μ ν리μΌμ΄μ μ λκ°μ μΈ‘μ κ°μ ν΅ν΄ νμ€μ μΈ ννλ‘ λͺ¨λν°λ§ν μ μλ€.
- λ컀 μμ§μ μΈ‘μ κ°λ κ°μ νμμΌλ‘ μΆμΆν μ μλ€.
- ν΄λΉ κΈ°λ₯μ μ¬μ©νλ €λ©΄ νλ‘λ©ν μ°μ€ μΈ‘μ κΈ°λ₯μ λͺ μμ μΌλ‘ νμ±νν΄μΌ νλ€.
$ vi /etc/docker/daemon.json
{
"metrics-addr" : "0.0.0.0:9323",
"experimental" : true
}
$ sudo systemctl restart docker
http://[IP]:9323/metrics
# HELP builder_builds_failed_total Number of failed image builds
# TYPE builder_builds_failed_total counter
builder_builds_failed_total{reason="build_canceled"} 0
builder_builds_failed_total{reason="build_target_not_reachable_error"} 0
builder_builds_failed_total{reason="command_not_supported_error"} 0
builder_builds_failed_total{reason="dockerfile_empty_error"} 0
builder_builds_failed_total{reason="dockerfile_syntax_error"} 0
builder_builds_failed_total{reason="error_processing_commands_error"} 0
builder_builds_failed_total{reason="missing_onbuild_arguments_error"} 0
builder_builds_failed_total{reason="unknown_instruction_error"} 0
# HELP builder_builds_triggered_total Number of triggered image builds
# TYPE builder_builds_triggered_total counter
builder_builds_triggered_total 0
# HELP engine_daemon_container_actions_seconds The number of seconds it takes to process each container action
# TYPE engine_daemon_container_actions_seconds histogram
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.005"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.01"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.025"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.05"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.1"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.25"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.5"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="1"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="2.5"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="5"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="10"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="+Inf"} 1
...
- μΈ‘μ λ κ° μνμ λ³΄κ° Key Value ννλ‘ ννλλ ν μ€νΈ κΈ°λ° ν¬λ§·μ΄λ€.
$ hostIP=$(ip addr show enp0s5 | grep -oP '(?<=inet\\s)\\d+(\\.\\d+){3}')
$ docker container run -e DOCKER_HOST=$hostIP -d -p 9090:9090 diamol/prometheus:2.13.1
- prometheus λ UI λ₯Ό ν΅ν΄ μΈ‘μ κ°μ νμΈνκ±°λ 쿼리λ₯Ό μ€νν μ μλ€.
- κ° μνλ³ μ»¨ν μ΄λ μλ μ€ν¨ν ν¬μ€ μ²΄ν¬ νμ κ°μ κ³ μμ€ μ 보λΆν° λ컀 μμ§μ΄ μ μ μ€μΈ λ©λͺ¨λ¦¬ μ©λ κ°μ μ μμ€ μ 보κΉμ§ μ»μ μ μλ€.
9.2 μ ν리μΌμ΄μ μ μΈ‘μ κ° μΆλ ₯νκΈ°
- μ ν리μΌμ΄μ μ κ²½μ° λ©νΈλ¦ μμ§ μλν¬μΈνΈλ₯Ό ν΅ν΄ μμ§ν μ μλ€.
- μ£Όμ μΈμ΄λ€μ νλ‘λ©ν μ°μ€μ λΌμ΄λΈλ¬κ° μ 곡λλ€.
- λΌμ΄λΈλ¬λ¦¬λ₯Ό ν΅ν΄ μμ§λ μ 보λ λ°νμ μμ€μ μΈ‘μ κ°μΌλ‘, ν΄λΉ 컨ν μ΄λκ° μ²λ¦¬νλ μμ κ³Ό λΆνμ μ λμ μ λ³΄κ° λ°νμμ κ΄μ μμ ννλλ€.
$ vi docker-compose.yml
version: "3.7"
services:
accesslog:
image: diamol/ch09-access-log
ports:
- "8012:80"
networks:
- app-net
iotd:
image: diamol/ch09-image-of-the-day
ports:
- "8011:80"
networks:
- app-net
image-gallery:
image: diamol/ch09-image-gallery
ports:
- "8010:80"
depends_on:
- accesslog
- iotd
networks:
- app-net
prometheus:
image: diamol/ch09-prometheus
ports:
- "9090:9090"
environment:
- DOCKER_HOST=${HOST_IP}
networks:
- app-net
networks:
app-net:
external:
name: nat
$ docker rm -f $(docker ps -aq)
$ docker network create nat
$ docker compose -f docker-comopose.yml up -d
# http://[HOST_IP]:8010/metrics
# HELP go_gc_duration_seconds A summary of the GC invocation durations.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 0
go_gc_duration_seconds{quantile="0.25"} 0
go_gc_duration_seconds{quantile="0.5"} 0
go_gc_duration_seconds{quantile="0.75"} 0
go_gc_duration_seconds{quantile="1"} 0
go_gc_duration_seconds_sum 0
go_gc_duration_seconds_count 0
...
- μ΄λ¬ν λ°νμ μν μΈ‘μ κ°μ λ컀 μμ§μμ μ»μ μΈνλΌμ€νΈλ¬μ² μΈ‘μ κ°κ³Όλ λ λ€λ₯Έ μμ€μ μ 보λ₯Ό μ 곡νλ€.
- μ ν리μΌμ΄μ μ μ΄λ²€νΈ μ, νκ· μλ΅ μ²λ¦¬ μκ°, νμ± μ¬μ©μ μ λ±μ μ ν리μΌμ΄μ μ°μ° μ 보 λΆν° λΉμ¦λμ€ μ 보 λ±μ ννν μ μλ€.
9.3 μΈ‘μ κ° μμ§μ 맑μ νλ‘λ©ν μ°μ€ 컨ν μ΄λ μ€ννκΈ°
- prometheus λ μ§μ μΈ‘μ κ°μ λμ μμ€ν μμ λ°μμ μμ§νλ νλ§ λ°©μμΌλ‘ λμνλ€.
- prometheus μμ μΈ‘μ κ°μ μμ§νλ κ³Όμ μ μ€ν¬λν μ΄λΌκ³ νλ€.
- μ€ν¬λνμ νκΈ° μν΄μλ λμ μ ν리μΌμ΄μ μ μλν¬μΈνΈλ₯Ό μ€μ ν΄μΌ νλ€.
global:
scrape_interval: 10s
scrape_configs:
- job_name: "image-gallery"
metrics_path: /metrics
static_configs:
- targets: ["image-gallery"]
- job_name: "iotd-api"
metrics_path: /actuator/prometheus
static_configs:
- targets: ["iotd"]
- job_name: "access-log"
metrics_path: /metrics
scrape_interval: 3s
dns_sd_configs:
- names:
- accesslog
type: A
port: 80
- job_name: "docker"
metrics_path: /metrics
static_configs:
- targets: ["DOCKER_HOST:9323"]
- global scrape_interval μ€μ μ μ 체 λμμ μ€ν¬λνμ μ£ΌκΈ°λ₯Ό μ€μ νλ€. (10μ΄)
- access-log 컨ν μ΄λμ κ²½μ° dns_sd_configs μ€μ μ ν΅ν΄ DNS κΈ°λ° μλΉμ€ λμ€μ»€λ²λ¦¬λ₯Ό μ¬μ©νλ€.
- κ·Έ μ΄μ λ access-log μ κ²½μ° μλ²κ° Scale Out λμ΄ μμ΄ λ컀 DNS λ₯Ό ν΅ν΄ λ΄λΆ IP λ₯Ό μ°Ύμμ ν΅μ νκΈ° μν¨μ΄λ€.
- type: A λ λλ©μΈ μ΄λ¦μ IPv4 μ£Όμλ‘ λ§€ννλ κ²μ΄λ€.
$ docker compose -f docker-compose-scale.yml up -d --scale accesslog=3
[+] Running 6/6
β Container exercises-prometheus-1 Started 0.3s
β Container exercises-accesslog-3 Started 0.5s
β Container exercises-accesslog-1 Started 0.3s
β Container exercises-accesslog-2 Started 0.6s
β Container exercises-iotd-1 Started 0.3s
β Container exercises-image-gallery-1 Started
$ for i in {1..10}; do curl <http://localhost:8010> > /dev/null; done
access_log_total
- κΈ°λ³Έ μ€μ μ΄ λμ΄μλ νλ‘λ©ν μ°μ€ μ΄λ―Έμ§λ₯Ό λ§λ€λ©΄ λ§€λ² μΆλΌκ³ μ€μ μ μμ±νμ§ μμλ λλ©°, νμν κ²½μ° κΈ°λ³Έκ°μ μμ ν μ μλ€.
- νλ‘λ©ν μ°μ€λ λ μ΄λΈμ λΆμ¬ λ©νΈλ¦μ λν΄ λ€μν 컨ν μ€νΈλ₯Ό μΆκ°ν μ μλ€.
- λν, λ μ΄λΈμ μ΄μ©ν΄ νλ‘λ©ν μ°μ€ 쿼리λ₯Ό μ΄μ©ν΄ μ§κ³ λ° λΆμμ΄ κ°λ₯νλ€.
access_log_total{instance="172.20.0.6:80"}
sum(image_gallery_requests_total{code="200"}) without(instance)
9.4 μΈ‘μ κ° μκ°νλ₯Ό μν κ·ΈλΌνλ 컨ν μ΄λ μ€ννκΈ°
- μΈ‘μ κ°μ κ°κ³΅νλ κ²μ promethus μμ μ§ννκ³ , κ°κ³΅λ μΈ‘μ κ°μ ν΅ν΄ λμ보λλ₯Ό ꡬμ±νλ κ²μ grafana λ₯Ό μ¬μ©νλ€.
- κ·ΈλΌνλ λμ보λλ μ ν리μΌμ΄μ μ ν΅μ¬ μ 보λ₯Ό λ€μν μμ€μμ μ 곡νλ€.
- μκ°νλ κ·Έλνλ PromQL(Prometheus Query Language) λ‘ μμ±λ λ¨μΌ μΏΌλ¦¬λ‘ κ·Έλ €μ§λ€.
- PromQL κ°λ ₯νκ³ μ§κ΄μ μΈ λ°©μμΌλ‘ λ°μ΄ν°λ₯Ό νν°λ§, μ§κ³, κ³μ°ν μ μλλ‘ μ€κ³λμ΄μλ€.
$ hostIP=$(ip addr show enp0s5 | grep -oP '(?<=inet\\s)\\d+(\\.\\d+){3}')
$ docker compose -f docker-compose-with-grafana.yml up -d --scale accesslog=3
[+] Running 10/10
β grafana Pulled 11.6s
β 29bddadc8f3f Pull complete 2.2s
β d9b0d74c7b70 Pull complete 2.2s
β 3fb7e7639feb Pull complete 2.5s
β 3cd42e0f5101 Pull complete 8.0s
β af31ba937280 Pull complete 8.0s
β 7c7f1ccbce63 Pull complete 8.0s
β fc130f9b4964 Pull complete 8.0s
β ca4c94507a97 Pull complete 8.0s
β a2a6b53e5a03 Pull complete 8.0s
[+] Running 7/7
β Container exercises-accesslog-3 Started 0.8s
β Container exercises-prometheus-1 Started 0.4s
β Container exercises-accesslog-1 Started 0.3s
β Container exercises-accesslog-2 Started 0.6s
β Container exercises-iotd-1 Started 0.3s
β Container exercises-grafana-1 Started 0.7s
β Container exercises-image-gallery-1 Started
$ for i in {1..20}; do curl <http://localhost:8010> > /dev/null; done
PromQL μμ
# 200 μλ΅ count
sum(image_gallery_requests_total{code="200"}) without(instance)
# νμ¬ μ²λ¦¬ μ€μΈ μμ² μ
sum(image_gallery_requests) without(instance)
# λ©λͺ¨λ¦¬ μ¬μ©λ
go_memstats_bytes{job="image-gallery"}
# κ³ λ£¨ν΄ νμ± μ
sum(go_goroutinces{job="image_gallery"}) without(instance)
- λμ보λμ κ·Έλνλ μ λμ μΈ κ°λ³΄λ€λ λ³ννλ μΆμΈμμ μ μ μλ μ λ΄ λ§λ€.
- νκ· κ°μμ μμΉκ° ν¬κ² μ¬λΌκ°λ μκ°μ΄ μΈμ μΈμ§λ₯Ό νμ νλκ²μ΄ μ€μνλ€.
- μ»΄νΌλνΈμ μΈ‘μ κ°μ μ‘°ν©ν΄ μ ν리μΌμ΄μ μ μ΄μ νμκ³Ό μκ΄κ΄κ³λ₯Ό μ°ΎμμΌ νλ€.
9.5 ν¬λͺ μ±μ μμ€
- κ°λ¨ν κ°λ κ²μ¦ μμ€μ νλ‘λνΈμμ μ€μ μλΉμ€ μμ€μΌλ‘ λμκ°κΈ° μν΄ ν¬λͺ μ±μ λ°λμ νμνλ€.
- μ€μ μ΄μνκ²½μ κ²½μ° μμΈν μν©μ μ μ μλ λͺ¨λν°λ§ λμ보λλ λ°λμ νμνλ€.
- μ ν리μΌμ΄μ μ μ 체 μν©μ μ‘°λ§νλ λμ보λλ κ°μ₯ μ€μνλ€.
- λμ€ν¬ μ©λ, CPU, λ©λͺ¨λ¦¬, λ€νΈμν¬ μμ λ± λͺ¨λ μλ²μ μν©μ 보μ¬μ£Όλ μΈνλΌμ€νΈλμ² λμ보λλ μ’λ€.
- μΈ‘μ κ° μ€μμ μ ν리μΌμ΄μ μ μ€μν λ°μ΄ν°λ₯Ό λͺ¨μ νλμ νλ©΄μΌλ‘ ꡬμ±ν μ μμ΄μΌ νλ€.
9.6 μ°μ΅λ¬Έμ
- Prometheus μ Grafana λ₯Ό ν΅ν λͺ¨λν°λ§ ꡬμΆν΄λ³΄κΈ°.
- docker compose μ¬μ©νκΈ°
Prometheus
# prometheus.yml
global:
scrape_interval: 10s
scrape_configs:
- job_name: "todo-list"
metrics_path: /metrics
static_configs:
- targets: ["todo-list"]
# Dockerfile
FROM diamol/prometheus:2.13.1
COPY prometheus.yml /etc/prometheus/prometheus.yml
Grafana
Provision dashboards and data sources | Grafana Labs
Prometheus data source | Grafana documentation
# Dockerfile
FROM diamol/grafana:6.4.3
COPY datasource-prometheus.yaml ${GF_PATHS_PROVISIONING}/datasources/
COPY dashboard-provider.yaml ${GF_PATHS_PROVISIONING}/dashboards/
COPY dashboard.json /var/lib/grafana/dashboards/
# dashboard-provider.yml
apiVersion: 1
providers:
- name: 'default'
orgId: 1
folder: ''
type: file
disableDeletion: true
updateIntervalSeconds: 0
options:
path: /var/lib/grafana/dashboards
# datasoruce-prometheus.yml
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: <http://prometheus:9090>
basicAuth: false
version: 1
editable: true
Docker Compose
version: "3.7"
services:
todo-list:
image: diamol/ch09-todo-list
ports:
- "8050:80"
networks:
- app-net
prometheus:
image: diamol/ch09-lab-prometheus
ports:
- "9090:9090"
networks:
- app-net
grafana:
image: diamol/ch09-lab-grafana
ports:
- "3000:3000"
depends_on:
- prometheus
networks:
- app-net
networks:
app-net:
external:
name: nat
9μ₯ 컨ν μ΄λ λͺ¨λν°λ§μΌλ‘ ν¬λͺ μ± μλ μ ν리μΌμ΄μ λ§λ€κΈ°
- 컨ν μ΄λμμ μ€νλλ μ ν리μΌμ΄μ μ ν¬λͺ μ±μ λ§€μ° μ€μν μμλ€.
- ν¬λͺ μ±μ ν보ν΄μΌ μ ν리μΌμ΄μ μ λμ λ° μν, λ¬Έμ μ μμΈμ μ νν νμ ν μ μλ€.
9.1 컨ν μ΄λνλ μ ν리μΌμ΄μ μμ μ¬μ©λλ λͺ¨λν°λ§ κΈ°μ μ€ν
- νλ‘λ©ν μ°μ€λ₯Ό μ¬μ©νλ©΄ λͺ¨λν°λ§μ μ€μν μΈ‘λ©΄μΈ μΌκ΄μ±μ΄ ν보λλ€.
- λͺ¨λ μ ν리μΌμ΄μ μ λκ°μ μΈ‘μ κ°μ ν΅ν΄ νμ€μ μΈ ννλ‘ λͺ¨λν°λ§ν μ μλ€.
- λ컀 μμ§μ μΈ‘μ κ°λ κ°μ νμμΌλ‘ μΆμΆν μ μλ€.
- ν΄λΉ κΈ°λ₯μ μ¬μ©νλ €λ©΄ νλ‘λ©ν μ°μ€ μΈ‘μ κΈ°λ₯μ λͺ μμ μΌλ‘ νμ±νν΄μΌ νλ€.
$ vi /etc/docker/daemon.json
{
"metrics-addr" : "0.0.0.0:9323",
"experimental" : true
}
$ sudo systemctl restart docker
http://[IP]:9323/metrics
# HELP builder_builds_failed_total Number of failed image builds
# TYPE builder_builds_failed_total counter
builder_builds_failed_total{reason="build_canceled"} 0
builder_builds_failed_total{reason="build_target_not_reachable_error"} 0
builder_builds_failed_total{reason="command_not_supported_error"} 0
builder_builds_failed_total{reason="dockerfile_empty_error"} 0
builder_builds_failed_total{reason="dockerfile_syntax_error"} 0
builder_builds_failed_total{reason="error_processing_commands_error"} 0
builder_builds_failed_total{reason="missing_onbuild_arguments_error"} 0
builder_builds_failed_total{reason="unknown_instruction_error"} 0
# HELP builder_builds_triggered_total Number of triggered image builds
# TYPE builder_builds_triggered_total counter
builder_builds_triggered_total 0
# HELP engine_daemon_container_actions_seconds The number of seconds it takes to process each container action
# TYPE engine_daemon_container_actions_seconds histogram
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.005"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.01"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.025"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.05"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.1"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.25"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.5"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="1"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="2.5"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="5"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="10"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="+Inf"} 1
...
- μΈ‘μ λ κ° μνμ λ³΄κ° Key Value ννλ‘ ννλλ ν μ€νΈ κΈ°λ° ν¬λ§·μ΄λ€.
$ hostIP=$(ip addr show enp0s5 | grep -oP '(?<=inet\\s)\\d+(\\.\\d+){3}')
$ docker container run -e DOCKER_HOST=$hostIP -d -p 9090:9090 diamol/prometheus:2.13.1
hostIP=$(ifconfig en0 | grep -e 'inet\\s' | awk '{print $2}')
# νκ²½ λ³μλ‘ λ‘컬 μ»΄ν¨ν°μ IP μ£Όμλ₯Ό μ λ¬ν΄ 컨ν
μ΄λλ₯Ό μ€ν
docker container run -e DOCKER_HOST=$hostIP -d -p 9090:9090 diamol/prometheus:2.13.1
- prometheus λ UI λ₯Ό ν΅ν΄ μΈ‘μ κ°μ νμΈνκ±°λ 쿼리λ₯Ό μ€νν μ μλ€.
- κ° μνλ³ μ»¨ν μ΄λ μλ μ€ν¨ν ν¬μ€ μ²΄ν¬ νμ κ°μ κ³ μμ€ μ 보λΆν° λ컀 μμ§μ΄ μ μ μ€μΈ λ©λͺ¨λ¦¬ μ©λ κ°μ μ μμ€ μ 보κΉμ§ μ»μ μ μλ€.
9.2 μ ν리μΌμ΄μ μ μΈ‘μ κ° μΆλ ₯νκΈ°
- μ ν리μΌμ΄μ μ κ²½μ° λ©νΈλ¦ μμ§ μλν¬μΈνΈλ₯Ό ν΅ν΄ μμ§ν μ μλ€.
- μ£Όμ μΈμ΄λ€μ νλ‘λ©ν μ°μ€μ λΌμ΄λΈλ¬κ° μ 곡λλ€.
- λΌμ΄λΈλ¬λ¦¬λ₯Ό ν΅ν΄ μμ§λ μ 보λ λ°νμ μμ€μ μΈ‘μ κ°μΌλ‘, ν΄λΉ 컨ν μ΄λκ° μ²λ¦¬νλ μμ κ³Ό λΆνμ μ λμ μ λ³΄κ° λ°νμμ κ΄μ μμ ννλλ€.
$ vi docker-compose.yml
version: "3.7"
services:
accesslog:
image: diamol/ch09-access-log
ports:
- "8012:80"
networks:
- app-net
iotd:
image: diamol/ch09-image-of-the-day
ports:
- "8011:80"
networks:
- app-net
image-gallery:
image: diamol/ch09-image-gallery
ports:
- "8010:80"
depends_on:
- accesslog
- iotd
networks:
- app-net
prometheus:
image: diamol/ch09-prometheus
ports:
- "9090:9090"
environment:
- DOCKER_HOST=${HOST_IP}
networks:
- app-net
networks:
app-net:
external:
name: nat
$ docker rm -f $(docker ps -aq)
$ docker network create nat
$ docker compose -f docker-comopose.yml up -d
# http://[HOST_IP]:8010/metrics
# HELP go_gc_duration_seconds A summary of the GC invocation durations.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 0
go_gc_duration_seconds{quantile="0.25"} 0
go_gc_duration_seconds{quantile="0.5"} 0
go_gc_duration_seconds{quantile="0.75"} 0
go_gc_duration_seconds{quantile="1"} 0
go_gc_duration_seconds_sum 0
go_gc_duration_seconds_count 0
...
- μ΄λ¬ν λ°νμ μν μΈ‘μ κ°μ λ컀 μμ§μμ μ»μ μΈνλΌμ€νΈλ¬μ² μΈ‘μ κ°κ³Όλ λ λ€λ₯Έ μμ€μ μ 보λ₯Ό μ 곡νλ€.
- μ ν리μΌμ΄μ μ μ΄λ²€νΈ μ, νκ· μλ΅ μ²λ¦¬ μκ°, νμ± μ¬μ©μ μ λ±μ μ ν리μΌμ΄μ μ°μ° μ 보 λΆν° λΉμ¦λμ€ μ 보 λ±μ ννν μ μλ€.
9.3 μΈ‘μ κ° μμ§μ 맑μ νλ‘λ©ν μ°μ€ 컨ν μ΄λ μ€ννκΈ°
- prometheus λ μ§μ μΈ‘μ κ°μ λμ μμ€ν μμ λ°μμ μμ§νλ νλ§ λ°©μμΌλ‘ λμνλ€.
- prometheus μμ μΈ‘μ κ°μ μμ§νλ κ³Όμ μ μ€ν¬λν μ΄λΌκ³ νλ€.
- μ€ν¬λνμ νκΈ° μν΄μλ λμ μ ν리μΌμ΄μ μ μλν¬μΈνΈλ₯Ό μ€μ ν΄μΌ νλ€.
global:
scrape_interval: 10s
scrape_configs:
- job_name: "image-gallery"
metrics_path: /metrics
static_configs:
- targets: ["image-gallery"]
- job_name: "iotd-api"
metrics_path: /actuator/prometheus
static_configs:
- targets: ["iotd"]
- job_name: "access-log"
metrics_path: /metrics
scrape_interval: 3s
dns_sd_configs:
- names:
- accesslog
type: A
port: 80
- job_name: "docker"
metrics_path: /metrics
static_configs:
- targets: ["DOCKER_HOST:9323"]
- global scrape_interval μ€μ μ μ 체 λμμ μ€ν¬λνμ μ£ΌκΈ°λ₯Ό μ€μ νλ€. (10μ΄)
- access-log 컨ν μ΄λμ κ²½μ° dns_sd_configs μ€μ μ ν΅ν΄ DNS κΈ°λ° μλΉμ€ λμ€μ»€λ²λ¦¬λ₯Ό μ¬μ©νλ€.
- κ·Έ μ΄μ λ access-log μ κ²½μ° μλ²κ° Scale Out λμ΄ μμ΄ λ컀 DNS λ₯Ό ν΅ν΄ λ΄λΆ IP λ₯Ό μ°Ύμμ ν΅μ νκΈ° μν¨μ΄λ€.
- type: A λ λλ©μΈ μ΄λ¦μ IPv4 μ£Όμλ‘ λ§€ννλ κ²μ΄λ€.
$ docker compose -f docker-compose-scale.yml up -d --scale accesslog=3
[+] Running 6/6
β Container exercises-prometheus-1 Started 0.3s
β Container exercises-accesslog-3 Started 0.5s
β Container exercises-accesslog-1 Started 0.3s
β Container exercises-accesslog-2 Started 0.6s
β Container exercises-iotd-1 Started 0.3s
β Container exercises-image-gallery-1 Started
$ for i in {1..10}; do curl <http://localhost:8010> > /dev/null; done
access_log_total
- κΈ°λ³Έ μ€μ μ΄ λμ΄μλ νλ‘λ©ν μ°μ€ μ΄λ―Έμ§λ₯Ό λ§λ€λ©΄ λ§€λ² μΆλΌκ³ μ€μ μ μμ±νμ§ μμλ λλ©°, νμν κ²½μ° κΈ°λ³Έκ°μ μμ ν μ μλ€.
- νλ‘λ©ν μ°μ€λ λ μ΄λΈμ λΆμ¬ λ©νΈλ¦μ λν΄ λ€μν 컨ν μ€νΈλ₯Ό μΆκ°ν μ μλ€.
- λν, λ μ΄λΈμ μ΄μ©ν΄ νλ‘λ©ν μ°μ€ 쿼리λ₯Ό μ΄μ©ν΄ μ§κ³ λ° λΆμμ΄ κ°λ₯νλ€.
access_log_total{instance="172.20.0.6:80"}
sum(image_gallery_requests_total{code="200"}) without(instance)
9.4 μΈ‘μ κ° μκ°νλ₯Ό μν κ·ΈλΌνλ 컨ν μ΄λ μ€ννκΈ°
- μΈ‘μ κ°μ κ°κ³΅νλ κ²μ promethus μμ μ§ννκ³ , κ°κ³΅λ μΈ‘μ κ°μ ν΅ν΄ λμ보λλ₯Ό ꡬμ±νλ κ²μ grafana λ₯Ό μ¬μ©νλ€.
- κ·ΈλΌνλ λμ보λλ μ ν리μΌμ΄μ μ ν΅μ¬ μ 보λ₯Ό λ€μν μμ€μμ μ 곡νλ€.
- μκ°νλ κ·Έλνλ PromQL(Prometheus Query Language) λ‘ μμ±λ λ¨μΌ μΏΌλ¦¬λ‘ κ·Έλ €μ§λ€.
- PromQL κ°λ ₯νκ³ μ§κ΄μ μΈ λ°©μμΌλ‘ λ°μ΄ν°λ₯Ό νν°λ§, μ§κ³, κ³μ°ν μ μλλ‘ μ€κ³λμ΄μλ€.
$ hostIP=$(ip addr show enp0s5 | grep -oP '(?<=inet\\s)\\d+(\\.\\d+){3}')
$ docker compose -f docker-compose-with-grafana.yml up -d --scale accesslog=3
[+] Running 10/10
β grafana Pulled 11.6s
β 29bddadc8f3f Pull complete 2.2s
β d9b0d74c7b70 Pull complete 2.2s
β 3fb7e7639feb Pull complete 2.5s
β 3cd42e0f5101 Pull complete 8.0s
β af31ba937280 Pull complete 8.0s
β 7c7f1ccbce63 Pull complete 8.0s
β fc130f9b4964 Pull complete 8.0s
β ca4c94507a97 Pull complete 8.0s
β a2a6b53e5a03 Pull complete 8.0s
[+] Running 7/7
β Container exercises-accesslog-3 Started 0.8s
β Container exercises-prometheus-1 Started 0.4s
β Container exercises-accesslog-1 Started 0.3s
β Container exercises-accesslog-2 Started 0.6s
β Container exercises-iotd-1 Started 0.3s
β Container exercises-grafana-1 Started 0.7s
β Container exercises-image-gallery-1 Started
$ for i in {1..20}; do curl <http://localhost:8010> > /dev/null; done
PromQL μμ
# 200 μλ΅ count
sum(image_gallery_requests_total{code="200"}) without(instance)
# νμ¬ μ²λ¦¬ μ€μΈ μμ² μ
sum(image_gallery_requests) without(instance)
# λ©λͺ¨λ¦¬ μ¬μ©λ
go_memstats_bytes{job="image-gallery"}
# κ³ λ£¨ν΄ νμ± μ
sum(go_goroutinces{job="image_gallery"}) without(instance)
- λμ보λμ κ·Έλνλ μ λμ μΈ κ°λ³΄λ€λ λ³ννλ μΆμΈμμ μ μ μλ μ λ΄ λ§λ€.
- νκ· κ°μμ μμΉκ° ν¬κ² μ¬λΌκ°λ μκ°μ΄ μΈμ μΈμ§λ₯Ό νμ νλκ²μ΄ μ€μνλ€.
- μ»΄νΌλνΈμ μΈ‘μ κ°μ μ‘°ν©ν΄ μ ν리μΌμ΄μ μ μ΄μ νμκ³Ό μκ΄κ΄κ³λ₯Ό μ°ΎμμΌ νλ€.
9.5 ν¬λͺ μ±μ μμ€
- κ°λ¨ν κ°λ κ²μ¦ μμ€μ νλ‘λνΈμμ μ€μ μλΉμ€ μμ€μΌλ‘ λμκ°κΈ° μν΄ ν¬λͺ μ±μ λ°λμ νμνλ€.
- μ€μ μ΄μνκ²½μ κ²½μ° μμΈν μν©μ μ μ μλ λͺ¨λν°λ§ λμ보λλ λ°λμ νμνλ€.
- μ ν리μΌμ΄μ μ μ 체 μν©μ μ‘°λ§νλ λμ보λλ κ°μ₯ μ€μνλ€.
- λμ€ν¬ μ©λ, CPU, λ©λͺ¨λ¦¬, λ€νΈμν¬ μμ λ± λͺ¨λ μλ²μ μν©μ 보μ¬μ£Όλ μΈνλΌμ€νΈλμ² λμ보λλ μ’λ€.
- μΈ‘μ κ° μ€μμ μ ν리μΌμ΄μ μ μ€μν λ°μ΄ν°λ₯Ό λͺ¨μ νλμ νλ©΄μΌλ‘ ꡬμ±ν μ μμ΄μΌ νλ€.
9.6 μ°μ΅λ¬Έμ
- Prometheus μ Grafana λ₯Ό ν΅ν λͺ¨λν°λ§ ꡬμΆν΄λ³΄κΈ°.
- docker compose μ¬μ©νκΈ°
Prometheus
# prometheus.yml
global:
scrape_interval: 10s
scrape_configs:
- job_name: "todo-list"
metrics_path: /metrics
static_configs:
- targets: ["todo-list"]
# Dockerfile
FROM diamol/prometheus:2.13.1
COPY prometheus.yml /etc/prometheus/prometheus.yml
Grafana
Provision dashboards and data sources | Grafana Labs
Prometheus data source | Grafana documentation
# Dockerfile
FROM diamol/grafana:6.4.3
COPY datasource-prometheus.yaml ${GF_PATHS_PROVISIONING}/datasources/
COPY dashboard-provider.yaml ${GF_PATHS_PROVISIONING}/dashboards/
COPY dashboard.json /var/lib/grafana/dashboards/
# dashboard-provider.yml
apiVersion: 1
providers:
- name: 'default'
orgId: 1
folder: ''
type: file
disableDeletion: true
updateIntervalSeconds: 0
options:
path: /var/lib/grafana/dashboards
# datasoruce-prometheus.yml
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: <http://prometheus:9090>
basicAuth: false
version: 1
editable: true
Docker Compose
version: "3.7"
services:
todo-list:
image: diamol/ch09-todo-list
ports:
- "8050:80"
networks:
- app-net
prometheus:
image: diamol/ch09-lab-prometheus
ports:
- "9090:9090"
networks:
- app-net
grafana:
image: diamol/ch09-lab-grafana
ports:
- "3000:3000"
depends_on:
- prometheus
networks:
- app-net
networks:
app-net:
external:
name: nat
9μ₯ 컨ν μ΄λ λͺ¨λν°λ§μΌλ‘ ν¬λͺ μ± μλ μ ν리μΌμ΄μ λ§λ€κΈ°
- 컨ν μ΄λμμ μ€νλλ μ ν리μΌμ΄μ μ ν¬λͺ μ±μ λ§€μ° μ€μν μμλ€.
- ν¬λͺ μ±μ ν보ν΄μΌ μ ν리μΌμ΄μ μ λμ λ° μν, λ¬Έμ μ μμΈμ μ νν νμ ν μ μλ€.
9.1 컨ν μ΄λνλ μ ν리μΌμ΄μ μμ μ¬μ©λλ λͺ¨λν°λ§ κΈ°μ μ€ν
- νλ‘λ©ν μ°μ€λ₯Ό μ¬μ©νλ©΄ λͺ¨λν°λ§μ μ€μν μΈ‘λ©΄μΈ μΌκ΄μ±μ΄ ν보λλ€.
- λͺ¨λ μ ν리μΌμ΄μ μ λκ°μ μΈ‘μ κ°μ ν΅ν΄ νμ€μ μΈ ννλ‘ λͺ¨λν°λ§ν μ μλ€.
- λ컀 μμ§μ μΈ‘μ κ°λ κ°μ νμμΌλ‘ μΆμΆν μ μλ€.
- ν΄λΉ κΈ°λ₯μ μ¬μ©νλ €λ©΄ νλ‘λ©ν μ°μ€ μΈ‘μ κΈ°λ₯μ λͺ μμ μΌλ‘ νμ±νν΄μΌ νλ€.
$ vi /etc/docker/daemon.json
{
"metrics-addr" : "0.0.0.0:9323",
"experimental" : true
}
$ sudo systemctl restart docker
http://[IP]:9323/metrics
# HELP builder_builds_failed_total Number of failed image builds
# TYPE builder_builds_failed_total counter
builder_builds_failed_total{reason="build_canceled"} 0
builder_builds_failed_total{reason="build_target_not_reachable_error"} 0
builder_builds_failed_total{reason="command_not_supported_error"} 0
builder_builds_failed_total{reason="dockerfile_empty_error"} 0
builder_builds_failed_total{reason="dockerfile_syntax_error"} 0
builder_builds_failed_total{reason="error_processing_commands_error"} 0
builder_builds_failed_total{reason="missing_onbuild_arguments_error"} 0
builder_builds_failed_total{reason="unknown_instruction_error"} 0
# HELP builder_builds_triggered_total Number of triggered image builds
# TYPE builder_builds_triggered_total counter
builder_builds_triggered_total 0
# HELP engine_daemon_container_actions_seconds The number of seconds it takes to process each container action
# TYPE engine_daemon_container_actions_seconds histogram
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.005"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.01"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.025"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.05"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.1"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.25"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.5"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="1"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="2.5"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="5"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="10"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="+Inf"} 1
...
- μΈ‘μ λ κ° μνμ λ³΄κ° Key Value ννλ‘ ννλλ ν μ€νΈ κΈ°λ° ν¬λ§·μ΄λ€.
$ hostIP=$(ip addr show enp0s5 | grep -oP '(?<=inet\\s)\\d+(\\.\\d+){3}')
$ docker container run -e DOCKER_HOST=$hostIP -d -p 9090:9090 diamol/prometheus:2.13.1
hostIP=$(ifconfig en0 | grep -e 'inet\\s' | awk '{print $2}')
# νκ²½ λ³μλ‘ λ‘컬 μ»΄ν¨ν°μ IP μ£Όμλ₯Ό μ λ¬ν΄ 컨ν
μ΄λλ₯Ό μ€ν
docker container run -e DOCKER_HOST=$hostIP -d -p 9090:9090 diamol/prometheus:2.13.1
- prometheus λ UI λ₯Ό ν΅ν΄ μΈ‘μ κ°μ νμΈνκ±°λ 쿼리λ₯Ό μ€νν μ μλ€.
- κ° μνλ³ μ»¨ν μ΄λ μλ μ€ν¨ν ν¬μ€ μ²΄ν¬ νμ κ°μ κ³ μμ€ μ 보λΆν° λ컀 μμ§μ΄ μ μ μ€μΈ λ©λͺ¨λ¦¬ μ©λ κ°μ μ μμ€ μ 보κΉμ§ μ»μ μ μλ€.
9.2 μ ν리μΌμ΄μ μ μΈ‘μ κ° μΆλ ₯νκΈ°
- μ ν리μΌμ΄μ μ κ²½μ° λ©νΈλ¦ μμ§ μλν¬μΈνΈλ₯Ό ν΅ν΄ μμ§ν μ μλ€.
- μ£Όμ μΈμ΄λ€μ νλ‘λ©ν μ°μ€μ λΌμ΄λΈλ¬κ° μ 곡λλ€.
- λΌμ΄λΈλ¬λ¦¬λ₯Ό ν΅ν΄ μμ§λ μ 보λ λ°νμ μμ€μ μΈ‘μ κ°μΌλ‘, ν΄λΉ 컨ν μ΄λκ° μ²λ¦¬νλ μμ κ³Ό λΆνμ μ λμ μ λ³΄κ° λ°νμμ κ΄μ μμ ννλλ€.
$ vi docker-compose.yml
version: "3.7"
services:
accesslog:
image: diamol/ch09-access-log
ports:
- "8012:80"
networks:
- app-net
iotd:
image: diamol/ch09-image-of-the-day
ports:
- "8011:80"
networks:
- app-net
image-gallery:
image: diamol/ch09-image-gallery
ports:
- "8010:80"
depends_on:
- accesslog
- iotd
networks:
- app-net
prometheus:
image: diamol/ch09-prometheus
ports:
- "9090:9090"
environment:
- DOCKER_HOST=${HOST_IP}
networks:
- app-net
networks:
app-net:
external:
name: nat
$ docker rm -f $(docker ps -aq)
$ docker network create nat
$ docker compose -f docker-comopose.yml up -d
# http://[HOST_IP]:8010/metrics
# HELP go_gc_duration_seconds A summary of the GC invocation durations.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 0
go_gc_duration_seconds{quantile="0.25"} 0
go_gc_duration_seconds{quantile="0.5"} 0
go_gc_duration_seconds{quantile="0.75"} 0
go_gc_duration_seconds{quantile="1"} 0
go_gc_duration_seconds_sum 0
go_gc_duration_seconds_count 0
...
- μ΄λ¬ν λ°νμ μν μΈ‘μ κ°μ λ컀 μμ§μμ μ»μ μΈνλΌμ€νΈλ¬μ² μΈ‘μ κ°κ³Όλ λ λ€λ₯Έ μμ€μ μ 보λ₯Ό μ 곡νλ€.
- μ ν리μΌμ΄μ μ μ΄λ²€νΈ μ, νκ· μλ΅ μ²λ¦¬ μκ°, νμ± μ¬μ©μ μ λ±μ μ ν리μΌμ΄μ μ°μ° μ 보 λΆν° λΉμ¦λμ€ μ 보 λ±μ ννν μ μλ€.
9.3 μΈ‘μ κ° μμ§μ 맑μ νλ‘λ©ν μ°μ€ 컨ν μ΄λ μ€ννκΈ°
- prometheus λ μ§μ μΈ‘μ κ°μ λμ μμ€ν μμ λ°μμ μμ§νλ νλ§ λ°©μμΌλ‘ λμνλ€.
- prometheus μμ μΈ‘μ κ°μ μμ§νλ κ³Όμ μ μ€ν¬λν μ΄λΌκ³ νλ€.
- μ€ν¬λνμ νκΈ° μν΄μλ λμ μ ν리μΌμ΄μ μ μλν¬μΈνΈλ₯Ό μ€μ ν΄μΌ νλ€.
global:
scrape_interval: 10s
scrape_configs:
- job_name: "image-gallery"
metrics_path: /metrics
static_configs:
- targets: ["image-gallery"]
- job_name: "iotd-api"
metrics_path: /actuator/prometheus
static_configs:
- targets: ["iotd"]
- job_name: "access-log"
metrics_path: /metrics
scrape_interval: 3s
dns_sd_configs:
- names:
- accesslog
type: A
port: 80
- job_name: "docker"
metrics_path: /metrics
static_configs:
- targets: ["DOCKER_HOST:9323"]
- global scrape_interval μ€μ μ μ 체 λμμ μ€ν¬λνμ μ£ΌκΈ°λ₯Ό μ€μ νλ€. (10μ΄)
- access-log 컨ν μ΄λμ κ²½μ° dns_sd_configs μ€μ μ ν΅ν΄ DNS κΈ°λ° μλΉμ€ λμ€μ»€λ²λ¦¬λ₯Ό μ¬μ©νλ€.
- κ·Έ μ΄μ λ access-log μ κ²½μ° μλ²κ° Scale Out λμ΄ μμ΄ λ컀 DNS λ₯Ό ν΅ν΄ λ΄λΆ IP λ₯Ό μ°Ύμμ ν΅μ νκΈ° μν¨μ΄λ€.
- type: A λ λλ©μΈ μ΄λ¦μ IPv4 μ£Όμλ‘ λ§€ννλ κ²μ΄λ€.
$ docker compose -f docker-compose-scale.yml up -d --scale accesslog=3
[+] Running 6/6
β Container exercises-prometheus-1 Started 0.3s
β Container exercises-accesslog-3 Started 0.5s
β Container exercises-accesslog-1 Started 0.3s
β Container exercises-accesslog-2 Started 0.6s
β Container exercises-iotd-1 Started 0.3s
β Container exercises-image-gallery-1 Started
$ for i in {1..10}; do curl <http://localhost:8010> > /dev/null; done
access_log_total
- κΈ°λ³Έ μ€μ μ΄ λμ΄μλ νλ‘λ©ν μ°μ€ μ΄λ―Έμ§λ₯Ό λ§λ€λ©΄ λ§€λ² μΆλΌκ³ μ€μ μ μμ±νμ§ μμλ λλ©°, νμν κ²½μ° κΈ°λ³Έκ°μ μμ ν μ μλ€.
- νλ‘λ©ν μ°μ€λ λ μ΄λΈμ λΆμ¬ λ©νΈλ¦μ λν΄ λ€μν 컨ν μ€νΈλ₯Ό μΆκ°ν μ μλ€.
- λν, λ μ΄λΈμ μ΄μ©ν΄ νλ‘λ©ν μ°μ€ 쿼리λ₯Ό μ΄μ©ν΄ μ§κ³ λ° λΆμμ΄ κ°λ₯νλ€.
access_log_total{instance="172.20.0.6:80"}
sum(image_gallery_requests_total{code="200"}) without(instance)
9.4 μΈ‘μ κ° μκ°νλ₯Ό μν κ·ΈλΌνλ 컨ν μ΄λ μ€ννκΈ°
- μΈ‘μ κ°μ κ°κ³΅νλ κ²μ promethus μμ μ§ννκ³ , κ°κ³΅λ μΈ‘μ κ°μ ν΅ν΄ λμ보λλ₯Ό ꡬμ±νλ κ²μ grafana λ₯Ό μ¬μ©νλ€.
- κ·ΈλΌνλ λμ보λλ μ ν리μΌμ΄μ μ ν΅μ¬ μ 보λ₯Ό λ€μν μμ€μμ μ 곡νλ€.
- μκ°νλ κ·Έλνλ PromQL(Prometheus Query Language) λ‘ μμ±λ λ¨μΌ μΏΌλ¦¬λ‘ κ·Έλ €μ§λ€.
- PromQL κ°λ ₯νκ³ μ§κ΄μ μΈ λ°©μμΌλ‘ λ°μ΄ν°λ₯Ό νν°λ§, μ§κ³, κ³μ°ν μ μλλ‘ μ€κ³λμ΄μλ€.
$ hostIP=$(ip addr show enp0s5 | grep -oP '(?<=inet\\s)\\d+(\\.\\d+){3}')
$ docker compose -f docker-compose-with-grafana.yml up -d --scale accesslog=3
[+] Running 10/10
β grafana Pulled 11.6s
β 29bddadc8f3f Pull complete 2.2s
β d9b0d74c7b70 Pull complete 2.2s
β 3fb7e7639feb Pull complete 2.5s
β 3cd42e0f5101 Pull complete 8.0s
β af31ba937280 Pull complete 8.0s
β 7c7f1ccbce63 Pull complete 8.0s
β fc130f9b4964 Pull complete 8.0s
β ca4c94507a97 Pull complete 8.0s
β a2a6b53e5a03 Pull complete 8.0s
[+] Running 7/7
β Container exercises-accesslog-3 Started 0.8s
β Container exercises-prometheus-1 Started 0.4s
β Container exercises-accesslog-1 Started 0.3s
β Container exercises-accesslog-2 Started 0.6s
β Container exercises-iotd-1 Started 0.3s
β Container exercises-grafana-1 Started 0.7s
β Container exercises-image-gallery-1 Started
$ for i in {1..20}; do curl <http://localhost:8010> > /dev/null; done
PromQL μμ
# 200 μλ΅ count
sum(image_gallery_requests_total{code="200"}) without(instance)
# νμ¬ μ²λ¦¬ μ€μΈ μμ² μ
sum(image_gallery_requests) without(instance)
# λ©λͺ¨λ¦¬ μ¬μ©λ
go_memstats_bytes{job="image-gallery"}
# κ³ λ£¨ν΄ νμ± μ
sum(go_goroutinces{job="image_gallery"}) without(instance)
- λμ보λμ κ·Έλνλ μ λμ μΈ κ°λ³΄λ€λ λ³ννλ μΆμΈμμ μ μ μλ μ λ΄ λ§λ€.
- νκ· κ°μμ μμΉκ° ν¬κ² μ¬λΌκ°λ μκ°μ΄ μΈμ μΈμ§λ₯Ό νμ νλκ²μ΄ μ€μνλ€.
- μ»΄νΌλνΈμ μΈ‘μ κ°μ μ‘°ν©ν΄ μ ν리μΌμ΄μ μ μ΄μ νμκ³Ό μκ΄κ΄κ³λ₯Ό μ°ΎμμΌ νλ€.
9.5 ν¬λͺ μ±μ μμ€
- κ°λ¨ν κ°λ κ²μ¦ μμ€μ νλ‘λνΈμμ μ€μ μλΉμ€ μμ€μΌλ‘ λμκ°κΈ° μν΄ ν¬λͺ μ±μ λ°λμ νμνλ€.
- μ€μ μ΄μνκ²½μ κ²½μ° μμΈν μν©μ μ μ μλ λͺ¨λν°λ§ λμ보λλ λ°λμ νμνλ€.
- μ ν리μΌμ΄μ μ μ 체 μν©μ μ‘°λ§νλ λμ보λλ κ°μ₯ μ€μνλ€.
- λμ€ν¬ μ©λ, CPU, λ©λͺ¨λ¦¬, λ€νΈμν¬ μμ λ± λͺ¨λ μλ²μ μν©μ 보μ¬μ£Όλ μΈνλΌμ€νΈλμ² λμ보λλ μ’λ€.
- μΈ‘μ κ° μ€μμ μ ν리μΌμ΄μ μ μ€μν λ°μ΄ν°λ₯Ό λͺ¨μ νλμ νλ©΄μΌλ‘ ꡬμ±ν μ μμ΄μΌ νλ€.
9.6 μ°μ΅λ¬Έμ
- Prometheus μ Grafana λ₯Ό ν΅ν λͺ¨λν°λ§ ꡬμΆν΄λ³΄κΈ°.
- docker compose μ¬μ©νκΈ°
Prometheus
# prometheus.yml
global:
scrape_interval: 10s
scrape_configs:
- job_name: "todo-list"
metrics_path: /metrics
static_configs:
- targets: ["todo-list"]
# Dockerfile
FROM diamol/prometheus:2.13.1
COPY prometheus.yml /etc/prometheus/prometheus.yml
Grafana
Provision dashboards and data sources | Grafana Labs
Prometheus data source | Grafana documentation
# Dockerfile
FROM diamol/grafana:6.4.3
COPY datasource-prometheus.yaml ${GF_PATHS_PROVISIONING}/datasources/
COPY dashboard-provider.yaml ${GF_PATHS_PROVISIONING}/dashboards/
COPY dashboard.json /var/lib/grafana/dashboards/
# dashboard-provider.yml
apiVersion: 1
providers:
- name: 'default'
orgId: 1
folder: ''
type: file
disableDeletion: true
updateIntervalSeconds: 0
options:
path: /var/lib/grafana/dashboards
# datasoruce-prometheus.yml
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: <http://prometheus:9090>
basicAuth: false
version: 1
editable: true
Docker Compose
version: "3.7"
services:
todo-list:
image: diamol/ch09-todo-list
ports:
- "8050:80"
networks:
- app-net
prometheus:
image: diamol/ch09-lab-prometheus
ports:
- "9090:9090"
networks:
- app-net
grafana:
image: diamol/ch09-lab-grafana
ports:
- "3000:3000"
depends_on:
- prometheus
networks:
- app-net
networks:
app-net:
external:
name: nat
9μ₯ 컨ν μ΄λ λͺ¨λν°λ§μΌλ‘ ν¬λͺ μ± μλ μ ν리μΌμ΄μ λ§λ€κΈ°
- 컨ν μ΄λμμ μ€νλλ μ ν리μΌμ΄μ μ ν¬λͺ μ±μ λ§€μ° μ€μν μμλ€.
- ν¬λͺ μ±μ ν보ν΄μΌ μ ν리μΌμ΄μ μ λμ λ° μν, λ¬Έμ μ μμΈμ μ νν νμ ν μ μλ€.
9.1 컨ν μ΄λνλ μ ν리μΌμ΄μ μμ μ¬μ©λλ λͺ¨λν°λ§ κΈ°μ μ€ν
- νλ‘λ©ν μ°μ€λ₯Ό μ¬μ©νλ©΄ λͺ¨λν°λ§μ μ€μν μΈ‘λ©΄μΈ μΌκ΄μ±μ΄ ν보λλ€.
- λͺ¨λ μ ν리μΌμ΄μ μ λκ°μ μΈ‘μ κ°μ ν΅ν΄ νμ€μ μΈ ννλ‘ λͺ¨λν°λ§ν μ μλ€.
- λ컀 μμ§μ μΈ‘μ κ°λ κ°μ νμμΌλ‘ μΆμΆν μ μλ€.
- ν΄λΉ κΈ°λ₯μ μ¬μ©νλ €λ©΄ νλ‘λ©ν μ°μ€ μΈ‘μ κΈ°λ₯μ λͺ μμ μΌλ‘ νμ±νν΄μΌ νλ€.
$ vi /etc/docker/daemon.json
{
"metrics-addr" : "0.0.0.0:9323",
"experimental" : true
}
$ sudo systemctl restart docker
http://[IP]:9323/metrics
# HELP builder_builds_failed_total Number of failed image builds
# TYPE builder_builds_failed_total counter
builder_builds_failed_total{reason="build_canceled"} 0
builder_builds_failed_total{reason="build_target_not_reachable_error"} 0
builder_builds_failed_total{reason="command_not_supported_error"} 0
builder_builds_failed_total{reason="dockerfile_empty_error"} 0
builder_builds_failed_total{reason="dockerfile_syntax_error"} 0
builder_builds_failed_total{reason="error_processing_commands_error"} 0
builder_builds_failed_total{reason="missing_onbuild_arguments_error"} 0
builder_builds_failed_total{reason="unknown_instruction_error"} 0
# HELP builder_builds_triggered_total Number of triggered image builds
# TYPE builder_builds_triggered_total counter
builder_builds_triggered_total 0
# HELP engine_daemon_container_actions_seconds The number of seconds it takes to process each container action
# TYPE engine_daemon_container_actions_seconds histogram
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.005"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.01"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.025"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.05"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.1"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.25"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.5"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="1"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="2.5"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="5"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="10"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="+Inf"} 1
...
- μΈ‘μ λ κ° μνμ λ³΄κ° Key Value ννλ‘ ννλλ ν μ€νΈ κΈ°λ° ν¬λ§·μ΄λ€.
$ hostIP=$(ip addr show enp0s5 | grep -oP '(?<=inet\\s)\\d+(\\.\\d+){3}')
$ docker container run -e DOCKER_HOST=$hostIP -d -p 9090:9090 diamol/prometheus:2.13.1
hostIP=$(ifconfig en0 | grep -e 'inet\\s' | awk '{print $2}')
# νκ²½ λ³μλ‘ λ‘컬 μ»΄ν¨ν°μ IP μ£Όμλ₯Ό μ λ¬ν΄ 컨ν
μ΄λλ₯Ό μ€ν
docker container run -e DOCKER_HOST=$hostIP -d -p 9090:9090 diamol/prometheus:2.13.1
- prometheus λ UI λ₯Ό ν΅ν΄ μΈ‘μ κ°μ νμΈνκ±°λ 쿼리λ₯Ό μ€νν μ μλ€.
- κ° μνλ³ μ»¨ν μ΄λ μλ μ€ν¨ν ν¬μ€ μ²΄ν¬ νμ κ°μ κ³ μμ€ μ 보λΆν° λ컀 μμ§μ΄ μ μ μ€μΈ λ©λͺ¨λ¦¬ μ©λ κ°μ μ μμ€ μ 보κΉμ§ μ»μ μ μλ€.
9.2 μ ν리μΌμ΄μ μ μΈ‘μ κ° μΆλ ₯νκΈ°
- μ ν리μΌμ΄μ μ κ²½μ° λ©νΈλ¦ μμ§ μλν¬μΈνΈλ₯Ό ν΅ν΄ μμ§ν μ μλ€.
- μ£Όμ μΈμ΄λ€μ νλ‘λ©ν μ°μ€μ λΌμ΄λΈλ¬κ° μ 곡λλ€.
- λΌμ΄λΈλ¬λ¦¬λ₯Ό ν΅ν΄ μμ§λ μ 보λ λ°νμ μμ€μ μΈ‘μ κ°μΌλ‘, ν΄λΉ 컨ν μ΄λκ° μ²λ¦¬νλ μμ κ³Ό λΆνμ μ λμ μ λ³΄κ° λ°νμμ κ΄μ μμ ννλλ€.
$ vi docker-compose.yml
version: "3.7"
services:
accesslog:
image: diamol/ch09-access-log
ports:
- "8012:80"
networks:
- app-net
iotd:
image: diamol/ch09-image-of-the-day
ports:
- "8011:80"
networks:
- app-net
image-gallery:
image: diamol/ch09-image-gallery
ports:
- "8010:80"
depends_on:
- accesslog
- iotd
networks:
- app-net
prometheus:
image: diamol/ch09-prometheus
ports:
- "9090:9090"
environment:
- DOCKER_HOST=${HOST_IP}
networks:
- app-net
networks:
app-net:
external:
name: nat
$ docker rm -f $(docker ps -aq)
$ docker network create nat
$ docker compose -f docker-comopose.yml up -d
# http://[HOST_IP]:8010/metrics
# HELP go_gc_duration_seconds A summary of the GC invocation durations.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 0
go_gc_duration_seconds{quantile="0.25"} 0
go_gc_duration_seconds{quantile="0.5"} 0
go_gc_duration_seconds{quantile="0.75"} 0
go_gc_duration_seconds{quantile="1"} 0
go_gc_duration_seconds_sum 0
go_gc_duration_seconds_count 0
...
- μ΄λ¬ν λ°νμ μν μΈ‘μ κ°μ λ컀 μμ§μμ μ»μ μΈνλΌμ€νΈλ¬μ² μΈ‘μ κ°κ³Όλ λ λ€λ₯Έ μμ€μ μ 보λ₯Ό μ 곡νλ€.
- μ ν리μΌμ΄μ μ μ΄λ²€νΈ μ, νκ· μλ΅ μ²λ¦¬ μκ°, νμ± μ¬μ©μ μ λ±μ μ ν리μΌμ΄μ μ°μ° μ 보 λΆν° λΉμ¦λμ€ μ 보 λ±μ ννν μ μλ€.
9.3 μΈ‘μ κ° μμ§μ 맑μ νλ‘λ©ν μ°μ€ 컨ν μ΄λ μ€ννκΈ°
- prometheus λ μ§μ μΈ‘μ κ°μ λμ μμ€ν μμ λ°μμ μμ§νλ νλ§ λ°©μμΌλ‘ λμνλ€.
- prometheus μμ μΈ‘μ κ°μ μμ§νλ κ³Όμ μ μ€ν¬λν μ΄λΌκ³ νλ€.
- μ€ν¬λνμ νκΈ° μν΄μλ λμ μ ν리μΌμ΄μ μ μλν¬μΈνΈλ₯Ό μ€μ ν΄μΌ νλ€.
global:
scrape_interval: 10s
scrape_configs:
- job_name: "image-gallery"
metrics_path: /metrics
static_configs:
- targets: ["image-gallery"]
- job_name: "iotd-api"
metrics_path: /actuator/prometheus
static_configs:
- targets: ["iotd"]
- job_name: "access-log"
metrics_path: /metrics
scrape_interval: 3s
dns_sd_configs:
- names:
- accesslog
type: A
port: 80
- job_name: "docker"
metrics_path: /metrics
static_configs:
- targets: ["DOCKER_HOST:9323"]
- global scrape_interval μ€μ μ μ 체 λμμ μ€ν¬λνμ μ£ΌκΈ°λ₯Ό μ€μ νλ€. (10μ΄)
- access-log 컨ν μ΄λμ κ²½μ° dns_sd_configs μ€μ μ ν΅ν΄ DNS κΈ°λ° μλΉμ€ λμ€μ»€λ²λ¦¬λ₯Ό μ¬μ©νλ€.
- κ·Έ μ΄μ λ access-log μ κ²½μ° μλ²κ° Scale Out λμ΄ μμ΄ λ컀 DNS λ₯Ό ν΅ν΄ λ΄λΆ IP λ₯Ό μ°Ύμμ ν΅μ νκΈ° μν¨μ΄λ€.
- type: A λ λλ©μΈ μ΄λ¦μ IPv4 μ£Όμλ‘ λ§€ννλ κ²μ΄λ€.
$ docker compose -f docker-compose-scale.yml up -d --scale accesslog=3
[+] Running 6/6
β Container exercises-prometheus-1 Started 0.3s
β Container exercises-accesslog-3 Started 0.5s
β Container exercises-accesslog-1 Started 0.3s
β Container exercises-accesslog-2 Started 0.6s
β Container exercises-iotd-1 Started 0.3s
β Container exercises-image-gallery-1 Started
$ for i in {1..10}; do curl <http://localhost:8010> > /dev/null; done
access_log_total
- κΈ°λ³Έ μ€μ μ΄ λμ΄μλ νλ‘λ©ν μ°μ€ μ΄λ―Έμ§λ₯Ό λ§λ€λ©΄ λ§€λ² μΆλΌκ³ μ€μ μ μμ±νμ§ μμλ λλ©°, νμν κ²½μ° κΈ°λ³Έκ°μ μμ ν μ μλ€.
- νλ‘λ©ν μ°μ€λ λ μ΄λΈμ λΆμ¬ λ©νΈλ¦μ λν΄ λ€μν 컨ν μ€νΈλ₯Ό μΆκ°ν μ μλ€.
- λν, λ μ΄λΈμ μ΄μ©ν΄ νλ‘λ©ν μ°μ€ 쿼리λ₯Ό μ΄μ©ν΄ μ§κ³ λ° λΆμμ΄ κ°λ₯νλ€.
access_log_total{instance="172.20.0.6:80"}
sum(image_gallery_requests_total{code="200"}) without(instance)
9.4 μΈ‘μ κ° μκ°νλ₯Ό μν κ·ΈλΌνλ 컨ν μ΄λ μ€ννκΈ°
- μΈ‘μ κ°μ κ°κ³΅νλ κ²μ promethus μμ μ§ννκ³ , κ°κ³΅λ μΈ‘μ κ°μ ν΅ν΄ λμ보λλ₯Ό ꡬμ±νλ κ²μ grafana λ₯Ό μ¬μ©νλ€.
- κ·ΈλΌνλ λμ보λλ μ ν리μΌμ΄μ μ ν΅μ¬ μ 보λ₯Ό λ€μν μμ€μμ μ 곡νλ€.
- μκ°νλ κ·Έλνλ PromQL(Prometheus Query Language) λ‘ μμ±λ λ¨μΌ μΏΌλ¦¬λ‘ κ·Έλ €μ§λ€.
- PromQL κ°λ ₯νκ³ μ§κ΄μ μΈ λ°©μμΌλ‘ λ°μ΄ν°λ₯Ό νν°λ§, μ§κ³, κ³μ°ν μ μλλ‘ μ€κ³λμ΄μλ€.
$ hostIP=$(ip addr show enp0s5 | grep -oP '(?<=inet\\s)\\d+(\\.\\d+){3}')
$ docker compose -f docker-compose-with-grafana.yml up -d --scale accesslog=3
[+] Running 10/10
β grafana Pulled 11.6s
β 29bddadc8f3f Pull complete 2.2s
β d9b0d74c7b70 Pull complete 2.2s
β 3fb7e7639feb Pull complete 2.5s
β 3cd42e0f5101 Pull complete 8.0s
β af31ba937280 Pull complete 8.0s
β 7c7f1ccbce63 Pull complete 8.0s
β fc130f9b4964 Pull complete 8.0s
β ca4c94507a97 Pull complete 8.0s
β a2a6b53e5a03 Pull complete 8.0s
[+] Running 7/7
β Container exercises-accesslog-3 Started 0.8s
β Container exercises-prometheus-1 Started 0.4s
β Container exercises-accesslog-1 Started 0.3s
β Container exercises-accesslog-2 Started 0.6s
β Container exercises-iotd-1 Started 0.3s
β Container exercises-grafana-1 Started 0.7s
β Container exercises-image-gallery-1 Started
$ for i in {1..20}; do curl <http://localhost:8010> > /dev/null; done
PromQL μμ
# 200 μλ΅ count
sum(image_gallery_requests_total{code="200"}) without(instance)
# νμ¬ μ²λ¦¬ μ€μΈ μμ² μ
sum(image_gallery_requests) without(instance)
# λ©λͺ¨λ¦¬ μ¬μ©λ
go_memstats_bytes{job="image-gallery"}
# κ³ λ£¨ν΄ νμ± μ
sum(go_goroutinces{job="image_gallery"}) without(instance)
- λμ보λμ κ·Έλνλ μ λμ μΈ κ°λ³΄λ€λ λ³ννλ μΆμΈμμ μ μ μλ μ λ΄ λ§λ€.
- νκ· κ°μμ μμΉκ° ν¬κ² μ¬λΌκ°λ μκ°μ΄ μΈμ μΈμ§λ₯Ό νμ νλκ²μ΄ μ€μνλ€.
- μ»΄νΌλνΈμ μΈ‘μ κ°μ μ‘°ν©ν΄ μ ν리μΌμ΄μ μ μ΄μ νμκ³Ό μκ΄κ΄κ³λ₯Ό μ°ΎμμΌ νλ€.
9.5 ν¬λͺ μ±μ μμ€
- κ°λ¨ν κ°λ κ²μ¦ μμ€μ νλ‘λνΈμμ μ€μ μλΉμ€ μμ€μΌλ‘ λμκ°κΈ° μν΄ ν¬λͺ μ±μ λ°λμ νμνλ€.
- μ€μ μ΄μνκ²½μ κ²½μ° μμΈν μν©μ μ μ μλ λͺ¨λν°λ§ λμ보λλ λ°λμ νμνλ€.
- μ ν리μΌμ΄μ μ μ 체 μν©μ μ‘°λ§νλ λμ보λλ κ°μ₯ μ€μνλ€.
- λμ€ν¬ μ©λ, CPU, λ©λͺ¨λ¦¬, λ€νΈμν¬ μμ λ± λͺ¨λ μλ²μ μν©μ 보μ¬μ£Όλ μΈνλΌμ€νΈλμ² λμ보λλ μ’λ€.
- μΈ‘μ κ° μ€μμ μ ν리μΌμ΄μ μ μ€μν λ°μ΄ν°λ₯Ό λͺ¨μ νλμ νλ©΄μΌλ‘ ꡬμ±ν μ μμ΄μΌ νλ€.
9.6 μ°μ΅λ¬Έμ
- Prometheus μ Grafana λ₯Ό ν΅ν λͺ¨λν°λ§ ꡬμΆν΄λ³΄κΈ°.
- docker compose μ¬μ©νκΈ°
Prometheus
# prometheus.yml
global:
scrape_interval: 10s
scrape_configs:
- job_name: "todo-list"
metrics_path: /metrics
static_configs:
- targets: ["todo-list"]
# Dockerfile
FROM diamol/prometheus:2.13.1
COPY prometheus.yml /etc/prometheus/prometheus.yml
Grafana
Provision dashboards and data sources | Grafana Labs
Prometheus data source | Grafana documentation
# Dockerfile
FROM diamol/grafana:6.4.3
COPY datasource-prometheus.yaml ${GF_PATHS_PROVISIONING}/datasources/
COPY dashboard-provider.yaml ${GF_PATHS_PROVISIONING}/dashboards/
COPY dashboard.json /var/lib/grafana/dashboards/
# dashboard-provider.yml
apiVersion: 1
providers:
- name: 'default'
orgId: 1
folder: ''
type: file
disableDeletion: true
updateIntervalSeconds: 0
options:
path: /var/lib/grafana/dashboards
# datasoruce-prometheus.yml
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: <http://prometheus:9090>
basicAuth: false
version: 1
editable: true
Docker Compose
version: "3.7"
services:
todo-list:
image: diamol/ch09-todo-list
ports:
- "8050:80"
networks:
- app-net
prometheus:
image: diamol/ch09-lab-prometheus
ports:
- "9090:9090"
networks:
- app-net
grafana:
image: diamol/ch09-lab-grafana
ports:
- "3000:3000"
depends_on:
- prometheus
networks:
- app-net
networks:
app-net:
external:
name: nat
9μ₯ 컨ν μ΄λ λͺ¨λν°λ§μΌλ‘ ν¬λͺ μ± μλ μ ν리μΌμ΄μ λ§λ€κΈ°
- 컨ν μ΄λμμ μ€νλλ μ ν리μΌμ΄μ μ ν¬λͺ μ±μ λ§€μ° μ€μν μμλ€.
- ν¬λͺ μ±μ ν보ν΄μΌ μ ν리μΌμ΄μ μ λμ λ° μν, λ¬Έμ μ μμΈμ μ νν νμ ν μ μλ€.
9.1 컨ν μ΄λνλ μ ν리μΌμ΄μ μμ μ¬μ©λλ λͺ¨λν°λ§ κΈ°μ μ€ν
- νλ‘λ©ν μ°μ€λ₯Ό μ¬μ©νλ©΄ λͺ¨λν°λ§μ μ€μν μΈ‘λ©΄μΈ μΌκ΄μ±μ΄ ν보λλ€.
- λͺ¨λ μ ν리μΌμ΄μ μ λκ°μ μΈ‘μ κ°μ ν΅ν΄ νμ€μ μΈ ννλ‘ λͺ¨λν°λ§ν μ μλ€.
- λ컀 μμ§μ μΈ‘μ κ°λ κ°μ νμμΌλ‘ μΆμΆν μ μλ€.
- ν΄λΉ κΈ°λ₯μ μ¬μ©νλ €λ©΄ νλ‘λ©ν μ°μ€ μΈ‘μ κΈ°λ₯μ λͺ μμ μΌλ‘ νμ±νν΄μΌ νλ€.
$ vi /etc/docker/daemon.json
{
"metrics-addr" : "0.0.0.0:9323",
"experimental" : true
}
$ sudo systemctl restart docker
http://[IP]:9323/metrics
# HELP builder_builds_failed_total Number of failed image builds
# TYPE builder_builds_failed_total counter
builder_builds_failed_total{reason="build_canceled"} 0
builder_builds_failed_total{reason="build_target_not_reachable_error"} 0
builder_builds_failed_total{reason="command_not_supported_error"} 0
builder_builds_failed_total{reason="dockerfile_empty_error"} 0
builder_builds_failed_total{reason="dockerfile_syntax_error"} 0
builder_builds_failed_total{reason="error_processing_commands_error"} 0
builder_builds_failed_total{reason="missing_onbuild_arguments_error"} 0
builder_builds_failed_total{reason="unknown_instruction_error"} 0
# HELP builder_builds_triggered_total Number of triggered image builds
# TYPE builder_builds_triggered_total counter
builder_builds_triggered_total 0
# HELP engine_daemon_container_actions_seconds The number of seconds it takes to process each container action
# TYPE engine_daemon_container_actions_seconds histogram
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.005"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.01"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.025"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.05"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.1"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.25"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="0.5"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="1"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="2.5"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="5"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="10"} 1
engine_daemon_container_actions_seconds_bucket{action="changes",le="+Inf"} 1
...
- μΈ‘μ λ κ° μνμ λ³΄κ° Key Value ννλ‘ ννλλ ν μ€νΈ κΈ°λ° ν¬λ§·μ΄λ€.
$ hostIP=$(ip addr show enp0s5 | grep -oP '(?<=inet\\s)\\d+(\\.\\d+){3}')
$ docker container run -e DOCKER_HOST=$hostIP -d -p 9090:9090 diamol/prometheus:2.13.1
hostIP=$(ifconfig en0 | grep -e 'inet\\s' | awk '{print $2}')
# νκ²½ λ³μλ‘ λ‘컬 μ»΄ν¨ν°μ IP μ£Όμλ₯Ό μ λ¬ν΄ 컨ν
μ΄λλ₯Ό μ€ν
docker container run -e DOCKER_HOST=$hostIP -d -p 9090:9090 diamol/prometheus:2.13.1
- prometheus λ UI λ₯Ό ν΅ν΄ μΈ‘μ κ°μ νμΈνκ±°λ 쿼리λ₯Ό μ€νν μ μλ€.
- κ° μνλ³ μ»¨ν μ΄λ μλ μ€ν¨ν ν¬μ€ μ²΄ν¬ νμ κ°μ κ³ μμ€ μ 보λΆν° λ컀 μμ§μ΄ μ μ μ€μΈ λ©λͺ¨λ¦¬ μ©λ κ°μ μ μμ€ μ 보κΉμ§ μ»μ μ μλ€.
9.2 μ ν리μΌμ΄μ μ μΈ‘μ κ° μΆλ ₯νκΈ°
- μ ν리μΌμ΄μ μ κ²½μ° λ©νΈλ¦ μμ§ μλν¬μΈνΈλ₯Ό ν΅ν΄ μμ§ν μ μλ€.
- μ£Όμ μΈμ΄λ€μ νλ‘λ©ν μ°μ€μ λΌμ΄λΈλ¬κ° μ 곡λλ€.
- λΌμ΄λΈλ¬λ¦¬λ₯Ό ν΅ν΄ μμ§λ μ 보λ λ°νμ μμ€μ μΈ‘μ κ°μΌλ‘, ν΄λΉ 컨ν μ΄λκ° μ²λ¦¬νλ μμ κ³Ό λΆνμ μ λμ μ λ³΄κ° λ°νμμ κ΄μ μμ ννλλ€.
$ vi docker-compose.yml
version: "3.7"
services:
accesslog:
image: diamol/ch09-access-log
ports:
- "8012:80"
networks:
- app-net
iotd:
image: diamol/ch09-image-of-the-day
ports:
- "8011:80"
networks:
- app-net
image-gallery:
image: diamol/ch09-image-gallery
ports:
- "8010:80"
depends_on:
- accesslog
- iotd
networks:
- app-net
prometheus:
image: diamol/ch09-prometheus
ports:
- "9090:9090"
environment:
- DOCKER_HOST=${HOST_IP}
networks:
- app-net
networks:
app-net:
external:
name: nat
$ docker rm -f $(docker ps -aq)
$ docker network create nat
$ docker compose -f docker-comopose.yml up -d
# http://[HOST_IP]:8010/metrics
# HELP go_gc_duration_seconds A summary of the GC invocation durations.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 0
go_gc_duration_seconds{quantile="0.25"} 0
go_gc_duration_seconds{quantile="0.5"} 0
go_gc_duration_seconds{quantile="0.75"} 0
go_gc_duration_seconds{quantile="1"} 0
go_gc_duration_seconds_sum 0
go_gc_duration_seconds_count 0
...
- μ΄λ¬ν λ°νμ μν μΈ‘μ κ°μ λ컀 μμ§μμ μ»μ μΈνλΌμ€νΈλ¬μ² μΈ‘μ κ°κ³Όλ λ λ€λ₯Έ μμ€μ μ 보λ₯Ό μ 곡νλ€.
- μ ν리μΌμ΄μ μ μ΄λ²€νΈ μ, νκ· μλ΅ μ²λ¦¬ μκ°, νμ± μ¬μ©μ μ λ±μ μ ν리μΌμ΄μ μ°μ° μ 보 λΆν° λΉμ¦λμ€ μ 보 λ±μ ννν μ μλ€.
9.3 μΈ‘μ κ° μμ§μ 맑μ νλ‘λ©ν μ°μ€ 컨ν μ΄λ μ€ννκΈ°
- prometheus λ μ§μ μΈ‘μ κ°μ λμ μμ€ν μμ λ°μμ μμ§νλ νλ§ λ°©μμΌλ‘ λμνλ€.
- prometheus μμ μΈ‘μ κ°μ μμ§νλ κ³Όμ μ μ€ν¬λν μ΄λΌκ³ νλ€.
- μ€ν¬λνμ νκΈ° μν΄μλ λμ μ ν리μΌμ΄μ μ μλν¬μΈνΈλ₯Ό μ€μ ν΄μΌ νλ€.
global:
scrape_interval: 10s
scrape_configs:
- job_name: "image-gallery"
metrics_path: /metrics
static_configs:
- targets: ["image-gallery"]
- job_name: "iotd-api"
metrics_path: /actuator/prometheus
static_configs:
- targets: ["iotd"]
- job_name: "access-log"
metrics_path: /metrics
scrape_interval: 3s
dns_sd_configs:
- names:
- accesslog
type: A
port: 80
- job_name: "docker"
metrics_path: /metrics
static_configs:
- targets: ["DOCKER_HOST:9323"]
- global scrape_interval μ€μ μ μ 체 λμμ μ€ν¬λνμ μ£ΌκΈ°λ₯Ό μ€μ νλ€. (10μ΄)
- access-log 컨ν μ΄λμ κ²½μ° dns_sd_configs μ€μ μ ν΅ν΄ DNS κΈ°λ° μλΉμ€ λμ€μ»€λ²λ¦¬λ₯Ό μ¬μ©νλ€.
- κ·Έ μ΄μ λ access-log μ κ²½μ° μλ²κ° Scale Out λμ΄ μμ΄ λ컀 DNS λ₯Ό ν΅ν΄ λ΄λΆ IP λ₯Ό μ°Ύμμ ν΅μ νκΈ° μν¨μ΄λ€.
- type: A λ λλ©μΈ μ΄λ¦μ IPv4 μ£Όμλ‘ λ§€ννλ κ²μ΄λ€.
$ docker compose -f docker-compose-scale.yml up -d --scale accesslog=3
[+] Running 6/6
β Container exercises-prometheus-1 Started 0.3s
β Container exercises-accesslog-3 Started 0.5s
β Container exercises-accesslog-1 Started 0.3s
β Container exercises-accesslog-2 Started 0.6s
β Container exercises-iotd-1 Started 0.3s
β Container exercises-image-gallery-1 Started
$ for i in {1..10}; do curl <http://localhost:8010> > /dev/null; done
access_log_total
- κΈ°λ³Έ μ€μ μ΄ λμ΄μλ νλ‘λ©ν μ°μ€ μ΄λ―Έμ§λ₯Ό λ§λ€λ©΄ λ§€λ² μΆλΌκ³ μ€μ μ μμ±νμ§ μμλ λλ©°, νμν κ²½μ° κΈ°λ³Έκ°μ μμ ν μ μλ€.
- νλ‘λ©ν μ°μ€λ λ μ΄λΈμ λΆμ¬ λ©νΈλ¦μ λν΄ λ€μν 컨ν μ€νΈλ₯Ό μΆκ°ν μ μλ€.
- λν, λ μ΄λΈμ μ΄μ©ν΄ νλ‘λ©ν μ°μ€ 쿼리λ₯Ό μ΄μ©ν΄ μ§κ³ λ° λΆμμ΄ κ°λ₯νλ€.
access_log_total{instance="172.20.0.6:80"}
sum(image_gallery_requests_total{code="200"}) without(instance)
9.4 μΈ‘μ κ° μκ°νλ₯Ό μν κ·ΈλΌνλ 컨ν μ΄λ μ€ννκΈ°
- μΈ‘μ κ°μ κ°κ³΅νλ κ²μ promethus μμ μ§ννκ³ , κ°κ³΅λ μΈ‘μ κ°μ ν΅ν΄ λμ보λλ₯Ό ꡬμ±νλ κ²μ grafana λ₯Ό μ¬μ©νλ€.
- κ·ΈλΌνλ λμ보λλ μ ν리μΌμ΄μ μ ν΅μ¬ μ 보λ₯Ό λ€μν μμ€μμ μ 곡νλ€.
- μκ°νλ κ·Έλνλ PromQL(Prometheus Query Language) λ‘ μμ±λ λ¨μΌ μΏΌλ¦¬λ‘ κ·Έλ €μ§λ€.
- PromQL κ°λ ₯νκ³ μ§κ΄μ μΈ λ°©μμΌλ‘ λ°μ΄ν°λ₯Ό νν°λ§, μ§κ³, κ³μ°ν μ μλλ‘ μ€κ³λμ΄μλ€.
$ hostIP=$(ip addr show enp0s5 | grep -oP '(?<=inet\\s)\\d+(\\.\\d+){3}')
$ docker compose -f docker-compose-with-grafana.yml up -d --scale accesslog=3
[+] Running 10/10
β grafana Pulled 11.6s
β 29bddadc8f3f Pull complete 2.2s
β d9b0d74c7b70 Pull complete 2.2s
β 3fb7e7639feb Pull complete 2.5s
β 3cd42e0f5101 Pull complete 8.0s
β af31ba937280 Pull complete 8.0s
β 7c7f1ccbce63 Pull complete 8.0s
β fc130f9b4964 Pull complete 8.0s
β ca4c94507a97 Pull complete 8.0s
β a2a6b53e5a03 Pull complete 8.0s
[+] Running 7/7
β Container exercises-accesslog-3 Started 0.8s
β Container exercises-prometheus-1 Started 0.4s
β Container exercises-accesslog-1 Started 0.3s
β Container exercises-accesslog-2 Started 0.6s
β Container exercises-iotd-1 Started 0.3s
β Container exercises-grafana-1 Started 0.7s
β Container exercises-image-gallery-1 Started
$ for i in {1..20}; do curl <http://localhost:8010> > /dev/null; done
PromQL μμ
# 200 μλ΅ count
sum(image_gallery_requests_total{code="200"}) without(instance)
# νμ¬ μ²λ¦¬ μ€μΈ μμ² μ
sum(image_gallery_requests) without(instance)
# λ©λͺ¨λ¦¬ μ¬μ©λ
go_memstats_bytes{job="image-gallery"}
# κ³ λ£¨ν΄ νμ± μ
sum(go_goroutinces{job="image_gallery"}) without(instance)
- λμ보λμ κ·Έλνλ μ λμ μΈ κ°λ³΄λ€λ λ³ννλ μΆμΈμμ μ μ μλ μ λ΄ λ§λ€.
- νκ· κ°μμ μμΉκ° ν¬κ² μ¬λΌκ°λ μκ°μ΄ μΈμ μΈμ§λ₯Ό νμ νλκ²μ΄ μ€μνλ€.
- μ»΄νΌλνΈμ μΈ‘μ κ°μ μ‘°ν©ν΄ μ ν리μΌμ΄μ μ μ΄μ νμκ³Ό μκ΄κ΄κ³λ₯Ό μ°ΎμμΌ νλ€.
9.5 ν¬λͺ μ±μ μμ€
- κ°λ¨ν κ°λ κ²μ¦ μμ€μ νλ‘λνΈμμ μ€μ μλΉμ€ μμ€μΌλ‘ λμκ°κΈ° μν΄ ν¬λͺ μ±μ λ°λμ νμνλ€.
- μ€μ μ΄μνκ²½μ κ²½μ° μμΈν μν©μ μ μ μλ λͺ¨λν°λ§ λμ보λλ λ°λμ νμνλ€.
- μ ν리μΌμ΄μ μ μ 체 μν©μ μ‘°λ§νλ λμ보λλ κ°μ₯ μ€μνλ€.
- λμ€ν¬ μ©λ, CPU, λ©λͺ¨λ¦¬, λ€νΈμν¬ μμ λ± λͺ¨λ μλ²μ μν©μ 보μ¬μ£Όλ μΈνλΌμ€νΈλμ² λμ보λλ μ’λ€.
- μΈ‘μ κ° μ€μμ μ ν리μΌμ΄μ μ μ€μν λ°μ΄ν°λ₯Ό λͺ¨μ νλμ νλ©΄μΌλ‘ ꡬμ±ν μ μμ΄μΌ νλ€.
9.6 μ°μ΅λ¬Έμ
- Prometheus μ Grafana λ₯Ό ν΅ν λͺ¨λν°λ§ ꡬμΆν΄λ³΄κΈ°.
- docker compose μ¬μ©νκΈ°
Prometheus
# prometheus.yml
global:
scrape_interval: 10s
scrape_configs:
- job_name: "todo-list"
metrics_path: /metrics
static_configs:
- targets: ["todo-list"]
# Dockerfile
FROM diamol/prometheus:2.13.1
COPY prometheus.yml /etc/prometheus/prometheus.yml
Grafana
Provision dashboards and data sources | Grafana Labs
Prometheus data source | Grafana documentation
# Dockerfile
FROM diamol/grafana:6.4.3
COPY datasource-prometheus.yaml ${GF_PATHS_PROVISIONING}/datasources/
COPY dashboard-provider.yaml ${GF_PATHS_PROVISIONING}/dashboards/
COPY dashboard.json /var/lib/grafana/dashboards/
# dashboard-provider.yml
apiVersion: 1
providers:
- name: 'default'
orgId: 1
folder: ''
type: file
disableDeletion: true
updateIntervalSeconds: 0
options:
path: /var/lib/grafana/dashboards
# datasoruce-prometheus.yml
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: <http://prometheus:9090>
basicAuth: false
version: 1
editable: true
Docker Compose
version: "3.7"
services:
todo-list:
image: diamol/ch09-todo-list
ports:
- "8050:80"
networks:
- app-net
prometheus:
image: diamol/ch09-lab-prometheus
ports:
- "9090:9090"
networks:
- app-net
grafana:
image: diamol/ch09-lab-grafana
ports:
- "3000:3000"
depends_on:
- prometheus
networks:
- app-net
networks:
app-net:
external:
name: nat
728x90
λ°μν