본문 바로가기

생활코딩

라즈베리파이 시스템 지표 모니터링

반응형

라즈베리파이 시스템 지표 모니터링 대시보드

홈 서버로 사용하고 있는 라즈베리파이들을 레고로 만든 케이스에 넣은 후 과열이 우려가 되어 온도를 모니터링 하겠다고 시작한 작업이 라즈베리파이 전체 시스템 지표(System Metrics) 모니터링까지 진행됐습니다. 기록 차원에서 해당 내용을 정리해 둡니다.

보통 시스템의 상황을 나타내는 각종 수치들을 영어로 System Metrics 라고 하는데, 이를 한국어로는 '시스템 성능 지표', '시스템 지표', '시스템 메트릭' 등으로 부릅니다. 이 글에서는 꼭 성능에만 초점이 맞추어 진것은 아니어서 '시스템 지표'라는 말을 사용하겠습니다.

0. 준비

보통 시간 순으로 연속되는 값을 모니터링 할 때는 다음과 같은 프로그램을 사용해서 구성합니다. 홈 서버의 모니터링 데이터는 매우 잘 관리될 필요는 없어서 가장 간단하게 구성할 수 있는 방향으로 초점을 맞췄습니다. 그래서, 기본적으로 Docker로 쉽게 구동할 수 있는 것들을 선택했습니다. 각 항목들에서 선택된 것들은 그런 관점으로 선택됐다고 보시면 될 거 같습니다.

 

1. 시계열(Time Series) DBMS

시간 연속순을 같는 데이터에 특화된 데이터베이스 시스템입니다. 전통적으로  InfluxDB가 유명하며, 요새는 Prometheus가 쿠버네티스의 유명세와 함께 많이 쓰입니다. 그 외에도 Graphite 등 다양한 종류가 있습니다. 관심 있는 분들은 여기를 한 번 참고하셔도 좋습니다.

시계열 DBMS는 Graphite를 선택했습니다. 뭘 선택해도 상관 없는 상황이기는 했는데, 간단히 각 DBMS들의 문서를 살펴보니 Graphite가 Docker로 간단하게 구동할 수 있게 가이드를 제공해서 선택했습니다.

 

2. 지표 수집기

시스템의 각종 지표를 수집 및 지정된 DBMS로 저장하는 역할을 합니다. 이 영역에도 당연히 다양한 프로그램이 존재합니다만, apt로 바로 설치해서 쉽게 쓸 수 있는 collectd를 선택했습니다.

 

3. 시각화 도구

시계열 DBMS에 저장돼 있는 데이터를 보기 좋게 시각화 해주는 도구입니다. 대표적으로 Grafna 같은 것들이 있습니다. 이 쪽은 여러가지를 살펴지는 않았고, 바로 Grafana를 보니 Docker로도 잘 구동할 수 있게 돼 있어서 Grafana를 선택했습니다.

 

1. Graphite

먼저 Graphite의 저장 데이터와 설정 파일을 호스트 디렉토리에 연계되게 볼륨 마운트로 지정할 디렉토리들을 만들어 줍니다. /home/pi/docker_volume 이라는 디렉토리 하위로 만든다고 가정하겠습니다.

> mkdir -p /home/pi/docker_volume/graphite/configs
> mkdir /home/pi/docker_volume/graphite/storge
> mkdir /home/pi/docker_volume/graphite/statsd

 

디렉토리를 만들고 나서 Docker를 실행합니다.

docker run -d \
--name graphite \
--restart=always \
-p 8888:80 \
-p 2003-2004:2003-2004 \
-p 2023-2024:2023-2024 \
-p 8125:8125/udp \
-p 8126:8126 \
-v /home/pi/docker_volume/graphite/configs:/opt/graphite/conf \
-v /home/pi/docker_volume/graphite/data:/opt/graphite/storage \
-v /home/pi/docker_volume/graphite/statsd:/opt/statsd/config \
graphiteapp/graphite-statsd

 

실행할 때 한가지 주의할 점은 graphite가 root로 실행돼야 한다는 것입니다. --user 옵션으로 권한이 축소된 특정 사용자로 실행할 수 없습니다. 그 이유는 graphite Docker 이미지가 runit을 init 시스템처럼 사용하기 때문이라고 하는데요 관련된 자세한 사항이 궁금하신 분은 여기를 참고하시기 바랍니다. 중요한 점은 Docker 컨테이너 내에서 graphite가 root로 실행되기 때문에 volume 마운트된 /home/pi/docker_voluem/graphite 하위 디렉토리에 생성되는 파일들로 root 권한으로 생성된다는 것입니다.

 

8888 포트로 웹 UI를 접속하게 지정했습니다. 다른 포트를 원하는 경우 8888을 원하는 값으로 바꾸면 됩니다. 기동 후에 브라우저로 라즈베리파이의 8888 번 포트로 접속했을 때 다음과 같은 화면이 나오면 정상적으로 기동된 겁니다.

 

설정 파일과 데이터 파일을 호스트에 저장되도록 볼륨 마운트를 지정했기 때문에 docker 실행을 종료하거나 삭제한 후에 다시 실행시켜도 /home/pi/docker_volume/graphite 하위의 데이터만 삭제하지 않으면 그대로 유지됩니다. graphite의 설정을 바꾸거나 데이터 파일을 삭제하려는 경우에는 보통 다음과 같이 하면 됩니다.

> docker stop graphite
# 설정 파일을 수정합니다.
> docker start graphite

 

이렇게 하면 graphite는 준비가 끝났습니다. 온도 데이터 수집과 관련해서 설정을 하나 바꾸어 줘야 하는게 그거는 온도 데이터 수집 부분에서 얘기하겠습니다.

2. 수집 

2.1 온도 데이터 수집

라즈베리파이의 시스템 온도 측정 방법은 https://intotherealworld.tistory.com/75 에 설명돼 있습니다. 여기서는 수집 방법만 이야기 하도록 하겠습니다.

 

라즈베리파이 온도 확인

라즈베리파이에는 기본적으로 주요 칩에 대한 온도 측정 센서가 탑재돼 있습니다. 그래서 다음과 같은 명령어로 온도를 확인할 수 있습니다. SoC(System on Chip) 온도> vcgencmd measure_temp 라즈베리파

intotherealworld.tistory.com

온도 데이터 수집을 위해 먼저 다음과 같은 간단한 쉘 스크립트 파일을 만듭니다.

#!/usr/bin/env bash

echo "metrics.pi5.temperature.soc $(vcgencmd measure_temp | sed -E 's/.*=([0-9.]+).*/\1/') `date +%s`" | nc -v -q 1 127.0.0.1 2003
echo "metrics.pi5.temperature.pmic $(vcgencmd measure_temp pmic | sed -E 's/.*=([0-9.]+).*/\1/') `date +%s`" | nc -v -q 1 127.0.0.1 2003

 

3번째 줄만 설명하면 vcgencmd 명령어를 실행해서 출력되는 SoC의 온도에서 수치 부분만 발췌하고 현재 시간과 같이 nc라는 툴을 사용해서 graphite로 데이터를 저장하는 내용입니다. 두 가지를 눈여겨 봐야 하는데, 앞 부분에 나오는 metrics.pi5.temerature.soc  부분과 거의 끝에 나오는 ip 주소 부분입니다. 앞의 metrics.pi5.temerature.soc 이 부분은 메트릭 경로라고 부르는 부분으로 원하는대로 이름은 지으면 되며, 점(.)으로  구분하여 계층 구조를 갖는다고 보면 됩니다. metrics.pi5.temerature.soc, metrics.pi5.temerature.pmic 이렇게 두 개를 저장하는데 이렇게 하면 개념적으로 metrics.pi5.temerature 하위에 soc와 pmic 데이터가 존재하게 됩니다. ip 주소 부분은 graphite가 실행돼 있는 라즈베리파이 주소입니다. 지금처럼 같은 라즈베리파이 내에서라면 로컬 주소를 써 주면 되고 다른 라즈베리 파이라면 해당 라즈베리파이의 IP 주소를 적어주면 됩니다.

metric path는 단순히 해도 되기는 한데 collectd의 메트릭 패스 체계와 결을 맞춰서 Grafana에서 시각화할 때 좀 더 용이하게 하려고 좀 복잡하게 했습니다. 요 부분은 collectd 부분에서 조금 더 설명하겠습니다.

이제 쉘 스크립트 파일을 크론 작업으로 매 분마다 실행되게 하면 됩니다. 그런데, 그 전에 graphite에 설정을 추가해 줘야 합니다. 

> docker stop graphite
> vi /home/pi/docker_volume/configs/storage-aggregation.conf

 

그리고, 나서 다음과 같은 내용을 [default_average] 부분 위에 추가해 줍니다.

[temperature]
pattern = \.temperature\.*
xFilesFactor = 0
aggregationMethod = average

 

이 부분의 내용은 중간 경로에 temperature가 있는 메트릭에 대해서는 xFileFactor를 0으로 설정하고 집계 방법을 평균으로 하라는 의미입니다. 여기서 중요한 부분은 xFilesFactor입니다. 시계열 DBMS들은 보통 시간이 지난 데이터들은 유입된 그대로 가지고 있지 않고 설정된 주기에 따라 집계하여 저장합니다. 온도 데이터는 크론 작업으로 1분마다 저장할 것입니다. 이 것이 설정에 따라 일정 시간이 지난 것들은 집계를 하여 평균으로 저장을 하는데 xFilesFactor를 충족하는 것들만 집계 및 저장을 합니다. xFilesFactor는 0 ~ 1.0의 범위 값을 갖는데 해당 기간동안 집계 단위 시간 별로 데이터가 있는 비율을 말합니다. 예를 들어 1초마다 데이터를 집계한다고 설정돼 있고, xFilesFactor 값이 1이라면, 특정 기간의 데이터가 1초 간격으로 하나라도 비는 경우가 있으면 집계에서 제외됩니다. 0이라는 설정 값은 누락 여부에 관계 없이 무조건 집계 하는 것입니다.

수집 주기와 집계/보관 주기는 storage-schemas.conf에서 설정할 수 있습니다. 해당 설정 파일을 열어보면 기본 설정 값은 다음과 같습니다.

[default_1min_for_1day]
pattern = .*
retentions = 10s:6h,1m:6d,10m:1800d

 

여기서 retentions 부분을 하나씩 설명하면 다음과 같습니다.

  • 10s:6h : 각 데이터 포인트는 10초 간격이며 해당 데이터는 6시간 보관
  • 1m:6d: 10초 단위 포인트를 1분 단위로 집계(다운 샘플링 한다고 합니다)하여 6일 보관
  • 10m:1800d: 1분 단위 데이터를 10분 단위로 집계하여 1800일 보관

온도 데이터를 1분 간격으로 저장할 때, retentions 설정은 위와 같고 xFilesFactor가 0.3 (기본 설정)이라고 하면, 첫 번째 설정에 의해 1분마다 들어가는 데이터는 6시간까지는 유지가 되지만, 그 다음 집계시에 1분 간격에서 최소 30%의 데이터 포인트가 있어야 집계되는데 하나 밖에 없을 것이므로 누락(실제로는 값이 null로 설정됨) 됩니다. 그러므로, 위에서 한 것처럼 xFilesFactor를 0.1 이하 값으로 설정해 주거나 아니면 storage-schemas.conf 에 다음과 같은 설정을 추가할 수 있습니다.

[temperature]
pattern = \.temperature\.*
retentions = 1m:6h,10m:6d

 

설정 파일을 수정했으면 graphite를 다시 실행합니다.

> docker run graphite

 

이제, 다음과 같이 쉘 스크립트 파일을 크론 작업으로 설정하여 매 분마다 실행되게 합니다.

> crontab -e
# 에디터가 실행되면 다음과 같은 줄을 마지막에 추가
* * * * * /스크립트파일경로/스크립트파일이름

 

이렇게 하면 매 분마다 SoC와 PMIC의 온도 데이터가 Graphite에 추가됩니다.

2.2 collectd로 각종 시스템 지표 수집

collectd를 설치합니다.

sudo apt install collectd

 

이렇게 하면 systemctl로 제어할 수 있는 형태로 설치가 되며, collectd가 데몬으로 실행됩니다. 일단 collectd를 다음과 같이 멈추고 설정을 합니다.

> sudo systemctl stop collectd

 

설정파일의 경로는 /etc/collectd/collectd.conf 입니다. 해당 파일을 vi로 열어보면 상당히 많은 설정 내용이 주석으로 돼 있을 겁니다. 그 중에서 사용할 부분만 주석을 해제하거나 설정해서 사용하면 됩니다. 제가 설정한 내용은 다음과 같습니다.

Hostname "pi5"
FQDNLookup false

LoadPlugin syslog

<Plugin syslog>
	LogLevel info
</Plugin>

LoadPlugin aggregation
LoadPlugin battery
LoadPlugin cpu
LoadPlugin df
LoadPlugin disk
LoadPlugin entropy
LoadPlugin interface
LoadPlugin irq
LoadPlugin load
LoadPlugin memory
LoadPlugin processes
LoadPlugin rrdtool
LoadPlugin swap
LoadPlugin users
LoadPlugin write_graphite

<Plugin aggregation>
	<Aggregation>
		Plugin "cpu"
		Type "cpu"
		GroupBy "Host"
		GroupBy "TypeInstance"
		CalculateAverage true
	</Aggregation>
</Plugin>

<Plugin df>
  # expose host's mounts into container using -v /:/host:ro  (location inside container does not matter much)
  # ignore rootfs; else, the root file-system would appear twice, causing
  # one of the updates to fail and spam the log
	FSType rootfs
  # ignore the usual virtual / temporary file-systems
	FSType sysfs
	FSType proc
	FSType devtmpfs
	FSType devpts
	FSType tmpfs
	FSType fusectl
	FSType cgroup
	FSType overlay
	FSType debugfs
	FSType pstore
	FSType securityfs
	FSType hugetlbfs
	FSType squashfs
	FSType mqueue
	MountPoint "/etc/resolv.conf"
	MountPoint "/etc/hostname"
	MountPoint "/etc/hosts"
	IgnoreSelected true
	ReportByDevice false
	ReportInodes true
	ValuesAbsolute true
	ValuesPercentage true
	ReportInodes true
</Plugin>

<Plugin disk>
	IgnoreSelected false
	Disk "/^[hs]d[a-z]/"
	Disk "/^mmcblk0p[0-9]/"
</Plugin>

<Plugin rrdtool>
	DataDir "/var/lib/collectd/rrd"
</Plugin>

<Plugin write_graphite>
	<Node "graphite">
		Host "localhost"
		Port "2003"
		Protocol "tcp"
		ReconnectInterval 0
		LogSendErrors true
		Prefix "metrics."
		StoreRates true
		AlwaysAppendDS false
		EscapeCharacter "_"
		SeparateInstances true
	</Node>
</Plugin>

<Include "/etc/collectd/collectd.conf.d">
	Filter "*.conf"
</Include>

 

이 내용은 https://github.com/torkelo/dashboards/blob/master/collectd-graphite-single-server/collectd.conf 여기를 참고했습니다. 아래에서 Grafana에서 다시 언급되겠지만, 그라파나 설정과 collectd 설정은 이 분꺼를 사용했다고 보면 됩니다. 

위의 설정에서 신경 쓰셔야 하는 부분은 write_graphie 설정 부분에서 host와 Prefix 부분입니다. host 설정은 graphite의 IP 주소입니다. 같은 서버에 있을 때는 위와 같이 localhost로 지정하면 되고, 별도의 서버에 있다면 해당 서버의 IP 주소를 적어주면 됩니다. 

Prefix는 graphite의 메트릭 경로의 앞부분을 지정하는 겁니다. 위에 처럼 metrics. 지정하면 메트릭 경로가 metrics.{Hostname}.{지표이름}... 식으로 지정됩니다. 위에서는 Hostname을 pi5로 지정했으므로, 경로가 metrics.pi5.processes... 식으로 지정됩니다. 그래서, 위에서 온도 값의 경로를 metrics.pi5.temperature로 맞춘겁니다. 이렇게 해 놓으면 Grafana에서 호스트별로나 같이 지표를 볼 수 있습니다. 이 거는 Grafana 부분에서 좀 더 자세히 이야기 하겠습니다.

설정을 완료한 후에 collectd를 재시작하면 시스템의 각종 지표(LoadPlugin에 있는 항목들)가 graphite로 수집됩니다.

> sudo systemctl start collectd

 

3. Grafana

3.1 설치

graphite와 같이 먼저 관련 파일을 호스트 디렉토리에 연계되게 볼륨 마운트로 지정할 디렉토리들을 만들어 줍니다.

> mkdir /home/pi/docker_volume/grafana

 

그리고, 다음과 같이 docker로 grafana를 실행 시킵니다.

docker run -d \
 --name=grafana \
 -p 3000:3000 \
 --user "$(id -u):$(id -g)" \
 --volume /home/pi/docker_volume/grafana:/var/lib/grafana \
 -e "GF_SERVER_ROOT_URL=http://라즈베리파이아이피주소:3000/" \
 grafana/grafana-oss

 

여기서는 외부 연결 포트를 3000번으로 지정했습니다. -p 다음과의 첫번째 3000과 -e 부분의 끝에 3000을 같은 값으로 원하는 포트로 바꿀 수 있습니다. 한 가지 눈여결 볼 것은 --user 옵션입니다. user 옵션을 docker를 실행하는 사용자 권한으로 지정하면 /home/pi/docker_volume/grafana 에 저장되는 파일이 해당 사용자과 그룹으로 생성됩니다. 실제로 이 user는 Grafana Docker Image 내에 정의돼 있는 사용자로 지정해야 하지만, 이런 식으로 없는 사용자를 지정해도 Grafana 사용에는 문제가 없고 /home/pi/docker_volume/grafana 에 생성되는 파일 권한도 적절히 부여할 수 있어서 편리합니다. 

 

이제 브라우저로 라즈베리파이 IP 주소의 3000번으로 연결하면 다음과 같은 화면을 볼 수 있습니다.

 

관리자 기본 아이디와 암호는 admin / admin 입니다. 이렇게 로그인을 하면 알아서 암호를 변경하라고 나옵니다. 이제 시스템 지표를 살펴볼 수 있게 Grafana 대시보드를 설정할 차례입니다.

3.2 설정

3.2.1 Data source 추가

왼쪽 메뉴 Connections > Data sources > Add new data source 를 클릭합니다. 그리고, 아래와 같이 나오면 Graphite를 선택합니다.

 

다음과 같은 화면이 나오면 URL에 http://자신의라즈베리파이IP주소:8888 을 입력한 후 맨 아래에 Save & test 버튼을 클릭합니다. 포트를 이 문서에서 한 것처럼 8888이 아니라 다르게 했다면 해당 포트 주소를 적어야 합니다.

 

이제 대시보드를 추가할 차례입니다.

3.2.1 대시보드

왼쪽 메뉴 Dashboards > New > New Dashboard 단계로 클릭을 한 후 나오는 화면에서 오른쪽 상단에 Settings를 클릭합니다. Settings 화면에서 Variables 탭을 클릭하고 나서 Add Variable 버튼을 눌러 다음의 두개의 변수를 등록합니다.

Variable Type Name Value Query
Constant prefix metrics  
Query host   $prefix.*

 

다 등록하고 나면 다음과 같은 형태가 될 겁니다.

 

이 두 변수는 대시보드 화면에서 host를 편리하고 선택하기 위해서 설정한 변수입니다. Visualization을 추가할 때 왜 이렇게 설정했는지 알 수 있습니다.

우측 상단에 Save dashboard로 저장을 한 번 한 후 Bact to dashboard 버튼을 클릭해 다시 대시보드로 돌아옵니다. 이제 Visualization을 등록할 차례입니다. Add Visualization을 클릭하면 Select data source라는 화면이 나올겁니다. 거기에서 아까 등록했던 graphite를 선택합니다.

이런 화면이 나올겁니다. 이제 데이터 항목을 선택하고 각 항목을 옵션을 설정하면 됩니다. 온도 값의 Visualization은 이런 식으로 설정됩니다.

 

$prefix.$host 부분이 보일 겁니다. 이 부분이 아까 지정한 변수 부분입니다. 그리고, 그 종류가 복수일 경우 상단에 host 라는 이름으로 목록 상자가 나오는 것처럼 그렇게 선택할 수 있게 해 줍니다. 여러대의 라즈베리파이에서 각각 host 이름 달리하여 수집하면 한 번에 각각이 다 모여진 그래프를 볼 수도 있고 개별로 선택하여 개별 호스트에 대한 그래프만 볼 수 있습니다.

개별적인 설정 방법은 이 글의 범위를 벗어나는 것 같고, 참고하시라고 제가 설정한 대시보드 내용을 첨부하도록 하겠습니다. 이 파일을 다운로드 한 후에 Import dashboard 기능으로 불러 들이면 설정한 내용들을 보실 수 있습니다.

raspberrypi-dashboard.json
0.03MB

 

제가 설정한 내용은 https://grafana.com/grafana/dashboards/24-collectd-server-metrics/ 를 참고했습니다.

 

CollectD Server Metrics | Grafana Labs

Simple Server Metrics Dashboard using Graphite and CollectD. Dashboard metrics CPU Average (over all cores)LoadProcesses (Forks, state)Memory usageDisc usageNetwork Packets, Traffic, Errors CollectD config can be found here: collectd.conf That config file

grafana.com

 

다 설정하고 나면 다음과 같은 화면으로 시스템 지표를 모니터링 할 수 있습니다.

라즈베리파이 시스템 지표 모니터링 대시보드

이 화면은 라즈베리파이 3, 5 각각 두 대의 호스트를 이름을 pi3, pi5 지정하여 수집하고 있는 모습니다.

3.2.2 알림 설정

Grafana는 알림 기능이 있어서 특정 지표가 기준 이상을 넘어가면 다양한 매체로 알림을 보낼 수 있습니다. 기본적으로는 Email 알림을 지원하며, 그 외에도 슬랙, 디스코드, 라인 등 아주 다양한 매체를 지원합니다.

카톡은 지원하지 않아 처음에는 웹훅 기능으로 내부적으로 카톡으로 메시지를 보내는 API를 하나 만들고 그 URL을 호출하는 식으로 해서 카톡으로 알림을 받으려고 했습니다. 그래서, 카카오 개발자 사이트의 가이드에 맞춰서 나에게 톡을 보내는 기능을 다 구현은 했는데, 구현하고 나서 보니 나에게 보내는 톡은 앱으로 푸시 알림이 안 오더군요. 개발자 사이트에서 Q&A쪽에 보니 기획 의도상 나에게 보내는 메시지는 메모 성격이라 외부에서 보내더라도 푸시 알림을 보내지 않는다고 답변이 돼 있더군요. 이게 특정 채팅방에 메시지를 보내려면 사업자 등록도 하고 심사도 받아야 해서 포기했습니다. 그리고나서 비교적 사용이 편리한 라인을 사용해서 알림을 받도록 설정했습니다. 라인의 경우는 특정 대화방에 메시지를 보낼 수 있는 웹훅을 지원하고 있어서 편리하게 메시지를 보낼 수 있게 당연히 푸시 알림도 잘 옵니다.

온도가 80˚ 넘을 때 알림이 오도록 설정했고, 넘는 경우에는 다음과 같이 알림이 옵니다.

 

4. 참고