13년차의 서버실

서버, 인프라, 홈랩 기술 블로그

[태그:] OpenStack 문제 해결

  • [OpenStack] 오픈스택 업그레이드 실패 사례 분석: Horizon 대시보드 접근 불가 문제 해결

    [OpenStack] 오픈스택 업그레이드 실패 사례 분석: Horizon 대시보드 접근 불가 문제 해결

    [OpenStack] 오픈스택 업그레이드 실패 사례 분석: Horizon 대시보드 접근 불가 문제 해결

    오픈스택 업그레이드 실패를 한 번이라도 겪어보신 분이라면 공감하실 겁니다. 업그레이드 작업 자체는 끝났는데, 막상 Horizon(호라이즌, 웹 기반 대시보드)이 안 열리면 정말 답답하더라고요. API는 살아 있는 것 같은데 웹 화면만 500 에러가 뜨거나, 로그인 루프가 걸리거나, 정적 파일이 깨져서 CSS 없이 하얀 화면만 나오는 경우가 꽤 많습니다. 저도 홈랩과 테스트 환경에서 이런 업그레이드 후 장애를 몇 번 겪었는데, 처음엔 이게 네트워크 문제인지 애플리케이션 문제인지 감이 안 오더라고요.

    이번 글은 제가 실제로 자주 밟았던 흐름을 기준으로, 오픈스택 업그레이드 실패 이후 발생한 Horizon 대시보드 오류를 어떻게 좁혀가고, 어떤 순서로 복구하면 좋은지 정리한 글입니다. 특정 배포판이나 특정 릴리스에만 묶이지 않도록, 검증된 일반 원칙과 현장에서 바로 써먹을 수 있는 점검 순서 중심으로 풀어보겠습니다.

    오픈스택 업그레이드 실패와 Horizon 대시보드 접근 구조를 설명하는 아키텍처 이미지

    Horizon, 웹 서버, Keystone, Memcached, 정적 파일 경로의 관계를 한눈에 보여주는 아키텍처 개요 이미지입니다.

    왜 Horizon만 죽는 걸까요? 오픈스택 업그레이드 실패의 전형적인 패턴

    쉽게 말해 Horizon은 혼자 동작하는 화면이 아닙니다. Apache(아파치, 웹 서버)나 Nginx(엔진엑스, 웹 서버) 뒤에서 돌아가고, 내부적으로는 Django(장고, 파이썬 웹 프레임워크) 기반 설정을 읽고, 로그인은 보통 Keystone(키스톤, 인증 서비스)과 연동되고, 세션은 Memcached(메모리 캐시)를 쓰는 경우가 많습니다. 여기에 정적 파일(static files), 정책 파일(policy files), WSGI(웹 서버 게이트웨이 인터페이스) 경로까지 얽혀 있죠.

    그래서 업그레이드 직후 Horizon 접근이 안 된다고 해서 원인이 꼭 Horizon 패키지 하나에만 있지는 않습니다. 실제로는 아래처럼 엮여 있는 경우가 많더라고요.

    • 웹 서버 설정은 살아 있지만 WSGI 경로가 이전 버전을 가리키는 경우
    • 패키지 업그레이드 후 정적 파일이 재배포되지 않아 화면이 깨지는 경우
    • local_settings.py 같은 설정 파일이 유지되면서 새 릴리스와 충돌하는 경우
    • Memcached 세션 문제로 로그인만 무한 반복되는 경우
    • Keystone 엔드포인트(endpoint, 서비스 접속 주소)나 도메인 설정이 달라져 인증만 실패하는 경우

    여기서 중요한 포인트가 있습니다. Horizon 대시보드 오류는 증상이 비슷해 보여도 원인은 꽤 다르거든요. 그래서 무작정 재시작부터 하면 시간만 더 씁니다. 저도 처음엔 서비스 재시작만 반복했었는데, 로그를 순서대로 본 날부터 복구 시간이 확 줄었습니다.

    증상별로 원인을 좁히는 방법

    제가 직접 해보니 가장 빨랐던 방법은 증상 기준으로 분류하는 거였습니다. 아래 표처럼 보면 훨씬 덜 헤맵니다.

    증상 가능성 높은 원인 우선 확인할 곳
    브라우저에서 500 Internal Server Error Django 설정 충돌, WSGI 오류, 패키지 의존성 문제 웹 서버 에러 로그, Horizon 애플리케이션 로그
    로그인 후 다시 로그인 화면으로 돌아감 세션 저장 실패, Memcached 문제, 쿠키/호스트 설정 문제 memcached 상태, local_settings.py, 브라우저 쿠키
    화면은 열리는데 CSS/JS가 깨짐 정적 파일 누락, collectstatic 미실행, 웹 서버 alias 불일치 정적 파일 경로, 웹 서버 설정
    특정 메뉴만 403 또는 비정상 정책 파일, RBAC(Role-Based Access Control, 역할 기반 접근 제어) 반영 문제 policy 파일, 서비스 연동 상태
    대시보드가 매우 느리거나 간헐 실패 Keystone 연동 지연, 캐시 문제, DNS 또는 백엔드 네트워크 이슈 API 응답, DNS, 캐시 상태

    이 표를 기준으로 보면, 막연한 OpenStack 문제 해결이 아니라 실제 점검 순서를 잡을 수 있습니다. 장애 대응에서 이 차이가 꽤 크더라고요.

    실전 점검 1단계: 웹 서버와 Horizon 프로세스부터 확인

    저는 항상 가장 바깥쪽부터 봅니다. 사용자는 웹으로 접속하니까, 먼저 웹 서버가 정상 응답하는지 확인해야 하거든요.

    1. Horizon 가상호스트(vhost, 가상 호스트) 설정이 로드되는지 확인합니다.
    2. 웹 서버 프로세스가 살아 있는지 봅니다.
    3. 에러 로그에서 Python traceback(트레이스백, 예외 호출 기록)이 있는지 찾습니다.
    # Debian/Ubuntu 계열 예시
    systemctl status apache2
    journalctl -u apache2 -n 100 --no-pager
    
    # RHEL 계열 예시
    systemctl status httpd
    journalctl -u httpd -n 100 --no-pager
    
    # Horizon 관련 설정 파일 위치 예시 확인
    ls -al /etc/openstack-dashboard/
    ls -al /usr/share/openstack-dashboard/
    

    여기서 ModuleNotFoundError, ImportError, TemplateDoesNotExist 같은 에러가 보이면 방향이 꽤 명확해집니다. 대개 패키지 업그레이드 이후 Python 모듈 경로나 템플릿, 또는 설정 파일이 새 구조와 안 맞는 경우가 많거든요.

    반대로 웹 서버는 멀쩡하고 정적 파일만 404가 난다면, 애플리케이션 자체보다 배포 경로나 alias 설정 쪽이 더 의심스럽습니다.

    오픈스택 업그레이드 실패 시 Horizon 대시보드 오류 진단 순서를 보여주는 이미지

    웹 서버 로그 확인, WSGI 점검, Keystone 인증 확인, 정적 파일 점검 순서를 정리한 트러블슈팅 플로우차트입니다.

    실전 점검 2단계: 설정 파일과 WSGI 경로를 비교합니다

    업그레이드 후 장애에서 정말 자주 나오는 게 이전 설정 파일이 남아 있는 상태입니다. 특히 local_settings.py는 환경마다 많이 손보는 파일이라, 예전 옵션이 새 코드와 충돌하기 쉽습니다. 저도 처음엔 설정을 많이 남겨두는 게 안전하다고 생각했는데, 실제로 써보니까 최소 설정만 남기고 차이를 다시 보는 쪽이 훨씬 낫더라고요.

    # 설정 파일 백업 후 비교
    cp /etc/openstack-dashboard/local_settings.py /root/local_settings.py.bak
    
    # 배포판에 따라 샘플 파일 위치는 다를 수 있으므로 실제 경로를 확인해서 비교
    find /usr/share/openstack-dashboard -name "*local_settings*" -o -name "settings.py"
    

    이 단계에서 제가 중점적으로 보는 항목은 아래입니다.

    • OPENSTACK_HOST: Keystone 또는 컨트롤러 접근 대상
    • ALLOWED_HOSTS: 웹 접근 호스트 허용 목록
    • CACHES: Memcached 백엔드 주소와 포트
    • SESSION_ENGINE: 세션 저장 방식
    • WEBROOT: 프록시 뒤 경로가 바뀐 경우 중요
    • 압축, 보안 헤더, SSL 종료 위치와 관련된 프록시 옵션

    WSGI 설정도 꼭 같이 봐야 합니다. 웹 서버가 여전히 예전 Python 경로나 예전 Horizon 설치 디렉터리를 바라보면, 패키지는 업그레이드됐는데 실행은 이전 구조를 참조하는 애매한 상태가 생기거든요.

    # 웹 서버 설정에서 dashboard, wsgi, static 경로 확인
    grep -R "wsgi\|static\|dashboard" /etc/apache2 /etc/httpd 2>/dev/null
    

    혹시 이런 경험 있으신가요? 서비스는 살아 있는데 브라우저에선 계속 500만 보이는 상황이요. 그런 경우 로그 안에 실제 원인이 거의 다 들어 있습니다. 눈에 잘 안 띄어서 그럴 뿐이죠.

    예시: 점검 포인트를 정리한 설정 스니펫

    # local_settings.py 예시 점검 포인트
    OPENSTACK_HOST = "controller"
    ALLOWED_HOSTS = ['*']
    WEBROOT = '/'
    
    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.PyMemcacheCache',
            'LOCATION': '127.0.0.1:11211',
        }
    }
    
    SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
    

    위 값 자체가 정답이라는 뜻은 아닙니다. 환경마다 다르거든요. 중요한 건 업그레이드 전후에 같은 의도를 유지하고 있는지, 그리고 새 버전에서 더 이상 쓰지 않는 옵션이 없는지를 보는 겁니다.

    실전 점검 3단계: Keystone 인증과 세션 문제를 분리해서 봅니다

    Horizon이 안 열릴 때 많은 분들이 웹 서버만 보는데, 로그인 단계에서 튕긴다면 사실상 Keystone 연동과 세션 저장을 같이 봐야 합니다. 특히 업그레이드 후 장애에서 많이 나오는 게 로그인 성공처럼 보이는데 다시 로그인 화면으로 돌아오는 케이스입니다. 이건 체감상 정말 답답합니다 ㅎㅎ

    1. CLI로 Keystone 인증이 정상인지 확인합니다.
    2. 서비스 엔드포인트가 올바른지 확인합니다.
    3. Memcached가 정상인지 확인합니다.
    # OpenStack CLI 인증 확인 예시
    openstack token issue
    openstack endpoint list
    openstack service list
    
    # memcached 상태 확인 예시
    systemctl status memcached
    ss -lntp | grep 11211
    

    CLI 인증이 되는데 Horizon 로그인만 실패하면, 저는 거의 항상 세션이나 쿠키 설정을 의심합니다. 반대로 CLI 인증부터 안 되면 Horizon 복구 전에 Keystone 쪽부터 정상화해야 하죠. 이 순서를 뒤집으면 시간을 많이 버립니다.

    Horizon 대시보드 오류 원인인 설정 파일과 Memcached 연동을 설명하는 이미지

    Horizon 설정, Keystone 인증 흐름, Memcached 세션 저장 위치를 연결해서 보여주는 구성 다이어그램입니다.

    실전 복구: 제가 주로 쓰는 복구 절차

    여기부터는 제가 직접 해보니 성공 확률이 높았던 순서입니다. 핵심은 한 번에 많이 바꾸지 않는 것입니다. 급하다고 이것저것 동시에 손대면, 나중에 뭐가 원인이었는지 또 모르게 되거든요.

    1. 웹 서버 에러 로그에서 첫 번째 traceback을 확보합니다.
    2. local_settings.py의 커스텀 값을 최소화하고, 필수 값만 남겨 재시작합니다.
    3. 정적 파일 경로와 권한을 확인합니다.
    4. 세션 캐시를 점검하고 필요 시 캐시를 비웁니다.
    5. 웹 서버를 재시작한 뒤 브라우저 캐시를 비우고 다시 접속합니다.
    # 정적 파일 경로 및 권한 예시 확인
    find /usr/share/openstack-dashboard -maxdepth 3 -type d | grep static
    find /var/lib/openstack-dashboard -maxdepth 3 -type d 2>/dev/null
    
    # 웹 서버 재시작 예시
    systemctl restart apache2 || systemctl restart httpd
    
    # 재시작 후 즉시 로그 확인
    journalctl -u apache2 -n 50 --no-pager || journalctl -u httpd -n 50 --no-pager
    

    정적 파일이 의심될 때는 CSS, JS, 폰트 요청이 200인지 404인지 브라우저 개발자 도구에서도 꼭 봅니다. 화면이 아예 안 열리는 것과, 사실은 HTML은 뜨는데 리소스만 깨지는 건 대응 방식이 다르니까요.

    정적 파일 문제가 의심될 때

    패키지 업그레이드 이후 정적 파일 alias 경로가 달라졌거나, 수집된 파일이 맞지 않으면 화면이 하얗게 깨집니다. 이때는 웹 서버 설정의 Alias 또는 정적 파일 루트를 먼저 확인합니다. 배포판마다 관리 방식이 다르니, 임의 명령을 바로 넣기보다 현재 패키징 구조를 확인하는 게 더 안전합니다.

    세션 문제가 의심될 때

    로그인 루프는 세션 저장 실패일 가능성이 높습니다. Memcached 주소가 바뀌었거나, 로컬호스트/호스트명 해석이 꼬였거나, 여러 컨트롤러 노드에서 캐시 설정이 일치하지 않으면 이런 증상이 나옵니다. HA(High Availability, 고가용성) 환경이면 더 자주 겪습니다.

    ⚠️ 실제로 많이 겪는 함정들

    여긴 진짜 중요합니다. 저도 삽질을 좀 했습니다 ㅎㅎ 아래 항목들은 문서만 보고는 놓치기 쉬운데, 현장에서는 자주 만납니다.

    • 브라우저 캐시 때문에 복구가 안 된 것처럼 보이는 경우
      정적 파일이 바뀐 뒤에도 예전 JS/CSS를 잡고 있으면 여전히 깨져 보입니다.
    • 로드밸런서 뒤에서 WEBROOT 또는 호스트 헤더가 어긋나는 경우
      리버스 프록시(reverse proxy, 역방향 프록시)를 쓰면 경로와 스킴 전달이 중요합니다.
    • 정책 파일만 옛것을 유지해 메뉴가 사라지는 경우
      대시보드가 안 뜨는 문제와는 다르지만, 사용자는 같은 장애로 인식합니다.
    • 패키지 업그레이드는 됐는데 서비스 재기동 순서가 꼬인 경우
      특히 캐시와 웹 서버가 엇갈리면 증상이 애매합니다.
    • 컨트롤러가 여러 대인데 노드마다 설정이 다른 경우
      한 번은 되고 한 번은 안 되는 증상은 이 패턴이 많습니다.

    저는 이런 함정을 막으려고, 업그레이드 전에 꼭 아래 체크리스트를 남겨둡니다.

    # 업그레이드 전 백업/기록 체크 예시
    cp -a /etc/openstack-dashboard /root/backup-openstack-dashboard-$(date +%F)
    cp -a /etc/apache2 /root/backup-apache2-$(date +%F) 2>/dev/null || true
    cp -a /etc/httpd /root/backup-httpd-$(date +%F) 2>/dev/null || true
    
    openstack endpoint list > /root/openstack-endpoints-before.txt
    openstack service list > /root/openstack-services-before.txt
    

    이런 기록이 있으면 나중에 비교가 정말 빨라집니다. 문서화가 귀찮아도, 장애 한 번 줄이면 바로 본전 뽑습니다.

    검증: 복구가 끝났다면 어디까지 확인해야 할까

    대시보드 첫 화면만 뜬다고 끝이 아닙니다. 저는 최소한 아래까지 확인해야 진짜 복구라고 봅니다.

    1. 로그인 성공 후 프로젝트 목록이 정상 표시되는지 확인
    2. 인스턴스(Instance, 가상 머신) 목록 페이지가 열리는지 확인
    3. 이미지(Image), 네트워크(Network), 볼륨(Volume) 메뉴 접근 확인
    4. 브라우저 개발자 도구에서 정적 파일 404/500이 없는지 확인
    5. 웹 서버 로그에 신규 에러가 없는지 확인
    # API 자체는 정상인지 교차 검증
    openstack server list
    openstack network list
    openstack volume list
    

    CLI 결과가 정상이고 Horizon 화면까지 문제없이 뜬다면, 그제야 드디어 됐다! 싶은 순간이 옵니다. 저는 이때 꼭 운영 노트에 원인과 조치 순서를 적어둡니다. 다음 업그레이드 때 똑같은 실수를 안 하려고요.

    오픈스택 업그레이드 실패 복구 후 Horizon 대시보드 정상 검증을 보여주는 이미지

    로그인 성공, 프로젝트 목록, 인스턴스/네트워크/볼륨 메뉴 확인이 완료된 상태를 보여주는 검증 이미지입니다.

    정리: 오픈스택 업그레이드 실패를 줄이려면

    이번 사례를 한 줄로 정리하면 이렇습니다. 오픈스택 업그레이드 실패처럼 보이는 현상도, Horizon만 놓고 보면 웹 서버, 설정 파일, 인증, 세션, 정적 파일 중 하나로 꽤 잘 분해됩니다. 전체를 한 번에 보지 말고, 바깥에서 안쪽으로 좁혀가는 게 핵심입니다.

    점검 영역 핵심 질문 복구 힌트
    웹 서버 500 에러가 나는가? journalctl, error log, WSGI 경로 확인
    설정 파일 기존 커스텀 설정이 남아 있는가? local_settings.py 최소화 후 비교
    인증 CLI 인증은 되는가? openstack token issue, endpoint 점검
    세션/캐시 로그인 루프가 있는가? Memcached 상태와 주소 확인
    정적 파일 CSS/JS가 깨지는가? static 경로, alias, 브라우저 네트워크 탭 확인

    다음 글에서는 업그레이드 전에 미리 확인해야 할 체크리스트와 롤백 전략도 따로 다뤄볼 예정입니다. 이전 글에서 다뤘던 컨트롤러 노드 점검 루틴과 같이 보시면 더 흐름이 잘 잡히실 겁니다.

    오픈스택 업그레이드 실패와 Horizon 대시보드 오류 점검 우선순위를 요약한 이미지

    웹 서버, 설정 파일, 인증, 캐시, 정적 파일 순서로 점검하는 우선순위를 요약한 인포그래픽입니다.

    자주 묻는 질문

    Q1. Horizon만 안 되고 OpenStack CLI는 되면 어디부터 봐야 하나요?

    웹 서버 로그와 local_settings.py를 먼저 보시면 됩니다. 이 경우는 대개 Horizon 애플리케이션 계층 문제거나 세션/정적 파일 문제인 경우가 많습니다.

    Q2. 로그인만 반복되면 Keystone 장애라고 봐야 하나요?

    반드시 그렇진 않습니다. Keystone 자체보다 세션 저장이나 쿠키 처리 문제일 때도 많습니다. 그래서 CLI 인증과 웹 로그인 문제를 꼭 분리해서 확인하셔야 합니다.

    Q3. 업그레이드 후 장애를 줄이려면 가장 중요한 건 뭔가요?

    제가 느낀 1순위는 설정 백업과 차이 비교입니다. 그다음이 서비스별 검증 순서 고정입니다. 즉흥적으로 대응하면 같은 장애를 반복하게 되더라고요.

    혹시 지금 비슷한 Horizon 대시보드 오류를 겪고 계시다면, 위 순서대로만 점검해도 원인 범위를 꽤 빠르게 좁히실 수 있을 겁니다. 완벽한 정답보다, 재현 가능한 점검 루틴을 갖는 게 훨씬 강합니다.