DCloud Infra 구축하기 -2-

이제 서버와 오픈스택까지 구축을 했으니 이제 저희 상황에 맞게 수정을 해야하는데 이렇게 되면 개발기간이 너무 소요가 되기 때문에 OpenStack Skyline 대시보드의 기능을 보완하고 플랫폼 특화 기능을 제공하기 위해, FastAPI 기반의 독자적인 확장 백엔드(Skyline API Server Extension)를 구축했습니다.

이 글에서는 시스템의 전체적인 아키텍처를 조망하고, 특히 핵심 난제였던 '장기 실행 프로세스 처리'와 '외부 네트워크 오케스트레이션'을 코드 레벨에서 어떻게 해결했는지 포스팅 할려고 합니다.

원본 소스

원본 소스는 차세대 Openstack DashBoard인 Skyline을 가져와 수정을 했습니다.

GitHub - openstack/skyline-apiserver: A modern dashboard for OpenStack - API server. Mirror of code maintained at opendev.org.
A modern dashboard for OpenStack - API server. Mirror of code maintained at opendev.org. - openstack/skyline-apiserver

시스템 아키텍처 개요

일단 먼저 크게 오픈스택의 기존 서비스들을 건지 않기 위해 중간에 FastAPI을 중계자 느낌을 두고 오픈스택의 서비스 와 연동을 하게 했습니다. 이렇게 한 이유는

  1. 오픈스택을 수정하지 않음으로써 유지보수가 편리함
  2. FastAPI을 점검할때 오픈스택 서비스들 전부 가동하면서 점검가능
  3. 중간에 코드 수정이 용의함

때문에 이렇게 구성을 해두었고, 확장 서버는 클라이언트(대시보드)와 인프라(OpenStack 및 외부 시스템) 사이에서 중개자(Middleware) 및 오케스트레이터(Orchestrator) 역할을 수행합니다.

위 다이어그램은 요청의 흐름과 주요 컴포넌트 간의 상호작용을 보여줍니다.

  • FastAPI Extension Server: 시스템의 핵심 두뇌입니다. 안정적인 유지보수를 위해 동기(Sync) 방식의 뷰 핸들러를 채택했지만, 무거운 작업은 백그라운드로 위임합니다.
  • Local DB: OpenStack Keystone이 관리하지 않는 사용자 추가 정보(예: 학번)와 플랫폼 전용 활동 로그를 저장합니다.
  • External Proxy VM: 사설 IP를 가진 인스턴스에 외부 접속 포트(SSH 등)를 제공하기 위한 별도의 네트워크 게이트웨이입니다. (추후 포스팅 예정)

주요 코드와 구현 디테일

1. 동기(Sync) 아키텍처에서 긴 프로비저닝 작업 처리하기

가상 머신 생성은 수분이 걸리는 작업입니다. 만약 API가 이 작업이 끝날 때까지 클라이언트의 요청을 붙잡고 있다면(Blocking), 서버 리소스는 금방 고갈될 것입니다.

우리는 FastAPI의 BackgroundTasks 패턴을 적용하여 이 문제를 해결했습니다. 코드를 살펴보겠습니다.

[skyline_apiserver/api/v1/instance.py 참조]

# 인스턴스 생성 요청 핸들러 (Sync 방식)
@router.post("", response_model=CreatedResponse, status_code=status.HTTP_202_ACCEPTED)
def create_instance(
    req: CreateServerRequest,
    background_tasks: BackgroundTasks, # FastAPI 의존성 주입
    # ... 기타 의존성
):
    # 1. 요청 검증 및 사전 작업 (매우 빠름)
    validate_request(req)
    request_id = generate_uuid()
    
    # 2. 무거운 작업을 백그라운드 큐에 등록
    background_tasks.add_task(
        _provision_instance, # 실제 프로비저닝 함수
        request_id=request_id,
        # ... 필요한 파라미터 전달
    )

    # 3. 클라이언트에게 즉시 202 Accepted 응답 반환
    return CreatedResponse(request_id=request_id)

API 엔드포인트 자체는 동기적으로 작성되어 요청을 검증하고 작업을 예약한 후 즉시 응답합니다. 실제 Nova와 Cinder를 호출하며 대기하는 무거운 작업(_provision_instance)은 응답이 나간 후 서버의 별도 스레드 풀에서 비동기적으로 실행됩니다. 이를 통해 코드의 직관성을 유지하면서도 높은 동시성 처리 능력을 확보했습니다.

2.자유로운 네트워크 포트포워딩 시스템

가장 큰 난관은 "Private Subnet에 생성된 VM에 외부 사용자가 어떻게 즉시 접속하게 할 것인가?" 였습니다. OpenStack Neutron의 Floating IP만으로는 부족하여, 외부 Proxy VM과 연동하는 자체 로직을 구현했습니다.

이 과정은 정교한 상태 기반의 오케스트레이션이 필요합니다.

[skyline_apiserver/api/v1/instance.pyclient/portforward_client.py 참조]

  1. Polling & Wait: 백그라운드 태스크는 Nova 인스턴스를 생성한 후, 인스턴스가 ACTIVE 상태가 되고 내부 IP를 할당받을 때까지 주기적으로 상태를 확인(Polling)합니다.
  2. Cross-System Call: 인스턴스가 준비되면, 확장 서버는 portforward_client 모듈을 통해 외부 Proxy VM의 API를 호출합니다.
# portforward_client.py 내부 로직 간소화
def create_portforward_rule(self, internal_ip, internal_port, ...):
    # 사전에 설정된 보안 키를 이용해 외부 Proxy API 인증
    headers = {"Authorization": f"Bearer {self.auth_key}"}
    payload = {
        "internal_ip": internal_ip,
        "internal_port": 22, # SSH 포트 자동 개방
        # ...
    }
    # Proxy VM에게 포트포워딩 규칙 생성 요청
    response = httpx.post(f"{self.proxy_api_url}/rules", json=payload, headers=headers)
    return response.json() # 할당된 외부 IP와 포트 정보 반환

이 오케스트레이션을 통해 사용자는 복잡한 네트워크 설정 없이, 인스턴스 생성과 동시에 접속 가능한 외부 접속 주소를 발급받게 됩니다.

3. 리소스 누수 방지를 위한 안전한 삭제 파이프라인 (GC)

클라우드 리소스 관리의 핵심은 생성만큼이나 '깔끔한 삭제'에 있습니다. 인스턴스만 삭제하고 연결된 볼륨이나 포트포워딩 규칙을 방치하면 심각한 리소스 누수(Leak)가 발생합니다.

이렇게 되면 안돼잖아...

우리는 다음과 같은 엄격한 순서의 삭제 파이프라인을 구현했습니다.

  1. 외부 연동 해제: 외부 Proxy VM에 API를 호출하여 관련 포트포워딩 규칙을 먼저 삭제합니다.
  2. 인스턴스 삭제: Nova 인스턴스 삭제를 요청합니다.
  3. 지연된 볼륨 삭제 (Delayed GC): 인스턴스가 삭제되는 동안 볼륨은 in-use 상태이므로 즉시 삭제할 수 없습니다. 따라서 별도의 백그라운드 태스크가 인스턴스의 완전한 소멸을 확인한 후, 볼륨이 available 상태로 돌아왔을 때 안전하게 삭제를 수행합니다.

마치며

이번 Skyline API Server Extension 프로젝트는 제가 원하는 기능을 구현을 하고 테스트 함으로써 Openstack에 대해 이해하였으며 요즘 Proxmox을 많이 쓴다고 하는데 Openstack의 장점에 대해 많이 알았습니다.

그리고 FastAPI의 유연한 구조 덕분에 동기식 코드의 안정성과 비동기식 처리의 성능이라는 두 마리 토끼를 잡을 수 있었으며, 외부 시스템과의 긴밀한 연동을 통해 진정한 의미의 '커스텀 클라우드 오케스트레이터'를 완성할 수 있었습니다.

GitHub - INMD1/skyline-apiserver-extenstion: Skyline 기본에 Dcloud에 필요한 특화된 기능 추가
Skyline 기본에 Dcloud에 필요한 특화된 기능 추가. Contribute to INMD1/skyline-apiserver-extenstion development by creating an account on GitHub.

이 다음은 사용자가 보는 데시보드를 어떻게 구성했는지 포스트 할려고합니다. 여기까지 읽어주신분들 대단히 감사합니다.