CloudStack의 app 서버에서 노드 SSH 연결 모니터링
CloudStack management/app 서버에서 KVM 노드 SSH 연결을 주기적으로 확인하는 스크립트입니다. BatchMode, ConnectTimeout, 대상 파일, 로그, 실패 원인 분리를 정리했습니다.
CloudStack management/app 서버에서 각 KVM 노드로 SSH가 안 되면 agent 점검, 로그 수집, 수동 복구 작업이 지연됩니다. 이 글의 목적은 “SSH 명령 한 번 실행”이 아니라, 여러 노드를 대상으로 연결 성공/실패를 기록하고 타임아웃을 빠르게 감지하는 모니터링 스크립트를 만드는 것입니다.
노드 목록 준비
모니터링 대상은 파일로 관리합니다. 운영 계정, 호스트명, 포트를 명시합니다.
sudo install -d -m 755 /etc/cloudstack-monitor
sudo tee /etc/cloudstack-monitor/node-ssh-targets.conf >/dev/null <<'EOF'
# name user host port
kvm-node-01 root kvm-node-01.example.com 22
kvm-node-02 root kvm-node-02.example.com 22
EOF
CloudStack API를 쓰는 환경이라면 host 목록을 주기적으로 생성해도 됩니다.
cloudmonkey list hosts type=Routing filter=id,name,state,ipaddress
SSH 연결 모니터링 스크립트
자동 모니터링에서는 패스워드 프롬프트가 뜨면 안 됩니다. BatchMode=yes로 비대화형 연결만 허용하고, ConnectTimeout과 전체 timeout을 함께 둡니다.
#!/usr/bin/env bash
set -Eeuo pipefail
TARGET_FILE="${1:-/etc/cloudstack-monitor/node-ssh-targets.conf}"
LOG_FILE="/var/log/cloudstack-node-ssh-monitor.log"
ALERT_TO="cloud-ops@example.com"
SSH_TIMEOUT=5
log() {
printf '%s %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" | tee -a "${LOG_FILE}"
}
alert() {
local subject="$1"
local body="$2"
log "ALERT ${subject} ${body}"
if command -v mailx >/dev/null 2>&1; then
printf '%s\n' "${body}" | mailx -s "${subject}" "${ALERT_TO}" || true
fi
}
check_ssh() {
local name="$1"
local user="$2"
local host="$3"
local port="$4"
if timeout "$((SSH_TIMEOUT + 2))" ssh \
-o BatchMode=yes \
-o ConnectTimeout="${SSH_TIMEOUT}" \
-o ConnectionAttempts=1 \
-o StrictHostKeyChecking=accept-new \
-p "${port}" \
"${user}@${host}" 'echo ok' >/tmp/cloudstack-ssh-check.$$ 2>&1; then
log "OK ssh name=${name} host=${host} port=${port}"
rm -f /tmp/cloudstack-ssh-check.$$
return 0
fi
local detail
detail="$(tr '\n' ' ' < /tmp/cloudstack-ssh-check.$$ | sed 's/[[:space:]]\\+/ /g' | cut -c1-300)"
rm -f /tmp/cloudstack-ssh-check.$$
alert "CloudStack node SSH failed: ${name}" "host=${host} port=${port} detail=${detail}"
return 1
}
overall=0
while read -r name user host port; do
[ -z "${name:-}" ] && continue
[[ "${name}" =~ ^# ]] && continue
check_ssh "${name}" "${user}" "${host}" "${port}" || overall=1
done < "${TARGET_FILE}"
exit "${overall}"
등록과 로그 확인
sudo install -m 755 cloudstack-node-ssh-monitor.sh /usr/local/sbin/cloudstack-node-ssh-monitor.sh
sudo touch /var/log/cloudstack-node-ssh-monitor.log
sudo chmod 640 /var/log/cloudstack-node-ssh-monitor.log
sudo crontab -e
*/3 * * * * /usr/local/sbin/cloudstack-node-ssh-monitor.sh >/dev/null 2>&1
tail -f /var/log/cloudstack-node-ssh-monitor.log
실패 원인 분리
스크립트가 실패를 기록하면 다음 순서로 분리합니다.
# management/app 서버에서
nc -vz -w 3 kvm-node-01.example.com 22
ssh -vvv -o BatchMode=yes -o ConnectTimeout=5 root@kvm-node-01.example.com 'echo ok'
# 대상 노드 콘솔에서
systemctl status sshd --no-pager
journalctl -u sshd -n 100 --no-pager
ss -lntp | grep ':22'
Permission denied는 키/계정 문제이고, Connection timed out은 네트워크/방화벽 문제입니다. Connection refused는 포트는 도달했지만 sshd가 listen하지 않는 경우가 많습니다.
운영 주의사항
모니터링 전용 SSH 키는 권한을 최소화하고, 가능하면 root 대신 읽기/점검 전용 계정을 사용합니다. 비밀번호 로그인에 의존하면 크론에서 멈추거나 보안상 위험하므로 공개키 기반 비대화형 인증을 기준으로 구성하세요.