본문으로 건너뛰기

Grafana + Prometheus + MySQL Exporter를 활용한 MySQL 모니터링 설정기

· 약 5분
고현림
프론트엔드 | 블록체인 Developer

최근에 인프라 관련된 수업을 진행하면서 내 스스로 할 수 있는 프로젝트가 뭔지, 어떻게 하면 오픈소스들을 잘 사용할 수 있을지 고민을 해보았습니다. 그 결과 DB를 만들고 DB에 데이터가 많이 몰리게 되었을 때 관리할 수 있는 흐름을 만들면 좋겠다 생각을 했습니다.

따라서 MySQL을 모니터링하기 위해 Prometheus와 Grafana를 연동해 대시보드를 구성하는 작업을 진행했습니다. 이 글에서는 그 전체 과정을 정리해봤어요.

🏗️ 전체 아키텍처

추후에 좀 더 복잡한 아키텍처도 만져보면서 계속해서 확장해나가보면 좋을거 같은 생각이듭니다!

MySQL ← mysqld_exporter → Prometheus → Grafana

phpMyAdmin (관리용)

📁 프로젝트 구조

grafana/
├── provisioning/
│ ├── dashboards/
│ │ └── dashboard.yml
│ └── datasources/
│ └── datasource.yml
├── mysql/
│ └── mysql_data/
├── mysqld-exporter/
│ └── my.cnf
├── prometheus/
│ └── prometheus.yml
├── .env
└── docker-compose.yml

🐳 Docker Compose 설정

전체 스택을 한 번에 관리하기 위해 다음과 같이 docker-compose.yml을 구성했어요.

볼륨 설정시 파일 위치 실수를 방지하기 위해서 하나의 파일 내에서 관련된 파일들을 모두 관리해주었습니다.(이렇게 하니깐 확실히 상대경로로 관리하기 쉽다는 점이 좋았습니다.) 그리고 $로 표시한 내용에 대해서는 중요파일이기 때문에 .env로 파일을 설정해주었습니다. .env 파일에 대한 내용은 아래에 보면 확인할 수 있어요.

version: "3.8"

services:
mysql:
image: mysql:8.0
container_name: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
volumes:
- ./mysql/mysql_data:/var/lib/mysql
ports:
- "3306:3306"

phpmyadmin:
image: phpmyadmin/phpmyadmin
container_name: phpmyadmin
platform: linux/amd64
ports:
- "8080:80"
environment:
PMA_HOST: mysql
PMA_PORT: 3306
depends_on:
- mysql

mysqld-exporter:
image: prom/mysqld-exporter
container_name: mysqld_exporter
volumes:
- ./mysqld-exporter/my.cnf:/etc/mysql/my.cnf:ro
depends_on:
- mysql
ports:
- "9104:9104"
command: ["--config.my-cnf=/etc/mysql/my.cnf"]

prometheus:
image: prom/prometheus
container_name: prometheus
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
depends_on:
- mysqld-exporter

grafana:
image: grafana/grafana
container_name: grafana
environment:
GF_SECURITY_ADMIN_USER: ${GF_SECURITY_ADMIN_USER}
GF_SECURITY_ADMIN_PASSWORD: ${GF_SECURITY_ADMIN_PASSWORD}
volumes:
- ./grafana/provisioning/dashboards:/etc/grafana/provisioning/dashboards
- ./grafana/provisioning/datasources:/etc/grafana/provisioning/datasources
ports:
- "3000:3000"
depends_on:
- prometheus

volumes:
mysql_data:

.env 설정 파일이에요. MYSQL에서 root로 접근할 때 사용할 수 있는 password와 사용할 database를 지정을 해줍니다. Grafana와 같은 경우에는 비밀번호를 설정해주지 않으면 아이디와 비밀번호가 admin으로 설정이 되어있어요. 그리고 비밀번호를 변경하라는 메세지가 나오는데 docker 컨테이너를 내리고 다시 실행을 하게 되면 계속해서 비밀번호를 설정하라는 창이 나와서 설정해주는게 편했습니다.

MYSQL_ROOT_PASSWORD=
MYSQL_DATABASE=

GF_SECURITY_ADMIN_USER=
GF_SECURITY_ADMIN_PASSWORD=

🔧 주요 설정 파일들

1. mysqld_exporter 설정 (my.cnf)

여기서 중요한 점은 user와 password는 내가 접근하고자하는 mysql의 내용이어야 돼요. 즉 user에 exporter가 설정이 되어 있지 않으면 access denied가 설정이 될 수 있어요. 이를 유의해서 작성해주어야 해요. 아래 내용에서 이와 관련된 문제 해결을 적어두었습니다.

[client]
user=exporter
password=exporter_password

2. Prometheus 설정 (prometheus.yml)

Prometheus가 타겟으로 하는 mysqld-expoert를 설정을 해주어야 합니다.

global:
scrape_interval: 15s

scrape_configs:
- job_name: "mysqld-exporter"
static_configs:
- targets: ["mysqld-exporter:9104"]

3. Grafana 데이터소스 자동 설정 (datasource.yml)

Grafana를 처음 실행을 하게 되면 data source를 정하는 과정이 있습니다. 이 과정을 하지 않으면 데이터를 가져오지 않기 때문에 당연히 대시보드가 정상적으로 만들어지지 않아요. 아래 파일을 설정을 해주면 Grafana가 실행할 때 자동으로 Prometheus를 설정해줍니다.

apiVersion: 1

datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://prometheus:9090
isDefault: true

🚨 주요 문제들과 해결책

1. mysqld_exporter access denied 문제 해결

문제: mysqld_exporter 실행 시 다음 오류 발생

[ERROR] Access denied for user 'exporter'@'localhost'

해결책:

exporter가 접근할 user와 해당 user의 password를 my.cnf에 잘 설정 해주는 것이 중요합니다. my.cnf에 exporter를 설정을 해두었는데 mysql user에 exporter가 없다면 당연히 에러가 나요.

2. Grafana에서 Prometheus 연결 실패

문제: Grafana에서 http://localhost:9090으로 설정했더니 연결 실패

해결책: 도커 컨테이너 환경에서는 서비스 이름으로 접근하는 것이 핵심이었습니다.

❌ http://localhost:9090
✅ http://prometheus:9090

이유: 도커 컨테이너에서 localhost는 자기 자신(컨테이너 내부)을 의미하므로, 같은 네트워크 내의 다른 컨테이너에 접근할 때는 서비스명을 사용해야 합니다!

3. Grafana 설정 자동화

2번과 같이 수동 설정으로 설정하는 과정에 있어서 문제가 발생할 수도 있고, 컨테이너가 down 된 상태에서 다시 실행을 한다면 매번 해주는 과정이 귀찮아질 수 있어 data source를 자동화 해줄 수 있습니다.

provisioning 디렉터리를 활용한 자동화 구현:

./grafana/provisioning/
├── dashboards/ # 대시보드 자동 로딩
└── datasources/ # 데이터소스 자동 설정

이렇게 하면 컨테이너 초기 실행 시 모든 설정이 자동으로 적용됨

4. phpMyAdmin 추가로 관리 편의성 향상

터미널 기반 MySQL 관리의 불편함을 해결하기 위해 phpMyAdmin 추가했어요.:

  • 포트: 8080 (보통 잘 사용하기 때문에 docker ps -a 를 활용해서 해당 포트를 잡고 있는 컨테이너가 있는지 확인해주어야 해요.)
  • 시각적 테이블 관리
  • 사용자 권한 설정 간편화

5. Grafana MySQL Overview Dashboard 데이터 표시 문제

문제: 모든 패널이 No data 표시

원인: 템플릿 변수와 쿼리 간 연동 문제가 있었어요.

  • $host 변수 설정 오류가 있어 prometheus로 부터 데이터를 가지고 오지 못해서 No data가 보였어요.

해결책:

  1. $host 변수 재설정:

    • Query type: Label values
    • Metric: mysql_global_status_threads_connected
    • Label: instance
  2. 변수 새로고침 설정:

    • On dashboard load로 설정
    • 또는 패널에서 수동 Run query 실행

📊 최종 구성 결과

전체 코드 보러 갈래요

설정 완료 후 Grafana 대시보드에서 실시간으로 확인 가능한 지표들은 아래와 같아요:

  • MySQL Uptime: 서버 가동 시간
  • Threads Connected/Running: 연결된 스레드 수
  • QPS (Queries per Second): 초당 쿼리 수
  • InnoDB Buffer Pool: 버퍼 풀 사용량
  • Connections: 연결 상태
  • Table Locks: 테이블 잠금 현황
  • Thread Cache: 스레드 캐시 상태

대시보드 새로고침 간격을 5초로 설정하여 실시간에 가까운 모니터링 환경 구축할 수 있었습니다! 아래는 구성 후 결과물입니다.