13년차의 서버실

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

[카테고리:] openstack

  • [OpenStack] MicroStack 1년 운영 회고: 소규모 프라이빗 클라우드 구축 경험과 한계

    [OpenStack] MicroStack 1년 운영 회고: 소규모 프라이빗 클라우드 구축 경험과 한계

    [프라이빗 클라우드] MicroStack 1년 운영 회고: 소규모 환경 구축 경험과 한계

    1. 홈랩에 프라이빗 클라우드가 필요했던 이유

    안녕하세요, 13년차 서버실 지킴이입니다. 오늘은 제 홈랩에서 1년 넘게 운영해온 MicroStack(마이크로스택)에 대한 솔직한 회고를 해볼까 합니다. 인프라 엔지니어라면 누구나 한 번쯤 나만의 클라우드를 꿈꾸지 않나요? 저도 그랬습니다. AWS, Azure, GCP 같은 퍼블릭 클라우드도 좋지만, 직접 바닥부터 쌓아 올리는 프라이빗 클라우드의 매력은 또 다르거든요. 특히 OpenStack(오픈스택)은 예전부터 계속 만져보고 싶었던 기술이었는데, 제 홈랩 환경에서는 너무 무겁고 복잡해서 엄두를 못 내고 있었죠.

    그러다 "가볍게 OpenStack을 경험할 수 있다"는 말에 홀려 MicroStack을 만나게 됐습니다. 처음에는 "이게 진짜 OpenStack이라고?" 싶을 정도로 간편한 설치에 놀랐어요. 작은 서버 한 대로 온프레미스 클라우드를 꾸리고 싶었던 저에게는 정말 솔깃한 제안이었거든요. 제 홈랩에서 다양한 서비스를 올리고 내리면서 자유롭게 테스트하고 싶었고, Public Cloud 비용 걱정 없이 마구 실험해보고 싶다는 욕구가 컸습니다. 과연 1년 동안 MicroStack은 저의 이런 기대를 얼마나 충족시켜줬을까요? 삽질 경험과 함께 솔직한 후기를 공유해볼게요.

    MicroStack은 단일 서버 위에서 LXD 컨테이너 기술을 활용해 OpenStack 핵심 구성 요소들을 경량으로 실행하는 아키텍처를 가집니다.

    2. MicroStack이란 무엇인가요?

    MicroStack은 Ubuntu를 개발하는 Canonical(캐노니컬)에서 만든 OpenStack 배포판 중 하나입니다. 기존 OpenStack은 수십 대의 서버와 복잡한 설정이 필요한 거대한 프로젝트인데, MicroStack은 이런 복잡성을 확 줄여서 단일 서버에서도 OpenStack의 핵심 기능들을 사용할 수 있게 해주는 경량 솔루션이에요. 쉽게 말해, "홈랩이나 소규모 환경을 위한 미니 OpenStack"이라고 생각하시면 편합니다.

    • LXD 기반: 컨테이너 기술인 LXD(Linux Container Daemon)를 활용해서 OpenStack의 다양한 서비스들(Nova, Neutron, Glance, Keystone 등)을 컨테이너 형태로 실행합니다. 덕분에 자원 효율성이 좋고, 격리된 환경에서 안정적으로 운영할 수 있어요.

    • Snap 패키징: Ubuntu의 Snap(스냅) 패키지 형태로 제공되어서 설치와 관리가 굉장히 간편합니다. snap install 한 줄이면 끝이에요. 업데이트도 자동이라 관리 부담이 적습니다.

    • 단일 노드 지향: 기본적으로 단일 서버에서 모든 OpenStack 서비스가 돌아가는 구조를 지향합니다. 고가용성(HA, High Availability)이나 대규모 확장이 목표가 아니라, 빠르고 쉽게 OpenStack을 시작해보는 데 초점이 맞춰져 있어요.

    이런 특징 덕분에 저처럼 "OpenStack은 너무 어려울 것 같고… 그래도 한 번쯤 경험해보고 싶다" 하는 분들에게는 아주 좋은 진입점이라고 생각했습니다.

    3. 설치 및 초기 구성: 이렇게 쉬워도 되나?

    MicroStack의 가장 큰 장점 중 하나는 바로 설치 간편성입니다. 정말 너무 쉬워서 처음엔 놀랐어요. Ubuntu 서버만 있다면 몇 가지 명령어만으로 바로 OpenStack 환경을 구축할 수 있습니다.

    3.1. 설치 명령어

    # MicroStack 설치
    sudo snap install microstack --classic
    
    # 초기화 (All-in-one 모드 선택, 네트워크 설정 등) 
    # 이 과정에서 OpenStack 서비스들이 LXD 컨테이너로 배포됩니다.
    sudo microstack init --auto --control --compute --network --config
    
    # OpenStack CLI 환경 설정 (OpenStack Client를 통해 컨트롤)
    source /snap/microstack/common/etc/microstack.rc
    
    # OpenStack 서비스 상태 확인
    sudo microstack status
    

    microstack init 명령어를 실행하면 몇 가지 질문이 나오는데, 기본적으로 All-in-one 모드로 진행하면 됩니다. 네트워크 구성이나 인증 방식 등은 나중에 다시 설정할 수 있으니 부담 없이 진행해도 괜찮아요. 이 과정에서 LXD 컨테이너들이 생성되고 그 안에 Nova(컴퓨트), Neutron(네트워킹), Glance(이미지), Keystone(인증) 같은 OpenStack 핵심 서비스들이 배포됩니다. 몇 분 기다리면 OpenStack 환경이 뚝딱 만들어지는 걸 보면서 정말 감탄했어요 🎉.

    3.2. 네트워크 설정, 그리고 삽질 시작

    MicroStack 설치는 쉬웠지만, 진짜 "내 것"으로 만들려면 네트워크 설정이 중요하죠. 특히 외부에서 생성된 VM(Virtual Machine)에 접근하려면 Floating IP(플로팅 IP)를 할당해야 하는데, 이를 위한 네트워크 구성을 제대로 해줘야 합니다. 저는 처음에는 내부 네트워크만 만들고 외부 연결이 안 돼서 한참을 헤맸습니다 😅.

    # 외부 네트워크 생성 (내부망과 연결할 라우터 역할을 합니다)
    # --external은 이 네트워크가 외부와 연결될 수 있음을 나타냅니다.
    openstack network create --external --provider-physical-network extnet --provider-network-type flat ext_net
    
    # 서브넷 생성 (외부망 IP 대역과 일치하게 설정)
    # --no-dhcp 옵션을 사용해 DHCP 서버가 IP를 자동으로 할당하지 않도록 합니다 (외부망과 충돌 방지)
    # --gateway는 외부망 게이트웨이 IP를 입력합니다.
    openstack subnet create --network ext_net \ 
      --subnet-range 192.168.0.0/24 \ 
      --no-dhcp \ 
      --gateway 192.168.0.1 \ 
      ext_subnet
    
    # 라우터 생성
    openstack router create router1
    
    # 라우터에 외부 네트워크 연결
    openstack router set router1 --external-gateway ext_net
    
    # 내부 네트워크 생성 (VM들이 사용할 사설 네트워크)
    openstack network create int_net
    
    # 내부 서브넷 생성
    openstack subnet create --network int_net --subnet-range 10.0.0.0/24 int_subnet
    
    # 라우터에 내부 네트워크 인터페이스 추가
    openstack router add subnet router1 int_subnet
    

    이런 식으로 네트워크를 구성해주고 나서 VM을 생성할 때 int_net에 연결하고, 필요할 경우 ext_net의 IP 대역에서 Floating IP를 할당해주면 외부에서 VM에 접근할 수 있게 됩니다. 이 부분을 이해하는 데 좀 시간이 걸렸네요. OpenStack 네트워크 개념인 Provider Network, Tenant Network, Router, Floating IP 등을 잘 알아야 해요.

    OpenStack Horizon 대시보드 스크린샷: VM 인스턴스 목록과 네트워크 토폴로지

    OpenStack Horizon 대시보드를 통해 생성된 가상머신과 네트워크 구성을 한눈에 볼 수 있습니다.

    4. 1년 운영 경험: 장점, 단점 그리고 한계

    1년 동안 MicroStack을 운영하면서 느낀 장점과 단점을 솔직하게 정리해봤습니다.

    4.1. 장점: 쉬운 접근성과 자원 효율성 ✅

    • 빠른 배포 및 관리 용이성: snap과 microstack CLI 덕분에 설치, 업그레이드, 관리가 정말 편했습니다. "OpenStack은 어렵다"는 고정관념을 깨기에 충분했죠.

    • 자원 효율성: LXD 컨테이너 기반이라 일반 가상머신보다 훨씬 가볍게 OpenStack 서비스를 운영할 수 있었습니다. 제 홈랩의 서버 자원이 제한적이라 이 점이 가장 만족스러웠어요.

    • OpenStack 학습 도구로 최적: 실제 OpenStack 환경에서 CLI 명령어를 직접 쳐보고, Horizon(호라이즌, 웹 대시보드)을 만져보면서 OpenStack의 핵심 개념(Nova, Neutron, Glance, Keystone 등)을 빠르게 익힐 수 있었습니다. 덕분에 회사에서 OpenStack 관련 프로젝트를 할 때 훨씬 더 빠르게 적응할 수 있었어요.

    4.2. 단점 및 한계점: 삽질의 연속 ⚠️

    하지만 장점만 있었던 건 아닙니다. "미니 OpenStack"이라는 태생적 한계와 함께 몇몇 삽질을 피할 수 없었습니다.

    • 단일 노드 아키텍처의 한계: MicroStack은 기본적으로 단일 서버에 모든 서비스가 올라가는 All-in-one 구조입니다. 이는 곧 고가용성(HA)을 전혀 보장할 수 없다는 의미예요. 서버가 한 번 죽으면 모든 VM과 OpenStack 서비스가 멈춥니다. 홈랩이야 괜찮지만, 실제 운영 환경에서는 절대 사용할 수 없는 구조죠.

    • 문제 발생 시 디버깅의 어려움: LXD 컨테이너 안에 OpenStack 서비스들이 돌아가다 보니, 문제가 생겼을 때 로그를 찾거나 디버깅하는 과정이 생각보다 복잡했습니다. 일반적인 OpenStack 설치라면 `systemctl`로 서비스를 제어하고 로그를 바로 확인할 수 있지만, MicroStack은 LXD 컨테이너 내부로 들어가서 각 서비스의 로그를 찾아야 했어요. 예를 들어 Nova 서비스에 문제가 생기면 다음과 같이 접근해야 합니다.

      # MicroStack의 LXD 컨테이너 목록 확인
      sudo lxc list
      
      # nova 컨테이너 쉘 접근
      sudo lxc exec microstack-nova -- bash
      
      # 컨테이너 내부에서 nova 서비스 로그 확인 (예시)
      # 경로와 파일명은 OpenStack 버전에 따라 다를 수 있습니다.
      tail -f /var/log/nova/nova-conductor.log
      

      이런 과정이 익숙지 않은 초보자에게는 진입 장벽이 될 수 있습니다.

    • 복잡한 네트워크 구성의 제약: 위에서 보여드린 기본적인 네트워크 구성은 가능하지만, OpenStack의 고급 네트워킹 기능(예: SD-WAN 통합, 복잡한 로드밸런싱 등)을 활용하기에는 제약이 많았습니다. 특히 물리 네트워크 인터페이스를 여러 개 활용하거나 VLAN(Virtual LAN)을 섬세하게 제어하는 부분은 쉽지 않았어요.

    • OpenStack 버전 관리 및 호환성: Snap 패키지 덕분에 업데이트는 편하지만, 특정 OpenStack 버전(예: Wallaby, Xena)을 선택하거나 고정하기는 어려웠습니다. 항상 최신 안정화 버전으로 유지되는데, 이는 호환성 문제가 발생할 수도 있다는 의미입니다. 제가 겪었던 문제 중 하나는 특정 이미지 포맷이 지원되지 않거나, CLI와 Horizon의 기능 차이가 발생하는 경우였습니다.

    • 커뮤니티 지원 부족: 일반적인 OpenStack 커뮤니티에 비해 MicroStack만의 정보는 상대적으로 적습니다. 문제가 생겼을 때 구글링이나 스택오버플로우에서 해답을 찾기 어려울 때가 많았어요. 결국 OpenStack 자체의 지식을 바탕으로 직접 해결해야 하는 경우가 많았습니다.

    5. MicroStack vs. 다른 OpenStack 배포판: 선택의 고민

    MicroStack이 편리하긴 하지만, "진짜" OpenStack을 경험하거나 운영하려는 분들에게는 다른 선택지도 있습니다. 제가 고민했던 몇 가지 옵션과 MicroStack을 비교해봤어요.

    특징 MicroStack (Snap + LXD) DevStack (스크립트 설치) Packstack (Ansible 기반) RDO/OpenStack-Ansible (프로덕션 배포)
    주요 목적 빠른 학습, 홈랩, 소규모 테스트 개발, 테스트 환경 구축 소규모 프로덕션, 테스트 엔터프라이즈 프로덕션 환경
    설치 난이도 매우 쉬움 (snap install) 쉬움 (git clone && ./stack.sh) 보통 (Ansible 지식 필요) 어려움 (복잡한 설정, HA 구성)
    자원 요구량 낮음 (LXD 컨테이너) 보통 (VM 또는 베어메탈) 보통~높음 높음 (다중 노드 필수)
    고가용성 (HA) 지원 안 함 (단일 노드) 지원 안 함 제한적 지원 완벽 지원
    관리 용이성 매우 좋음 (Snap 업데이트) 낮음 (수동 스크립트) 좋음 (Ansible 관리) 높음 (자동화 도구)
    확장성 없음 없음 제한적 매우 좋음
    추천 사용자 OpenStack 입문자, 홈랩 사용자 OpenStack 개발자, 기능 테스트 소규모 운영팀, POC 대규모 클라우드 운영팀
    MicroStack 홈랩 운영 장점과 한계 요약 인포그래픽

    MicroStack은 간편함이 가장 큰 장점이지만, 프로덕션 환경에 필요한 기능과 안정성에는 한계가 명확합니다.

    6. 누구에게 MicroStack이 적합할까? 나의 결론 💡

    1년 동안 MicroStack을 직접 운영해본 결과, 저는 다음과 같은 분들에게 MicroStack을 추천하고 싶습니다.

    1. OpenStack 초보자 및 학습자: "OpenStack이 뭔지 한 번 경험해보고 싶다" 하는 분들에게는 이만한 진입점이 없습니다. 복잡한 설치 과정 없이 핵심 기능을 빠르게 만져볼 수 있어요. CLI 명령어와 Horizon 대시보드 사용법을 익히는 데 아주 유용합니다.

    2. 홈랩 환경에서 가벼운 프라이빗 클라우드를 원하는 분: 저처럼 개인 서버 한 대로 가상 환경을 구축하고, 다양한 OS 이미지를 올려보고 싶을 때 좋습니다. 퍼블릭 클라우드 비용이 부담스러울 때 대안이 될 수 있죠.

    3. 가벼운 PoC(개념 증명) 또는 테스트 환경이 필요한 개발자: 특정 OpenStack API를 활용하는 애플리케이션을 개발하거나, 간단한 테스트 환경을 빠르게 구축해야 할 때 유용합니다. 복잡한 프로덕션 환경을 그대로 구현할 필요가 없을 때 말이죠.

    하지만 실제 프로덕션 환경에 OpenStack을 도입하려는 분이라면 MicroStack은 부적합합니다. 고가용성, 확장성, 안정성 등 엔터프라이즈 환경에서 필요한 요소들을 MicroStack은 제공하지 않거든요. 이런 경우에는 DevStack이나 Packstack으로 개념을 잡고, 더 나아가 RDO나 OpenStack-Ansible 같은 프로덕션용 배포판을 고려해야 합니다.

    7. 마무리: 1년의 경험을 통해 배운 점, 그리고 다음 스텝

    MicroStack 1년 운영은 저에게 많은 것을 알려줬습니다. OpenStack의 핵심 개념을 직접 손으로 익히고, 프라이빗 클라우드 운영의 재미와 동시에 한계를 명확히 깨닫게 해줬어요. 특히 "간편함"과 "안정성/확장성"은 상충되는 가치라는 것을 다시 한번 실감했습니다. 작은 홈랩에서 시작했지만, 덕분에 회사에서 더 큰 규모의 클라우드 인프라를 이해하고 설계하는 데 큰 도움이 됐습니다.

    솔직히 삽질도 많이 했지만, 그 과정에서 얻은 지식과 경험은 무엇과도 바꿀 수 없는 소중한 자산이 되었습니다. OpenStack이라는 거대한 프로젝트에 대한 막연한 두려움을 깼다는 것만으로도 충분히 만족스러웠네요. 앞으로는 MicroK8s(마이크로케이츠)처럼 경량 Kubernetes(쿠버네티스) 솔루션도 홈랩에 도입해서, MicroStack과 연동하는 하이브리드 클라우드 환경을 구축해보는 것도 재미있을 것 같다는 생각이 듭니다. 홈랩은 언제나 새로운 기술을 실험하고 배우는 저만의 놀이터거든요!

    혹시 여러분도 OpenStack에 관심이 있으시다면, MicroStack으로 가볍게 시작해보는 건 어떠세요? 분명 좋은 경험이 될 겁니다. 궁금한 점이 있다면 언제든 댓글로 남겨주세요. 제가 겪었던 삽질 경험을 바탕으로 최대한 도와드리겠습니다! 💪

    13년차 인프라 엔지니어가 홈랩에서 MicroStack 대시보드를 보며 만족하는 모습

    13년차 인프라 엔지니어가 홈랩 서버 앞에서 MicroStack 대시보드를 보며 만족스럽게 웃고 있습니다.

  • [OpenStack] OpenStack Ceph 마이그레이션 결정 기준과 절차

    [OpenStack] OpenStack Ceph 마이그레이션 결정 기준과 절차

    OpenStack Ceph 마이그레이션 결정 기준과 절차

    OpenStack Ceph 마이그레이션을 검토할 때 저는 늘 같은 질문부터 던집니다. "지금 바꾸면 뭐가 좋아지고, 대신 무엇을 새로 운영해야 하나"라는 질문이죠. 핵심은 단순한 저장소 교체가 아니라 운영 모델의 변경입니다. Cinder 볼륨만 옮길지, Glance 이미지 저장소까지 묶을지, Nova의 에페메럴 디스크까지 Ceph RBD로 정리할지에 따라 난이도와 장애 반경이 완전히 달라지거든요. 실제 운영에서는 성능 수치보다 스케줄링 일관성, Ceph 재배치 부담, 인증 권한, 롤백 가능성이 더 자주 발목을 잡습니다.

    이 글은 OpenStack과 Ceph의 일반적인 운영 패턴을 기준으로 정리했습니다. 특정 벤더 확장 기능이나 과장된 수치 없이, 현장에서 일정 잡을 때 실제로 보는 판단 기준과 절차만 남겼습니다. 한 줄로 줄이면 이렇습니다. 기존 백엔드를 덮어쓰지 말고, 새 백엔드를 병행 등록한 뒤 신규 유입과 기존 자산 이동을 분리해서 진행하는 편이 안전합니다. 관련해서 볼륨 타입 설계나 Ceph 풀 설계 글도 함께 보시면 운영 그림이 훨씬 빨리 잡힙니다.

    OpenStack Ceph 마이그레이션 전체 아키텍처 다이어그램

    OpenStack 서비스 계층과 Ceph 풀(pool) 구조, 데이터 이동 흐름을 한눈에 보여주는 개요 이미지입니다.

    1. OpenStack Ceph 마이그레이션을 고민하는 대표적인 이유

    운영 현장에서는 보통 "Ceph가 좋아 보여서"가 아니라 아래 같은 이유로 움직입니다.

    • 풀 구조가 성장 패턴을 못 따라갈 때: 같은 풀에 서로 다른 I/O 성격의 볼륨이 섞이면 운영 판단이 흐려집니다.
    • 볼륨 타입 정책을 분리해야 할 때: 테넌트별, 워크로드별, 복제 정책별로 다른 백엔드가 필요해집니다.
    • 증설과 장애 대응의 표준화가 필요할 때: 하드웨어별 절차보다 Ceph 기준으로 운영 일관성을 맞추고 싶을 때가 많습니다.
    • 기존 백엔드가 OpenStack 스케줄러와 잘 안 맞을 때: 사용자는 타입을 골랐는데 실제 배치가 정책대로 안 되는 경우가 반복됩니다.

    제가 실무에서 특히 중요하게 보는 건 "왜 옮기느냐"보다 어디까지 옮기느냐입니다. Cinder만 옮기면 블록 스토리지 정책 문제로 한정되지만, Glance까지 함께 들어가면 이미지 캐시와 부팅 경로가 바뀝니다. Nova 에페메럴까지 손대는 순간부터는 스토리지 변경이라기보다 컴퓨트 설계 변경에 가깝습니다.

    2. OpenStack Ceph 마이그레이션 결정 기준은 성능보다 운영 책임입니다

    Ceph 도입 여부를 성능 하나로만 판단하면 나중에 꼬이기 쉽습니다. 더 정확한 질문은 이겁니다. "이 팀이 Ceph의 재배치, 권한, 풀 정책, 장애 메시지를 자기 책임으로 읽고 운영할 준비가 됐는가"예요. 이 기준이 생각보다 훨씬 현실적입니다.

    판단 항목 기존 유지가 더 나은 경우 Ceph 전환이 더 나은 경우 실무 체크 포인트
    운영 복잡도 현재 절차가 단순하고 장애 대응 경로가 고정돼 있음 확장, 복제, 장애 도메인 관리를 한 체계로 묶고 싶음 클라우드 팀이 Ceph 경고 메시지와 재배치 상태를 직접 해석할 수 있는지
    볼륨 타입 정책 사실상 단일 티어로도 충분함 테넌트/업무군별로 다른 풀과 정책이 필요함 volume_backend_name, extra_specs, 타입 명명 규칙을 먼저 설계했는지
    장애 허용 구조 외부 스토리지가 이미 안정적으로 이중화됨 CRUSH 규칙과 failure domain을 직접 설계할 가치가 있음 복제 단위가 host인지 rack인지, 기존 가용영역 설계와 충돌하지 않는지
    마이그레이션 방식 짧은 점검창도 확보하기 어려움 신규/기존을 분리하고 몇 주에 걸쳐 점진 전환 가능 붙어 있는(in-use) 볼륨의 정책 변경 허용 여부와 드라이버 지원 범위
    운영 비용 전담 인력이 없고 스토리지 운영을 단순화해야 함 학습 비용을 들여도 장기적으로 통합 운영 이득이 큼 모니터링, 알림, 장애 복구 문서가 Ceph 기준으로 이미 준비됐는지

    짧게 정리하면 이렇습니다. 볼륨 타입 분리와 점진 전환이 필요하면 Ceph 쪽이 유리하고, 운영 역량이 아직 약하면 기존 백엔드를 남겨둔 병행 운영이 맞습니다. 반대로 다운타임 제로만 바라보면서 한 번에 덮어쓰는 방식은 실무에서 꽤 위험하더라고요.

    3. OpenStack 스토리지 교체 범위를 자르면 난이도가 확 줄어듭니다

    OpenStack 스토리지 교체는 기술 문제라기보다 범위 관리 문제인 경우가 많습니다. 보통 아래 셋으로 끊습니다.

    1. Cinder 볼륨만 전환: 가장 현실적이고, 실패해도 영향 반경을 제한하기 쉽습니다.
    2. Glance 이미지까지 전환: 이미지 업로드, 캐시, 부팅 경로를 함께 봐야 합니다.
    3. Nova 에페메럴 디스크까지 전환: 성능과 일관성 이득은 크지만 컴퓨트 노드 영향이 급격히 커집니다.

    제가 추천하는 순서는 거의 같습니다. Cinder -> Glance -> Nova예요. 이유는 단순합니다. Cinder는 볼륨 타입이라는 절연층이 있지만, Nova 루트/에페메럴까지 한 번에 건드리면 인스턴스 부팅 실패가 곧바로 서비스 장애로 번지기 쉽습니다.

    실무에서 자주 보는 장면도 있습니다. 기존에는 외부 SAN을 쓰다가 "이번에 Ceph도 붙였으니 볼륨도 이미지도 같이 넘기자"고 범위를 넓히는 경우죠. 이때 Cinder 신규 볼륨은 정상 생성되는데, 부팅 지연이나 이미지 캐시 미스 때문에 운영팀이 Glance 문제를 Ceph 문제로 오해하는 일이 꽤 많습니다. 그래서 저는 첫 전환 주기에는 신규 볼륨 경로와 이미지 경로를 일부러 분리합니다. 원인 분리가 정말 편해집니다.

    4. OpenStack Ceph 마이그레이션 사전 점검

    이 단계는 체크리스트라기보다 진입 금지선에 가깝습니다. 상태가 좋지 않으면 일정부터 미루는 편이 맞습니다. 마이그레이션 자체보다, 진행 중 나타난 문제의 원인이 Ceph인지 OpenStack인지 분리하기 어려워지기 때문입니다.

    ceph -s
    ceph health detail
    ceph osd stat
    ceph osd tree
    ceph osd df tree
    ceph osd pool ls detail
    rados df
    openstack volume service list
    openstack volume type list --long
    openstack volume list --status in-use --long

    여기서는 보통 이렇게 읽습니다.

    • ceph -s: 클러스터 전체 상태와 recovery/backfill 진행 여부를 먼저 봅니다. 단순 HEALTH_WARN보다 경고 원인이 재배치인지 용량 임계치인지가 더 중요합니다.
    • ceph health detail: degraded, undersized, inactive, nearfull 계열 메시지가 보이면 이동 작업을 미룹니다.
    • ceph osd df tree: 특정 OSD만 유독 가득 찼다면 마이그레이션 중 backfill이 겹치면서 체감 성능이 흔들릴 가능성이 큽니다.
    • ceph osd pool ls detail: 새 풀의 복제 정책, CRUSH rule, autoscale 상태를 봅니다. 풀 이름만 맞고 규칙이 다르면 기대한 장애 도메인이 깨질 수 있습니다.
    • openstack volume service list: 대상 cinder-volume 서비스가 up이고 enabled인지 확인합니다.
    • openstack volume type list --long: 현재 타입과 백엔드 이름 연결이 살아 있는지 확인합니다.
    • openstack volume list --status in-use --long: 붙어 있는 볼륨 비중이 높다면 온라인 정책 변경이 가능한지부터 따져야 합니다.

    실제 실패 모드도 비슷합니다. 새 타입은 잘 만들었는데 Ceph 쪽에서 이미 backfill이 길게 돌고 있던 상황이죠. OpenStack API는 성공으로 보이는데 사용자는 I/O 지연을 바로 체감합니다. OpenStack의 성공 응답이 Ceph 내부 재배치 비용까지 끝났다는 뜻은 아니라는 점, 이 부분은 꼭 분리해서 봐야 합니다.

    OpenStack Ceph 마이그레이션 사전 점검과 볼륨 타입 매핑 이미지

    Ceph 클러스터 헬스 체크, 풀 상태, Cinder 볼륨 타입과 백엔드 이름 매핑 관계를 설명하는 이미지입니다.

    5. 백엔드 설계는 pool보다 volume type을 먼저 잡아야 합니다

    운영에서 더 오래 가는 설계는 "풀 이름 중심"이 아니라 볼륨 타입 중심입니다. 사용자는 타입을 고르고, Cinder 스케줄러는 타입의 extra_specs를 보고 백엔드를 고르거든요. 그래서 이름 규칙이 중요합니다.

    • 백엔드 섹션 이름: 운영자가 구분하기 쉬운 내부 이름
    • volume_backend_name: 타입과 연결되는 스케줄링 식별자
    • Ceph 풀 이름: 실제 데이터가 놓이는 물리적 대상

    많이 헷갈리는 지점이 하나 있습니다. [rbd-new] 같은 설정 섹션 이름과 volume_backend_name=rbd-new는 같은 개념이 아닙니다. 우연히 같게 맞출 수는 있지만, 스케줄러가 직접 참조하는 값은 섹션명이 아니라 백엔드 이름입니다. 여기 오타가 나면 타입은 멀쩡해 보여도 No valid host 오류가 나기 쉽습니다.

    5-1. OpenStack Ceph 마이그레이션용 cinder.conf 예시

    [DEFAULT]
    enabled_backends = rbd-old,rbd-new
    
    [backend_defaults]
    rbd_ceph_conf = /etc/ceph/ceph.conf
    rbd_user = cinder
    rbd_secret_uuid = 11111111-2222-3333-4444-555555555555
    volume_driver = cinder.volume.drivers.rbd.RBDDriver
    
    [rbd-old]
    volume_backend_name = rbd-old
    rbd_pool = volumes_old
    
    [rbd-new]
    volume_backend_name = rbd-new
    rbd_pool = volumes_new

    현재 Cinder 샘플 설정에서도 공통 백엔드 옵션은 [backend_defaults] 섹션을 사용합니다. 여기서 중요한 건 세 가지예요. enabled_backends에 백엔드 섹션이 모두 들어가 있는지, 각 섹션의 volume_backend_name이 타입의 extra_specs와 정확히 일치하는지, 공통 설정을 쓴다면 [backend_defaults]와 개별 섹션의 덮어쓰기 관계를 이해하고 있는지입니다.

    기존 단일 백엔드 서비스에 다중 백엔드를 붙이는 경우, Cinder 서비스 호스트명이 host에서 host@backend 형태로 바뀌는 환경도 있습니다. 이런 경우 기존 볼륨의 host 메타데이터를 갱신하지 않으면 운영이 꼬일 수 있어서, 사전에 cinder-manage volume update_host 대상 여부를 꼭 확인하는 편이 좋습니다.

    5-2. Ceph 풀과 인증 준비

    새 풀만 만들고 끝내면 안 됩니다. RBD로 쓸 풀은 초기화와 권한까지 맞아야 합니다. 저는 신규 백엔드를 붙이기 전에 아래 항목을 먼저 확인합니다.

    ceph osd pool ls detail
    rbd pool init volumes_new
    ceph auth get-or-create client.cinder \
      mon 'profile rbd' \
      osd 'profile rbd pool=volumes_new, profile rbd pool=vms, profile rbd-read-only pool=images' \
      mgr 'profile rbd pool=volumes_new, profile rbd pool=vms'
    ceph auth get-or-create client.glance \
      mon 'profile rbd' \
      osd 'profile rbd pool=images' \
      mgr 'profile rbd pool=images'

    근본 원인은 늘 비슷합니다. 풀은 만들었는데 rbd pool init이 빠졌거나, client.cinder가 새 풀에 대한 cap을 갖고 있지 않거나, Glance와 Cinder 권한을 뭉뚱그려 잡아두는 식이죠. 이런 상태에선 볼륨 생성은 되는데 attach에서 실패하거나, 이미지 기반 볼륨 생성만 유독 실패하는 식으로 증상이 갈라집니다.

    5-3. 새 볼륨 타입 생성

    openstack volume type create ceph-rbd-new
    openstack volume type set --property volume_backend_name=rbd-new ceph-rbd-new
    openstack volume type show ceph-rbd-new
    openstack volume type list --long

    운영상 의미는 명확합니다. 신규 생성 경로를 먼저 새 백엔드로 돌리고, 기존 자산 이동은 그다음에 따로 한다는 거예요. 이 분리가 되면 실패했을 때 되돌리기도 쉬워집니다.

    6. OpenStack Ceph 마이그레이션 절차: 신규 유입과 기존 자산을 분리하세요

    실무 절차는 의외로 단순합니다. 대신 순서를 어기면 비용이 바로 커집니다.

    1. 새 백엔드를 등록하고 타입을 만든다: 아직 기존 타입은 그대로 둡니다.
    2. 신규 볼륨만 새 타입으로 생성하게 유도한다: 새 데이터 유입을 먼저 분리합니다.
    3. 테스트 프로젝트에서 생성, attach, detach, 삭제까지 한 사이클을 검증한다: 생성만 확인하면 부족합니다.
    4. 저위험 볼륨부터 정책 변경 또는 마이그레이션을 시작한다: 백업성 볼륨, 비핵심 업무부터 갑니다.
    5. Ceph 재배치 상태를 보며 배치를 늘린다: API 성공률이 아니라 클러스터 안정성을 기준으로 속도를 조절합니다.
    6. 기존 타입의 신규 생성을 막는다: 잔여 볼륨만 남기고 정리 단계로 들어갑니다.

    CLI는 환경에 따라 조금씩 다르게 씁니다. 현재 openstackclient에서는 볼륨 타입 변경을 openstack volume set --type로 수행할 수 있고, 일부 운영 환경은 여전히 cinder retype를 사용합니다. 핵심은 명령 이름보다 정책 변경이 실제 데이터 이동을 유발하는지를 테스트 볼륨으로 먼저 확인하는 겁니다.

    # 현재 openstackclient 계열에서 많이 쓰는 방식
    openstack volume set \
      --type ceph-rbd-new \
      --migration-policy on-demand \
      8f1f2f0d-1111-2222-3333-444444444444
    openstack volume show 8f1f2f0d-1111-2222-3333-444444444444
    
    # 환경에 따라 여전히 사용하는 cinder client 방식
    cinder retype \
      --migration-policy on-demand \
      8f1f2f0d-1111-2222-3333-444444444444 \
      ceph-rbd-new

    관리자가 목적지를 더 강하게 통제해야 한다면 백엔드 호스트를 직접 지정하는 방식도 씁니다.

    openstack volume migrate \
      --host host01@rbd-new#volumes_new \
      8f1f2f0d-1111-2222-3333-444444444444
    openstack volume show 8f1f2f0d-1111-2222-3333-444444444444 -f yaml

    저는 보통 이렇게 고릅니다. 볼륨 타입 정책까지 함께 정리하려면 retype 계열이 낫고, 특정 백엔드 호스트나 풀을 명시적으로 통제해야 하면 migrate가 더 직접적입니다. 다만 in-use 볼륨의 재타입은 마이그레이션이 동반되면 보통 관리자 권한이 필요하고, 암호화된 in-use 볼륨은 재타입 마이그레이션이 지원되지 않는 경우가 있습니다. 이런 케이스는 무리해서 실시간 전환하지 말고 점검창을 잡는 편이 더 안전합니다.

    OpenStack Ceph 마이그레이션 절차와 데이터 이동 흐름 이미지

    신규 생성 분리, 테스트 볼륨 이동, 운영 볼륨 확장 전환 순서를 보여주는 절차형 이미지입니다.

    7. OpenStack Ceph 마이그레이션에서 자주 부딪히는 실패 모드

    증상은 비슷해 보여도 원인은 다릅니다. 저는 아래 네 가지부터 먼저 자릅니다.

    7-1. 타입은 맞는데 스케줄링이 안 됩니다

    대부분은 volume_backend_name 불일치, 백엔드 서비스 비활성화, 드라이버 초기화 실패 셋 중 하나입니다.

    grep -E 'enabled_backends|volume_backend_name|rbd_pool|rbd_user' /etc/cinder/cinder.conf
    openstack volume service list
    journalctl -u openstack-cinder-scheduler -n 200 --no-pager
    journalctl -u openstack-cinder-volume -n 200 --no-pager

    배포판에 따라 systemd 유닛명은 다를 수 있으니 서비스 이름은 현 환경 기준으로 바꿔서 보시면 됩니다. 근본 원인은 흔히 두 가지예요. 첫째, 타입은 rbd-new를 보는데 실제 백엔드는 rbd_new처럼 다른 이름으로 등록된 경우. 둘째, 드라이버가 Ceph 인증 실패로 초기화되지 않았는데 운영자가 프로세스만 살아 있다고 착각하는 경우입니다.

    7-2. Ceph 인증 문제로 생성 또는 attach가 막힙니다

    이 경우는 생성 단계와 attach 단계의 증상이 달라서 더 헷갈립니다. 새 풀에 대한 cap이 없거나, Nova와 Cinder, Glance가 참조하는 사용자명과 시크릿, 키링 경로가 어긋나 있는 경우가 많습니다. 특히 Cinder가 볼륨을 만들 수 있는 권한과 Nova/libvirt가 그 볼륨을 실제로 매핑할 수 있는 권한은 완전히 같은 문제가 아닐 수 있습니다.

    7-3. 이동은 됐는데 체감 성능이 흔들립니다

    이건 마이그레이션 명령의 성공 여부보다 Ceph 내부 상태를 먼저 봐야 합니다. recovery, backfill, nearfull 경고가 길게 이어지면 배치를 줄이거나 윈도우를 다시 잡는 편이 맞습니다. 현장에서 자주 보는 패턴은 이렇습니다. 낮 시간대에 작은 볼륨 몇 개는 멀쩡해서 속도를 올렸는데, 저녁 배치에서 대용량 볼륨과 Ceph 재배치가 겹치며 지연이 튀는 거죠. 이거 진짜 자주 나옵니다.

    7-4. 소스 풀에 고아 이미지가 남습니다

    실패한 이동, 중단된 작업, 관리자의 수동 정리 이력 때문에 원본 풀에 RBD 이미지가 남을 수 있습니다. 그렇다고 바로 지우면 안 됩니다. 먼저 OpenStack DB가 가리키는 위치와 실제 풀 위치가 일치하는지 확인해야 합니다. 저는 최소 하루 이상 운영 검증을 둔 뒤 정리합니다.

    8. 검증은 보이는지보다 원하는 위치에서 실제로 쓰는지 봐야 합니다

    마이그레이션 후 검증은 세 겹으로 합니다. OpenStack 상태, Ceph 실체, 워크로드 체감입니다.

    1. 볼륨 메타데이터 확인: 타입, 상태, migration 관련 필드 확인
    2. 대상 풀의 실제 RBD 이미지 확인: 새 풀에 이미지가 생겼는지 확인
    3. attach 후 읽기/쓰기 확인: 실제 인스턴스에서 I/O 검증
    4. 소스 풀 잔존물 확인: 즉시 삭제하지 말고 정리 후보만 분리
    openstack volume show 8f1f2f0d-1111-2222-3333-444444444444
    rbd ls volumes_new
    rbd info volumes_new/volume-8f1f2f0d-1111-2222-3333-444444444444
    rbd ls volumes_old

    저는 운영 확인을 여기서 끝내지 않습니다. 인스턴스에 붙여 파일 생성, 재마운트, 재부팅 후 재연결까지 확인합니다. 볼륨이 새 풀에 존재하는 것과, 서비스가 그 볼륨을 문제없이 소비하는 것은 다른 검증이거든요. 여기까지 봐야 마음이 놓입니다.

    OpenStack Ceph 마이그레이션 완료 검증 대시보드 이미지

    볼륨 상태 확인, 대상 풀의 RBD 이미지 존재 여부, 운영 검증 체크리스트를 보여주는 결과 이미지입니다.

    9. 언제 Ceph 스토리지 전환을 고르고, 언제 병행 운영을 고를까

    현장 추천은 꽤 분명합니다.

    • 다운타임이 거의 없고 운영 안정성이 최우선이다: 기존 백엔드를 유지한 병행 운영 후, 새 타입으로 신규를 먼저 분리하고 기존은 점진적으로 옮기세요.
    • 목표가 스토리지 통합 운영과 볼륨 정책 세분화다: Ceph 백엔드를 붙이되, 처음 범위는 Cinder로 제한하세요.
    • 팀이 Ceph 장애 메시지와 재배치를 아직 익숙하게 다루지 못한다: 바로 전면 전환하지 말고 신규 볼륨만 새 백엔드로 보내며 운영 감각부터 쌓는 편이 낫습니다.
    • 이미 Ceph를 쓰고 있고 풀 구조만 재정비하고 싶다: 풀 직접 교체보다 새 백엔드와 새 타입을 따로 만들고 정책 전환으로 정리하는 편이 안전합니다.
    • Nova 에페메럴까지 한 번에 바꾸고 싶다: 말리고 싶습니다. Cinder 경로가 안정화된 뒤 별도 프로젝트로 다루는 편이 훨씬 덜 아픕니다.

    여러 번 겪어보면 결국 덜 아픈 방법은 비슷합니다. 새 백엔드를 먼저 붙이고, 신규 생성 경로를 갈라놓고, 기존 볼륨은 업무 중요도와 Ceph 상태를 보면서 천천히 옮기는 방식이죠. 빠른 전환보다 되돌릴 수 있는 전환이 훨씬 값집니다.

    FAQ

    Q. retype와 migrate 중 무엇을 먼저 고려하면 될까요?

    볼륨 타입 정책 자체를 바꾸는 게 목적이면 retype 계열이 더 자연스럽습니다. 특정 목적지 호스트와 풀을 명시적으로 통제해야 하면 migrate가 더 직접적입니다. 다만 둘 다 실제 데이터 복사 여부는 현재 배치와 드라이버 동작에 좌우되니, 테스트 볼륨 검증부터 해보는 게 맞습니다.

    Q. 기존 백엔드는 언제 제거하는 게 좋을까요?

    신규 생성이 완전히 차단되고, 잔여 볼륨과 소스 풀의 정리 후보가 분리되고, 운영 검증 기간을 지난 뒤가 적절합니다. 저는 최소 한 템포 두고 소스 풀을 정리합니다.

    Q. Ceph가 항상 정답인가요?

    아닙니다. Ceph의 장점은 기능 자체보다 운영 일관성에 있습니다. 팀이 그 일관성을 감당할 준비가 안 돼 있다면, Ceph 도입은 기술 선택이 아니라 운영 부채가 될 수도 있습니다.

    OpenStack Ceph 마이그레이션 결정 기준 요약 이미지

    어떤 상황에서 병행 운영, 점진 전환, 즉시 전환 중 무엇을 고를지 요약한 마무리 인포그래픽입니다.

  • [OpenStack] OpenStack 컨트롤러 노드 장애 진단 및 복구 전략

    [OpenStack] OpenStack 컨트롤러 노드 장애 진단 및 복구 전략

    OpenStack 컨트롤러 노드 장애 진단 및 복구 전략

    OpenStack 컨트롤러 노드 장애는 겉으로 보이는 증상보다 실제 원인이 한 단계 뒤에 숨어 있는 경우가 많습니다. Horizon이 멈췄다고 해서 Horizon만의 문제는 아니고, API 500 에러가 난다고 해서 무조건 Keystone이나 Nova API부터 재시작할 일도 아니더라고요. 제가 현장에서 가장 자주 봤던 패턴은 VIP는 살아 있는데 백엔드가 죽어 있는 경우, API 프로세스는 active인데 MQ나 DB 때문에 요청이 끝까지 처리되지 않는 경우, 그리고 클러스터는 떠 있으나 쿼럼이 깨져 상태 변경이나 쓰기가 막히는 경우였습니다. 그래서 OpenStack 컨트롤러 노드 장애는 서비스 이름보다 의존성의 방향으로 봐야 훨씬 빨리 풀립니다.

    운영 중이면 마음이 급해서 전체 재시작부터 누르기 쉽습니다. 그런데 그 한 번이 원인 추적 단서를 지워버리고, Galera나 RabbitMQ처럼 합류 상태가 중요한 구성요소는 오히려 더 꼬이게 만들 때가 많거든요. 제 경험상 복구 속도를 가장 크게 좌우하는 건 기술 스택 지식의 양보다, VIP → API 엔드포인트 → 인증 → MQ → DB → 스케줄링 순서로 범위를 줄이는 습관이었습니다. 이번 글은 그 순서를 기준으로, 실제 운영자가 바로 복붙해 확인할 수 있는 명령과 함께 OpenStack 복구 판단 기준을 정리한 버전입니다.

    컨트롤러 노드의 API, 메시지 큐, 데이터베이스, 가상 IP 흐름을 한눈에 보여주는 개요 이미지입니다.

    왜 OpenStack 컨트롤러 노드 장애가 까다로운가

    컨트롤러 노드는 단일 프로세스 집합이 아니라, 서로 실패를 전염시키는 제어면 묶음에 가깝습니다. 그래서 증상과 원인이 자주 어긋납니다. 예를 들어 사용자는 “로그인이 안 된다”고 말하지만 실제론 VIP가 다른 노드로 넘어가지 못한 경우가 있고, 운영자는 “Nova API가 죽었다”고 판단했는데 실제론 RabbitMQ 인증 불일치 때문에 scheduler와 conductor가 요청을 소비하지 못하는 경우도 있습니다. 이 차이를 빨리 읽어내는 게 OpenStack 디버깅의 핵심이더라고요.

    • API 계층: Apache HTTPD 또는 uWSGI 앞단은 떠 있어도 뒤쪽 WSGI 애플리케이션이 DB 세션 고갈, TLS 오류, 엔드포인트 오설정으로 실패할 수 있습니다.
    • 메시지 계층: RabbitMQ는 프로세스가 active여도 vhost 권한, DNS, Erlang cookie, 네트워크 분리 문제로 실질적인 메시지 전달이 끊길 수 있습니다.
    • 데이터 계층: Galera는 mysqld 프로세스가 떠 있다는 사실보다 Primary 쿼럼과 Synced 상태가 중요합니다. 여기서 어긋나면 조회 일부는 가능해 보여도 쓰기나 상태 변경이 막힐 수 있습니다.
    • 가상 IP 계층: Keepalived, HAProxy, Pacemaker는 각각 정상처럼 보여도 헬스체크 기준, 리소스 제약, fail count 누적으로 트래픽이 없는 노드로 붙어버릴 수 있습니다.

    이 구조에서 흔한 실수는 로그를 서비스별로 따로 읽는 겁니다. 실제로는 요청의 흐름으로 묶어 읽어야 합니다. 토큰 발급 실패면 Keystone 로그만 보는 게 아니라, Keystone이 의존하는 MariaDB 연결 오류와 HAProxy 백엔드 상태를 같이 봐야 합니다. 반대로 인스턴스 생성 실패라면 Nova API 로그만 보는 순간 반쯤 틀립니다. scheduler, conductor, RabbitMQ 연결, compute 서비스 heartbeat까지 같이 봐야 맞습니다.

    OpenStack 컨트롤러 노드 장애 복구 전에 정할 원칙

    OpenStack 복구는 “무엇을 고칠까”보다 “무엇을 아직 건드리지 말까”를 먼저 정하는 편이 안전합니다. 저는 장애가 나면 아래 다섯 가지부터 메모합니다. 이 습관이 생각보다 진짜 편하더라고요.

    1. 영향 범위 먼저 고정: 로그인만 실패하는지, 새 VM 생성만 안 되는지, 기존 VM 네트워크까지 영향이 있는지 적어둡니다. 복구 중 증상이 바뀌면 그 변화도 기록합니다.
    2. 단일 장애점 후보를 분리: VIP 문제, 인증 문제, MQ 문제, DB 쿼럼 문제를 한 바구니에 넣지 않습니다. 동시에 여러 계층을 건드리면 원인과 결과가 섞입니다.
    3. 재시작은 마지막 수단: 상태 확인 없이 systemctl restart를 반복하면, 장애 전 최초 오류 시점과 후속 오류가 뒤섞여 로그 해석이 더 어려워집니다.
    4. 클러스터는 프로세스가 아니라 합의 상태를 본다: Galera는 Primary, RabbitMQ는 노드 합류와 큐 소비 여부, Pacemaker는 리소스 위치와 fail count가 핵심입니다.
    5. 복구 완료 기준을 기능으로 잡는다: 프로세스 active는 통과선이 아니라 시작선입니다. 최소한 토큰 발급, 서비스 목록 조회, 테스트 생성 요청까지 확인해야 진짜 정상입니다.

    특히 HA 환경에서는 “한 대는 살아 있다”가 별 의미가 없을 때가 많습니다. VIP가 다른 노드에 남아 있거나, HAProxy가 헬스체크 기준 때문에 백엔드를 모두 제외한 상태라면 사용자는 전체 장애로 봅니다. 그래서 저는 컨트롤러 장애에서 먼저 리더를 찾는 게 아니라 현재 트래픽이 어디로 흘러야 하는지부터 확인합니다.

    실전 1단계: OpenStack 컨트롤러 노드 장애 범위 빠르게 좁히기

    처음 5분은 세부 원인보다 장애의 모양을 분류하는 시간입니다. Horizon만 안 열리는지, CLI도 안 되는지, 토큰은 발급되는데 특정 리소스 조회만 실패하는지 확인하면 절반은 끝납니다. 제가 자주 쓰는 1차 점검 묶음은 아래입니다.

    source admin-openrc
    
    openstack token issue
    openstack endpoint list
    openstack service list
    openstack compute service list
    openstack network agent list
    openstack hypervisor list

    여기서 해석 기준이 중요합니다.

    • openstack token issue 실패: Keystone 자체, Keystone DB 연결, Keystone 뒤단 VIP/TLS 문제를 먼저 의심합니다.
    • token issue는 성공하지만 compute service list 실패: Nova API 또는 Nova DB/MQ 경로를 좁혀봅니다.
    • CLI 전체가 타임아웃: VIP, HAProxy, 방화벽, DNS, 인증서 체인부터 봅니다.
    • 조회는 되는데 생성만 실패: 대체로 MQ, scheduler, conductor, compute heartbeat 쪽이 더 유력합니다.

    그다음엔 각 컨트롤러에서 서비스 상태를 넓게 훑되, “실패한 유닛 목록”과 “최근 30분 로그”를 같이 봅니다. active만 보면 놓치는 경우가 많아서요.

    sudo systemctl --failed
    sudo systemctl status apache2 httpd haproxy keepalived mariadb rabbitmq-server
    sudo journalctl -u haproxy -u keepalived -u mariadb -u rabbitmq-server --since "30 minutes ago"
    sudo journalctl -u openstack-keystone -u openstack-nova-api -u openstack-nova-scheduler -u openstack-nova-conductor -u neutron-server -u httpd --since "30 minutes ago"

    배포판별 차이도 미리 염두에 두는 게 좋습니다. Debian/Ubuntu 계열은 apache2, RHEL 계열은 httpd를 많이 씁니다. 패키지 방식에 따라 Keystone 서비스명이 다를 수 있고, WSGI 배치라면 개별 API 데몬보다 웹서버 로그가 먼저 단서를 줄 때도 있습니다. 이런 차이를 모르고 “서비스가 없다”고 오판하는 경우를 꽤 봤습니다.

    systemctl 상태와 OpenStack CLI 점검 명령이 터미널에 표시된 운영자 화면

    초기 장애 범위를 줄이기 위해 systemd 상태와 OpenStack CLI를 함께 점검하는 장면을 보여주는 이미지입니다.

    실전 2단계: VIP, HAProxy, Keepalived 또는 Pacemaker 확인

    컨트롤러가 2대 이상이면 API 장애처럼 보이는 이슈의 상당수가 사실은 진짜 API 장애가 아닙니다. VIP가 안 붙었거나, HAProxy가 헬스체크 실패로 백엔드를 전부 제외했거나, Pacemaker가 fail count 때문에 리소스 이동을 멈춘 경우가 더 실무적입니다. 제 판단 기준은 간단합니다. 토큰 발급도 안 되고 CLI가 아예 timeout이면 가장 먼저 L4/L7 진입점부터 본다입니다.

    Keepalived/HAProxy 조합을 쓰는 경우

    ip addr show
    sudo systemctl status keepalived haproxy
    sudo journalctl -u keepalived -u haproxy --since "20 minutes ago"
    echo "show stat" | sudo socat stdio /run/haproxy/admin.sock
    curl -sk https://VIP:5000/v3/
    curl -sk https://VIP:8774/

    여기서 보는 포인트는 세 가지입니다. 첫째, ip addr show로 VIP가 현재 노드에 실제로 붙었는지 확인합니다. 둘째, HAProxy admin socket의 show stat에서 프론트엔드는 열려 있지만 백엔드가 모두 DOWN인지 봅니다. 셋째, 단순 TCP 연결이 아니라 실제 API 경로에 curl을 때려 HTTP 응답 코드를 확인합니다. 401이 오면 인증 전 단계까지는 도달한 것이고, 503이면 백엔드 헬스체크나 라우팅 쪽을 더 의심해야 합니다.

    실무적으로는 HAProxy 헬스체크 정의가 너무 공격적일 때도 문제가 됩니다. 예를 들어 백엔드 프로세스는 살아 있는데 TLS 체인 오류나 리다이렉트 때문에 헬스체크가 실패하면, 사용자는 전체 장애처럼 보게 됩니다. 이럴 땐 애플리케이션을 고치기 전에 헬스체크가 무엇을 기준으로 down 판정을 내리는지부터 봐야 합니다.

    Pacemaker/Corosync 조합을 쓰는 경우

    sudo pcs status
    sudo pcs resource status
    sudo crm_mon -1
    sudo pcs resource failcount show
    sudo journalctl -u pacemaker -u corosync --since "30 minutes ago"

    Pacemaker 환경은 서비스 자체보다 정책이 장애처럼 보일 때가 많습니다. 리소스가 stop 상태인지, 특정 노드에 묶여 있는지, migration threshold를 넘어 fail count가 누적돼 더 이상 움직이지 않는지 확인해야 합니다. 제 경험상 이 구간은 서비스 지식보다 Pacemaker 제약 해석 능력이 복구 시간을 더 크게 좌우합니다. 그래서 운영 인원이 적거나 교대 근무가 잦은 팀이라면, 기능적으로 더 유연하더라도 복잡한 리소스 제약은 줄이는 편이 낫습니다.

    실전 3단계: MariaDB/Galera와 RabbitMQ를 분리해서 본다

    API 500 에러, 요청 지연, 일부 기능 실패는 DB와 MQ가 비슷한 얼굴로 나타납니다. 그래서 둘을 한꺼번에 “백엔드 문제”라고 묶으면 복구가 느려집니다. 제 방식은 이렇습니다. 인증과 조회 중심이면 DB를 먼저, 생성과 비동기 후속 작업이면 MQ를 먼저 봅니다. 물론 둘 다 봐야 하지만, 시작점은 달라야 합니다.

    MariaDB/Galera 확인 포인트

    sudo mysql -e "SHOW GLOBAL STATUS LIKE 'wsrep_cluster_size';"
    sudo mysql -e "SHOW GLOBAL STATUS LIKE 'wsrep_cluster_status';"
    sudo mysql -e "SHOW GLOBAL STATUS LIKE 'wsrep_local_state_comment';"
    sudo mysql -e "SHOW GLOBAL STATUS LIKE 'wsrep_ready';"
    sudo mysql -e "SHOW VARIABLES LIKE 'read_only';"
    sudo mysql -e "SHOW DATABASES;"

    판단 기준은 숫자보다 상태 문자열입니다.

    • wsrep_cluster_status=Primary가 아니면 일단 정상 쿼럼이 아닙니다. 프로세스가 살아 있어도 트랜잭션 경로는 신뢰하기 어렵습니다.
    • wsrep_local_state_comment=Synced가 아니면 노드가 합류 중이거나 분리된 상태일 수 있습니다.
    • wsrep_ready=ON이 아니면 노드가 애플리케이션 질의를 정상 처리하지 못할 가능성이 큽니다.
    • read_only=ON이거나 애플리케이션 쓰기만 실패하면, 클러스터 분할 또는 보호 모드 전환을 의심해야 합니다.
    • SHOW DATABASES;는 단순 접속 확인용일 뿐이고, 실제 장애 판단은 wsrep 상태와 쓰기 가능 여부로 해야 합니다.

    Galera에서 특히 위험한 순간은 “한 노드는 살아 보이는데 어느 노드가 마지막 정상 상태였는지 확신이 없을 때”입니다. 이때 성급하게 부트스트랩하면 데이터 최신성이 더 중요한 노드를 버리고 오래된 상태를 기준으로 클러스터를 다시 세울 수 있습니다. 그래서 강제 복구는 서비스 복구 명령이 아니라 데이터 기준점 선정 작업으로 봐야 합니다. 이 구분이 없으면 장애는 끝났는데 데이터 정합성 이슈가 남습니다.

    RabbitMQ 확인 포인트

    sudo rabbitmqctl cluster_status
    sudo rabbitmqctl list_queues name messages consumers durable
    sudo rabbitmqctl list_connections pid peer_host peer_port state user vhost
    sudo rabbitmqctl list_users
    sudo rabbitmqctl list_permissions --vhost /
    sudo journalctl -u rabbitmq-server --since "30 minutes ago"

    RabbitMQ는 “프로세스가 떠 있다”보다 “OpenStack 서비스가 올바른 계정과 vhost로 실제 연결 중인가”가 핵심입니다. 제가 많이 본 실패 모드는 아래와 같습니다.

    • 비밀번호 변경 후 부분 반영: 일부 컨트롤러만 새 transport_url을 쓰고 나머지는 예전 값이라, 특정 서비스만 간헐적으로 실패합니다.
    • 권한 불일치: 사용자는 존재하지만 vhost permission이 맞지 않아 연결은 되는데 소비가 안 되거나 채널 생성이 실패합니다.
    • DNS/호스트명 문제: RabbitMQ 노드 간 이름 해석이 어긋나 클러스터 합류가 불안정합니다.
    • Erlang cookie 불일치: 노드 프로세스는 살아 있으나 클러스터 멤버십이 정상 구성되지 않습니다.

    list_queues에서 메시지가 계속 쌓이고 소비자가 0에 가깝다면, 그 큐를 읽어야 할 서비스가 죽었거나 인증 문제로 붙지 못하는 경우가 유력합니다. 반대로 연결 수는 많은데 처리량이 안 나오는 상황은 DB 지연, API worker 부족, backend timeout까지 함께 봐야 합니다. 즉 RabbitMQ가 범인인지, RabbitMQ가 병목을 드러내는 거울인지를 구분해야 합니다.

    Galera 상태와 RabbitMQ 클러스터 상태를 나란히 비교하는 운영 대시보드 스타일 이미지

    데이터베이스 쿼럼과 메시지 큐 상태를 함께 확인해야 하는 이유를 보여주는 비교 이미지입니다.

    재현 가능한 실제 시나리오: API는 살아 보이는데 인스턴스 생성이 실패할 때

    이 패턴은 문서보다 현장에서 더 자주 나옵니다. Horizon 로그인은 되고 openstack token issue도 성공합니다. openstack server list도 됩니다. 그런데 openstack server create만 실패하거나, 요청이 accepted로 보였다가 일정 시간이 지나 ERROR로 떨어집니다. 이럴 때 저는 Nova API를 바로 재시작하지 않고, 요청이 메시지 큐를 타고 scheduler와 conductor로 이어지는 경로를 따라갑니다.

    1. 사용자가 VM 생성 요청을 보냅니다.
    2. Keystone 인증은 통과합니다.
    3. Nova API는 요청을 받아 DB와 MQ에 후속 작업을 남깁니다.
    4. scheduler 또는 conductor가 MQ 연결 문제, 권한 문제, 이름 해석 문제로 작업을 소비하지 못합니다.
    5. 사용자 입장에서는 “API는 사는데 생성만 안 되는 이상한 장애”로 보입니다.

    이 시나리오에서 제가 먼저 보는 명령은 아래입니다.

    source admin-openrc
    openstack server create --flavor m1.small --image TEST_IMAGE --network TEST_NET diag-test-vm
    openstack server event list diag-test-vm
    sudo journalctl -u openstack-nova-api -u openstack-nova-scheduler -u openstack-nova-conductor --since "15 minutes ago"
    sudo grep -R "transport_url\|rabbit" /etc/nova/
    sudo rabbitmqctl list_users
    sudo rabbitmqctl list_permissions --vhost /

    여기서 핵심은 실패 메시지 자체보다 어느 단계에서 멈췄는지입니다. API가 요청을 접수했는데 scheduler 로그가 비어 있으면 MQ 전달 경로를 의심하고, scheduler는 받았는데 conductor가 후속 작업을 못 하면 DB 또는 내부 RPC를 더 봅니다. transport_url은 특히 꼼꼼히 대조해야 합니다. 사용자명, 비밀번호, 호스트, 포트, vhost 중 하나만 틀려도 장애가 “간헐적”으로 보일 수 있습니다. 여러 컨트롤러 노드에서 설정 파일 버전이 미묘하게 다른 경우가 실제론 꽤 많습니다.

    다만 환경에 따라 openstack server event list 조회가 정책이나 권한 설정의 영향을 받을 수 있으니, 이벤트 조회가 막혀 있으면 Nova API와 scheduler 로그를 우선 기준으로 잡는 편이 안전합니다.

    선택 기준: 어떤 컨트롤러 노드 HA 구성이 복구에 유리한가

    컨트롤러 노드 HA는 기술적으로 더 많은 기능을 가진 구성이 항상 더 낫지는 않습니다. 제가 운영 관점에서 따지는 기준은 세 가지입니다. 새벽에 누가 복구하나, 리소스 이동 정책을 팀이 실제로 이해하나, 장애 원인을 10분 안에 좁힐 수 있나입니다. 그 기준으로 보면 선택은 꽤 선명해집니다.

    구성 방식 복구에 유리한 점 위험한 실패 모드 이럴 때 추천
    HAProxy + Keepalived 구조가 단순해 VIP와 백엔드 상태를 빠르게 추적하기 쉽습니다. 애플리케이션 리소스 자체의 정교한 제약 제어는 약합니다. 헬스체크 정의가 부정확하면 정상 서비스도 제외될 수 있습니다. 소규모 팀, 홈랩, 운영 인수인계가 잦은 환경
    Pacemaker + Corosync + HAProxy 리소스 이동 정책, 우선순위, 장애 전환 조건을 세밀하게 통제할 수 있습니다. fail count, constraint, stickiness 해석이 어렵습니다. 서비스는 정상인데 정책 때문에 복구가 지연될 수 있습니다. 엄격한 HA 정책이 필요하고, 클러스터 운영 숙련도가 팀 내에 확보된 환경
    단일 컨트롤러 + 정기 백업 원인 추적이 가장 단순하고 구성 관리 비용이 낮습니다. 컨트롤러 장애 시 제어면 중단을 감수해야 합니다. 복구 시간은 백업/복원 절차 숙련도에 좌우됩니다. 학습용, 비핵심 서비스, 짧은 중단을 허용할 수 있는 환경

    제 추천은 명확합니다. 운영 인원이 적고 장애 대응 절차가 아직 정교하지 않다면 단순한 HA 구성이 더 낫습니다. 반대로 리소스 제어 정책이 서비스 품질에 직접 연결되고, 팀이 Pacemaker 상태 해석에 익숙하다면 그때 복잡한 구성이 제값을 합니다. 기능이 아니라 복구 가능성을 기준으로 고르셔야 합니다.

    ⚠️ OpenStack 컨트롤러 노드 장애에서 자주 만나는 트러블슈팅 포인트

    • 시간 동기화 문제: 토큰 유효성 오류, TLS 검증 문제, 클러스터 노드 간 이상 동작이 전부 시간 어긋남에서 시작될 수 있습니다. timedatectl, chronyc sources -v, chronyc tracking을 같이 보세요.
    • 이름 해석 문제: VIP, 컨트롤러 FQDN, RabbitMQ 노드명 중 하나라도 서로 다르게 풀리면 MQ 클러스터, API endpoint, 인증서 검증이 동시에 흔들립니다.
    • TLS 인증서 만료 또는 CN/SAN 불일치: 프로세스는 모두 active인데 HTTPS 호출만 실패하는 전형적인 패턴입니다. 단순 ping보다 실제 핸드셰이크 확인이 낫습니다.
    • 부분 재시작의 함정: DB/MQ가 불안정한 상태에서 API만 재시작하면 재시도 로그만 늘고, 최초 오류 원인이 뒤로 묻힙니다.
    • 쿼럼 없는 강제 복구: Galera 부트스트랩은 마지막 정상 노드 기준이 불명확하면 데이터 정합성 리스크가 생깁니다.

    이 항목들은 사소해 보여도 현장에선 매우 자주 원인입니다. 특히 이름 해석과 시간 동기화는 “인프라는 멀쩡해 보이는데 왜 OpenStack만 이상하지?” 같은 상황을 만들어서 더 헷갈립니다. 그래서 저는 컨트롤러 장애 초기에 아래 묶음을 자주 함께 확인합니다.

    timedatectl
    chronyc sources -v
    chronyc tracking
    getent hosts controller-1 controller-2 controller-3
    getent hosts VIP_FQDN
    hostname -f
    openssl s_client -connect VIP:5000 -servername VIP_FQDN </dev/null

    여기서 인증서 출력은 길지만, 현장에선 세 가지만 봐도 충분할 때가 많습니다. 인증서 만료 여부, 요청한 서버 이름과 SAN 일치 여부, 체인 검증이 중간에서 끊기는지입니다. 애플리케이션 로그에서 SSL 오류만 보고 끝내면, 실제론 LB 앞단 인증서 배치 문제를 놓칠 수 있습니다.

    검증: 복구 후 무엇을 확인해야 하나

    복구는 서비스 프로세스가 올라온 시점이 아니라, 운영자가 다시 제어권을 회복한 시점에 끝납니다. 그래서 저는 확인 순서를 일부러 기능 기준으로 짭니다. 인증, 조회, 생성, HA 상태 재검증 순서입니다.

    1. openstack token issue 성공 여부
    2. openstack service list와 주요 에이전트 조회
    3. 네트워크, 이미지, 플레이버 목록 조회
    4. 테스트 포트 또는 테스트 인스턴스 생성 요청
    5. 기존 인스턴스의 콘솔, 볼륨, 네트워크 연결 상태 점검
    6. VIP, HAProxy 백엔드, Galera, RabbitMQ 클러스터 상태 재확인
    source admin-openrc
    
    openstack token issue
    openstack network list
    openstack image list
    openstack flavor list
    openstack server list
    openstack hypervisor list
    openstack compute service list
    openstack network agent list

    판단은 이렇게 하시면 됩니다. 인증은 되는데 특정 목록만 실패하면 그 서비스 API 또는 그 뒤단 백엔드가 아직 덜 복구된 겁니다. 조회는 되는데 생성이 안 되면 MQ, scheduler, compute 연동을 더 봐야 합니다. 그리고 정말 중요한 부분이 하나 더 있습니다. 복구 직후 5분만 보는 건 부족합니다. 큐 적체가 늦게 풀리거나, Galera가 재합류 후 상태가 흔들리는 경우가 있어서 최소한 짧은 관찰 구간은 두는 편이 안전합니다.

    복구 완료 후 OpenStack 서비스 목록과 정상 상태 체크리스트를 보여주는 검증 화면

    복구 후 단순 프로세스 상태가 아니라 실제 OpenStack 기능이 정상인지 검증하는 장면을 표현한 이미지입니다.

    정리 겸 FAQ: 현장에서 바로 결정하는 기준

    Q. OpenStack 컨트롤러 노드 장애가 났을 때 가장 먼저 뭘 봐야 하나요?

    A. 사용자 영향 범위와 VIP 진입점입니다. CLI와 Horizon이 같이 죽었다면 네트워크, VIP, HAProxy부터 보는 게 빠릅니다. 반대로 로그인은 되는데 특정 기능만 실패하면, 그 API 뒤의 MQ나 DB 의존성을 먼저 좁히는 편이 맞습니다.

    Q. 모든 서비스를 재시작하면 빨리 해결되지 않나요?

    A. 대체로 아닙니다. 특히 Galera와 RabbitMQ는 “살아났다”보다 “정상 합류했다”가 중요합니다. 합류 상태 확인 없이 재시작을 반복하면 원인도 흐려지고 복구 범위도 넓어질 수 있습니다.

    Q. 어떤 구조를 추천하나요?

    A. 결론은 분명합니다. 운영 난이도를 낮춰야 하는 환경이면 HAProxy + Keepalived가 더 낫고, 정교한 리소스 제어와 명확한 운영 절차가 이미 있는 팀이면 Pacemaker 기반 HA가 맞습니다. 홈랩이나 비핵심 서비스라면 단일 컨트롤러와 검증된 백업 절차가 오히려 더 현실적일 수 있습니다.

    현장에서 제일 빨리 통하는 한 문장을 남기면 이겁니다. OpenStack 컨트롤러 노드 장애는 서비스 이름 순서가 아니라 의존성 순서로 봐야 빨리 끝납니다. CLI 전체가 죽었으면 VIP와 LB부터, 인증만 안 되면 Keystone과 DB부터, 생성만 안 되면 Nova와 RabbitMQ부터 보세요. 그리고 운영 인원이 적다면 복잡한 HA보다 설명 가능한 HA가 더 안전합니다. 밤 2시에 문서 없이도 복구할 수 있는 구조가 결국 가장 좋은 구조더라고요.

    비슷한 운영 글을 계속 쓰신다면 Keystone 장애, RabbitMQ 권한 오류, Galera 쿼럼 복구 절차를 각각 내부 링크로 분리해 두는 것도 추천드립니다. 이런 묶음 글이 검색 유입도 잘 받고, 나중에 팀 온보딩할 때도 꽤 유용합니다.

    단순 구성과 고급 HA 구성의 선택 기준을 요약한 인포그래픽

    운영 규모에 따라 어떤 복구 전략과 HA 구성을 선택하면 좋은지 요약한 마무리 이미지입니다.

  • [OpenStack] OpenStack 환경에서 프로젝트 테넌트 마이그레이션 성공 사례

    [OpenStack] OpenStack 환경에서 프로젝트 테넌트 마이그레이션 성공 사례

    [OpenStack] OpenStack 환경에서 프로젝트 테넌트 마이그레이션 성공 사례

    OpenStack 테넌트 마이그레이션은 이름만 보면 프로젝트 소유자만 바꾸는 일처럼 들리지만, 실제 운영에서는 그렇게 움직이지 않습니다. 제가 현장에서 여러 번 겪어보니 이 작업의 본질은 프로젝트를 옮기는 것이 아니라, Nova, Neutron, Cinder, Keystone에 흩어진 소유권과 의존 관계를 안전하게 다시 조립하는 것이었습니다. 같은 서버라도 image-backed인지 volume-backed인지에 따라 절차가 갈리고, 포트 하나에 allowed address pairs가 묶여 있으면 네트워크 검증 포인트가 완전히 달라지죠.

    이번 글은 이론 설명보다 제가 실제로 운영/테스트 환경에서 실패를 줄이기 위해 어떤 판단 순서로 움직였는지에 초점을 맞췄습니다. 핵심은 세 가지였습니다. 첫째, DB 직접 수정으로 project_id를 바꾸지 않는다. 둘째, 리소스 존재 확인과 서비스 정상 확인을 분리한다. 셋째, 서버 단위가 아니라 종속성 단위로 이전 계획을 짠다. 이 기준만 잡아도 OpenStack 이전 작업의 절반은 정리됩니다.

    기존 프로젝트에서 새 프로젝트로 컴퓨트, 네트워크, 스토리지, 권한이 어떻게 이동하는지 보여주는 개요 이미지입니다.

    1. 왜 프로젝트 테넌트 마이그레이션이 생각보다 어렵나

    실무에서 어려운 이유는 단순합니다. 프로젝트라는 이름 아래에 있는 리소스들이 한 시스템에서 일관되게 관리되지 않기 때문입니다. Nova는 서버와 attach 정보를 보고, Neutron은 포트와 보안 그룹, 라우터를 보고, Cinder는 볼륨 상태와 transfer 가능 여부를 따로 판단합니다. 그래서 화면상으로는 하나의 프로젝트처럼 보여도, 이전할 때는 서비스별 제약을 따로 통과해야 합니다.

    • 인스턴스는 생성 시점의 flavor, image, port, volume 연결 정보를 함께 봐야 합니다.
    • 포트는 fixed IP, security group, allowed address pairs, binding 정보가 남아 있으면 단순 재생성으로 끝나지 않습니다.
    • 볼륨은 in-use, available, snapshot 종속 여부에 따라 transfer 가능 조건이 갈립니다.
    • 권한은 사용자 추가만으로 끝나지 않고 role assignment와 quota가 실제 동작 조건을 결정합니다.

    운영자가 많이 빠지는 함정은 여기입니다. “서버 목록이 보이니 다 옮길 수 있겠지”라고 생각하는 순간, 이미 계획이 서버 중심으로 기울어집니다. 하지만 실제 장애는 대부분 서버가 아니라 부팅 디스크, 추가 볼륨, 플로팅 IP, 포트 정책에서 터지곤 합니다. 제가 지금은 항상 먼저 묻는 질문도 이것뿐입니다. “이 서버는 무엇에 기대어 살아 있나?” 이걸 안 보고 진행하면, 마지막 검증에서 접속 불가나 데이터 불일치로 반드시 돌아오더라고요.

    2. OpenStack 테넌트와 프로젝트 개념, 헷갈리면 여기서 정리

    문서나 팀 대화에서 Tenant와 Project가 섞여 나오는 건 흔합니다. 다만 OpenStack 테넌트 마이그레이션 문서에서는 표현을 통일해야 작업 범위가 흐려지지 않습니다. 저는 실무 문서에서 무조건 old project / new project로 적습니다. 그래야 권한 이전인지, 리소스 재배치인지, 네트워크 재설계인지 문장만 봐도 구분이 됩니다.

    용어 실무 의미 마이그레이션 문서에서의 해석 제가 권장하는 표기
    Tenant 구버전 문서나 오래된 운영 습관에서 쓰는 격리 단위 대부분 Project와 같은 뜻으로 소비됨 Project로 통일
    Project 리소스, 사용자, quota의 실제 소유 경계 이전 대상의 기준 단위 Project
    Domain 프로젝트와 사용자 집합을 묶는 상위 경계 동일 도메인 내 이동인지, 도메인 간 분리인지 먼저 구분해야 함 Domain

    이 구분이 중요한 이유는 명확합니다. 같은 프로젝트 이전이라고 해도, 동일 Domain 안에서 새 Project를 만드는 경우와 도메인 분리까지 포함되는 경우는 사용자 재할당과 인증 정책 검토 범위가 달라집니다. 저는 작업 요청서가 들어오면 가장 먼저 domain_id를 확인해요. 이유는 간단합니다. 프로젝트만 옮기는 줄 알았는데 실제론 사용자 소속 재설계까지 포함된 경우가 생각보다 많기 때문이죠.

    3. OpenStack 이전 마이그레이션 전 체크리스트: 여기서 반은 끝납니다

    제 경험상 성공률을 가르는 건 복사 명령이 아니라 사전 인벤토리의 밀도입니다. 단순 목록 추출이 아니라, 서버별로 어떤 볼륨이 붙어 있고 어떤 포트를 쓰는지, 그 포트에 어떤 보안 그룹과 IP가 걸려 있는지까지 묶어서 봐야 합니다. 저는 서버를 기준으로 보지 않고 서비스 단위 묶음으로 봅니다. 예를 들면 “웹 2대 + 공통 SG + 외부 FIP 1개 + DB 볼륨 2개”처럼요. 이렇게 봐야 컷오버 시점에 빠지는 자원이 줄어듭니다.

    아래 명령은 제가 실제로 가장 먼저 실행하는 인벤토리 묶음입니다. 중요한 건 결과를 그냥 보는 게 아니라 파일로 남겨서 old project와 new project를 나란히 비교하는 겁니다.

    # 기본 컨텍스트 확인
    openstack token issue
    openstack project show OLD_PROJECT -f yaml
    openstack quota show OLD_PROJECT -f yaml
    
    # 컴퓨트 / 스토리지 / 네트워크 인벤토리
    openstack server list --project OLD_PROJECT --long -f yaml
    openstack volume list --project OLD_PROJECT -f yaml
    openstack volume snapshot list --project OLD_PROJECT -f yaml
    openstack port list --project OLD_PROJECT -f yaml
    openstack router list --project OLD_PROJECT -f yaml
    openstack floating ip list --project OLD_PROJECT -f yaml
    openstack security group list --project OLD_PROJECT -f yaml
    openstack role assignment list --project OLD_PROJECT --names -f yaml

    여기서 제가 꼭 확인하는 항목은 아래입니다.

    • 서버가 image-backed인지 volume-backed인지
    • 루트 디스크 외에 추가 데이터 볼륨이 있는지
    • 포트에 고정 IP, allowed address pairs, custom DNS name이 있는지
    • 보안 그룹이 이름만 같은 기본 그룹인지, 룰이 커스텀인지
    • 플로팅 IP를 그대로 재사용해야 하는지, DNS 전환으로 대체 가능한지
    • quota가 현재 사용량보다 낮아 새 프로젝트에서 생성 실패가 날 여지가 있는지

    운영에서 자주 놓치는 것도 거의 정해져 있습니다. 추가 NIC, 부팅 볼륨 여부, 라우터 외부 게이트웨이, 모니터링 에이전트 재등록입니다. Horizon 화면만 보고 체크하면 빠지고, CLI로만 봐도 관계성이 안 보일 때가 있어요. 저는 그래서 서버 한 대를 샘플로 골라 server show, port show, volume show를 연결해서 한 번 끝까지 추적합니다. 이 한 대에서 구조를 파악하면 나머지 서버군도 비슷한 패턴으로 묶입니다.

    # 샘플 서버 1대의 의존성 추적
    openstack server show VM01 -f yaml
    openstack server volume list VM01 -f yaml
    openstack port list --server VM01 -f yaml
    
    # 특정 포트 상세
    openstack port show PORT_ID -f yaml
    
    # 특정 볼륨 상세
    openstack volume show VOLUME_ID -f yaml

    이 단계에서 제 판단 기준은 분명합니다. 구조를 설명할 수 없으면 마이그레이션을 시작하지 않습니다. 나중에 문제가 생겼을 때 복구도 결국 구조를 이해한 사람만 할 수 있기 때문입니다.

    4. 제가 선택한 방식: “새 프로젝트 생성 후 자원 재구성”

    제가 운영 환경에서 가장 안정적으로 가져간 방식은 늘 비슷했습니다. 새 프로젝트를 생성하고, 권한과 quota를 먼저 맞춘 뒤, 리소스를 서비스별 지원 절차로 옮긴다. 작업량은 확실히 많습니다. 대신 롤백 지점이 명확하고, 감사 대응 문서가 남고, 중간 실패가 나도 어느 레이어에서 멈췄는지 추적하기 쉽습니다.

    방식 언제 적합한가 장점 치명적인 주의점 제 추천도
    새 프로젝트 생성 후 재구성 운영 환경, 권한 분리 목적, 감사 이력 필요 추적 가능, 롤백 경계 명확, 서비스별 검증이 쉬움 사전 인벤토리와 절차 문서가 허술하면 작업량만 늘어남 가장 권장
    이미지 snapshot 기반 재배포 stateless 서버, 테스트/개발 환경, 빠른 재생성 목적 절차가 단순하고 병렬 처리하기 좋음 애플리케이션 일관성 보장이 약함, 데이터 디스크 별도 처리 필요 조건부 권장
    볼륨 transfer 중심 이전 volume-backed 서버, 데이터 보존 우선, 부팅 디스크 포함 이전 디스크 데이터 보존에 유리 detach 불가, snapshot 종속, 다운타임 조율이 핵심 데이터 서버에 권장
    DB 직접 수정 사실상 권장하지 않음 겉보기에는 빠름 지원 범위 밖, 참조 불일치 시 장애 분석이 극도로 어려움 비권장

    제가 이 방식으로 굳어진 이유는 장애 처리 때문입니다. 문제는 항상 이전 도중이 아니라 이전 직후 첫 장애에서 드러나거든요. 그때 중요한 건 “어떻게 옮겼는가”를 설명할 수 있는가입니다. 새 프로젝트 재구성 방식은 이 질문에 답하기 쉽습니다. 반대로 편법은 옮기는 순간은 빨라도, 장애 원인이 리소스 참조 꼬임인지 애플리케이션 문제인지 분리하기가 어렵습니다.

    5. 실전 구현: 단계별 OpenStack 이전 절차

    5-1. 신규 프로젝트와 권한 준비

    저는 프로젝트를 만든 직후 바로 사용자부터 붙이지 않습니다. 먼저 quota를 설계합니다. 이유는 단순합니다. 권한을 준 다음 사용자가 접속해 리소스를 만들기 시작하면, 중간에 quota 수정이 운영 이슈로 변하기 때문입니다. 특히 ports, gigabytes, security-group-rules는 자주 빠집니다.

    # 신규 프로젝트 생성
    openstack project create NEW_PROJECT
    
    # 현재 사용량을 보고 quota를 맞춤
    openstack quota show OLD_PROJECT -f yaml
    
    # 예시: 인스턴스/코어/RAM/볼륨/용량/포트 기준으로 선반영
    openstack quota set \
      --instances 20 \
      --cores 40 \
      --ram 102400 \
      --volumes 20 \
      --gigabytes 2048 \
      --ports 100 \
      --security-groups 20 \
      --secgroup-rules 200 \
      NEW_PROJECT
    
    # 사용자 및 관리자 역할 부여
    openstack role assignment create --user USER_NAME --project NEW_PROJECT member
    openstack role assignment create --user ADMIN_USER --project NEW_PROJECT admin
    
    # 결과 재확인
    openstack role assignment list --project NEW_PROJECT --names -f yaml
    openstack quota show NEW_PROJECT -f yaml

    여기서 제 기준은 간단합니다. 기존 사용량보다 같거나 높게 잡되, 무작정 크게 주진 않습니다. 운영팀이 나중에 프로젝트 격리 정책을 유지하려면 새 프로젝트 quota도 결국 **프로젝트 관리**의 중요한 대상이 되거든요. 특히 old project가 이미 quota 한계 근처까지 써온 상태라면, OpenStack 이전 전에 먼저 증설 승인 절차를 붙이는 편이 낫습니다. 새 프로젝트에서 서버 생성이 중간에 막히면 마이그레이션 창이 길어지기 마련이죠.

    5-2. 보안 그룹과 네트워크 설계 복제

    네트워크는 “같이 보이게 만드는 것”과 “같이 동작하게 만드는 것”이 다릅니다. 저는 기존 설정을 그대로 베끼기보다, 실제 통신에 필요한 정책만 재생성하는 방식을 선호합니다. 이유는 오래된 프로젝트일수록 쓰지 않는 보안 그룹 룰이 쌓여 있고, 그 쓰레기 규칙까지 같이 복제하면 새 프로젝트의 위험 면적도 그대로 옮겨가기 때문입니다.

    # 기존 보안 그룹과 룰 확인
    openstack security group list --project OLD_PROJECT -f yaml
    openstack security group rule list SECURITY_GROUP_ID -f yaml
    
    # 신규 프로젝트에 보안 그룹 생성
    openstack security group create --project NEW_PROJECT web-sg
    openstack security group create --project NEW_PROJECT app-sg
    
    # 인바운드 규칙 예시
    openstack security group rule create --protocol tcp --dst-port 22 web-sg
    openstack security group rule create --protocol tcp --dst-port 80 web-sg
    openstack security group rule create --protocol tcp --dst-port 443 web-sg
    
    # remote group 참조 예시
    openstack security group rule create \
      --protocol tcp \
      --dst-port 8080 \
      --remote-group app-sg \
      web-sg

    여기서 흔한 실수는 --dst-port만 보고 규칙을 복사하는 겁니다. 실제로는 아래 항목까지 같이 봐야 합니다.

    • remote_ip_prefix가 특정 관리망만 허용하는지
    • remote_group_id로 내부 애플리케이션 간 통신을 열어뒀는지
    • IPv4만 있는지, IPv6 규칙도 필요한지
    • default security group에 기대는 통신이 있었는지

    네트워크 재구성에서 제 원칙은 이렇습니다. 같은 이름을 만드는 게 목적이 아니라 같은 패킷 흐름을 재현하는 게 목적입니다. 그래서 저는 이전 후 검증 항목도 “보안 그룹이 붙었는가”가 아니라 “애플리케이션 포트가 실제로 열렸는가”로 잡습니다.

    보안 그룹과 네트워크 재구성 흐름 다이어그램

    기존 프로젝트의 네트워크 정책을 새 프로젝트에 재구성하는 과정과 주요 확인 포인트를 보여주는 이미지입니다.

    5-3. 인스턴스 이전: 이미지 기반인지 볼륨 기반인지 먼저 구분

    여기서부터는 작업 방식이 분기됩니다. 저는 서버를 볼 때 이름보다 먼저 루트 디스크 타입을 봅니다. 이유는 이전 시간, 다운타임, 데이터 일관성, 검증 방식이 모두 여기서 달라지기 때문입니다.

    • 이미지 기반(image-backed): 무상태 웹 서버, 배치 서버처럼 재생성이 쉬운 경우에 적합합니다.
    • 볼륨 기반(volume-backed): 데이터가 붙어 있거나 루트 디스크 자체를 보존해야 하는 경우에 적합합니다.

    이미지 기반이라면 절차는 비교적 단순합니다. 다만 저는 스냅샷 전에 최소한 서비스 쓰기 작업을 멈추거나, 애플리케이션 레벨 flush 시점을 맞춥니다. 이유는 OpenStack 스냅샷이 애플리케이션 일관성까지 보장해 주는 건 아니기 때문입니다.

    # 기존 프로젝트에서 서버 스냅샷 생성
    openstack server image create --name vm01-migrate-snap VM01
    
    # 이미지 확인
    openstack image list --private -f yaml
    openstack image show vm01-migrate-snap -f yaml
    
    # 새 프로젝트에서 인스턴스 재생성
    openstack server create \
      --flavor m1.medium \
      --image vm01-migrate-snap \
      --network PRIVATE_NET \
      --security-group web-sg \
      vm01-new
    
    # 부팅 후 상태 확인
    openstack server show vm01-new -f yaml

    하지만 stateful 서버는 다르게 접근합니다. DB, 큐, 파일 업로드 서버 같은 워크로드는 OS가 뜨는지보다 애플리케이션 데이터가 일관되게 살아 있는지가 더 중요합니다. 이런 경우 저는 이미지 기반을 우선순위에서 내리고, 볼륨 중심 이전이나 애플리케이션 레벨 백업/복원을 우선 검토합니다. 실제로 서버는 잘 떠도 DB recovery가 길어지거나 서비스가 dirty state로 시작되는 경우가 더 까다로웠습니다.

    5-4. Cinder 볼륨 이전: transfer 기능 활용

    Cinder transfer는 제대로 쓰면 깔끔합니다. 대신 조건을 만족해야 합니다. 제가 현장에서 가장 많이 본 실패는 detach가 끝나지 않았는데 운영자가 다음 단계로 넘어가는 경우였습니다. CLI 출력은 금방 끝난 것처럼 보여도, 백엔드 스토리지 반영이 늦으면 attachments가 남아 있는 상태가 있습니다. 저는 이럴 때 절대 감으로 넘기지 않고 volume show를 기준으로 판단합니다.

    # 1) 인스턴스에서 볼륨 분리
    openstack server remove volume VM01 DATA_VOLUME
    
    # 2) 상태 확인: status=available, attachments=[] 이어야 다음 단계 진행
    openstack volume show DATA_VOLUME -f yaml
    
    # 3) transfer request 생성
    openstack volume transfer request create DATA_VOLUME -f yaml
    
    # 4) 출력값에서 id와 auth_key 확보 후 새 프로젝트에서 수락
    openstack volume transfer request accept \
      --auth-key TRANSFER_AUTH_KEY \
      TRANSFER_REQUEST_ID
    
    # 5) 새 프로젝트 인스턴스에 재연결
    openstack server add volume VM01_NEW DATA_VOLUME
    
    # 6) attach 결과 재확인
    openstack server volume list VM01_NEW -f yaml
    openstack volume show DATA_VOLUME -f yaml

    제가 transfer를 쓸 때 지키는 기준은 분명합니다.

    • status=available가 아니면 멈춥니다.
    • attachments 필드가 비지 않았으면 detach가 완전히 끝난 게 아닙니다.
    • snapshot 종속이 남아 있으면 먼저 관계를 확인합니다.
    • 운영 중 데이터 볼륨이라면 OS 내부 unmount 또는 애플리케이션 정지 절차를 작업서에 반드시 넣습니다.

    여기서 성패를 가르는 건 명령어 자체가 아니라 정지 창을 얼마나 잘 설계했는가입니다. 다운타임을 줄이겠다고 detach 직전까지 쓰기 트래픽을 열어두면, 이전은 끝나도 검증에서 파일시스템 체크나 애플리케이션 복구 시간이 길어지기 마련이죠. 제 경험상 데이터 서버는 짧은 이전보다 예측 가능한 일관성이 더 중요했습니다.

    5-5. 플로팅 IP와 포트 처리

    플로팅 IP는 환경 정책에 따라 이전 난이도가 크게 달라집니다. 어떤 환경은 같은 외부 네트워크 풀을 프로젝트 간 공유하지만, 어떤 환경은 프로젝트 소유 자원으로 강하게 묶여 있어서 재사용이 불가능합니다. 저는 그래서 제일 먼저 IP 재사용이 필수인지, DNS cutover로 충분한지를 사업 영향 기준으로 나눕니다.

    포트는 더 까다롭습니다. 이름과 fixed IP만 같아도 같다고 보면 안 됩니다. 아래 항목이 남아 있으면 새 프로젝트에서 동일한 동작이 깨질 수 있습니다.

    • allowed_address_pairs
    • port_security_enabled
    • custom DNS name 또는 extra DHCP option
    • 다중 NIC 구성과 각 NIC별 라우팅 기대값

    제가 실제로는 이렇게 판단합니다. 외부 공개 서비스면 플로팅 IP 정책 확인을 먼저 하고, 내부 연계가 많은 시스템이면 포트 상세와 라우팅 설계를 먼저 봅니다. 이유는 외부 IP는 우회 수단이 있어도, 내부 IP 충돌과 라우팅 문제는 이전 완료 후 장애로 더 오래 남기 때문입니다.

    6. 실제로 겪은 문제와 해결 방법

    현장에선 실패 원인이 늘 비슷한 곳에서 나옵니다. 중요한 건 증상만 적지 말고, 왜 그런 상태가 됐는지까지 작업 문서에 남기는 겁니다. 그래야 다음 이전에서 같은 실수를 줄일 수 있습니다.

    문제 1. 볼륨 transfer가 실패함

    증상은 transfer request create 실패, 또는 볼륨이 계속 in-use로 남는 형태가 많았습니다. 표면 원인은 detach 실패처럼 보여도, 근본 원인은 대개 리소스 상태 전이를 기다리지 않고 다음 단계로 넘어간 것이었습니다.

    • 원인 1: 하이퍼바이저 또는 백엔드 스토리지에서 detach 반영이 늦음
    • 원인 2: 게스트 OS에서 I/O가 남아 있어 상태 전이가 지연됨
    • 원인 3: snapshot 또는 다중 attach 의존성이 남아 있음

    저는 이럴 때 volume show 출력에서 status, attachments, multiattach 항목을 먼저 봅니다. 운영자가 놓치기 쉬운 포인트는 CLI 명령 성공과 상태 전이 완료가 같은 뜻이 아니라는 점이에요.

    문제 2. 새 프로젝트에서 서버는 떴는데 통신이 안 됨

    이건 정말 흔합니다. 서버 상태가 ACTIVE라고 해서 네트워크까지 정상이라는 뜻은 아닙니다. 제 경험상 근본 원인은 네 가지로 압축됐습니다.

    • 보안 그룹 룰은 복제했지만 remote group 참조를 빠뜨림
    • 포트는 붙었지만 기대하던 네트워크 세그먼트가 아님
    • 라우터 외부 게이트웨이 또는 내부 라우팅이 재구성되지 않음
    • 기존 포트의 allowed address pairs가 누락됨
    openstack server show VM01_NEW -f yaml
    openstack port list --server VM01_NEW -f yaml
    openstack port show PORT_ID -f yaml
    openstack security group rule list web-sg -f yaml
    openstack router list -f yaml
    openstack router show ROUTER_NAME -f yaml

    이때 저는 “SSH가 안 된다”를 진단 기준으로 삼지 않습니다. 패킷이 어디서 끊기는가를 봅니다. 콘솔 접속은 되는데 외부 접속만 안 되면 Neutron 쪽, 애플리케이션 포트만 안 열리면 security group 또는 OS 방화벽 쪽, 내부 서비스 간 통신만 실패하면 라우팅이나 remote group 참조 쪽일 가능성이 큽니다.

    문제 3. 이미지로 옮겼더니 애플리케이션 상태가 이상함

    이 경우도 겉으로는 이미지 이관 실패처럼 보이지만, 실제로는 워크로드 성격에 맞지 않는 이전 방식을 선택한 것이 근본 원인인 경우가 많았어요. 특히 DB, 메시지 큐, 검색 엔진처럼 디스크 쓰기 타이밍에 민감한 시스템은 이미지 스냅샷이 편해 보여도 복구 시간이 더 길어질 수 있습니다.

    • 무상태 웹 서버: 이미지 기반 이전이 대체로 효율적이었습니다.
    • 상태 저장 DB 서버: 볼륨 일관성 확보 후 이전 또는 애플리케이션 레벨 백업/복원이 더 안전했습니다.
    • 복잡한 미들웨어: 서버 이전보다 서비스 재배포가 낫다는 결론이 나온 경우도 있었고요.

    제가 지금도 지키는 기준은 분명합니다. 부팅 성공이 아니라 업무 정상성을 기준으로 이전 방식을 고른다. 이 한 줄이 작업 방식을 가장 많이 바꿉니다.

    볼륨 이전 실패와 네트워크 오류를 점검하는 트러블슈팅 장면

    볼륨 상태 확인, 포트 점검, 보안 그룹 검토 등 실제 장애 분석 흐름을 시각화한 이미지입니다.

    7. 검증과 결과 확인: 여기서 끝내면 안 됩니다

    마이그레이션은 리소스가 생성됐다고 끝나지 않습니다. 제가 운영 검증에서 가장 강조하는 건 리소스 확인과 서비스 확인을 분리하는 겁니다. OpenStack CLI는 인프라 상태를 보여주지만, 사용자가 느끼는 정상 여부는 애플리케이션 경로에서 결정됩니다.

    1. 사용자 계정으로 Horizon 또는 CLI 로그인 가능 여부
    2. 인스턴스가 ACTIVE이고 기대한 flavor, image, attached volume 구성이 맞는지
    3. 볼륨이 붙어 있을 뿐 아니라 게스트 OS에서 실제 장치와 파일시스템으로 인식되는지
    4. SSH 또는 서비스 포트 접근이 가능한지
    5. 서버 간 내부 통신이 기대 경로로 흐르는지
    6. 백업, 모니터링, 보안 에이전트가 새 프로젝트 기준으로 재등록됐는지
    # 신규 프로젝트 기준 검증
    openstack token issue
    openstack server list -f yaml
    openstack volume list -f yaml
    openstack port list -f yaml
    openstack floating ip list -f yaml
    
    # 인스턴스 내부 검증 예시
    ip addr
    ip route
    lsblk
    mount
    systemctl --failed

    이 단계에서 제가 완료 판정을 내리는 기준은 아주 보수적입니다.

    • ACTIVE여도 네트워크 미검증이면 미완료입니다.
    • in-use여도 OS에서 장치가 안 보이면 미완료입니다.
    • 플로팅 IP가 붙어 있어도 DNS 또는 외부 방화벽 반영 전이면 미완료입니다.
    • 모니터링이 복구되지 않았으면 운영 전환 완료로 보지 않습니다.

    실무에서는 이 마지막 한 끗이 중요합니다. 이전 직후에는 보통 운영팀이 안심하고 싶어서 “서버 떴다”에 집중합니다. 그런데 실제 장애는 그 다음날 백업 실패, 모니터링 누락, 로그 수집 누락으로 드러나는 경우가 많았거든요. 그래서 저는 항상 검증 항목에 인프라 레벨과 운영 레벨을 나눠 넣는 편입니다.

    마이그레이션 완료 후 인스턴스, 볼륨, 네트워크 상태를 검증하는 대시보드

    새 프로젝트에서 리소스 상태와 서비스 정상 여부를 확인하는 검증 결과 화면을 표현한 이미지입니다.

    8. 이번 작업에서 얻은 교훈과 추천 시나리오

    이번 OpenStack 테넌트 마이그레이션 사례를 다시 정리해보면, 핵심은 기술 스택을 많이 아는가보다 어떤 자원을 어느 경계에서 다시 묶을지 판단하는 능력이었습니다. 이런 복합적인 **클라우드 마이그레이션** 과정에서 저는 지금도 프로젝트 이전 요청이 오면 먼저 세 가지부터 고릅니다. 워크로드가 stateless인지 stateful인지, 플로팅 IP 유지가 필수인지, 네트워크 정책이 단순한지 복잡한지. 이 세 축만 정리해도 절차가 거의 결정됩니다.

    • 테스트 환경이라면: 이미지 스냅샷 기반 재배포가 빠르고 관리가 쉽습니다. 단, 검증 범위는 OS 부팅이 아니라 서비스 기동까지 잡으셔야 합니다.
    • 운영 환경의 데이터 서버라면: 볼륨 transfer 또는 애플리케이션 레벨 백업/복원이 더 안전합니다. 다운타임을 줄이는 것보다 데이터 일관성을 우선으로 두시는 편이 **더 안전하더라고요.**
    • 네트워크 정책이 복잡한 환경이라면: 포트와 보안 그룹을 재생성하되, old project의 패킷 흐름을 먼저 문서화하고 들어가셔야 합니다. 이름 복제가 아니라 통신 재현이 목적입니다.
    • 감사 대응이나 변경 이력 관리가 중요한 조직이라면: 새 프로젝트 생성 후 권한, quota, 네트워크, 스토리지를 순차적으로 재구성하는 방식이 가장 **깔끔했고요.**

    제가 실제로는 이렇게 결론 냅니다. 빠른 이전이 목표면 이미지 기반, 데이터 무결성이 목표면 볼륨 중심, 장애 회피와 추적 가능성이 목표면 새 프로젝트 재구성입니다. 반대로 DB 직접 수정은 작업 시간은 줄여도 운영 리스크는 크게 키우는 선택이라 지금도 **절대 권하지 않습니다.**

    한 번 해보면 느끼실 겁니다. 프로젝트를 옮긴다기보다, 서비스 관계를 다시 엮는 작업에 가깝습니다. 그래서 저는 늘 마지막에 이렇게 체크합니다. “리소스는 옮겨졌는가?”가 아니라 “사용자는 전과 같은 방식으로 서비스를 쓸 수 있는가?” 이 질문에 예라고 답할 수 있으면, 그때가 진짜 마이그레이션 완료 시점입니다.

    다음 단계가 남아 있다면 제 추천은 분명합니다. 먼저 1대 샘플 서버로 전체 절차를 끝까지 검증하고, 그 결과를 표준 작업서로 만든 뒤 나머지를 확장하세요. OpenStack 이전은 명령어보다 순서가 중요하고, 순서보다 기준이 더 중요했습니다. 다른 OpenStack 관련 **프로젝트 관리** 팁이나 **클라우드 마이그레이션** 성공 사례가 궁금하시다면, 저희 블로그의 다른 글들도 참고해 보세요.

    프로젝트 마이그레이션 방식별 선택 기준과 권장 시나리오 요약 인포그래픽

    이미지 기반, 볼륨 기반, 네트워크 재구성 방식 중 어떤 상황에서 무엇을 선택할지 요약한 이미지입니다.

    FAQ

    프로젝트 이름만 바꾸면 되는 경우도 있나요?

    이름 변경과 실제 자원 이전은 별개입니다. 권한 분리, 네트워크 정책 분리, quota 분리가 목적이라면 새 프로젝트를 만들고 리소스를 서비스별 절차로 재구성하는 편이 안전합니다.

    운영 중단 없이 완전 이전이 가능한가요?

    stateless 서비스는 비교적 유연하지만, stateful 서비스는 디스크 일관성 확보가 더 중요합니다. 제 기준으로는 “중단 없는 이전”보다 “예측 가능한 검증 가능한 이전”이 우선입니다.

    가장 먼저 확인해야 할 한 가지는 뭔가요?

    인스턴스가 image-backed인지 volume-backed인지입니다. 이 구분 하나가 스냅샷 전략, 다운타임 길이, 검증 방식, 실패 모드를 모두 바꿉니다.

  • [OpenStack] OpenStack 프로젝트 테넌트 격리 전략 비교와 보안 강화

    [OpenStack] OpenStack 프로젝트 테넌트 격리 전략 비교와 보안 강화

    OpenStack 프로젝트 테넌트 격리 전략 비교와 보안 강화

    OpenStack 프로젝트 테넌트 격리는 멀티테넌트 환경에서 가장 먼저 다져야 하는 기본기입니다. 겉으로는 프로젝트만 나누면 끝나 보이지만, 실제 운영에 들어가면 네트워크, 권한, 이미지, 볼륨, 스케줄링까지 같이 봐야 하더라고요. 저도 초반에는 프로젝트만 분리하면 충분하다고 생각했는데, 나중에 보니 공유 네트워크 하나가 경계를 흐리는 경우가 있었습니다.

    이번 글에서는 OpenStack 프로젝트 테넌트 격리를 어디까지 논리적으로 나눌지, 어디서부터 물리적 성격의 분리를 추가할지 비교해보겠습니다. 체크리스트만 훑는 글이 아니라, OpenStack 보안 관점에서 무엇을 먼저 적용해야 하는지와 테넌트 분리 수준별 운영 비용까지 같이 정리해보겠습니다.

    프로젝트, 네트워크, 하이퍼바이저, 스토리지 계층이 어떻게 분리되는지 한눈에 보여주는 아키텍처 이미지입니다.

    왜 OpenStack 프로젝트 테넌트 격리에서 프로젝트만 나누면 끝이 아닐까

    쉽게 말해 프로젝트는 행정 구역에 가깝고, 실제 경계는 따로 있습니다. 사용자는 프로젝트 기준으로 자원을 보지만, 패킷 흐름, 이미지 접근 권한, 볼륨 연결, 컴퓨트 노드 배치까지 자동으로 다 분리되지는 않거든요. 그래서 프로젝트 분리는 출발점일 뿐이고, 그 바깥 계층을 같이 설계해야 실전에서 흔들리지 않습니다.

    • Identity: 누가 어떤 프로젝트에 들어갈 수 있는지 결정합니다.
    • Network: 테넌트 간 동서 트래픽을 제어하는 핵심 축입니다.
    • Compute: 같은 하이퍼바이저에 섞을지, 분리할지 정합니다.
    • Storage: 이미지와 볼륨이 의도치 않게 공유되지 않도록 막아야 합니다.
    • Policy/RBAC: 운영자 권한이 지나치게 넓으면 격리 설계가 쉽게 무너집니다.

    운영해보면 사고는 화려한 기능보다 기본 설정 하나를 공유 상태로 둔 채 지나간 부분에서 더 자주 납니다. 특히 Horizon과 CLI로 만든 리소스가 섞이면 누가 무엇을 어떤 의도로 공유했는지 추적이 꽤 까다롭습니다. 이 지점이 생각보다 중요하더라고요.

    OpenStack 프로젝트 테넌트 격리 전략, 4단계로 나눠서 보기

    현업에서는 보통 4단계로 나눠 봅니다. 아래 표는 설계 검토할 때 바로 가져다 쓰기 좋은 기준에 가깝습니다.

    전략 핵심 방식 격리 강도 운영 복잡도 추천 상황 주의 포인트
    기본 논리 분리 프로젝트, 사용자, 보안 그룹 분리 중간 낮음 사내 개발/테스트 환경 공유 네트워크나 공개 이미지가 남아 있으면 경계가 약해집니다.
    네트워크 중심 분리 프로젝트별 네트워크, 라우터, RBAC 최소화 높음 중간 팀 간 독립 운영, 고객 분리 외부망 연결 방식과 Floating IP 정책을 같이 봐야 합니다.
    컴퓨트 배치 분리 Host Aggregate, Availability Zone 분리 높음 중간~높음 규제 대응, noisy neighbor 완화 스케줄링 정책과 리소스 부족 시 예외 처리 기준이 필요합니다.
    스토리지/암호화 포함 강한 분리 볼륨 타입 분리, 암호화, 이미지 접근 제한 매우 높음 높음 민감 데이터, 외부 고객 서비스 키 관리와 백업 경로까지 같이 분리해야 효과가 살아납니다.

    핵심은 단순합니다. OpenStack 보안은 기능 하나로 끝나지 않습니다. 프로젝트 분리는 시작이고, 네트워크와 권한 모델을 어떻게 묶느냐가 실제 체감 보안을 좌우합니다.

    기본 골격: 프로젝트, 사용자, 권한부터 단단하게

    처음 설계할 때는 프로젝트를 조직 단위로만 나누기 쉬운데, 실제로 써보면 환경 단위(dev, stage, prod)까지 별도 프로젝트로 자르는 편이 운영이 훨씬 편합니다. 같은 팀이라도 운영 환경과 개발 환경이 섞이면 이미지 공유나 보안 그룹 재사용이 자연스럽게 생기거든요. 나중에 감사나 장애 대응 때 차이가 꽤 크게 납니다.

    1. 프로젝트를 환경 또는 고객 기준으로 분리합니다.
    2. 사용자는 최소 권한 원칙에 맞춰 필요한 프로젝트에만 넣습니다.
    3. 운영자 계정은 범용 admin 하나로 뭉개지 말고 역할을 나눕니다.
    4. 공유 리소스는 허용보다 금지를 기본값으로 잡습니다.
    openstack project create prod-team-a
    openstack user create --project prod-team-a --password-prompt teama-admin
    openstack role add --project prod-team-a --user teama-admin member
    
    openstack project create dev-team-a
    openstack user create --project dev-team-a --password-prompt teama-dev
    openstack role add --project dev-team-a --user teama-dev member
    
    openstack role assignment list --project prod-team-a --names
    openstack quota show prod-team-a

    위 명령은 모두 OpenStackClient에서 일반적으로 사용하는 기본 흐름입니다. 다만 수동으로 반복 생성하기 시작하면 프로젝트마다 quota나 역할 구성이 조금씩 달라지기 쉽습니다. 이게 나중에 제일 사람을 힘들게 하더라고요.

    판단 기준도 같이 기억해두면 좋습니다.

    • role assignment list 결과에 예상하지 못한 admin 계열 역할이 보이면 권한 과다를 먼저 의심합니다.
    • quota show가 비어 있거나 기본값만 따라가면 특정 테넌트의 자원 폭주를 제어하기 어렵습니다.
    • 운영자 공용 계정을 여러 팀이 함께 쓰면 추적성이 크게 떨어집니다.

    OpenStack 프로젝트 테넌트 격리에서 실전 차이는 네트워크 분리에서 난다

    프로젝트를 나눠도 네트워크가 공유되면 체감상 같은 건물에 문패만 바꿔 다는 수준이 됩니다. 그래서 멀티테넌트 환경에서는 프로젝트별 자체 네트워크와 자체 라우터를 기본값으로 두는 편이 안전합니다. 공유 네트워크나 RBAC 공유는 예외 승인 방식으로 돌리는 게 번거로워 보여도, 사고 예방 효과는 확실합니다.

    openstack network create --project prod-team-a prod-team-a-net
    openstack subnet create --project prod-team-a \
      --network prod-team-a-net \
      --subnet-range 10.10.10.0/24 \
      prod-team-a-subnet
    
    openstack router create --project prod-team-a prod-team-a-router
    openstack router add subnet prod-team-a-router prod-team-a-subnet
    openstack router set --external-gateway public prod-team-a-router
    
    openstack security group create --project prod-team-a prod-team-a-web-sg
    openstack security group rule create --ingress --ethertype IPv4 \
      --protocol tcp --dst-port 22 prod-team-a-web-sg
    openstack security group rule create --ingress --ethertype IPv4 \
      --protocol tcp --dst-port 443 prod-team-a-web-sg
    
    openstack network rbac list
    openstack security group rule list prod-team-a-web-sg

    이 구간에서 자주 나오는 실수도 비슷합니다. 외부 게이트웨이만 다르면 충분하다고 생각하거나, 보안 그룹 규칙을 여러 프로젝트에서 관성적으로 복사해 쓰는 경우죠. 처음엔 편한데 규칙이 커질수록 누가 왜 열었는지 설명이 안 됩니다.

    OpenStack 프로젝트 테넌트 격리 네트워크 분리 구성 이미지

    각 프로젝트가 독립된 네트워크와 라우터를 가지며, 외부망은 공용이더라도 내부 통신 경계는 분리되는 구조를 보여주는 이미지입니다.

    운영하다 보면 테스트 서버 때문에 0.0.0.0/0로 SSH를 잠깐 열어뒀는데, 비슷한 규칙이 운영 프로젝트에도 따라 들어간 경우가 꼭 생깁니다. 이런 경험 한 번쯤 있으실 겁니다. 그래서 보안 그룹은 템플릿화하되, 프로젝트별 별도 객체로 관리하는 편이 훨씬 낫더라고요.

    재현 가능한 시나리오 하나

    예를 들어 팀 A와 팀 B가 같은 클라우드를 쓰고 있는데, 운영자가 편의를 위해 하나의 공유 네트워크를 두 프로젝트에 RBAC로 열어뒀다고 가정해보겠습니다. 그 상태에서 두 팀의 인스턴스가 같은 L2 세그먼트에 붙고 보안 그룹 규칙까지 느슨하면, 동서 통신이 예상보다 넓게 열릴 수 있습니다. 이럴 때는 아래 순서로 확인하면 됩니다.

    • openstack network show <network>로 네트워크 소유자와 공유 상태를 확인합니다.
    • openstack network rbac list에서 어떤 프로젝트에 접근이 열려 있는지 봅니다.
    • openstack port list --project <project>로 각 프로젝트 포트가 어느 네트워크에 붙었는지 추적합니다.

    여기서 중요한 건 숫자보다 의도하지 않은 연결 관계입니다. 보안 진단은 평균값을 보는 작업이라기보다 예외 케이스를 집요하게 확인하는 작업에 가깝습니다.

    한 단계 더: 컴퓨트와 스토리지까지 분리해야 하는 경우

    여기서부터는 고객 성격에 따라 판단이 갈립니다. 같은 하이퍼바이저에 다른 고객 워크로드가 같이 올라가도 되는지, 볼륨 백엔드가 완전히 공용이어도 되는지 따져봐야 하거든요. 규제 대응이나 민감한 데이터가 있다면 논리 분리만으로는 설명이 부족한 경우가 많습니다.

    • Availability Zone: 프로젝트별 또는 업무별 배치 경계를 만듭니다.
    • Host Aggregate: 특정 컴퓨트 노드 그룹으로 스케줄링합니다.
    • Volume Type: 성능, 백엔드, 암호화 정책을 나눕니다.
    • Image 접근 제어: 공개 이미지와 공유 이미지를 최소화합니다.
    openstack aggregate create team-a-aggregate
    openstack aggregate add host team-a-aggregate compute-01
    openstack aggregate add host team-a-aggregate compute-02
    openstack aggregate set --zone team-a-az team-a-aggregate
    
    openstack volume type list
    openstack image list --public
    openstack image list --shared
    openstack image show <image-id>

    명령 자체는 단순해 보여도 운영 포인트는 따로 있습니다. 스케줄링 실패 로그를 어떻게 해석할지 기준을 정해두지 않으면, 인스턴스 생성 실패를 무조건 리소스 부족으로만 보기 쉽습니다. 실제로는 aggregate 메타데이터나 AZ 선택이 맞지 않아 배치가 막히는 경우도 많습니다.

    이미지 공개 설정도 꼭 봐야 합니다. 프로젝트 격리를 열심히 해놨는데 public 또는 shared 이미지 안에 민감한 에이전트 설정이나 초기 계정 스크립트가 들어 있으면 다른 종류의 사고가 됩니다. 그래서 golden image를 쓰더라도 공개 범위는 아주 좁게 잡는 편이 안전합니다.

    OpenStack 프로젝트 테넌트 격리 컴퓨트 분리 다이어그램

    특정 프로젝트가 전용 컴퓨트 노드 그룹과 가용 영역으로 스케줄링되는 모습을 설명하는 이미지입니다.

    자주 봤던 문제와 해결 방법

    문서만 보면 구조가 깔끔해 보이지만, 실무에서는 늘 예외가 먼저 튀어나옵니다. 아래 네 가지는 멀티테넌트 환경에서 정말 자주 만나는 문제입니다.

    1. 공유 리소스가 남아 있는 경우

    가장 흔합니다. 네트워크, 이미지, 보안 그룹 템플릿 운영 방식 중 하나라도 사실상 공유 상태로 굴러가면 경계가 흐려집니다. 해결책은 단순합니다. 기본값을 비공유로 두고, 필요한 경우만 승인 절차로 열기입니다.

    2. 운영자 권한이 너무 넓은 경우

    도와주려고 준 권한이 나중에는 우회 경로가 됩니다. 도메인 관리자와 클라우드 관리자 역할을 분리하지 않으면 프로젝트 격리의 의미가 금방 약해집니다. 이 부분은 생각보다 체감 차이가 큽니다.

    3. 보안 그룹을 방화벽처럼 과신하는 경우

    보안 그룹은 중요하지만 전부는 아닙니다. 라우팅, 포트 소유, Floating IP 정책, 메타데이터 서비스 접근 제어까지 같이 봐야 합니다. 보안 그룹 하나로 다 해결하려고 하면 운영이 오히려 꼬입니다.

    4. 로그는 있는데 읽는 기준이 없는 경우

    이 문제도 꽤 큽니다. 예를 들어 인스턴스가 의도한 AZ에 올라가지 않았다면, 단순 실패로 넘기지 말고 격리 정책이 실제로 작동 중인지 또는 예외 정책이 필요한지를 같이 판단해야 합니다. 장애 대응 문서에는 아래 체크 순서를 넣어두면 도움이 됩니다.

    • 네트워크 문제면 포트 소속 프로젝트와 보안 그룹 규칙부터 확인
    • 배치 문제면 AZ, aggregate, flavor extra spec 사용 여부 확인
    • 스토리지 문제면 volume type과 백엔드 정책 일치 여부 확인

    처음엔 체크 항목이 많아 보여도, 순서를 정해두면 대응 속도가 확실히 빨라집니다. 이런 건 실제로 해보면 차이가 바로 느껴집니다.

    검증은 이렇게 합니다: 설정 확인보다 경계 확인

    OpenStack 프로젝트 테넌트 격리가 잘 됐는지 보려면 리소스가 생성됐는지만 보면 부족합니다. 다른 프로젝트 사용자 입장에서 안 보여야 할 것이 정말 안 보이는지, 붙으면 안 되는 네트워크가 실제로 안 붙는지까지 확인해야 합니다. 결국 중요한 건 설정값이 아니라 경계가 의도대로 작동하는지입니다.

    1. 프로젝트 A 계정으로 로그인해 프로젝트 B의 네트워크, 인스턴스, 볼륨이 보이는지 확인합니다.
    2. RBAC 목록에서 예상하지 못한 공유 규칙이 없는지 확인합니다.
    3. 공개 이미지와 공유 이미지 목록을 각각 점검합니다.
    4. 보안 그룹 규칙에 과도한 Any 규칙이 없는지 확인합니다.
    openstack server list --project prod-team-a
    openstack network list --project prod-team-a
    openstack port list --project prod-team-a
    openstack volume list --project prod-team-a
    openstack image list --private
    openstack image list --public
    openstack image list --shared
    openstack network rbac list

    해석 기준은 이렇습니다.

    • 보이면 안 되는 타 프로젝트 리소스가 보이면 Identity 또는 공유 정책 점검이 먼저입니다.
    • 프로젝트 전용 네트워크가 아닌 공용 네트워크에 포트가 붙어 있으면 설계 예외인지 설정 누락인지 바로 구분해야 합니다.
    • 공개 이미지나 공유 이미지가 과도하게 많으면 이미지 배포 체계를 다시 잡는 편이 좋습니다.
    • 보안 그룹에 광범위한 인바운드 규칙이 있으면 앞단 제어 계층까지 같이 검토하는 게 안전합니다.
    OpenStack 프로젝트 테넌트 격리 검증 결과 대시보드 이미지

    프로젝트별 리소스 목록, RBAC 규칙, 공개 이미지 수를 점검하는 운영 검증 화면을 표현한 이미지입니다.

    비교해보면, 어떤 전략을 선택해야 할까

    이쯤 되면 선택 기준이 조금 선명해집니다. 모든 환경에 최고 강도의 분리를 넣는다고 꼭 좋은 건 아닙니다. 운영 복잡도가 확 올라가거든요. 반대로 고객 서비스나 민감 데이터 환경인데 기본 논리 분리만 두는 것도 위험합니다.

    환경 추천 격리 수준 이유 추가 권고
    사내 개발/테스트 프로젝트 + 네트워크 분리 운영 부담을 크게 늘리지 않으면서도 사고 범위를 줄일 수 있습니다. 공유 리소스 승인 절차는 반드시 둡니다.
    운영 서비스 프로젝트 + 네트워크 + 이미지 통제 서비스 간 영향 최소화와 변경 추적이 중요합니다. 보안 그룹 템플릿과 quota 정책을 같이 표준화합니다.
    외부 고객 멀티테넌트 프로젝트 + 네트워크 + 컴퓨트 분리 고객 간 경계와 noisy neighbor 대응이 필요합니다. AZ, aggregate, 운영자 역할 분리를 같이 적용합니다.
    민감 정보/규제 환경 전 계층 분리 + 스토리지 암호화 논리 분리만으로는 설명 책임이 부족할 수 있습니다. 백업, 키 관리, 감사 로그 보존 정책까지 묶어 설계합니다.

    이 표는 정답표라기보다, 실제 운영에서 어디까지 해야 충분한지 가늠하는 기준점에 가깝습니다. 저도 가벼운 실험 환경에서는 단순하게 갔지만, 운영 환경으로 갈수록 네트워크와 권한 모델을 먼저 단단히 다지는 쪽이 결과가 좋았습니다.

    FAQ: OpenStack 프로젝트 테넌트 격리에서 헷갈리는 포인트

    프로젝트만 나누면 테넌트 분리가 끝난 건가요?

    아닙니다. 프로젝트는 시작점입니다. 네트워크 공유, 이미지 공개 또는 공유, 운영자 권한 범위가 남아 있으면 경계가 충분하지 않을 수 있습니다.

    보안 그룹만 잘 쓰면 되지 않나요?

    보안 그룹은 중요하지만 전부가 아닙니다. 라우터, RBAC, 이미지 접근, 컴퓨트 배치까지 같이 봐야 진짜 클라우드 보안이 됩니다.

    가용 영역 분리는 언제 필요할까요?

    고객별 워크로드 분리, 규제 대응, 성능 간섭 완화가 필요할 때 고려합니다. 다만 운영 복잡도가 올라가니 일반 개발 환경에는 과할 수 있습니다.

    현업 기준으로 권고를 딱 정리하면

    팀 내부 개발 환경이라면 프로젝트 분리, 프로젝트별 네트워크, 최소 권한 모델까지만 해도 효과가 큽니다. 이 조합이 운영 부담 대비 효율이 가장 좋습니다. 반면 외부 고객이 함께 쓰는 멀티테넌트 클라우드라면 여기서 멈추기 아쉽습니다. 그 경우에는 네트워크 공유 금지, 이미지 공개 최소화, AZ 또는 Host Aggregate 기반 배치 분리까지 넣는 편이 맞습니다.

    민감 데이터가 있는 서비스라면 더 분명합니다. 스토리지 암호화와 볼륨 타입 분리까지 포함해 전 계층으로 끌고 가는 게 낫습니다. 운영은 조금 복잡해져도, 사고 이후 설명 비용보다 훨씬 싸게 먹힙니다. 다음 글에서는 Keystone 역할 설계와 서비스 계정 분리 패턴도 다뤄보겠습니다. 이전 글의 보안 그룹 운영 기준과 함께 보면 흐름이 더 잘 잡힐 겁니다.

    OpenStack 프로젝트 테넌트 격리 전략 비교 인포그래픽

    개발, 운영, 외부 고객, 민감 정보 환경별로 어떤 격리 전략을 선택해야 하는지 요약한 인포그래픽 이미지입니다.

  • [OpenStack] OpenStack Magnum, 왜 다시 주목받나? CAPI Helm 최신 동향

    [OpenStack] OpenStack Magnum, 왜 다시 주목받나? CAPI Helm 최신 동향

    [인프라] OpenStack Magnum, 왜 다시 주목받나?

    OpenStack Magnum을 다시 보는 이유는 예전과 조금 다릅니다. 2026년 8월 기준 공식 문서와 릴리즈 노트를 다시 읽어보면, 지금의 Magnum은 단순히 Heat로 클러스터를 띄우는 오래된 서비스로 보기 어렵더라고요. 방향이 분명히 Cluster API 기반 Kubernetes as a Service 쪽으로 옮겨갔기 때문입니다.

    핵심은 이제 “쿠버네티스를 한 번 띄우는 법”이 아닙니다. Keystone 인증, Neutron 네트워크, Cinder 스토리지, Octavia 로드밸런서, Barbican 인증서 저장 같은 OpenStack 자원을 하나의 운영 모델로 묶을 수 있느냐가 더 중요하거든요. 이 글에서는 OpenStack Magnum을 언제 검토할 만한지, 반대로 언제 과감히 제외하는 게 맞는지 실무 관점으로 정리해 보겠습니다.

    OpenStack Magnum과 Cluster API 기반 프라이빗 클라우드 아키텍처 개요

    OpenStack Magnum이 Keystone, Neutron, Cinder, Octavia와 어떻게 연결되고 Cluster API 기반으로 Kubernetes 클러스터를 관리하는지 보여주는 개요 이미지입니다.

    1. OpenStack Magnum을 볼 때 먼저 버려야 할 오해

    Magnum을 아직도 “Heat로 쿠버네티스를 띄우는 서비스”로만 보면 판단이 자꾸 어긋납니다. 최신 Magnum 사용자 가이드는 Heat 드라이버가 deprecated이며, 앞으로 제거될 예정이라고 분명히 적고 있습니다. 신규 설계에서 Heat를 기본 전제로 잡는 건 이제 장기 운영 관점에서 무리가 있습니다.

    지금 봐야 할 축은 k8s_capi_helm과 k8s_cluster_api입니다. 특히 magnum-capi-helm은 OpenStack 거버넌스 아래에서 유지되고 있고, 공식 릴리즈 노트는 이 드라이버를 production use에 generally ready라고 설명합니다. 다만 이 표현을 곧바로 “대규모 운영에 아무 검증도 필요 없다”로 받아들이면 곤란합니다. 제 해석은 이렇습니다. 이제 Magnum의 실전성은 클러스터 생성 성공 여부보다, 관리 클러스터와 Cluster API 수명주기를 얼마나 안정적으로 운영하느냐에 달려 있습니다.

    • 예전 시선: Magnum이 Heat 템플릿으로 인프라를 직접 밀어 올린다.
    • 지금 시선: Magnum은 OpenStack API 진입점이고, 실제 클러스터 수명주기는 Cluster API와 provider가 선언적으로 맞춘다.
    • 실무 함의: 장애 지점도 Magnum API, 관리 클러스터, CAPO, Helm chart, addon reconciliation까지 넓게 봐야 한다.

    구성요소가 늘어나니 관찰 포인트도 많아집니다. 그래도 장점은 분명합니다. 예전에는 여기저기 흩어져 있던 업그레이드, 노드그룹 변경, autoscaling, 기본 정책 강제가 이제 플랫폼 계층에서 조금 더 정리되기 시작했거든요.

    2. OpenStack Magnum이 다시 주목받는 이유

    2026년 기준으로 다시 볼 만한 이유는 다섯 가지 정도로 압축됩니다.

    1. 공식 방향이 Heat에서 CAPI 계열로 옮겨갔습니다. Heat는 유지 중인 환경을 이해하는 용도에 가깝고, 신규 표준으로 추천되는 분위기는 아닙니다.
    2. magnum-capi-helm의 성숙도가 높아졌습니다. 공식 릴리즈 노트는 production use에 generally ready라고 밝히지만, 동시에 예상하지 못한 이슈 가능성도 언급합니다. 즉, 실전 배치 가능성은 높아졌지만 검증 책임이 사라진 건 아닙니다.
    3. 생성보다 변경 관리가 중심으로 들어왔습니다. create, delete, upgrade, node group size update 같은 수명주기 작업이 문서 중심에 올라와 있습니다.
    4. autoscaling 범위가 넓어졌습니다. 기본 워커뿐 아니라 non-default worker node group에도 min/max 정책을 줄 수 있고, 최신 릴리즈 노트 기준으로 min_node_count=0을 통한 scale-to-zero도 지원합니다. 다만 이 기능은 capi-helm-charts >= 0.26.0과 cluster-api-provider-openstack >= 0.26.0 조건을 확인해야 합니다.
    5. 운영자 기본값 설계가 쉬워졌습니다. [capi_helm_cluster_labels] 섹션에서 사이트 전역 기본 라벨을 둘 수 있어서 사용자 자유도와 플랫폼 일관성의 균형을 잡기 편해졌습니다.

    한 문장으로 줄이면 이렇습니다. OpenStack Magnum은 더 이상 “OpenStack에 쿠버네티스를 얹는 기능”이 아니라, OpenStack 조직 구조 안에서 Kubernetes 수명주기를 표준화하는 서비스에 가까워졌습니다.

    선택지 어울리는 환경 강점 숨은 비용 제 판단
    직접 kubeadm 운영 소규모 팀, 단일 클러스터, 빠른 실험 단순하게 시작 가능 업그레이드, 인증, 스토리지, LB 연동을 팀이 직접 책임져야 함 초반은 빠르지만 플랫폼화 단계에서 부담이 커짐
    Magnum + legacy Heat 이미 운영 중인 기존 환경 현재 자산을 당장 버리지 않아도 됨 공식 방향과 어긋나고 신규 기능 이점이 제한적 유지는 가능하지만 신규 표준으로는 비추천
    Magnum + CAPI Helm OpenStack 기반 프라이빗 KaaS OpenStack 자원과 일관된 수명주기 운영 관리 클러스터와 버전 조합 검증 필요 OpenStack이 핵심 플랫폼이면 가장 현실적
    외부 managed Kubernetes 퍼블릭 클라우드 우선, 운영 단순화가 최우선 제어면 운영 부담 감소 내부망, 규제, OpenStack 통합 요구에는 약할 수 있음 OpenStack 통합 가치가 작으면 이쪽이 더 나음

    3. OpenStack Magnum 운영에서 더 중요한 건 기본값 설계

    현장에서 진짜 갈리는 지점은 Magnum 자체보다 기본값을 어떻게 잠그느냐입니다. 많은 글이 ClusterTemplate 예제만 보여주고 끝나는데, 운영팀은 그 전에 무엇을 사용자 자율에 맡길지, 무엇을 플랫폼 기본값으로 강제할지 먼저 정해야 하거든요. 이걸 늦게 정하면 클러스터가 늘어날수록 편차가 커집니다.

    최신 magnum-capi-helm 설정 레퍼런스를 보면 핵심 섹션은 [capi_helm]와 [capi_helm_cluster_labels]입니다. 시작점으로는 아래와 같은 구성이 무난합니다.

    [capi_helm]
    kubeconfig_file = /etc/magnum/kubeconfig
    namespace_prefix = magnum
    helm_chart_repo = https://azimuth-cloud.github.io/capi-helm-charts
    helm_chart_name = openstack-cluster
    default_helm_chart_version = 0.26.0
    minimum_flavor_ram = 2048
    minimum_flavor_vcpus = 2
    
    [capi_helm_cluster_labels]
    auto_scaling_enabled = true
    min_node_count = 1
    max_node_count = 5
    monitoring_enabled = true
    kube_dashboard_enabled = false
    auto_healing_enabled = true
    keystone_auth_enabled = true
    octavia_provider = amphora
    octavia_lb_healthcheck = true
    csi_cinder_reclaim_policy = Retain
    csi_cinder_volume_binding_mode = WaitForFirstConsumer
    csi_cinder_allow_volume_expansion = true
    master_lb_floating_ip_enabled = true
    api_master_lb_allowed_cidrs = 10.20.0.0/16
    fixed_subnet_cidr = 10.40.0.0/24
    pod_network_cidr = 10.100.0.0/16
    service_network_cidr = 172.24.0.0/13

    몇 가지는 그냥 옵션 나열로 보면 안 됩니다.

    • kubeconfig_file: Magnum이 붙는 CAPI management cluster의 kubeconfig입니다. 이 관리 클러스터가 흔들리면 생성뿐 아니라 업그레이드와 노드그룹 변경도 같이 막힙니다.
    • namespace_prefix: 여러 Magnum 배포가 하나의 관리 클러스터를 공유할 때 충돌을 피하는 최소 장치입니다.
    • default_helm_chart_version: 여기서 버전을 통제하지 않으면 사용자별 드리프트가 시작됩니다.
    • minimum_flavor_ram, minimum_flavor_vcpus: 성능 튜닝이라기보다 실패 방지용 안전장치에 가깝습니다.
    • csi_cinder_volume_binding_mode=WaitForFirstConsumer: 멀티 AZ나 토폴로지 제약이 있는 환경에서는 특히 보수적으로 가져가는 편이 안전합니다.
    • api_master_lb_allowed_cidrs: Kubernetes API를 너무 넓게 여는 실수가 의외로 자주 나옵니다. 초기에 편하다고 넓게 열면 나중에 되돌리는 비용이 더 큽니다.

    제가 보는 핵심 질문은 하나입니다. 사용자가 바꿔야 하는 값과 플랫폼이 묶어야 하는 값을 구분했는가? OpenStack 기반 KaaS는 자유도보다 일관성이 중요할 때가 많습니다. 특히 여러 프로젝트가 같은 기반 인프라를 쓰는 조직에서는 더 그렇습니다. 이전에 다뤘던 Neutron·Octavia 운영 글과 함께 보면 이 경계가 더 또렷하게 잡힙니다.

    magnum.conf와 ClusterTemplate 라벨 설정 흐름 다이어그램

    운영자 설정 파일에서 기본 라벨을 정의하고, 사용자가 ClusterTemplate와 Cluster 생성 시 이를 어떻게 상속하거나 덮어쓰는지 보여주는 이미지입니다.

    4. ClusterTemplate는 청사진이 아니라 운영 계약서입니다

    ClusterTemplate를 만들 때 흔한 실수는 “생성만 되면 된다”는 태도로 옵션을 넣는 겁니다. 그렇게 만든 템플릿은 나중에 업그레이드, 보안, 확장성에서 발목을 잡습니다. Magnum의 템플릿은 사용자에게 노출되는 상품 정의서에 더 가깝습니다.

    아래 예시는 공식 CLI 문법에 맞춰 정리한 시작 예시입니다. 다만 이미지 이름이나 flavor 이름은 환경마다 다르니, 실제 배포 전에는 운영 중인 Glance 이미지와 Nova flavor를 먼저 맞춰 확인하는 편이 좋습니다.

    openstack coe cluster template create k8s-capi-template \
      --coe kubernetes \
      --image <validated-kubernetes-image> \
      --external-network public \
      --fixed-network tenant-net-prod \
      --fixed-subnet tenant-subnet-prod \
      --dns-nameserver 8.8.8.8 \
      --flavor m1.large \
      --master-flavor m1.large \
      --network-driver calico \
      --master-lb-enabled \
      --labels auto_scaling_enabled=true,min_node_count=1,max_node_count=3,monitoring_enabled=true,keystone_auth_enabled=true,octavia_provider=amphora,csi_cinder_volume_binding_mode=WaitForFirstConsumer,csi_cinder_reclaim_policy=Retain,api_master_lb_allowed_cidrs=10.20.0.0/16,pod_network_cidr=10.100.0.0/16,service_network_cidr=172.24.0.0/13 \
      k8s-capi-template
    
    openstack coe cluster create prod-k8s-01 \
      --cluster-template k8s-capi-template \
      --master-count 3 \
      --node-count 2 \
      --timeout 90 \
      prod-k8s-01
    
    openstack coe cluster config --dir ./kubeconfig --force prod-k8s-01
    export KUBECONFIG=./kubeconfig/config
    kubectl get nodes -o wide
    kubectl get storageclass
    kubectl get pods -A

    여기서 체크할 기준은 분명합니다.

    • 신규 구축이면 control plane 고가용성과 로드밸런서 경로를 먼저 잡는 편이 낫습니다. 실제로 magnum-capi-helm 문서는 업그레이드 안정성 측면에서 로드밸런서 사용을 강하게 시사합니다.
    • 운영 안정성이 우선이면 CNI는 Calico부터 시작하는 편이 안전합니다. 공식 문서도 Cilium 지원은 언급하지만, 정기 검증은 Calico 중심이라고 설명합니다.
    • master-lb-enabled는 CLI 옵션으로 존재하지만, CAPI Helm 문서상 현재 드라이버는 이 플래그를 사실상 무시합니다. 실무적으로는 로드밸런서를 전제로 설계하는 편이 낫습니다.

    그리고 하나 더 있습니다. autoscaling을 켜면 초기 워커 수 해석이 Heat 시절과 다를 수 있습니다. 공식 릴리즈 노트에 따르면 auto_scaling_enabled=true일 때 min_node_count, max_node_count를 존중하며, 이 경우 기본 워커는 node_count 대신 최소 노드 수로 시작할 수 있습니다. 이 부분은 운영팀이 미리 공유해 두는 게 좋습니다.

    5. nodegroup 설계가 좋으면 운영 절반은 끝납니다

    실무에서 비용과 안정성을 동시에 좌우하는 건 워커를 한 덩어리로 둘지, 역할별 nodegroup으로 나눌지입니다. OpenStack 위에서 Magnum을 쓸 때는 기본 워커 그룹 하나로 오래 버티는 설계가 나중에 꽤 답답해지더라고요.

    • 스토리지 성격이 다른 워크로드가 섞입니다.
    • ingress, 배치, 일반 애플리케이션의 확장 패턴이 다릅니다.
    • flavor 요구사항도 달라집니다.
    • scale-to-zero 같은 정책은 특정 그룹에만 적용하고 싶은 경우가 많습니다.

    그래서 역할 분리를 먼저 해두는 편이 낫습니다.

    openstack coe nodegroup create \
      --node-count 2 \
      --min-nodes 2 \
      --max-nodes 6 \
      --flavor m1.large \
      --role worker \
      --labels workload=general \
      prod-k8s-01 general-workers
    
    openstack coe nodegroup create \
      --node-count 1 \
      --min-nodes 0 \
      --max-nodes 4 \
      --flavor m1.xlarge \
      --role worker \
      --labels workload=batch \
      prod-k8s-01 batch-workers
    
    openstack coe nodegroup list prod-k8s-01
    openstack coe nodegroup show prod-k8s-01 batch-workers
    openstack coe cluster resize --nodegroup general-workers prod-k8s-01 3

    min_node_count=0은 확실히 매력적입니다. 다만 공식 릴리즈 노트 기준으로 scale-to-zero는 capi-helm-charts 0.26.0 이상과 cluster-api-provider-openstack 0.26.0 이상이 필요합니다. 조건이 안 맞으면 명시적 에러가 납니다. 이건 단순 옵션 문제가 아니라 플랫폼 버전 관리 문제로 봐야 합니다.

    워크로드 유형 추천 nodegroup 전략 이유 피해야 할 설계
    일반 웹/백엔드 기본 worker 그룹, min 2 이상 가용성과 예측 가능한 확장성 확보 모든 역할을 한 그룹에 섞기
    배치/야간 작업 별도 worker 그룹, 조건 충족 시 scale-to-zero 유휴 자원 점유 감소 stateful 서비스와 동일 그룹 사용
    Ingress/Gateway 별도 flavor와 보수적 min/max 트래픽 급변 대응과 네트워크 역할 분리 일반 앱 노드와 동일 정책
    스토리지 민감 워크로드 AZ와 volume 정책을 고려한 별도 그룹 Cinder 바인딩 충돌 감소 Immediate 바인딩 남용

    6. OpenStack Magnum 장애는 생성 실패보다 상태 전이 실패가 더 까다롭습니다

    문서만 보면 클러스터 생성 성공 여부가 가장 중요해 보입니다. 그런데 실무에서는 CREATE_IN_PROGRESS가 왜 오래 가는지, DELETE_IN_PROGRESS에서 왜 자원이 남는지, 노드는 떴는데 왜 Ready가 안 되는지를 빨리 분리하는 쪽이 훨씬 중요합니다.

    저는 장애를 볼 때 계층을 네 개로 나눠서 봅니다.

    • Magnum API 계층: 요청이 접수되고 상태 전이가 시작됐는가
    • OpenStack 인프라 계층: Nova, Neutron, Octavia, Cinder 자원이 기대대로 생성됐는가
    • CAPI management cluster 계층: CRD와 controller가 reconciliation을 정상 수행하는가
    • 워크로드 클러스터 계층: kubelet, CNI, CSI, addon이 정상 기동하는가

    이 구분 없이 한 화면만 보면 시간이 꽤 많이 날아갑니다. 아래처럼 대조해 보는 습관이 실제로 편합니다.

    openstack coe cluster show prod-k8s-01
    openstack coe nodegroup list prod-k8s-01
    openstack coe nodegroup show prod-k8s-01 general-workers
    openstack server list --name prod-k8s-01
    openstack loadbalancer list
    kubectl --kubeconfig /etc/magnum/kubeconfig get clusters.cluster.x-k8s.io -A
    kubectl --kubeconfig /etc/magnum/kubeconfig get machinedeployments.cluster.x-k8s.io -A
    kubectl --kubeconfig /etc/magnum/kubeconfig get openstackmachines.infrastructure.cluster.x-k8s.io -A

    이 명령 묶음이 좋은 이유는 분명합니다. Magnum에서 보이는 추상 상태와 CAPI에서 실제 reconcile 중인 객체 상태를 한 번에 비교할 수 있기 때문입니다.

    7. 자주 막히는 실패 모드와 원인

    7-1. Pod/Service CIDR 겹침: 증상은 Kubernetes인데 원인은 주소 설계일 때가 많습니다

    최신 설정 레퍼런스의 기본값은 fixed_subnet_cidr=10.0.0.0/24, pod_network_cidr=10.100.0.0/16, service_network_cidr=172.24.0.0/13입니다. 공식 문서도 Pod/Service CIDR가 OpenStack provider나 external network subnet과 겹치면 안 된다고 설명합니다.

    현장에서는 CNI부터 의심하기 쉽지만, 실제 원인이 Neutron 주소계획 충돌인 경우가 정말 있습니다. 이 부분은 감으로 보지 말고 숫자로 대조하는 게 빠릅니다.

    openstack subnet list
    openstack network list
    openstack coe cluster template show k8s-capi-template -f yaml
    openstack coe cluster show prod-k8s-01 -f yaml
    kubectl get nodes -o wide
    kubectl get pods -A -o wide

    7-2. Cilium 선택: 지원과 운영 추천은 다른 말입니다

    공식 릴리즈 노트에는 network_driver로 calico와 cilium을 선택할 수 있다고 나옵니다. 다만 magnum-capi-helm 구성 문서는 현재 정기 테스트가 Calico 중심이라고 적고 있습니다. 그래서 제 추천은 단순합니다. 운영 서비스 중심이면 Calico, 특정 네트워크 기능 검증이 목적이면 Cilium입니다.

    7-3. scale-to-zero 실패: autoscaling보다 버전 매트릭스를 먼저 봐야 합니다

    min_node_count=0이 안 먹는다면 autoscaler 설정만 볼 게 아닙니다. 공식 릴리즈 노트는 차트와 provider 버전 조건이 맞지 않으면 명시적으로 막는다고 설명합니다. 그래서 scale-to-zero 같은 기능은 사용자 문서보다 플랫폼 지원 매트릭스를 먼저 정리해 두는 게 훨씬 낫습니다.

    7-4. DELETE_IN_PROGRESS 잔류: 상태 표시와 실자원 정리는 다를 수 있습니다

    최신 릴리즈 노트에는 non-default node group 삭제 시 DELETE_IN_PROGRESS에 머물고 VM이 남는 이슈가 수정됐다고 나옵니다. 실무적으로 중요한 포인트입니다. 화면상 삭제 중인데 실제 자원 점유가 계속될 수 있기 때문이죠.

    • Magnum 상태: nodegroup 또는 cluster 상태 전이
    • 실자원 상태: Nova 인스턴스, 로드밸런서, 볼륨 잔존 여부

    7-5. 인증서 저장: 동작보다 수명주기 관리가 더 중요합니다

    Magnum 설치 가이드는 kubectl 접근용 TLS 인증서를 저장할 때 Barbican 사용을 권장합니다. 데이터베이스 저장도 가능하지만, 운영 환경에서는 누가 접근을 통제하고 어떻게 회전하고 감사 추적을 남길지가 더 중요하거든요. 이건 실제로 커질수록 차이가 크게 납니다.

    8. 무엇을 보면 정상이라고 판단할까

    클러스터가 생성됐다고 바로 정상 판정을 내리면 위험합니다. OpenStack 위의 KaaS는 클러스터 내부 상태와 OpenStack 연동 상태를 같이 봐야 하거든요. 저는 최소한 아래 네 묶음을 통과해야 초기 정상으로 봅니다.

    openstack coe cluster show prod-k8s-01 -f yaml
    kubectl get nodes
    kubectl get pods -A
    kubectl get storageclass
    kubectl get pvc -A
    kubectl cluster-info
    • Cluster 상태: 상태가 완료로 수렴하는지, API 주소가 기대대로 생성됐는지 확인합니다.
    • Node 상태: 모든 노드가 Ready인지 봅니다.
    • 스토리지 상태: 기본 StorageClass가 의도한 reclaim policy와 binding mode를 사용하는지 확인합니다.
    • API 접근 경로: 업그레이드 계획이 있다면 API endpoint가 로드밸런서 뒤에서 안정적으로 열리는지 확인해야 합니다.

    그리고 하나 더요. 정상 판정은 단발성 스냅샷보다 상태 전이의 일관성으로 보는 편이 낫습니다. 생성 직후 잠깐 좋아 보이는 건 큰 의미가 없더라고요.

    OpenStack Magnum으로 배포된 Kubernetes 클러스터 검증 화면과 상태 점검 개요

    클러스터 생성 완료 후 노드 상태, 스토리지 클래스, API 엔드포인트, 로드밸런서 연결 상태를 함께 검증하는 장면을 표현한 이미지입니다.

    9. 그래서 OpenStack Magnum은 언제 쓰고, 언제 쓰지 말아야 할까

    • OpenStack이 이미 조직의 핵심 플랫폼이고, 프로젝트 단위로 Kubernetes를 표준 서비스처럼 공급해야 한다면 Magnum을 검토할 가치가 충분합니다.
    • 기존 Heat 기반 Magnum 기억만으로 판단하면 안 됩니다. 공식 방향은 CAPI 계열에 집중돼 있습니다.
    • 퍼블릭 클라우드 managed Kubernetes 제약이 없고 OpenStack 통합 요구가 약하면 Magnum을 굳이 들고 오지 않는 편이 낫습니다.
    • 멀티테넌시, 내부망, 규제, 인증 통합, 스토리지 정책 일관성이 중요하면 Magnum 쪽 설득력이 커집니다.
    • 신규 구축이면 처음부터 CAPI Helm 기준으로 설계하는 편이 낫습니다.
    • 운영 안정성이 우선이면 Calico, 실험 목적이 분명할 때만 Cilium을 권합니다.
    • autoscaling이 필요하면 nodegroup 분리부터 먼저 설계해야 합니다.
    • 업그레이드를 생각한다면 API 로드밸런서를 전제로 잡는 편이 덜 아픕니다.
    OpenStack Magnum 도입 판단 기준과 선택 시나리오 요약 인포그래픽

    OpenStack Magnum을 도입해야 할 상황과 그렇지 않은 상황을 한눈에 비교하는 요약 이미지입니다.

    10. 결론: OpenStack Magnum은 이제야 자기 자리를 찾는 중입니다

    결론은 꽤 분명합니다. OpenStack Magnum은 지금 프라이빗 클라우드 안에서 Kubernetes를 OpenStack 자원처럼 제공하고 운영하려는 팀에게 다시 현실적인 선택지가 되고 있습니다. 유행이라서가 아니라 역할이 더 또렷해졌기 때문입니다.

    물론 환상은 버려야 합니다. Magnum을 넣는다고 운영이 자동으로 쉬워지지는 않습니다. 대신 운영 난이도가 개별 팀의 임시 스크립트와 수작업에서 플랫폼 차원의 제어로 옮겨갑니다. 이 차이가 꽤 큽니다.

    제 추천은 간단합니다. 기존 Heat 기반 환경은 CAPI 전환 검토를 시작하고, 신규 구축은 처음부터 CAPI Helm 기준으로 설계하세요. 반대로 OpenStack 통합 가치가 약한 조직이라면 외부 managed Kubernetes가 더 나을 수 있습니다. 이건 취향보다 운영 모델의 문제에 가깝습니다.

    다음 단계까지 이어간다면 두 가지를 먼저 정리해 두면 좋겠습니다. 하나는 관리 클러스터 운영 책임 주체, 다른 하나는 지원할 chart/provider 버전과 nodegroup 정책 매트릭스입니다. 이 두 가지가 정리되면 OpenStack Magnum이 훨씬 덜 추상적으로 보입니다.

    11. 참고한 공식 문서

  • [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 대시보드 오류를 겪고 계시다면, 위 순서대로만 점검해도 원인 범위를 꽤 빠르게 좁히실 수 있을 겁니다. 완벽한 정답보다, 재현 가능한 점검 루틴을 갖는 게 훨씬 강합니다.

  • [OpenStack] 오픈스택 비용 분석: 프로젝트별 자원 사용량 기반 차지백 모델

    [OpenStack] 오픈스택 비용 분석: 프로젝트별 자원 사용량 기반 차지백 모델

    [OpenStack] 오픈스택 비용 분석: 프로젝트별 자원 사용량 기반 차지백 모델

    오픈스택 비용 분석 이야기는 결국 운영팀과 서비스팀이 같은 숫자를 보느냐의 문제로 이어집니다. OpenStack(오픈스택)을 오래 만지다 보면 CPU는 누가 얼마나 썼는지, Block Storage(블록 스토리지)는 어느 프로젝트가 계속 늘리는지, 떠 있는 인스턴스는 왜 줄지 않는지 같은 질문이 계속 나오거든요. 저도 처음엔 단순히 Quota(쿼터)만 잘 걸면 되겠지 싶었는데, 실제로 운영해보니 그걸로는 안 되더라고요. **프로젝트 테넌트(Project/Tenant)별 자원 사용량을 근거로 한 차지백(Chargeback, 비용 청구) 모델**이 있어야 각 팀이 자기 사용량을 이해하고, 운영팀도 클라우드 비용 관리를 설득력 있게 할 수 있더라고요.

    특히 내부 프라이빗 클라우드에서는 퍼블릭 클라우드처럼 자동 청구서가 나오지 않으니, 오픈스택 비용 분석 체계를 직접 설계해야 합니다. 오늘은 제가 실제로 많이 부딪혔던 기준으로, 무엇을 측정할지, 어떻게 집계할지, 프로젝트별로 어떤 방식으로 금액화할지를 정리해보겠습니다. 복잡하게 시작하면 오래 못 갑니다. 그래서 이번 글은 작동하는 최소 모델부터 시작하는 방향으로 설명드릴게요.

    Keystone, Nova, Cinder, Glance, Ceilometer, Gnocchi, CloudKitty가 어떻게 연결되어 프로젝트별 비용 집계로 이어지는지 보여주는 개요 이미지입니다.

    왜 오픈스택 차지백이 필요한가

    쉽게 말해, 차지백은 "누가 얼마나 썼는지 보이고, 그에 맞게 비용을 배분하는 방식"입니다. Showback(쇼백, 사용량 공개만 하는 방식)에서 시작해 Chargeback(실제 비용 배분)으로 가는 경우가 많습니다.

    • 운영팀 입장: 증설 요청이 들어왔을 때 근거가 생깁니다.
    • 서비스팀 입장: 유휴 자원(idle resources)을 줄일 유인이 생깁니다.
    • 경영/관리 입장: 클라우드 비용 관리가 숫자로 보입니다.

    제가 처음 차지백 모델을 설계할 때 가장 많이 들었던 말이 "우린 그냥 공용 클라우드인데 굳이 계산해야 하나요?"였는데요, 몇 달만 지나면 분위기가 달라집니다. 누군가는 항상 더 많이 쓰고, 누군가는 자기가 손해 본다고 느끼거든요. 여기서 중요한 포인트! 차지백의 핵심은 완벽한 회계가 아니라, 합의 가능한 기준입니다.

    프로젝트 테넌트와 자원 사용량, 어디까지 볼 것인가

    OpenStack Identity(아이덴티티) 서비스인 Keystone(키스톤) 기준으로 Project(프로젝트)는 예전 표현으로 Tenant(테넌트)와 거의 같은 의미로 쓰입니다. 실제 운영 현장에서도 아직 프로젝트 테넌트라는 말을 섞어서 많이 쓰죠. 비용 배분의 기준 단위는 보통 이 프로젝트예요.

    그다음은 어떤 자원을 과금 대상으로 볼지 정해야 합니다. 저는 처음부터 너무 넓게 잡지 않는 걸 추천하는 편입니다.

    자원 영역 대표 서비스 과금 기준 예시 초기 적용 난이도
    Compute(컴퓨트) Nova vCPU, RAM, 인스턴스 가동 시간 낮음
    Block Storage(블록 스토리지) Cinder 볼륨 용량 GB, 스냅샷 용량 낮음
    Image(이미지) Glance 이미지 저장 용량 보통
    Object Storage(오브젝트 스토리지) Swift 저장 용량, 요청 수 보통
    Network(네트워크) Neutron Floating IP, LB, 트래픽 높음

    보통 처음에는 Compute + Volume만으로도 충분하거든요. 왜냐하면 이 두 항목이 가장 설명하기 쉽고, 프로젝트별 자원 사용량 변화가 잘 보이기 때문입니다. 반대로 Network egress(외부 송신 트래픽) 같은 항목은 측정과 합의가 조금 더 까다로워요.

    오픈스택 비용 분석의 기본 구조

    OpenStack Telemetry(텔레메트리) 쪽을 보면 Ceilometer(실로미터)가 미터(meter)와 샘플을 수집하고, 환경에 따라 Gnocchi(그노치) 같은 시계열 저장소와 함께 사용합니다. 그리고 CloudKitty(클라우드키티)는 공식 문서 기준으로 Rating-as-a-Service(과금/평가 서비스) 역할을 하는 프로젝트입니다. 즉, 사용량 수집과 요금 규칙 적용을 분리해서 생각하면 구조가 훨씬 명확해져요.

    1. Keystone에서 프로젝트 식별
    2. Nova, Cinder, Glance 등에서 자원 메타데이터 확인
    3. Ceilometer/Gnocchi로 사용량 데이터 수집
    4. CloudKitty 또는 별도 스크립트로 단가(rule) 적용
    5. 프로젝트별 월간 리포트 생성

    여기서 꼭 기억하실 부분이 있습니다. 사용량 데이터가 있다고 바로 비용 청구가 되는 게 아니더라고요. 측정값(Meter)과 과금 항목(Billable item)은 다르거든요. 예를 들어 CPU 사용률 자체보다는, 실제 운영에서는 할당된 vCPU 수와 인스턴스 실행 시간을 곱해서 보는 편이 훨씬 설명하기 쉽더라고요.

    오픈스택 차지백을 위한 Ceilometer와 CloudKitty 기반 비용 집계 파이프라인 이미지

    Telemetry 수집부터 프로젝트별 요금 계산, 리포트 생성까지 이어지는 파이프라인을 단계별로 표현한 이미지입니다.

    실전 구현 1: 최소 차지백 기준부터 정하기

    제가 직접 해보니 제일 먼저 해야 하는 건 도구 설치가 아니라 과금 기준표를 문서로 박는 일이었어요. 기준이 없으면 숫자가 나와도 싸움만 납니다 ㅎㅎ

    예를 들면 이런 식입니다.

    항목 과금 단위 설명
    vCPU vCPU-hour 인스턴스에 할당된 vCPU 수 x 실행 시간
    RAM GB-hour 할당 메모리 GB x 실행 시간
    Volume GB-month 볼륨 크기 기준 월간 보유량
    Snapshot GB-month 스냅샷 저장량 기준
    Floating IP 개수/월 예약 자원으로 단순화 가능

    이 모델의 장점은 간단해요.

    • 프로젝트 테넌트별 설명이 쉽습니다.
    • 월별 추세 비교가 가능합니다.
    • Idle VM(유휴 가상머신) 정리에 바로 효과가 납니다.

    반대로 단점도 물론 있어요.

    • 실사용 CPU와 할당 CPU가 다를 수 있습니다.
    • Overcommit(오버커밋) 환경을 100% 반영하지 못합니다.
    • 네트워크 사용량까지 정밀하게 포함하긴 어렵습니다.

    그래도 첫 버전은 이 정도가 딱 좋더라고요. 처음부터 완벽한 원가 계산으로 들어가면 운영팀만 지쳐요.

    실전 구현 2: OpenStack CLI로 프로젝트와 자원 목록 뽑기

    이제 실무적으로 데이터를 뽑아보겠습니다. OpenStackClient(오픈스택 클라이언트)가 있다는 전제입니다.

    1. 프로젝트 목록 확인

    openstack project list -f value -c ID -c Name

    이 명령으로 프로젝트 ID와 이름을 간단히 가져와요. 나중에 리포트에서 사람이 읽기 좋은 이름을 붙일 때 필요합니다.

    2. 인스턴스 목록 확인

    openstack server list --all-projects -f json

    기본 목록은 여기까지인데, 실제 비용 계산에서는 Flavor(플레이버) 정보가 꼭 필요하더라고요. vCPU와 RAM이 여기 들어 있으니까요.

    3. 볼륨 목록 확인

    openstack volume list --all-projects -f json

    볼륨은 생각보다 누수 포인트가 많아요. 인스턴스는 지워졌는데 볼륨은 남아 있는 경우, 스냅샷만 계속 쌓이는 경우 정말 흔하거든요.

    4. 사용량 통계 확인

    openstack usage list --start 2026-08-01 --end 2026-08-31

    환경에 따라 제공 정보가 제한적일 수 있지만, 월간 사용량 감을 잡는 데는 꽤 유용하더라고요.

    실전 구현 3: 간단한 비용 계산 스크립트 예시

    처음부터 CloudKitty를 붙이지 않고, CSV 또는 JSON 기반으로 먼저 검증하는 방식을 추천드립니다. 저도 실제로 써보니까 이 단계가 있어야 과금 로직을 눈으로 검산할 수 있어서 훨씬 편하더라고요.

    from decimal import Decimal
    
    RATES = {
        "vcpu_hour": Decimal("15"),
        "ram_gb_hour": Decimal("5"),
        "volume_gb_month": Decimal("1000"),
    }
    
    project_usage = {
        "team-a": {
            "vcpu_hours": Decimal("240"),
            "ram_gb_hours": Decimal("960"),
            "volume_gb_month": Decimal("500"),
        },
        "team-b": {
            "vcpu_hours": Decimal("120"),
            "ram_gb_hours": Decimal("480"),
            "volume_gb_month": Decimal("1200"),
        },
    }
    
    for project, usage in project_usage.items():
        total = (
            usage["vcpu_hours"] * RATES["vcpu_hour"]
            + usage["ram_gb_hours"] * RATES["ram_gb_hour"]
            + usage["volume_gb_month"] * RATES["volume_gb_month"]
        )
        print(project, total)

    숫자 자체는 예시입니다. 여기서 중요한 건 요금 규칙과 사용량 데이터를 분리하는 구조예요. 그러면 나중에 단가 조정, 할인 정책, 특정 프로젝트 예외 처리가 훨씬 쉬워져요.

    실제 운영에서는 보통 아래 흐름으로 갑니다.

    1. OpenStack API나 리포트로 원천 데이터 추출
    2. 프로젝트 ID 기준으로 그룹화
    3. vCPU-hour, GB-hour, GB-month 같은 과금 단위로 변환
    4. 단가 테이블 적용
    5. 월간 리포트 CSV/HTML/PDF 생성

    실전 구현 4: CloudKitty를 붙일 때 보는 포인트

    CloudKitty는 OpenStack용 차지백/레이팅에 특화된 프로젝트더라고요. 규모가 커지면 검토할 가치가 있어요. 공식 문서 기준으로 hashmap(해시맵) 방식의 rating module(평가 모듈)을 사용해 규칙 기반 요금 계산을 구성할 수 있거든요.

    cloudkitty module list

    이런 식으로 모듈 상태를 먼저 확인하고, 어떤 rating module을 쓸지 정합니다. 다만 여기서 한 가지. CloudKitty를 도입한다고 해서 비용 모델 설계가 자동으로 해결되는 건 아니더라고요. 오히려 내부 단가 기준과 메타데이터 정합성이 훨씬 더 중요해요.

    제가 삽질했던 포인트는 딱 세 가지더라고요.

    • 프로젝트명 변경 이력 관리가 안 되어 과거 리포트와 현재 명칭이 안 맞음
    • 삭제된 인스턴스의 사용 이력을 어디까지 반영할지 기준이 없음
    • Volume과 Snapshot의 집계 시점을 월말 기준으로 볼지 평균 보유량으로 볼지 합의가 안 됨

    이런 건 기술 문제가 아니라 운영 기준 문제예요. 그래서 저는 항상 먼저 문서화해요.

    프로젝트별 자원 사용량과 오픈스택 비용 분석 결과를 보여주는 대시보드 이미지

    프로젝트별 vCPU, 메모리, 볼륨 사용량과 월간 비용이 한눈에 보이는 내부 대시보드 예시 이미지입니다.

    ⚠️ 주의사항: 실제로 자주 터지는 문제들

    여기서부터는 정말 현업 냄새 나는 구간입니다. 저도 처음엔 이게 뭔가 싶었는데, 몇 번 월말 정산을 돌려보면 패턴이 보이더라고요.

    1. Meter와 Billing Unit을 혼동하는 문제

    Ceilometer에서 수집한 meter(미터)는 정말 많아요. 하지만 다 과금에 쓸 수 있는 건 아니더라고요. 예를 들어 CPU 누적 시간, 메모리 사용률 같은 값은 관제에는 좋은데, 비용 청구 기준으로는 오히려 설명하기가 어려워요.

    해결법: 운영팀이 설명 가능한 단위로 단순화하세요. vCPU-hour, GB-hour, GB-month가 시작점으로 좋습니다.

    2. 삭제 자원 누락 문제

    월중에 생성됐다가 삭제된 인스턴스는 목록 조회만으로는 빠질 수 있거든요. 이 때문에 "분명 썼는데 왜 청구가 안 됐지?" 또는 반대로 "왜 이 숫자가 나오지?"가 생깁니다.

    해결법: 상태 스냅샷만 보지 말고, 사용량 기록 또는 이벤트 이력을 기준으로 월간 집계하세요.

    3. 프로젝트 메타데이터 불일치

    프로젝트명, 비용 센터(cost center), 담당 조직 정보가 제각각이면 리포트가 엉망이 되더라고요.

    해결법: Keystone 프로젝트에 연결되는 관리용 메타데이터 체계를 따로 두고, 리포트 생성 전에 매핑 테이블을 정리하세요.

    4. 스토리지 과금 시점 논쟁

    볼륨 용량은 월말 시점만 볼지, 일평균 보유량을 볼지에 따라 결과가 달라지더라고요. 둘 다 틀린 건 아닌데, 기준이 매달 바뀌면 신뢰를 잃어요.

    해결법: 정책을 먼저 고정하고, 월별로 동일하게 적용하세요.

    검증: 리포트가 맞는지 어떻게 확인할까

    완성된 차지백 모델은 반드시 검증 단계를 거쳐야 하더라고요. 저는 보통 아래 3단계로 확인하는 편이에요.

    1. 샘플 프로젝트 1개를 골라 수작업으로 계산해 보기
    2. OpenStack CLI 결과와 리포트 결과를 대조하기
    3. 운영팀과 서비스팀이 함께 숫자를 리뷰하기

    예를 들면 이런 검증표를 만들어두면 좋습니다.

    검증 항목 원천 데이터 리포트 값 확인 포인트
    인스턴스 수 server list 월간 집계 수 삭제 자원 포함 여부
    vCPU 총합 flavor 매핑 vCPU-hour 가동 시간 반영 여부
    볼륨 총합 volume list GB-month Detached volume 포함 여부
    프로젝트명 project list 청구서 표기명 매핑 테이블 일치 여부

    이 과정을 지나면 드디어 “아, 이제 숫자가 말이 된다” 싶은 순간이 와요. 그때부터는 Showback 보고서만 돌려도 팀들이 먼저 반응하더라고요. 어떤 팀은 오래된 테스트 인스턴스를 지우고, 어떤 팀은 Snapshot 정리를 하더라고요. 이거 진짜 편합니다. 비용 청구 이전에 자원 최적화 효과가 먼저 나타나거든요.

    오픈스택 차지백 적용 전후의 비용 가시성 개선을 보여주는 인포그래픽

    유휴 자원 감소, 프로젝트별 비용 가시성 향상, 월간 리포트 정착 전후를 비교하는 요약 인포그래픽입니다.

    정리: 오픈스택 비용 분석은 완벽함보다 지속 가능성이 중요합니다

    오늘 정리한 내용을 한 문장으로 요약하면 이래요. 오픈스택 비용 분석은 Telemetry(텔레메트리) 수집보다, 프로젝트 테넌트 기준의 합의 가능한 과금 모델을 만드는 일이 훨씬 더 중요하더라고요.

    제가 여러 번 해보니 가장 현실적인 순서는 아래와 같더라고요.

    1. Compute와 Volume만으로 시작
    2. 프로젝트별 자원 사용량 리포트부터 정착
    3. Showback으로 1~2개월 운영
    4. 이후 Chargeback으로 확대
    5. 필요하면 CloudKitty 같은 전용 도구 도입

    혹시 지금 오픈스택 차지백을 준비 중이신가요? 그렇다면 처음부터 거대한 과금 엔진을 만들기보다, 설명 가능한 숫자를 먼저 만드는 걸 강력 추천해요. 그게 결국 오래 갑니다. 다음 글에서는 프로젝트별 태깅 전략과 비용 센터 매핑, 그리고 리포트 자동화 파이프라인을 더 깊게 다뤄볼 생각입니다. 이전 글에서 다뤘던 OpenStack 운영 표준화 이야기도 같이 보시면 흐름 잡는 데 도움이 되실 거예요.

    FAQ: 현장에서 자주 받는 질문

    Q1. 오픈스택 비용 분석은 반드시 CloudKitty가 있어야 하나요?

    아니에요. 초기에는 OpenStack API 결과와 간단한 스크립트만으로도 충분히 시작할 수 있어요. 다만 규모가 커지고 규칙이 복잡해지면 전용 도구 검토 가치가 있더라고요.

    Q2. 프로젝트 테넌트 기준이 항상 맞나요?

    대부분의 내부 차지백에서는 가장 관리하기 쉬운 기준이에요. 다만 조직 구조와 다르면 프로젝트와 비용 센터 매핑 테이블을 별도로 두는 편이 좋아요.

    Q3. CPU 사용률 기반 과금이 더 정확한 것 아닌가요?

    정확성만 보면 일리가 있지만, 실제 운영에서는 설명 가능성과 재현 가능성이 훨씬 더 중요하더라고요. 그래서 할당량 기반의 vCPU-hour 모델이 출발점으로 많이 쓰여요.

  • [OpenStack] 오픈스택 운영 회고: 안정성, 비용, 그리고 인프라 관리의 핵심

    [OpenStack] 오픈스택 운영 회고: 안정성, 비용, 그리고 인프라 관리의 핵심

    오픈스택 운영 회고: 안정성, 비용, 그리고 인프라 관리의 핵심

    오픈스택 운영 회고라는 주제로 글을 쓰게 된 이유는 단순합니다. 3년 정도 직접 굴려보니, 처음 기대했던 것과 실제 운영에서 마주치는 현실이 꽤 다르더라고요. 처음엔 “우리도 프라이빗 클라우드(Private Cloud, 사설 클라우드) 하나 제대로 만들어보자” 하고 시작했는데, 막상 돌려보면 기술보다 운영 체력이 더 중요했습니다. 특히 오픈스택 안정성, 클라우드 비용, 그리고 팀의 인프라 관리 방식이 서로 얽혀 있어서, 한 군데만 잘한다고 끝나지 않거든요.

    제가 직접 해보니 오픈스택은 분명히 강력합니다. 하지만 강력하다는 말이 곧 편하다는 뜻은 아니었습니다. 기능은 많고 유연성도 높지만, 그만큼 설계와 운영 기준이 없으면 금방 복잡도가 올라갑니다. 혹시 지금 오픈스택 도입을 고민 중이시거나, 이미 운영 중인데 “왜 이렇게 손이 많이 가지?” 싶은 분이라면 오늘 글이 꽤 현실적인 체크리스트가 될 겁니다.

    컨트롤 플레인과 컴퓨트, 스토리지, 네트워크가 어떻게 나뉘는지 한눈에 보여주는 아키텍처 이미지입니다.

    오픈스택 운영 회고를 시작하기 전에: 쉽게 말해 오픈스택이란?

    쉽게 말해 오픈스택(OpenStack)은 가상 서버, 네트워크, 스토리지 같은 인프라 자원을 API로 다루게 해주는 클라우드 운영 프레임워크입니다. 퍼블릭 클라우드(Public Cloud, 공개형 클라우드)에서 버튼 몇 번으로 VM을 만드는 경험을, 우리 데이터센터나 사내 서버 환경에서 구현한다고 생각하시면 이해가 빠릅니다.

    근데 여기서 오해하면 안 되는 게 하나 있어요. 오픈스택은 제품 하나를 설치하면 끝나는 패키지가 아니라, 여러 컴포넌트가 맞물려 돌아가는 생태계에 가깝습니다. 예를 들면 Nova(노바, 컴퓨트 관리), Neutron(뉴트론, 네트워크 관리), Cinder(신더, 블록 스토리지), Glance(글랜스, 이미지 관리), Keystone(키스톤, 인증) 같은 서비스가 서로 의존합니다. 처음엔 이게 뭔가 싶었는데, 실제로 써보니까 문제 하나가 다른 레이어로 전파되는 경우가 많아서 구조를 이해하는 게 정말 중요했습니다.

    영역 대표 컴포넌트 역할 운영 포인트
    인증 Keystone 사용자와 서비스 인증 토큰, 권한, 서비스 엔드포인트 정리
    컴퓨트 Nova 가상머신 생성과 스케줄링 하이퍼바이저 상태, 배치 정책 확인
    네트워크 Neutron 가상 네트워크와 라우팅 장애 시 추적 난도가 높음
    스토리지 Cinder, Swift 블록/오브젝트 스토리지 제공 백엔드 성능과 장애 복구 설계 중요
    이미지 Glance VM 이미지 관리 이미지 표준화가 운영 품질 좌우

    3년 운영하면서 느낀 핵심: 안정성은 소프트웨어보다 운영 기준에서 나옵니다

    여기서 중요한 포인트! 많은 분들이 오픈스택 안정성을 이야기할 때 소프트웨어 자체의 완성도만 떠올리시는데, 제 경험상 운영 결과를 가르는 건 오히려 다음 세 가지였습니다.

    • 변경 관리(Change Management, 변경 관리)가 있는가
    • 관측성(Observability, 모니터링/로그/메트릭 가시성)이 충분한가
    • 장애 복구 시나리오를 문서가 아니라 실제로 검증했는가

    처음 1년은 솔직히 삽질 좀 했습니다 ㅎㅎ 서비스는 떠 있는데 사용자 입장에서는 VM이 안 만들어지고, 네트워크는 붙은 것처럼 보이는데 외부 통신이 안 되고, 스토리지는 정상인데 attach가 지연되는 식의 애매한 문제가 많았거든요. 그때 깨달은 게 있습니다. 오픈스택은 장애가 안 나는 시스템이 아니라, 장애를 빨리 좁혀갈 수 있게 만들어야 하는 시스템이라는 점입니다.

    그래서 운영 기준을 바꿨습니다. 컴포넌트별 헬스체크를 따로 보고, API 응답 시간과 큐 적체 여부를 함께 보고, 배포 전에 롤백 경로를 먼저 정리했습니다. 그 뒤로 체감 안정성이 많이 올라갔습니다. 실제로 써보니까 “문제가 줄었다”기보다 “문제가 생겨도 덜 무섭다” 쪽이 더 정확하더라고요.

    비용 관점에서 본 오픈스택: 라이선스보다 사람이 비쌉니다

    클라우드 비용 이야기도 빼놓을 수 없죠. 오픈스택을 검토할 때 흔히 “오픈소스니까 싸지 않나요?”라는 질문을 받습니다. 반은 맞고 반은 틀립니다. 라이선스 비용만 보면 유리할 수 있습니다. 하지만 실제 총비용(TCO, Total Cost of Ownership)을 보면 얘기가 달라집니다.

    제가 정리한 기준은 이렇습니다.

    1. 하드웨어 조달 비용이 들어갑니다.
    2. 네트워크 설계와 스토리지 백엔드 운영 비용이 들어갑니다.
    3. 장애 대응 가능한 운영 인력 비용이 꽤 큽니다.
    4. 자동화와 표준화가 부족하면 사람 시간이 계속 녹습니다.

    특히 클라우드 비용에서 가장 자주 놓치는 부분이 “기회비용”입니다. 퍼블릭 클라우드라면 몇 분 안에 끝났을 일을, 온프레미스 OpenStack 환경에서는 승인, 자원 계획, 이미지 검증, 네트워크 정책 반영까지 여러 단계를 거쳐야 할 수 있거든요. 물론 규모가 커지고 워크로드가 고정적이면 오픈스택이 유리한 구간도 분명 있습니다. 다만 그 전제는 운영 자동화가 어느 정도 완성되어 있어야 한다

    항목 퍼블릭 클라우드 오픈스택 기반 프라이빗 클라우드
    초기 구축 낮음 높음
    확장 속도 빠름 설계 수준에 따라 다름
    운영 자유도 제한적 매우 높음
    인력 의존도 상대적으로 낮음 높음
    비용 예측 사용량 기반 고정비와 운영비 혼합

    실전 구현: 제가 운영 중 반복해서 확인한 기본 점검 절차

    이제 조금 실무적으로 가보겠습니다. 아래 절차는 제가 정기 점검이나 장애 초기 대응 때 자주 확인하던 흐름입니다. 배포 방식이 다르더라도 기본 개념은 비슷합니다.

    1. 서비스 상태 확인

    openstack service list
    openstack compute service list
    openstack network agent list
    openstack hypervisor list

    이 단계에서는 서비스가 “떠 있느냐”보다 비정상적으로 down 처리된 항목이 없는지를 먼저 봅니다. 특히 컴퓨트 노드가 보이는데 스케줄링이 안 되는 경우가 있어서, 단순 프로세스 상태만 믿으면 안 되더라고요.

    2. 리소스 생성 동작 확인

    openstack image list
    openstack flavor list
    openstack network list
    openstack server create --flavor m1.small --image test-image --network private-net test-vm
    openstack server list

    테스트 VM 하나를 실제로 올려보는 게 중요합니다. 모니터링이 모두 초록색이어도, 실제 프로비저닝(Provisioning, 자원 생성 절차) 단계에서 실패하는 경우가 꽤 있습니다. 저도 처음엔 대시보드만 보고 안심했었는데, 실사용 검증이 빠지면 꼭 뒤에서 터지더라고요.

    서비스 목록 확인, 하이퍼바이저 점검, 테스트 VM 생성 검증까지 이어지는 운영 점검 흐름을 설명하는 이미지입니다.

    3. 네트워크 연결성 확인

    openstack port list --server test-vm
    openstack floating ip list
    ping -c 4 <floating-ip>
    ssh -i ~/.ssh/id_rsa cloud-user@<floating-ip>

    네트워크는 늘 마지막까지 확인해야 합니다. Neutron(뉴트론, 네트워크 관리)은 구성 자유도가 큰 만큼 문제 원인도 다양합니다. 보안 그룹(Security Group, 가상 방화벽 규칙), 라우터, 플로팅 IP(Floating IP, 외부 연결용 IP), L2/L3 에이전트 상태를 같이 봐야 하거든요.

    4. 운영 표준 예시

    checks:
      - name: keystone-api
        type: http
        target: internal-endpoint
      - name: nova-services
        type: cli
        command: openstack compute service list
      - name: neutron-agents
        type: cli
        command: openstack network agent list
      - name: test-instance-boot
        type: workflow
        enabled: weekly
      - name: floating-ip-connectivity
        type: workflow
        enabled: weekly

    이건 실제 제품 설정이라기보다 운영 체크 항목을 어떻게 표준화할지 보여주는 예시입니다. 핵심은 정적 상태 점검과 동적 사용자 시나리오 점검을 분리해서 관리하는 겁니다.

    ⚠️ 트러블슈팅: 3년 동안 자주 만난 문제들

    여기서는 정말 많이 겪었던 문제만 추려보겠습니다. 혹시 이런 경험 있으신가요? 장애 알람은 없는데 사용자만 불편하다고 하는 상황이요. 오픈스택에서는 꽤 흔합니다.

    1. 서비스는 정상인데 VM 생성이 지연되는 문제

    처음엔 스케줄러(Scheduler, 자원 배치기) 문제인가 싶었는데, 실제로는 백엔드 스토리지 응답 지연이나 이미지 다운로드 지연이 원인인 경우가 있었습니다. 겉보기엔 Nova 문제처럼 보이는데, 파고들면 Glance나 스토리지 레이어였던 거죠. 이럴 땐 API 로그만 보지 말고 생성 요청이 어느 단계에서 오래 머무는지를 추적해야 합니다.

    2. 네트워크 연결이 간헐적으로 실패하는 문제

    이건 진짜 골치 아팠습니다. 제가 직접 해보니 네트워크 문제는 재현이 안 될 때가 가장 힘들더라고요. 보안 그룹 규칙, MTU, 라우팅 경로, 에이전트 상태가 모두 맞물리기 때문에 증상만 보고 섣불리 판단하면 시간만 씁니다. 그래서 저는 네트워크 이슈가 나면 아래 순서로 봤습니다.

    1. 포트 상태와 바인딩 확인
    2. 보안 그룹과 라우터 정책 확인
    3. 네임스페이스(namespace, 격리된 네트워크 공간) 내부 ping 확인
    4. 오버레이 네트워크 오작동 여부 확인

    3. 운영자만 아는 수동 절차가 쌓이는 문제

    이건 기술 문제라기보다 조직 문제에 가깝습니다. 누가 퇴근하면 아무도 못 건드리는 작업이 생기기 시작하면, 그 순간부터 안정성은 떨어진다고 봐야 합니다. 저도 한동안 특정 점검 절차를 머릿속으로만 기억하고 있었는데, 나중에 돌아보니 그게 제일 위험했어요. 문서화와 자동화가 귀찮아 보여도 결국 가장 싸게 먹힙니다.

    openstack server show test-vm
    openstack console log show test-vm
    openstack port show <port-id>
    openstack hypervisor stats show

    문제가 생기면 위 같은 기본 명령어부터 차근차근 보는 습관이 중요합니다. 급하다고 바로 재시작부터 하면 원인 단서가 금방 사라지거든요.

    검증과 결과: 운영이 편해졌다고 느낀 순간

    운영은 결국 체감이 중요합니다. 제가 오픈스택 경험을 통해 “이제 좀 자리 잡았구나” 느낀 기준은 화려한 기능 추가가 아니었습니다.

    • 새 VM 생성 성공 여부를 운영자가 감으로 판단하지 않게 됐을 때
    • 장애 발생 시 어느 레이어부터 볼지 팀 내 공통 언어가 생겼을 때
    • 정기 점검 결과가 사람마다 다르지 않게 됐을 때
    • 비용 논의에서 라이선스가 아니라 운영 방식이 중심이 됐을 때

    이런 변화가 생기면 인프라 관리의 수준이 한 단계 올라갑니다. 이전에는 문제를 “해결”하는 데 집중했다면, 이후에는 문제를 “예측 가능하게 만드는 것”으로 관점이 바뀌더라고요. 이 차이가 꽤 큽니다.

    오픈스택 경험 기반 운영 결과와 안정성 지표 이미지

    서비스 상태, 자원 사용량, 장애 추적 포인트를 한 화면에서 보는 운영 대시보드 느낌의 이미지입니다.

    오픈스택을 추천할 때와 말릴 때

    모든 환경에 오픈스택이 정답은 아닙니다. 이건 꼭 말씀드리고 싶었습니다. 제가 멘토처럼 조언드린다면 기준은 꽤 명확합니다.

    추천하는 경우

    • 워크로드가 비교적 예측 가능하고 장기 운영 비중이 큰 경우
    • 네트워크, 스토리지, 가상화에 대한 내부 이해도가 있는 경우
    • 자동화와 운영 표준화에 시간을 투자할 수 있는 경우
    • 데이터 주권이나 내부 통제가 중요한 경우

    말리고 싶은 경우

    • 소수 인원이 모든 걸 동시에 맡아야 하는 경우
    • 빠른 기능 출시가 최우선이고 인프라가 차별점이 아닌 경우
    • 장애 대응 경험이 부족한 상태에서 복잡한 네트워크 구성을 바로 가져가려는 경우
    • 운영 인력 확보 없이 비용 절감만 기대하는 경우

    근데 여기서 중요한 건, 말린다고 해서 기술이 나쁘다는 뜻은 아니라는 점입니다. 도구의 성격과 조직의 운영 성숙도가 맞아야 한다

    정리와 FAQ: 놓치지 말아야 할 것들

    오픈스택 운영 회고를 한 줄로 정리하면 이렇습니다. 안정성은 아키텍처보다 운영 기준에서 나오고, 비용은 라이선스보다 사람과 절차에서 갈립니다. 저도 처음엔 기능 중심으로 봤는데, 결국 오래 가는 환경은 단순하고 반복 가능하게 만든 환경이었습니다.

    다음 글에서는 홈랩(Home Lab, 개인 실험실) 기준으로 소규모 OpenStack 검증 환경을 어떻게 꾸렸는지, 그리고 어떤 식으로 실험 순서를 잡았는지 다뤄볼 예정입니다. 이전 글에서 다뤘던 가상화 레이어 점검 방법과 함께 보시면 더 이해가 쉬우실 겁니다.

    자주 묻는 질문

    Q. 오픈스택은 무조건 비용 절감에 유리한가요?

    A. 아닙니다. 하드웨어와 운영 인력, 자동화 수준까지 같이 봐야 합니다. 특히 초반에는 생각보다 손이 많이 갑니다.

    Q. 오픈스택 안정성을 높이려면 가장 먼저 뭘 해야 하나요?

    A. 서비스 상태 확인보다 먼저 운영 기준을 표준화하는 게 좋습니다. 누가 봐도 같은 절차로 점검할 수 있어야 합니다.

    Q. 오픈스택 경험이 적은 팀도 시작할 수 있을까요?

    A. 가능합니다. 다만 작은 범위에서 시작하고, 네트워크와 스토리지 복잡도를 초반에 과하게 올리지 않는 게 좋습니다.

    오픈스택 운영 회고의 핵심 교훈을 정리한 요약 이미지

    안정성, 비용, 운영 기준 세 가지 핵심 교훈을 요약해서 보여주는 마무리 인포그래픽 이미지입니다.

  • [OpenStack] 오픈스택 쿼터 초과 장애 해결: 테넌트 자원 고갈 진단부터 관리까지

    [OpenStack] 오픈스택 쿼터 초과 장애 해결: 테넌트 자원 고갈 진단부터 관리까지

    [OpenStack] 오픈스택 쿼터 초과 장애 해결: 테넌트 자원 고갈 진단부터 관리까지

    운영하다 보면 제일 당황스러운 순간이 있어요. 분명 하이퍼바이저(Hypervisor, 가상화 호스트) 자원은 남아 있는데 사용자 쪽에서는 인스턴스(Instance, 가상머신)가 더 이상 생성되지 않는 상황이거든요. 저도 홈랩(Home Lab, 개인 실험 환경)과 실무 환경에서 비슷한 일을 몇 번 겪었는데, 처음엔 컴퓨트 노드(Compute Node) 장애인가 싶어서 로그만 한참 뒤졌습니다. 그런데 원인은 의외로 단순했어요. 바로 오픈스택 쿼터 초과였거든요. 특히 여러 프로젝트(Project, 테넌트 단위)와 팀이 함께 쓰는 환경에서는 오픈스택 테넌트별 자원 제한을 제대로 보지 않으면, 겉으로는 인프라 장애처럼 보여도 실제로는 정책 문제인 경우가 대부분이에요.

    혹시 이런 경험 있으신가요? CPU나 메모리는 남아 있는데 신규 서버가 안 떠서 급하게 노바(Nova), 신더(Cinder), 뉴트론(Neutron) 로그부터 보는 경우요. 저도 그랬습니다 ㅎㅎ 이번 글에서는 제가 실제로 많이 겪었던 패턴을 바탕으로, 자원 고갈처럼 보이는 쿼터 이슈를 어떤 순서로 확인하고, 어떻게 복구하고, 이후엔 어떤 식으로 쿼터 관리 체계를 잡아야 덜 고생하는지 정리해보겠습니다.

    오픈스택 쿼터 초과와 테넌트별 자원 흐름을 설명하는 아키텍처 다이어그램

    프로젝트별로 컴퓨트, 스토리지, 네트워크 자원이 어떻게 제한되고 소비되는지 한눈에 보여주는 개요 이미지입니다.

    1. 왜 오픈스택 쿼터 초과가 장애처럼 보일까

    쉽게 말해 쿼터(Quota, 사용 한도)는 멀쩡한 클라우드 자원 앞에 달린 논리적 문지기예요. 물리 자원이 남아 있어도 테넌트에 할당된 한도를 넘으면 API 단계에서 요청이 거절됩니다. 그래서 현상만 보면 진짜 자원 부족과 거의 비슷해 보여요.

    • 인스턴스 생성 실패: vCPU, RAM, instances 한도 초과
    • 볼륨 생성 실패: 볼륨 수 또는 총 용량 한도 초과
    • 포트 생성 실패: 네트워크 포트 수 제한 도달
    • 플로팅 IP 부족처럼 보이는 현상: 실제 풀 부족이 아니라 프로젝트 쿼터 제한일 수 있음

    현장에서 무서운 건 여기서부터예요. 사용자 입장에서는 그냥 "서버가 안 만들어진다"로 보이고, 운영자도 로그만 대충 보면 스케줄러(Scheduler, 배치 결정기) 문제로 오해하기 쉽거든요. 오픈스택 장애 해결에서 중요한 건, 물리 자원 확인 전에 논리 자원 제한부터 보는 습관이에요. 이 순서 하나로 장애 대응 시간이 꽤 줄어듭니다.

    2. 핵심 개념 정리: 테넌트, 쿼터, 사용량

    저도 처음엔 프로젝트(Project)와 테넌트(Tenant) 용어가 좀 헷갈렸는데요. 실무에서는 거의 같은 맥락으로 쓰는 경우가 많습니다. 중요한 건 "누가 얼마까지 쓸 수 있나"를 나누는 단위라는 점입니다.

    항목 의미 장애와의 관련성
    Tenant / Project 자원을 사용하는 관리 단위 쿼터가 적용되는 기준
    Quota 인스턴스, 코어, RAM, 볼륨, 포트 등의 상한 초과 시 API 요청 실패
    Usage 현재 사용 중인 실제 자원량 삭제 누락, 유령 리소스 확인 포인트
    Limit 허용된 최대치 운영 정책과 연결됨

    여기서 중요한 포인트! 오픈스택 쿼터 초과는 꼭 사용자가 과하게 쓴 경우만 의미하지 않아요. 삭제했다고 생각한 리소스가 실제로는 남아 있거나, 포트(Port, 네트워크 연결 단위)나 스냅샷(Snapshot, 시점 복사본)처럼 눈에 잘 안 띄는 리소스가 누적돼도 발생합니다. 제가 직접 해보니 특히 테스트 환경에서 이런 잔여 리소스가 잘 쌓이더라고요.

    자주 막히는 리소스 종류

    • cores(vCPU 코어 수)
    • ram(메모리 총량)
    • instances(가상머신 개수)
    • volumes(볼륨 개수)
    • gigabytes(볼륨 총 용량)
    • ports(네트워크 포트 수)
    • floating-ips(공인 IP 할당 수)

    3. 증상 확인: 에러 메시지부터 방향을 잡아야 해요

    장애 대응 초반엔 일단 증상을 짧게 정리해야 합니다. 저는 아래 3가지를 먼저 봐요.

    1. 사용자가 어떤 작업에서 실패했는지 확인합니다. 인스턴스 생성인지, 볼륨 생성인지, 포트 할당인지가 중요하거든요.
    2. CLI(Command Line Interface, 명령행 도구) 또는 대시보드에서 에러 문구를 확인합니다.
    3. 관리자 권한으로 해당 프로젝트의 사용량과 쿼터를 바로 조회합니다.

    대표적으로 보게 되는 흐름은 이렇습니다.

    openstack server create --flavor m1.small --image ubuntu-test --network private-net test-vm

    이때 실패하면 사용자 쪽에서는 막연히 "인스턴스 생성 실패"로만 전달하는 경우가 많아요. 근데 실제로는 쿼터 메시지가 붙어 있는 경우가 있습니다. 그래서 저는 같은 프로젝트 컨텍스트(Context, 인증 범위)에서 자원 상태를 먼저 재현해 봅니다.

    오픈스택 쿼터 초과 점검을 위한 CLI 운영 화면 이미지

    쿼터 조회와 사용량 확인 명령을 실행하며 원인을 좁혀가는 운영 절차를 보여주는 이미지입니다.

    4. 실전 점검 절차: 제가 실제로 쓰는 확인 순서

    이 부분이 핵심이에요. 삽질 좀 했던 경험을 바탕으로, 지금은 거의 이 순서대로 갑니다. 괜히 노바 로그부터 깊게 파지 않고, 범위를 빠르게 좁히는 방식입니다.

    4-1. 프로젝트 쿼터 조회

    openstack quota show <PROJECT_ID 또는 PROJECT_NAME>

    이 명령으로 현재 제한값을 봐요. 환경에 따라 cores, instances, ram, volumes, snapshots, ports 같은 항목이 나옵니다. 숫자만 보지 말고, 어떤 항목이 업무 성격상 먼저 닳을지 감으로 연결해야 합니다. 예를 들어 쿠버네티스(Kubernetes, 컨테이너 오케스트레이션) 실험용 프로젝트는 포트가 생각보다 빨리 찹니다.

    4-2. 실제 사용량 확인

    openstack server list --project <PROJECT_ID>
    openstack volume list --project <PROJECT_ID>
    openstack port list --project <PROJECT_ID>

    여기서 저는 꼭 리소스 개수와 상태(Status, 현재 상태)를 같이 봐요. 삭제 중으로 남아 있거나 에러 상태인 리소스가 quota usage에 영향을 주는 경우가 있거든요. 처음엔 이게 뭔가 싶었는데, 특히 포트와 볼륨에서 잔재가 남는 경우가 꽤 있었습니다.

    4-3. 하이퍼바이저 자원과 분리해서 판단

    openstack hypervisor stats show

    이건 ‘진짜 인프라 자원 부족인지’를 분리하기 위한 확인이에요. 하이퍼바이저에 여유가 있는데 프로젝트 생성만 막히면, 높은 확률로 쿼터 또는 스케줄링 정책 쪽입니다. 반대로 전체 자원도 부족하다면 단순 쿼터 상향만으로는 해결이 안 됩니다.

    4-4. 필요 시 쿼터 조정

    openstack quota set --cores 40 --ram 81920 --instances 20 <PROJECT_ID>
    openstack quota set --volumes 20 --gigabytes 2000 <PROJECT_ID>
    openstack quota set --ports 150 <PROJECT_ID>

    여기서 중요한 게 하나 있어요. 무조건 늘리는 게 답이 아니라는 점입니다. 저도 예전엔 급하다고 넉넉하게 올려줬었는데, 결국 몇 주 뒤 다른 팀이 영향을 받는 식으로 되돌아오더라고요. 그래서 지금은 증상 완화용 임시 상향과 정책 반영용 영구 조정을 분리해요.

    4-5. 남은 리소스 재정리

    openstack server delete <SERVER_ID>
    openstack volume delete <VOLUME_ID>
    openstack port delete <PORT_ID>

    실제로 써보니까 쿼터를 늘리는 것보다 먼저 불필요 리소스를 비우는 편이 더 깔끔한 경우가 많았어요. 특히 테스트 프로젝트에서는 종료된 인스턴스보다 남아 있는 포트나 미사용 볼륨이 더 문제였습니다.

    5. 주의사항과 트러블슈팅: 여기서 많이 헷갈립니다

    오픈스택 장애 해결을 하다 보면 쿼터 문제는 금방 끝날 것 같지만, 실제로는 꼬인 상태가 종종 있어요. 제가 자주 봤던 패턴을 정리해보겠습니다.

    ⚠️ 1) 인스턴스는 없는데 쿼터가 찬 것처럼 보이는 경우

    이럴 땐 네트워크 포트나 볼륨, 스냅샷을 의심해요. 사용자는 VM만 지웠다고 생각하지만, 연결된 리소스가 남아 있는 경우가 많거든요.

    • 포트 목록 확인
    • 볼륨과 스냅샷 목록 확인
    • 에러 상태 리소스 확인

    ⚠️ 2) 쿼터를 올렸는데도 바로 안 되는 경우

    정책 반영 지연이라기보다, 실제 실패 원인이 다른 리소스일 수 있어요. 예를 들어 cores는 늘렸는데 ports가 이미 꽉 차 있으면 증상은 그대로입니다. 저도 한 번 이걸 놓쳐서 "왜 안 풀리지?" 하면서 한참 돌았습니다.

    ⚠️ 3) 관리자와 사용자 기준 숫자가 다르게 보이는 경우

    프로젝트 스코프(Project Scope, 프로젝트 범위)나 도메인(Domain, 계정 그룹) 선택이 다르면 조회 결과가 달라질 수 있어요. CLI 인증 정보부터 다시 보는 게 좋습니다.

    ⚠️ 4) 임시 증설이 상시 정책이 되는 경우

    이게 은근 위험해요. 한 번 올려준 쿼터는 잘 안 내려가거든요. 결국 특정 오픈스택 테넌트가 과도한 자원을 점유하면서 다른 팀 배포에 영향을 줄 수 있습니다. 그래서 저는 변경 후 꼭 사유를 남겨요.

    # 예시: 변경 전후 값을 운영 기록에 남기기
    openstack quota show <PROJECT_ID>

    운영 기록은 위키나 티켓 시스템에 남겨두는 편이 좋습니다. 나중에 "왜 이 프로젝트만 이렇게 높지?"라는 질문이 꼭 나오더라고요.

    오픈스택 쿼터 초과 원인 분석과 잔여 리소스 점검 흐름도

    인스턴스, 볼륨, 포트, 스냅샷 중 어디를 먼저 확인할지 보여주는 트러블슈팅 흐름도입니다.

    6. 검증 방법: 수정 후엔 꼭 다시 확인해야 합니다

    조치가 끝났다고 바로 닫으면 안 돼요. 저는 최소한 아래 순서로 검증합니다.

    1. 실패했던 동일 작업을 다시 실행합니다.
    2. 프로젝트 쿼터와 사용량을 다시 조회합니다.
    3. 사용자에게 실제 서비스 배포가 진행되는지 확인받습니다.
    4. 다른 프로젝트에 영향이 없는지도 봐요.
    openstack quota show <PROJECT_ID>
    openstack server create --flavor m1.small --image ubuntu-test --network private-net quota-check-vm
    openstack server list --project <PROJECT_ID>

    검증 포인트는 단순히 "생성이 된다"가 아니에요. 자원 고갈이 구조적으로 반복될 상황인지까지 봐야 합니다. 예를 들어 일시적으로 1대 생성은 되지만, 자동 확장(Auto Scaling, 부하에 따라 자동 증설) 워크로드가 예정돼 있다면 지금 쿼터로는 또 막힐 수 있거든요. 여기서 한 번 더 업무 패턴을 확인해두면 같은 장애를 반복하지 않아요.

    오픈스택 쿼터 초과 해결 후 사용량 변화를 보여주는 대시보드 이미지

    조치 후 VM 생성 성공과 리소스 사용량 증가가 정상적으로 반영된 결과 화면을 보여주는 이미지입니다.

    7. 운영 기준 제안: 쿼터 관리를 이렇게 바꾸니 덜 아팠습니다

    제가 몇 번 데이고 나서 바꾼 방식이 있어요. 그냥 요청 올 때마다 수동으로 늘려주는 방식은 오래 못 갑니다. 결국 장애 대응도 늦고, 정책도 흐려져요.

    • 기본 쿼터 표준화: 개발, 테스트, 운영 프로젝트별 기본값을 구분합니다.
    • 증설 요청 기준 문서화: 인스턴스 수, 코어, RAM, 볼륨 증설 사유를 받습니다.
    • 유휴 자원 정리 주기화: 미사용 볼륨, 포트, 스냅샷 점검 일정을 둬요.
    • 임시 상향 만료 기준: 이벤트성 증설은 종료 시점에 원복 여부를 검토합니다.

    특히 쿼터 관리는 자원 절약만의 문제가 아니에요. 장애를 예측 가능하게 만드는 운영 체계에 가까워요. 드디어 됐다! 하고 쿼터만 올려두면 그날은 끝나지만, 다음 분기엔 더 큰 문제로 돌아오더라고요.

    운영 방식 장점 단점
    요청 올 때마다 수동 증설 즉시 대응 가능 정책 일관성 부족, 누적 위험
    프로젝트 유형별 기본 쿼터 예측 가능성 높음 초기 설계 필요
    정기 점검 기반 조정 유휴 자원 회수 가능 운영 습관이 필요

    8. 정리와 FAQ: 오픈스택 쿼터 초과 대응의 핵심

    정리하면 이렇습니다. 오픈스택 쿼터 초과는 물리 자원이 남아 있어도 충분히 발생할 수 있고, 겉으로는 인프라 장애처럼 보이기 때문에 더 헷갈려요. 그래서 확인 순서는 아주 단순해야 해요. 프로젝트 쿼터 확인, 실제 사용량 확인, 잔여 리소스 점검, 필요한 경우에만 제한 조정. 이 순서만 몸에 익어도 대응 속도가 확실히 빨라집니다.

    저도 처음엔 무조건 시스템 로그부터 깊게 봤었는데, 실제로는 쿼터 하나 때문에 시간을 꽤 썼습니다. 근데 여기서 배운 게 있어요. 장애 대응은 많이 아는 것보다 먼저 의심할 순서를 잘 세우는 게 더 중요하다는 점입니다. 다음 글에서는 프로젝트별 자원 사용량을 주기적으로 점검하는 방법이나, 간단한 자동화 스크립트로 경고를 만드는 방법도 다뤄볼 예정입니다. 이전 글에서 다룬 스토리지 정리 루틴과 함께 보시면 운영 흐름을 잡는 데 더 도움이 될 거예요.

    자주 묻는 질문

    • Q. 하이퍼바이저 자원이 남는데도 생성이 실패할 수 있나요?
      A. 네, 가능해요. 프로젝트 쿼터가 먼저 막고 있을 수 있습니다.
    • Q. 쿼터를 무조건 크게 잡는 게 안전한가요?
      A. 아니에요. 특정 팀의 과점유를 막기 위해 적정선이 필요합니다.
    • Q. 가장 자주 놓치는 리소스는 뭔가요?
      A. 경험상 포트, 볼륨, 스냅샷 같은 잔여 리소스가 많았어요.
    오픈스택 쿼터 초과 예방을 위한 쿼터 관리 체크리스트 인포그래픽

    운영자가 바로 참고할 수 있도록 쿼터 점검 순서와 관리 원칙을 요약한 인포그래픽 이미지입니다.

    ✅ 핵심만 다시 적어보면, 오픈스택 쿼터 초과는 흔하지만 의외로 진단 순서만 잡으면 빠르게 해결돼요. 🎉 중요한 건 단발성 복구가 아니라, 같은 유형의 자원 고갈 이슈가 반복되지 않게 운영 기준을 만드는 거예요. 저처럼 처음에 로그만 파다가 시간 보내지 마시고, 다음 장애 때는 꼭 쿼터부터 확인해보세요. 이거 진짜 편하더라고요.