앞 글 “Nginx 한 대로 시험한 ELK를 Nginx Proxy Manager에 합치기“에서 만든 Docker ELK에 이번에는 Metricbeat를 붙였다.

로그가 무슨 일이 있었는지를 남긴다면 Metricbeat는 서버가 지금 어떤 상태인지를 모은다. CPU 사용량, 남은 메모리, 디스크 공간 같은 지표를 주기적으로 수집해 Elasticsearch로 보내는 도구다. 컴퓨터 건강 검진을 자동으로 해주는 프로그램이라고 보면 된다.

컨테이너로 붙이는 데 바꾼 파일 다섯 개

앞 글의 docker-compose.yml에 metricbeat 서비스를 추가했다. /var/run/docker.sock을 읽기 전용으로 마운트해서 docker 모듈이 컨테이너 지표를 읽게 한다.

metricbeat:
  build:
    context: ../elk/metricbeat/
    args:
      ELASTIC_VERSION: ${ELASTIC_VERSION}
  container_name: metricbeat
  user: root  # needed to access host metrics
  volumes:
    - ../elk/metricbeat/config/metricbeat.yml:/usr/share/metricbeat/metricbeat.yml:ro,Z
    - /var/run/docker.sock:/var/run/docker.sock:ro
  environment:
    - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
    - ELASTICSEARCH_USERNAME=metricbeat_internal
    - METRICBEAT_INTERNAL_PASSWORD=${METRICBEAT_INTERNAL_PASSWORD:-}
  networks:
    - nginx_proxy_manager
  depends_on:
    - elasticsearch
    - kibana

elasticsearch/config/elasticsearch.yml에는 한 줄을 더했다.

# Metricbeat 관련 추가 항목
xpack.monitoring.collection.enabled: true

metricbeat/Dockerfile은 로그 디렉토리만 만든다.

ARG ELASTIC_VERSION

FROM docker.elastic.co/beats/metricbeat:${ELASTIC_VERSION}

USER root

RUN mkdir /var/log/metricbeat && chown metricbeat /var/log/metricbeat

metricbeat/config/metricbeat.yml에서는 system 모듈과 docker 모듈을 10초 주기로 켰다.

metricbeat.config:
  modules:
    path: ${path.config}/modules.d/*.yml
    reload.enabled: false

metricbeat.modules:
  - module: system
    metricsets:
      - cpu
      - load
      - memory
      - network
      - process
      - process_summary
    enabled: true
    period: 10s
    processes: ['.*']

  - module: docker
    metricsets:
      - container
      - cpu
      - diskio
      - healthcheck
      - info
      - memory
      - network
    hosts: ["unix:///var/run/docker.sock"]
    period: 10s

output.elasticsearch:
  hosts: ['elasticsearch:9200']
  username: 'metricbeat_internal'
  password: '${METRICBEAT_INTERNAL_PASSWORD}'

setup.kibana:
  host: "kibana:5601"

마지막으로 metricbeat_internal이 쓸 롤을 setup/roles/metricbeat_writer.json에 둔다. 앞 글의 setup 서비스는 이미 METRICBEAT_INTERNAL_PASSWORD를 받고 있다.

{
  "cluster": ["monitor", "manage_index_templates", "manage_ilm"],
  "indices": [
    {
      "names": ["metricbeat-*"],
      "privileges": ["manage", "index", "create_index", "view_index_metadata", "read"]
    }
  ]
}

Mac에서는 컨테이너가 Mac을 보지 못한다

여기서 막혔다. Mac 환경에서는 Metricbeat 컨테이너가 Mac의 시스템 메트릭을 수집하는 데 제한이 있었다. 방법을 찾아봤지만 Mac에서 메트릭 수집을 시험하려면 결국 Metricbeat를 Mac 호스트에 직접 설치해야 했다.

Docker Desktop은 컨테이너를 Mac 위가 아니라 Linux VM 안에서 돌린다. 그래서 컨테이너가 볼 수 있는 호스트는 Mac이 아니라 그 VM이다. 컨테이너 쪽 설정을 아무리 만져도 Mac의 CPU 사용량은 나오지 않는다.

Mac에 직접 설치하는 방법은 이렇다.

curl -L -O https://artifacts.elastic.co/downloads/beats/metricbeat/metricbeat-8.14.3-darwin-x86_64.tar.gz

tar xzvf metricbeat-8.14.3-darwin-x86_64.tar.gz

cd metricbeat-8.14.3-darwin-x86_64

# metricbeat.yml 생성
vi metricbeat.yml

metricbeat.yml에는 아래 내용을 넣는다. 컨테이너용 설정보다 metricset을 넓게 잡고 CPU와 메모리 기준 상위 프로세스 5개씩을 따로 남긴다. 호스트에서 돌기 때문에 Elasticsearch와 Kibana는 localhost로 부른다.

metricbeat.modules:
- module: system
  metricsets:
    - cpu             # CPU usage
    - load            # CPU load averages
    - memory          # Memory usage
    - network         # Network IO
    - process         # Per process metrics
    - process_summary # Process summary
    - uptime          # System Uptime
    - socket_summary  # Socket summary
    - core            # Per CPU core usage
    - diskio          # Disk IO
  processes: ['.*']
  process.include_top_n:
    by_cpu: 5      # include top 5 processes by CPU
    by_memory: 5   # include top 5 processes by memory

output.elasticsearch:
  hosts: ["localhost:9200"]
  username: "metricbeat_internal"
  password: "{metricbeat 비밀번호(※초기 changeme로 설정한상태)}"

setup.kibana:
  host: "localhost:5601"
# Metricbeat 실행
./metricbeat -e

Kibana에서 CPU 사용량 확인하기

  1. http://localhost:5601에 접속한다.

  2. 좌측 Stack Management > Data View > Create Data View

  3. 인덱스 명: metricbeat (중요하지 않다)

  4. 인덱스 패턴: metricbeat-* (Metricbeat가 기본으로 쓰는 인덱스 패턴)

  5. Time field: @timestamp

Kibana 초기 화면에서 Dashboard > Create dashboard > Add visualization으로 들어가 host.cpu.usage 필드를 차트로 끌어오면 시스템 메트릭이 수집되고 있는 게 보인다.

리눅스 서버라고 컨테이너 구성을 그대로 쓸 수 있는 것도 아니다. 공식 문서를 보면 system 모듈이 호스트를 보려면 /proc, /sys/fs/cgroup, /를 /hostfs 아래로 마운트해야 한다. 지금 compose에는 docker.sock만 있으니 이건 다음에 다시 봐야겠다.