시스템 엔지니어 일상/OPENSTACK

OpenStack(Kolla-Ansible) 점검 체크리스트 정리

IT재테크 2026. 4. 28. 10:59

 

OpenStack은 여러 서비스가 컨테이너 기반으로 연결되어 동작한다. 특히 Kolla-Ansible 환경에서는 Nova, Neutron, Cinder, Glance, Keystone, Placement, Horizon 등이 각각 Docker 컨테이너로 실행되며, MariaDB, ProxySQL, RabbitMQ, HAProxy 같은 공통 인프라 서비스에도 의존한다.

따라서 장애가 발생했을 때 단순히 docker ps에서 컨테이너가 Up인지 확인하는 것만으로는 충분하지 않다. 컨테이너는 떠 있어도 내부 API 애플리케이션이 DB 연결 실패, RabbitMQ 연결 실패, health check 실패로 인해 실제 서비스는 불가능한 상태일 수 있다.

이번 글에서는 Kolla-Ansible 기반 OpenStack 환경에서 매일 아침 확인하면 좋은 점검 항목과, 점검 결과를 자동으로 분석해 OK / WARNING / CRITICAL로 분류하는 방식에 대해 정리한다.


1. 아침 점검의 목적

아침 점검의 목적은 단순히 컨테이너가 떠 있는지 보는 것이 아니다.

실제로 확인해야 할 것은 다음과 같다.

1. Docker 컨테이너가 정상 상태인지
2. OpenStack 인증이 가능한지
3. Nova, Cinder, Neutron 등 주요 서비스가 정상 응답하는지
4. API 엔드포인트가 503/500 오류를 반환하지 않는지
5. 최근 로그에 DB, RabbitMQ, Keystone, Placement 관련 에러가 없는지
6. 호스트 디스크, inode, 메모리, load 상태가 정상인지
7. 인스턴스나 볼륨에 ERROR 상태가 없는지

OpenStack 장애는 대부분 하나의 서비스만 보고 판단하기 어렵다. 예를 들어 Horizon 웹 화면에 오류가 발생하더라도 실제 원인은 Horizon이 아니라 Nova, Placement, Cinder API 또는 DB 연결 문제일 수 있다.


2. 점검 전 환경 준비

Kolla-Ansible로 설치한 OpenStack을 CLI로 점검하려면 먼저 Python 가상환경과 OpenStack 관리자 환경변수를 적용한다.

source /root/kolla-venv/bin/activate
source /etc/kolla/admin-openrc.sh

그다음 Keystone 인증이 정상인지 확인한다.

openstack token issue

토큰이 정상 발급되면 Keystone 인증 계층은 우선 정상으로 볼 수 있다.


3. Docker 컨테이너 상태 확인

가장 먼저 확인할 것은 비정상 컨테이너다.

docker ps -a --format "table {{.Names}}\t{{.Status}}" | egrep -i "unhealthy|exited|dead|restarting"

아무것도 출력되지 않으면 컨테이너 상태는 대체로 정상이다.

문제가 있는 경우 다음과 같은 상태가 표시된다.

Exited
unhealthy
Restarting
Dead

각 상태의 의미는 다음과 같다.

Exited
→ 컨테이너 프로세스가 종료된 상태
→ 해당 서비스는 동작하지 않음

Up (unhealthy)
→ 컨테이너 프로세스는 살아 있음
→ 내부 health check 실패
→ HAProxy가 백엔드에서 제외할 수 있음
→ 실제 API 호출은 실패할 수 있음

Up (healthy)
→ 컨테이너 프로세스와 health check 모두 정상

Up
→ 컨테이너는 떠 있으나 health check가 없는 컨테이너일 수 있음
→ 로그 또는 CLI로 추가 확인 필요

주요 컨테이너만 보고 싶다면 다음 명령어를 사용한다.

docker ps -a | egrep 'mariadb|proxysql|rabbitmq|keystone|placement|nova|neutron|cinder|glance|horizon|haproxy'

4. OpenStack 주요 서비스 확인

컨테이너 상태가 정상이어도 OpenStack 서비스 상태가 정상이라는 의미는 아니다. 반드시 OpenStack CLI로 서비스 상태를 확인해야 한다.

4.1 Compute 서비스 확인

openstack compute service list

정상 기준은 다음과 같다.

nova-scheduler   enabled   up
nova-conductor   enabled   up
nova-compute     enabled   up

Hypervisor도 확인한다.

openstack hypervisor list

4.2 Volume 서비스 확인

openstack volume service list

정상 기준은 다음과 같다.

cinder-scheduler   enabled   up
cinder-volume      enabled   up
cinder-backup      enabled   up 또는 down

cinder-backup은 백업 백엔드 설정 여부에 따라 down일 수 있다. 운영 정책상 백업 기능을 사용하지 않는다면 별도 판단이 필요하다.

Cinder API가 비정상일 경우 다음과 같은 오류가 발생할 수 있다.

503 Service Unavailable: No server is available to handle this request.

이 경우 CLI는 HAProxy까지 도달했지만, 뒤쪽의 Cinder API 백엔드가 정상 응답하지 못하는 상태로 볼 수 있다.


4.3 Network 서비스 확인

openstack network agent list

정상 기준은 Neutron agent들이 Alive 상태여야 한다.

Open vSwitch agent   Alive
DHCP agent           Alive
L3 agent             Alive
Metadata agent       Alive

4.4 Image 서비스 확인

openstack image list

이미지 목록이 정상 조회되면 Glance API가 기본적으로 응답하고 있다고 볼 수 있다.


5. API HTTP 응답 확인

CLI 서비스 명령 외에도 API 포트가 직접 응답하는지 확인하면 좋다.

curl -s -o /dev/null -w "keystone: %{http_code}\n" http://192.168.111.130:5000/v3
curl -s -o /dev/null -w "placement: %{http_code}\n" http://192.168.111.130:8780/
curl -s -o /dev/null -w "nova: %{http_code}\n" http://192.168.111.130:8774/
curl -s -o /dev/null -w "cinder: %{http_code}\n" http://192.168.111.130:8776/
curl -s -o /dev/null -w "glance: %{http_code}\n" http://192.168.111.130:9292/
curl -s -o /dev/null -w "neutron: %{http_code}\n" http://192.168.111.130:9696/

응답 코드 해석은 다음과 같다.

000
→ 연결 자체 실패

500
→ API 내부 오류

503
→ HAProxy가 사용 가능한 백엔드를 찾지 못함
→ 컨테이너 unhealthy 또는 API 프로세스 장애 가능성

2xx / 3xx / 4xx
→ 일단 HTTP 응답은 있음
→ 401, 403, 404는 인증 또는 경로 문제일 수 있으나 API 프로세스는 응답 중

6. 주요 로그 확인

아침 점검에서 전체 로그를 모두 읽기는 어렵다. 따라서 최근 로그 중 장애 판단에 필요한 키워드만 필터링하는 방식이 효율적이다.

6.1 주요 서비스 로그 에러 필터링

for f in \
/var/log/kolla/nova/nova-api.log \
/var/log/kolla/nova/nova-conductor.log \
/var/log/kolla/nova/nova-scheduler.log \
/var/log/kolla/placement/placement-api.log \
/var/log/kolla/cinder/cinder-api.log \
/var/log/kolla/cinder/cinder-scheduler.log \
/var/log/kolla/cinder/cinder-volume.log \
/var/log/kolla/neutron/neutron-server.log \
/var/log/kolla/glance/glance-api.log \
/var/log/kolla/horizon/horizon.log \
/var/log/kolla/horizon/apache-error.log
do
  echo ""
  echo "==================== $f ===================="
  if [ -f "$f" ]; then
    egrep -i "error|critical|traceback|exception|failed|denied|refused|timeout|unhealthy|fatal|database|mysql|rabbit|amqp|keystone|placement|503" "$f" | tail -n 30
  else
    echo "SKIP - file not found"
  fi
done

6.2 특히 봐야 할 로그 키워드

이번 유형의 장애에서 가장 중요하게 볼 키워드는 다음과 같다.

Max connect timeout reached while reaching hostgroup 0

이 문구는 OpenStack 서비스가 ProxySQL을 통해 MariaDB에 연결하려 했지만, DB backend hostgroup에 연결하지 못했다는 의미로 볼 수 있다.

이 경우 Nova, Placement, Cinder가 연쇄적으로 unhealthy가 될 수 있다.


Placement 관련 문제는 다음 문구를 확인한다.

Failed to initialize placement client
The placement service ... exists but does not have any supported versions

이 문구는 Nova conductor 또는 scheduler가 Placement API를 정상적으로 discovery하지 못했다는 의미다. 실제 원인은 Placement API 장애, DB 연결 실패, endpoint 문제일 수 있다.


API backend 장애는 다음 문구를 확인한다.

503 Service Unavailable
No server is available to handle this request

이 경우 HAProxy 뒤쪽 API 컨테이너가 unhealthy이거나 실제 API 앱이 정상 응답하지 못하는 상태일 가능성이 높다.


7. DB / ProxySQL / RabbitMQ 확인

OpenStack의 주요 서비스들은 DB와 메시지 큐에 크게 의존한다. 따라서 아침 점검에서 MariaDB, ProxySQL, RabbitMQ 상태는 반드시 확인하는 것이 좋다.

7.1 컨테이너 상태 확인

docker ps -a | egrep 'mariadb|proxysql|rabbitmq'

7.2 MariaDB 로그 확인

egrep -i "error|failed|denied|timeout|aborted|crash|innodb" /var/log/kolla/mariadb/mariadb.log | tail -n 50

7.3 ProxySQL 로그 확인

egrep -i "error|failed|timeout|connect|mysql|hostgroup|offline|shun|denied|monitor" /var/log/kolla/proxysql/proxysql.log | tail -n 50

7.4 RabbitMQ 로그 확인

docker logs rabbitmq --tail 300 2>&1 | egrep -i "error|failed|timeout|connection|alarm|memory|disk|partition" | tail -n 50

8. 호스트 자원 상태 확인

OpenStack 장애는 서비스 설정 문제뿐 아니라 호스트 자원 부족으로도 발생할 수 있다.

8.1 디스크 사용량

df -h

특히 다음 경로를 주의해서 본다.

/var
/var/lib/docker
/var/lib/mysql
/var/log

8.2 inode 사용량

df -ih

디스크 용량이 남아 있어도 inode가 부족하면 로그 파일 생성이나 DB 파일 생성에 문제가 생길 수 있다.

8.3 메모리 확인

free -h

8.4 Load Average 확인

uptime

Load Average가 CPU Core 수보다 지속적으로 높으면 성능 문제나 서비스 응답 지연이 발생할 수 있다.

8.5 Docker 디스크 사용량

docker system df

9. VM / 볼륨 상태 확인

운영 중인 인스턴스나 볼륨의 상태도 확인한다.

9.1 인스턴스 상태 확인

openstack server list --all-projects

ERROR 상태만 보고 싶으면:

openstack server list --all-projects | egrep -i "ERROR|SHUTOFF|PAUSED|SUSPENDED"

9.2 볼륨 상태 확인

openstack volume list --all-projects

문제 상태만 보고 싶으면:

openstack volume list --all-projects | egrep -i "error|creating|deleting|attaching|detaching"

10. 자동 분석 기준

아침 점검 스크립트에서는 결과를 다음 3단계로 구분하면 좋다.

10.1 OK

Docker 비정상 컨테이너 없음
Keystone token 발급 정상
Nova 서비스 up
Cinder 서비스 up
Neutron agent alive
주요 API 503/500 없음
최근 주요 로그에 심각한 에러 없음
디스크/메모리 사용률 정상
ERROR 상태 인스턴스/볼륨 없음

10.2 WARNING

서비스는 동작하지만 점검이 필요한 상태

예:
- 일부 로그에 error 문구 존재
- cinder-backup down
- 디스크 사용률 80% 이상
- 사용 가능 메모리 1GB 미만
- 일부 볼륨이 creating/deleting 상태로 오래 유지
- 일부 인스턴스가 SHUTOFF 또는 SUSPENDED 상태

10.3 CRITICAL

즉시 확인이 필요한 장애 상태

예:
- unhealthy / exited 컨테이너 존재
- Keystone token 발급 실패
- Nova compute service down
- Cinder API 503 발생
- Placement API 503 발생
- Neutron agent down
- DB 연결 timeout 발생
- RabbitMQ alarm 발생
- 디스크 사용률 90% 이상
- ERROR 상태 인스턴스 존재

11. 자동 분석 스크립트의 핵심 아이디어

아침 점검 스크립트는 단순히 명령어 결과를 출력하는 데서 끝나지 않고, 마지막에 다음과 같이 분석 요약을 출력하도록 구성하면 좋다.

Critical Count : 0
Warning Count  : 1
OK Count       : 24

RESULT: WARNING
판단: 서비스는 동작 중일 수 있으나 점검이 필요한 특이사항이 있습니다.

Warning Items
- Cinder backup service down

장애가 있는 경우:

Critical Count : 3
Warning Count  : 2
OK Count       : 15

RESULT: CRITICAL
판단: 즉시 확인이 필요한 장애 또는 서비스 중단 가능성이 있습니다.

Critical Items
- Docker 비정상 컨테이너 존재
- Cinder API 503 Service Unavailable
- Nova compute service 상태 이상

12. 자동 분석 스크립트 예시

아래 스크립트는 아침 점검을 수행하고 마지막에 OK / WARNING / CRITICAL로 결과를 분류한다.

#!/bin/bash

REPORT_DATE=$(date +%Y%m%d_%H%M%S)
REPORT_FILE="/root/openstack_morning_check_${REPORT_DATE}.log"

CRITICAL_COUNT=0
WARNING_COUNT=0
OK_COUNT=0

ISSUES=()
WARNINGS=()
OKS=()

add_critical() {
  CRITICAL_COUNT=$((CRITICAL_COUNT+1))
  ISSUES+=("$1")
}

add_warning() {
  WARNING_COUNT=$((WARNING_COUNT+1))
  WARNINGS+=("$1")
}

add_ok() {
  OK_COUNT=$((OK_COUNT+1))
  OKS+=("$1")
}

print_header() {
  echo ""
  echo "=================================================="
  echo "$1"
  echo "=================================================="
}

check_log_error() {
  local name="$1"
  local file="$2"
  local pattern="$3"

  if [ ! -f "$file" ]; then
    add_warning "$name 로그 파일 없음: $file"
    return
  fi

  local count
  count=$(egrep -i "$pattern" "$file" | tail -n 100 | wc -l)

  if [ "$count" -gt 0 ]; then
    add_warning "$name 최근 로그에 에러성 문구 발견: ${count}건"
  else
    add_ok "$name 최근 주요 에러 없음"
  fi
}

{
echo "=================================================="
echo " OpenStack Morning Check + Auto Analysis"
echo " Date: $(date)"
echo " Host: $(hostname)"
echo "=================================================="

print_header "[0] Load OpenStack Admin Environment"

if [ -f /root/kolla-venv/bin/activate ]; then
  source /root/kolla-venv/bin/activate
  echo "OK - kolla-venv activated"
else
  echo "WARN - /root/kolla-venv/bin/activate not found"
  add_warning "kolla-venv 경로를 찾지 못함"
fi

if [ -f /etc/kolla/admin-openrc.sh ]; then
  source /etc/kolla/admin-openrc.sh
  echo "OK - admin-openrc loaded"
else
  echo "CRITICAL - /etc/kolla/admin-openrc.sh not found"
  add_critical "admin-openrc.sh 파일 없음"
fi

print_header "[1] Docker Abnormal Containers"

ABNORMAL_CONTAINERS=$(docker ps -a --format "table {{.Names}}\t{{.Status}}" | egrep -i "unhealthy|exited|dead|restarting" || true)

if [ -n "$ABNORMAL_CONTAINERS" ]; then
  echo "$ABNORMAL_CONTAINERS"
  add_critical "Docker 비정상 컨테이너 존재"
else
  echo "OK - No abnormal containers"
  add_ok "Docker 컨테이너 상태 정상"
fi

echo ""
echo "---- Main OpenStack Containers ----"
docker ps -a --format "table {{.Names}}\t{{.Status}}" | egrep 'mariadb|proxysql|rabbitmq|keystone|placement|nova|neutron|cinder|glance|horizon|haproxy' || true

print_header "[2] Keystone Token Check"

if openstack token issue >/dev/null 2>&1; then
  echo "OK - Keystone token issued"
  add_ok "Keystone 인증 정상"
else
  echo "CRITICAL - Keystone token issue failed"
  add_critical "Keystone 토큰 발급 실패"
fi

print_header "[3] Compute Service Check"

COMPUTE_OUTPUT=$(openstack compute service list 2>&1)
echo "$COMPUTE_OUTPUT"

if echo "$COMPUTE_OUTPUT" | egrep -i "down|disabled|error|503|failed|unavailable" >/dev/null; then
  add_critical "Nova compute service 상태 이상"
else
  add_ok "Nova compute service 정상"
fi

print_header "[4] Hypervisor Check"

HYPERVISOR_OUTPUT=$(openstack hypervisor list 2>&1)
echo "$HYPERVISOR_OUTPUT"

if echo "$HYPERVISOR_OUTPUT" | egrep -i "error|503|failed|unavailable" >/dev/null; then
  add_warning "Hypervisor 조회 오류"
else
  add_ok "Hypervisor 조회 정상"
fi

print_header "[5] Volume Service Check"

VOLUME_OUTPUT=$(openstack volume service list 2>&1)
echo "$VOLUME_OUTPUT"

if echo "$VOLUME_OUTPUT" | egrep -i "503|failed|unavailable|error" >/dev/null; then
  add_critical "Cinder volume service 조회 실패 또는 API 장애"
elif echo "$VOLUME_OUTPUT" | egrep -i "down|disabled" >/dev/null; then
  add_warning "Cinder volume service 중 down/disabled 존재"
else
  add_ok "Cinder volume service 정상"
fi

print_header "[6] Network Agent Check"

NETWORK_OUTPUT=$(openstack network agent list 2>&1)
echo "$NETWORK_OUTPUT"

if echo "$NETWORK_OUTPUT" | egrep -i "xxx|down|false|error|503|failed|unavailable" >/dev/null; then
  add_critical "Neutron network agent 상태 이상"
else
  add_ok "Neutron network agent 정상"
fi

print_header "[7] Image Service Check"

IMAGE_OUTPUT=$(openstack image list 2>&1)
echo "$IMAGE_OUTPUT"

if echo "$IMAGE_OUTPUT" | egrep -i "error|503|failed|unavailable" >/dev/null; then
  add_warning "Glance image list 조회 오류"
else
  add_ok "Glance image list 조회 정상"
fi

print_header "[8] API HTTP Response Check"

API_IP="192.168.111.130"

check_api() {
  local name="$1"
  local url="$2"

  code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 --max-time 5 "$url")
  echo "$name : $url -> HTTP $code"

  if [ "$code" = "000" ]; then
    add_critical "$name API 연결 실패 HTTP 000"
  elif [ "$code" = "503" ]; then
    add_critical "$name API 503 Service Unavailable"
  elif [ "$code" = "500" ]; then
    add_critical "$name API 500 Internal Server Error"
  elif [[ "$code" =~ ^2|^3|^4 ]]; then
    add_ok "$name API 응답 있음 HTTP $code"
  else
    add_warning "$name API 의심 응답 HTTP $code"
  fi
}

check_api "Keystone"  "http://${API_IP}:5000/v3"
check_api "Placement" "http://${API_IP}:8780/"
check_api "Nova"      "http://${API_IP}:8774/"
check_api "Cinder"    "http://${API_IP}:8776/"
check_api "Glance"    "http://${API_IP}:9292/"
check_api "Neutron"   "http://${API_IP}:9696/"

print_header "[9] Recent Major Log Errors"

ERROR_PATTERN="error|critical|traceback|exception|failed|denied|refused|timeout|unhealthy|fatal|database|mysql|rabbit|amqp|keystone|placement|503|Max connect timeout|hostgroup"

LOG_FILES=(
"/var/log/kolla/nova/nova-api.log"
"/var/log/kolla/nova/nova-conductor.log"
"/var/log/kolla/nova/nova-scheduler.log"
"/var/log/kolla/placement/placement-api.log"
"/var/log/kolla/cinder/cinder-api.log"
"/var/log/kolla/neutron/neutron-server.log"
"/var/log/kolla/glance/glance-api.log"
"/var/log/kolla/horizon/horizon.log"
"/var/log/kolla/horizon/apache-error.log"
)

for f in "${LOG_FILES[@]}"; do
  echo ""
  echo "-------------------- $f --------------------"
  if [ -f "$f" ]; then
    egrep -i "$ERROR_PATTERN" "$f" | tail -n 20 || echo "OK - No matching errors"
  else
    echo "SKIP - file not found"
  fi
done

check_log_error "Nova API" "/var/log/kolla/nova/nova-api.log" "$ERROR_PATTERN"
check_log_error "Nova Conductor" "/var/log/kolla/nova/nova-conductor.log" "$ERROR_PATTERN"
check_log_error "Nova Scheduler" "/var/log/kolla/nova/nova-scheduler.log" "$ERROR_PATTERN"
check_log_error "Placement API" "/var/log/kolla/placement/placement-api.log" "$ERROR_PATTERN"
check_log_error "Cinder API" "/var/log/kolla/cinder/cinder-api.log" "$ERROR_PATTERN"
check_log_error "Neutron Server" "/var/log/kolla/neutron/neutron-server.log" "$ERROR_PATTERN"
check_log_error "Glance API" "/var/log/kolla/glance/glance-api.log" "$ERROR_PATTERN"
check_log_error "Horizon" "/var/log/kolla/horizon/horizon.log" "$ERROR_PATTERN"

print_header "[10] Host Resource Check"

echo ""
echo "---- Disk ----"
df -h

ROOT_USE=$(df -h / | awk 'NR==2 {print $5}' | tr -d '%')
if [ "$ROOT_USE" -ge 90 ]; then
  add_critical "루트 파일시스템 사용률 ${ROOT_USE}%"
elif [ "$ROOT_USE" -ge 80 ]; then
  add_warning "루트 파일시스템 사용률 ${ROOT_USE}%"
else
  add_ok "루트 파일시스템 사용률 정상 ${ROOT_USE}%"
fi

echo ""
echo "---- Inode ----"
df -ih

ROOT_INODE=$(df -ih / | awk 'NR==2 {print $5}' | tr -d '%')
if [ "$ROOT_INODE" -ge 90 ]; then
  add_critical "루트 inode 사용률 ${ROOT_INODE}%"
elif [ "$ROOT_INODE" -ge 80 ]; then
  add_warning "루트 inode 사용률 ${ROOT_INODE}%"
else
  add_ok "루트 inode 사용률 정상 ${ROOT_INODE}%"
fi

echo ""
echo "---- Memory ----"
free -h

MEM_AVAILABLE_MB=$(free -m | awk '/Mem:/ {print $7}')
if [ "$MEM_AVAILABLE_MB" -lt 1024 ]; then
  add_warning "사용 가능 메모리 1GB 미만: ${MEM_AVAILABLE_MB}MB"
else
  add_ok "사용 가능 메모리 정상: ${MEM_AVAILABLE_MB}MB"
fi

echo ""
echo "---- Load ----"
uptime

print_header "[11] VM / Volume Error State Check"

SERVER_OUTPUT=$(openstack server list --all-projects 2>&1)
echo "$SERVER_OUTPUT"

if echo "$SERVER_OUTPUT" | egrep -i "ERROR" >/dev/null; then
  add_warning "ERROR 상태 인스턴스 존재"
else
  add_ok "ERROR 상태 인스턴스 없음"
fi

echo ""

VOLUME_LIST_OUTPUT=$(openstack volume list --all-projects 2>&1)
echo "$VOLUME_LIST_OUTPUT"

if echo "$VOLUME_LIST_OUTPUT" | egrep -i "error|creating|deleting|attaching|detaching" >/dev/null; then
  add_warning "비정상 또는 진행 중인 볼륨 상태 존재"
else
  add_ok "볼륨 상태 특이사항 없음"
fi

print_header "[12] Auto Analysis Summary"

echo "Critical Count : $CRITICAL_COUNT"
echo "Warning Count  : $WARNING_COUNT"
echo "OK Count       : $OK_COUNT"

echo ""
echo "-------------------- Overall Status --------------------"

if [ "$CRITICAL_COUNT" -gt 0 ]; then
  echo "RESULT: CRITICAL"
  echo "판단: 즉시 확인이 필요한 장애 또는 서비스 중단 가능성이 있습니다."
elif [ "$WARNING_COUNT" -gt 0 ]; then
  echo "RESULT: WARNING"
  echo "판단: 서비스는 동작 중일 수 있으나 점검이 필요한 특이사항이 있습니다."
else
  echo "RESULT: OK"
  echo "판단: 현재 주요 서비스와 컨테이너 상태에 특이사항이 없습니다."
fi

echo ""
echo "-------------------- Critical Items --------------------"
if [ "${#ISSUES[@]}" -eq 0 ]; then
  echo "None"
else
  for item in "${ISSUES[@]}"; do
    echo "- $item"
  done
fi

echo ""
echo "-------------------- Warning Items --------------------"
if [ "${#WARNINGS[@]}" -eq 0 ]; then
  echo "None"
else
  for item in "${WARNINGS[@]}"; do
    echo "- $item"
  done
fi

echo ""
echo "-------------------- Recommended Action --------------------"

if [ "$CRITICAL_COUNT" -gt 0 ]; then
  echo "1. Docker 비정상 컨테이너를 먼저 확인합니다."
  echo "2. 503 또는 API 장애가 있으면 HAProxy와 해당 API 컨테이너 로그를 확인합니다."
  echo "3. DB timeout 또는 hostgroup 문제가 있으면 MariaDB/ProxySQL부터 확인합니다."
  echo "4. Placement 문제가 있으면 Placement 정상화 후 Nova conductor/scheduler를 재시작합니다."
elif [ "$WARNING_COUNT" -gt 0 ]; then
  echo "1. Warning 항목의 로그를 우선 확인합니다."
  echo "2. 서비스가 실제로 응답하는지 openstack CLI로 재확인합니다."
  echo "3. down 상태 서비스가 있으면 해당 서비스 로그를 먼저 확인 후 개별 재시작합니다."
else
  echo "현재 별도 조치가 필요해 보이지 않습니다."
fi

echo ""
echo "Report saved to: $REPORT_FILE"
echo "=================================================="
echo " Check Finished"
echo "=================================================="

} | tee "$REPORT_FILE"

13. 스크립트 저장 및 실행 방법

파일 생성:

vi /root/openstack_morning_check_analyze.sh

권한 부여:

chmod +x /root/openstack_morning_check_analyze.sh

실행:

/root/openstack_morning_check_analyze.sh

로그는 /root 경로에 자동 저장된다.

/root/openstack_morning_check_YYYYMMDD_HHMMSS.log

최근 점검 결과 확인:

ls -ltr /root/openstack_morning_check_*.log | tail

마지막 분석 결과만 보고 싶으면:

grep -A 80 "Auto Analysis Summary" /root/openstack_morning_check_*.log | tail -n 100

14. 크론 등록 예시

매일 아침 8시에 자동 점검하려면 다음과 같이 등록한다.

crontab -e

아래 내용 추가:

0 8 * * * /root/openstack_morning_check_analyze.sh >/dev/null 2>&1

이렇게 하면 매일 아침 /root/openstack_morning_check_날짜_시간.log 형태로 점검 결과가 저장된다.


15. 장애 발생 시 기본 재시작 순서

이번 장애처럼 DB/ProxySQL 연결 문제로 Nova, Placement, Cinder가 연쇄적으로 장애가 발생한 경우에는 다음 순서로 재시작하는 것이 좋다.

docker restart mariadb
sleep 40

docker restart proxysql
sleep 30

docker restart placement_api
sleep 30

docker restart nova_api nova_metadata
sleep 30

docker restart nova_conductor nova_scheduler
sleep 30

docker restart cinder_api
sleep 30

docker restart haproxy
sleep 10

docker restart horizon

이 순서가 중요한 이유는 OpenStack 서비스 간 의존성 때문이다.

MariaDB / ProxySQL
→ Placement
→ Nova API
→ Nova conductor / scheduler
→ Cinder API
→ HAProxy
→ Horizon

예를 들어 Placement API가 DB에 연결하지 못하면 Nova conductor와 scheduler는 Placement discovery에 실패하면서 죽을 수 있다. Cinder API도 DB 연결에 실패하면 uWSGI 프로세스는 떠 있어도 health check는 unhealthy가 되고, CLI에서는 503 오류가 발생할 수 있다.


16. 결론

Kolla-Ansible 기반 OpenStack 아침 점검에서 가장 중요한 것은 단순히 컨테이너가 Up인지 확인하는 것이 아니다.

반드시 다음을 함께 확인해야 한다.

Docker health 상태
OpenStack CLI 서비스 상태
API HTTP 응답 상태
최근 주요 로그 에러
DB / ProxySQL / RabbitMQ 상태
호스트 리소스 상태
VM / Volume 오류 상태

특히 다음과 같은 로그는 장애의 핵심 단서가 된다.

Max connect timeout reached while reaching hostgroup 0
The placement service ... exists but does not have any supported versions
503 Service Unavailable
No server is available to handle this request

아침 점검 스크립트에 자동 분석 기능을 넣어두면, 단순 결과 확인을 넘어 현재 상태를 OK / WARNING / CRITICAL로 빠르게 구분할 수 있다. 이를 통해 장애 징후를 조기에 발견하고, 서비스 영향이 커지기 전에 조치할 수 있다.