Skip to content
isdnetworks
Go back

한 대만 보고 판단했다

수집 서버가 네 대였다. 자료가 일부 안 들어온다는 얘기를 듣고 한 대에 접속해 로그를 봤다.

정상이었고 문제없다고 답했다. 이틀 뒤에 같은 얘기가 또 왔다.

Table of contents

Open Table of contents

나머지 세 대는 안 봤다

이번에는 네 대를 다 봤다.

srv-01  정상
srv-02  정상
srv-03  디스크 98%, 저장 실패 다수
srv-04  정상

srv-03 만 문제였다. 처음에 srv-01 을 보고 전체를 판단한 것이다.

그 한 대를 고른 이유를 되짚어 보니 아무것도 없었다. 접속 정보 목록에서 맨 위에 있어서였다.

원인 — 확인 단위와 구성 단위

srv-01 부터 srv-04 까지 네 대가 같은 일을 나눠서 한다. 각자 다른 대상을 맡고 있으니 한 대의 상태가 다른 대를 대신 말해 주지 않는다.

그런데 확인은 한 대 단위로 했다. 구성은 넷인데 확인은 하나였으니 처음부터 답이 나올 수 없는 구조였다.

한 대에서 tail 로 로그를 보고 나머지도 정상일 것이라는 가정을 세운 적도 없다. 그냥 그렇게 행동했고 그것이 가정이라는 것도 이틀 뒤에 알았다.

한 번에 보는 방법을 만들었다

네 대를 하나씩 접속하는 것이 번거로워 한 번에 돌게 묶었다.

#!/bin/sh
for h in srv-01 srv-02 srv-03 srv-04; do
  echo "=== $h ==="
  ssh "$h" '
    echo "disk: $(df -h /data | awk "NR==2 {print \$5}")"
    echo "proc: $(pgrep -c -f collector)"
    echo "last: $(tail -1 /var/log/collector.log)"
  '
done

df 로 남은 자리를 보고 pgrep -c 로 프로세스 수를 세고 로그 마지막 줄을 가져온다. 한 번 돌리면 네 대가 차례로 나온다.

접속이 안 되는 경우도 표시하게 했다.

if ! ssh -o ConnectTimeout=5 "$h" true 2>/dev/null; then
  echo "=== $h === 접속 불가"
  continue
fi

접속이 안 되는 것도 하나의 상태다. 그냥 건너뛰면 확인하지 않은 대가 목록에서 사라지고 정상이라 안 나오는 것과 구분이 안 된다.

ConnectTimeout 을 5초로 둔 것은 죽은 대에서 ssh 가 오래 붙들리지 않게 하려는 것이다. 한 대가 멈춰 있으면 나머지 세 대의 확인도 그만큼 늦어진다.

수치를 한 표로 모았다

각 대의 값을 나란히 놓고 비교했다.

호스트   디스크   수집건수(1h)  실패(1h)
srv-01   62%      12,040        3
srv-02   58%      11,890        2
srv-03   98%       8,210      412
srv-04   61%      12,110        1

srv-03 이 세 열에서 모두 튄다. 디스크가 98%이고 수집 건수는 삼분의 이 수준이고 실패는 백 배가 넘는다.

df 값에 절대 기준이 없어도 네 대를 서로 비교하면 이상이 드러난다. 실패 세 건이 많은 것인지는 혼자 보면 모르는데 옆에 나란히 놓으면 412가 무엇인지는 바로 안다.

조치 — 각 대가 상태를 보내게

손으로 돌리는 것보다 각 대가 스스로 보고하는 쪽이 나았다.

# 각 서버에서 5분마다
curl -s -X POST http://monitor/api/status \
  -d "host=$(hostname)" \
  -d "disk=$(df /data | awk 'NR==2 {print $5}' | tr -d '%')" \
  -d "collected=$(count_recent)" \
  -d "failed=$(count_failed)"

hostname 과 디스크 사용률과 최근 수집·실패 건수를 5분마다 감시 서버로 보낸다. 모이니 한 화면에서 넷을 본다.

안 보내는 대가 있으면 그것도 드러난다.

SELECT host, MAX(reg_date) FROM server_status GROUP BY host;

MAX(reg_date) 가 오래된 대가 있으면 그 대에 문제가 있다는 뜻이다. curl 을 돌리는 쪽이 죽으면 그것이 침묵으로 나타난다.

대상 목록을 자료로 뒀다

서버 목록을 스크립트에 박아 두면 대가 늘 때마다 스크립트를 고쳐야 한다.

# /etc/monitor/hosts
srv-01
srv-02
srv-03
srv-04

/etc/monitor/hosts 에서 읽게 하고 대가 늘면 한 줄을 더한다. 감시 서버에서도 이 목록과 보고를 대조했다.

SELECT h.host FROM expected_hosts h
LEFT JOIN (SELECT host FROM server_status WHERE reg_date >= DATE_SUB(NOW(), INTERVAL 15 MINUTE)) s
  ON s.host = h.host
WHERE s.host IS NULL;

expected_hosts 에 있는데 최근 15분 보고가 없는 대를 뽑는다. 보고가 온 것만 보면 안 온 대를 영영 못 본다.

무엇이 빠졌는지는 있는 것만 봐서는 알 수 없다. 있어야 할 목록이 따로 있어야 그 비교가 된다.

변경 내용 — 확인 순서

문제 얘기를 들었을 때의 순서 자체를 바꿨다.

전  한 대에 접속 → 로그 확인 → 판단
후  전체 상태 조회 → 이상한 대 식별 → 그 대에 접속

server_status 를 먼저 보면 어디를 봐야 할지가 정해진다. 접속할 대를 고르는 것이 감이 아니라 표에서 나온 값이 된다.

순서를 바꾼 것뿐인데 같은 실수를 할 자리가 없어졌다. 첫 단계에서 네 대가 다 보이므로 한 대만 보고 답하는 경로 자체가 사라진다.

정리


Share this post on:

Previous Post
쓰기 전에 지워야 한다
Next Post
패키지 하나에 보드가 둘이었다