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
Provision dashboards and data sources | Grafana Labs
By Grafana Labs Team Last update on August 29, 2024 Intermediate Introduction Learn how you can reuse dashboards and data sources across multiple teams by provisioning Grafana from version-controlled configuration files. In this tutorial, you’ll: Provisi
grafana.com
Prometheus data source | Grafana documentation
Prometheus data source | Grafana documentation
Intro to metrics with Grafana: Prometheus, Grafana Mimir, and beyond In this webinar, we’ll go over challenges when scaling metrics systems, with a particular focus on Prometheus and Grafana Mimir.
grafana.com
# 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
'📚 책 > 도커 교과서' 카테고리의 다른 글
도커 교과서 11장 도커와 도커 컴포즈를 이용한 애플리케이션 빌드 및 테스트 (0) | 2024.12.18 |
---|---|
도커 교과서 10장 도커 컴포즈를 이용한 여러 환경 구성 (3) | 2024.12.09 |
도커 교과서 8장 헬스 체크와 디펜던시 체크로 애플리케이션의 신뢰성 확보하기 (2) | 2024.12.01 |
도커 교과서 7장 도커 컴포즈로 분산 애플리케이션 실행하기 (0) | 2024.11.26 |
도커 교과서 6장 도커 볼륨을 이용한 퍼시스턴트 스토리지 (1) | 2024.11.25 |