콘텐츠로 이동

PCI Passthrougu + Placement API 적용

0. 사전 확인 사항

  • Ubuntu 24.04 + Openstack 2025.2 환경에서 진행
  • GPU 노드에 IOMMU 커널 설정 확인
  • GPU 관리자가 VFIO인지 확인

1. Nova 설정 오버라이딩 (GPU 인식시키기)

Kolla-Ansible은 /etc/kolla/config/nova/nova.conf 파일을 우선순위로 적용합니다. 여기에 GPU 정보를 박제합니다.

# 사용할 PCI 장비의 이름 생성
# CUSTOM_ 접두사는 필수로 들어가야 함
openstack resource class create CUSTOM_<RESOURCE_NAME>
# 설정 디렉토리 생성
sudo mkdir -p /etc/kolla/config/nova

# 설정 파일 작성
sudo vi /etc/kolla/config/nova/nova.conf
[pci]
# 1. [Compute 노드용] 물리 서버의 PCI 장치 화이트리스트
device_spec = [{"vendor_id": "<VENDOR_ID>", "product_id": "<PRODUCT_ID>"}]

# 2. [API 노드용] Flavor에서 사용할 별칭(Alias) 정의
# name은 나중에 Flavor 만들 때 씁니다. (여기서는 'nvidia-gpu'로 정함)
# nova가 장치를 못 찾겠다 할 때, type-PCI 변경 필요
alias = {"vendor_id": "<VENDOR_ID>", "product_id": "<PRODUCT_ID>", "device_type": "type-PCI", "name": "<RESOURCE_NAME>"}

# 3. PCI를 placement에 통합
report_in_placement = true

[filter_scheduler]
# 3. [Scheduler 노드용] PCI 필터 활성화 (기존 필터 뒤에 추가)
available_filters = nova.scheduler.filters.all_filters
enabled_filters = ComputeFilter,ImagePropertiesFilter,PciPassthroughFilter

pci_in_placement = true

참고로 device_type 은 아래와 같은 옵션이 있습니다. SR-IOV 기능이 있다면 type-PF 로 해야 인식합니다.

타입 명칭 설명 비유 용도
type-PCI 일반 PCI 장치 "SR-IOV 기능이 없거나, 안 쓰는 일반 장치." "단독주택 (쪼갤 수 없음, 통째로 써야 함)" "일반적인 GPU Passthrough (RTX, T4 등을 통으로 쓸 때)"
type-PF Physical Function SR-IOV를 지원하는 부모 장치. 자식(VF)을 생성할 능력이 있음. 아파트 주인 (세를 놓을 수 있음) 호스트 OS가 VF를 관리하기 위해 붙들고 있는 용도. (VM에 잘 안 줌)
type-VF Virtual Function 부모(PF)로부터 파생된 자식 장치. 아파트 세입자 (한 호실만 빌려 씀) 고성능 네트워크(SR-IOV)나 vGPU를 VM에 할당할 때 사용.

SR-IOV를 지원하는지는 아래와 같은 명령으로 확인할 수 있습니다.

# 1. 먼저 GPU의 PCI 주소를 찾습니다.
lspci | grep -i nvidia
# 예: 41:00.0 3D controller: NVIDIA Corporation ...

# 2. 해당 주소(-s)의 상세 정보(-vvv)에서 SR-IOV 키워드를 검색합니다.
sudo lspci -s <PCI_ADDRESS> -vvv | grep -i "Single Root I/O Virtualization"

1.1 2025.2 버전에 추가된 항목

GPU 보안 관련

device_spec 에서 one_time_use 항목을 추가 시, 사용자가 쓰고 반납한 GPU는 reserved 상태가 되어 다른 사용자가 사용할 수 없는 상태가 됩니다.

이를 관리자가 스크립트로 GPU 초기화 후, openstack resource provider inventory set --reserved 0 ... 명령을 실행해야 다시 사용할 수 있게 됩니다.

[pci]
device_spec = [{"vendor_id": "<VENDOR_ID>", "product_id": "<PRODUCT_ID>", "one_time_use": "true"}]

Live Migration

live_migratable"GPU를 달고 있는 VM도 끄지 않고 다른 서버로 이사(Live Migration)갈 수 있게 해주는 스위치"입니다.

이를 사용하기 위해선 아래와 같은 조건을 충족해야 합니다.

  1. SR-IOV 사용 가능 여부
  2. NVIDIA vGPU 라이선스
[pci]
device_spec = [{ "vendor_id": "<VENDOR_ID>", "product_id": "<PRODUCT_ID>", "live_migratable": "true" }]
alias = { "name": "<RESOURCE_NAME>", ... "live_migratable": "true" }

2. 설정 적용 (Reconfigure)

기존 오픈스택을 끄지 않고 설정만 업데이트합니다.

# 가상환경 활성화 필수
source ~/kolla-venv/bin/activate

# 재설정 적용 (Nova 서비스들만 재시작됨)
kolla-ansible reconfigure -i multinode --tags nova

(전체를 다 돌리면 오래 걸리니 --tags nova로 시간 단축 가능합니다.)


3. Placement 등록 검증

Nova가 GPU를 감지하고 Placement에 "나 GPU 있어!"라고 보고했는지 확인합니다.

3.1. 물리 서버(Compute Node) UUID 확인

openstack resource provider list
  • 여기서 GPU 노드의 자식 ID (UUID)를 복사하세요.

3.2. 인벤토리 조회

# [UUID] 자리에 복사한 ID를 넣으세요
openstack resource provider inventory list [UUID]

[성공 판독] 출력 결과에 아래와 비슷한 항목이 보여야 합니다.

  • PCI_DEVICE: total: 1 (또는 GPU 개수만큼)
  • 또는 CUSTOM_PCI_10DE_20B7: total: ...

4. 인스턴스 생성 테스트

이제 "GPU가 달린 + 인터넷이 되는" 인스턴스를 만듭니다.

4.1. GPU Flavor 생성

아까 nova.conf에서 정한 alias 이름(nvidia-gpu)을 씁니다.

openstack flavor create --ram 8192 --disk 50 --vcpus 4 <FLAVOR_NAME>
openstack flavor set \
  --property "pci_passthrough:alias"="<RESOURCE_NAME>:1" \
  --property "resources:<CUSTOM_RESOURCE_CLASS>=1" \
  --property "hw:pci_numa_affinity_policy"="preferred" \
  --property hw_machine_type=q35 \
  <FLAVOR_NAME>

만약 RTX 계열의 개인용 GPU를 사용한다면 --property hw:kvm_hidden=true 옵션도 함께 적용합니다.

※ 일부 환경에서는 alias + resources를 동시에 쓸 경우 이중 차감됨. 이 경우 resources 항목만 제거하고 alias만 사용 권장.

4.2. 인스턴스 시작

openstack server create --flavor gpu.flavor \
  --image "Ubuntu 24.04" \
  --network internal \
  my-gpu-vm

4.3. 최종 확인

VM 접속 후:

  • lspci: NVIDIA 장치가 보이는지?
  • ping 8.8.8.8: 인터넷이 되는지?
  • nvidia-smi: 드라이버 설치 후 GPU가 잡히는지?

5. API 기반 할당 검증 (Advanced Verification)

CLI나 대시보드 상에서는 확인하기 어려운 "실제 리소스 점유 현황(Placement)""Flavor 내부 설정(Nova)"을 API를 통해 직접 검증합니다.

5.0. 환경 변수 설정

검증에 필요한 변수들을 미리 선언합니다. < >로 표시된 부분에 실제 값을 입력하세요.

# 1. 접속 정보
export CONTROLLER_IP=$(openstack endpoint list --service keystone --interface public -c URL -f value | awk -F/ '{print $3}' | cut -d: -f1)
export PLACEMENT_PORT=$(openstack endpoint list --service placement --interface public -c URL -f value | awk -F: '{print $3}' | cut -d/ -f1)
export NOVA_PORT=$(openstack endpoint list --service compute --interface public -c URL -f value | awk -F: '{print $3}' | cut -d/ -f1)

# 2. 검증 대상 UUID (사전 확인 필요)
# 생성된 인스턴스의 ID
export SERVER_ID="<INSTANCE_ID>"
# 생성한 GPU Flavor의 ID
export FLAVOR_ID="<FLAVOR_ID>"
# GPU 자원을 가진 물리 노드(혹은 자식 노드)의 UUID
export RP_UUID=$(openstack resource provider allocation show $SERVER_ID -c resource_provider -c resources -f value | grep "CUSTOM_" | awk '{print $1}')

5.1. 인증 토큰 발급 (토큰이 없는 경우)

# 관리자 권한 로드 후 토큰 발급
source /etc/kolla/admin-openrc.sh
export OS_TOKEN=$(openstack token issue -c id -f value)
echo "Token: $OS_TOKEN"

5.2. Placement API 검증 (하드웨어 관점)

GPU 자원이 물리적으로 존재하며, 생성한 인스턴스가 이를 실제로 점유하고 있는지 확인합니다.

1) Resource Inventory 조회 (재고 확인)

curl -s -X GET "http://${CONTROLLER_IP}:${PLACEMENT_PORT}/resource_providers/${RP_UUID}/inventories" \
  -H "X-Auth-Token: ${OS_TOKEN}" \
  -H "OpenStack-API-Version: placement 1.28" \
  -H "Content-Type: application/json" | json_pp

[확인 포인트]

  • total 값이 실제 물리 GPU 개수와 일치하는지 확인
  • 리소스 클래스 이름이 CUSTOM_<RESOURCE_NAME> (또는 자동 생성된 이름)인지 확인

2) Resource Allocations 조회 (점유 확인 ★중요)

curl -s -X GET "http://${CONTROLLER_IP}:${PLACEMENT_PORT}/resource_providers/${RP_UUID}/allocations" \
  -H "X-Auth-Token: ${OS_TOKEN}" \
  -H "OpenStack-API-Version: placement 1.28" \
  -H "Content-Type: application/json" | json_pp

[확인 포인트]

  • 응답 JSON의 Key 값(Consumer UUID)에 <INSTANCE_ID>가 포함되어 있어야 함
  • 해당 인스턴스가 CUSTOM_<RESOURCE_NAME> 자원을 1개 사용 중이어야 함

5.3. Nova API 검증 (소프트웨어 관점)

인스턴스가 올바른 Flavor와 스펙으로 생성되었는지 확인합니다.

1) Flavor 상세 스펙(Extra Specs) 조회

Flavor 조회 시 기본 정보에는 GPU 관련 설정이 나오지 않으므로, /os-extra_specs 엔드포인트를 호출해야 합니다.

curl -s -X GET "http://${CONTROLLER_IP}:${NOVA_PORT}/v2.1/flavors/${FLAVOR_ID}/os-extra_specs" \
  -H "X-Auth-Token: ${OS_TOKEN}" \
  -H "Content-Type: application/json" | json_pp

[확인 포인트]

  • "pci_passthrough:alias": "<RESOURCE_NAME>:1" 설정 존재 여부
  • "resources:CUSTOM_<RESOURCE_CLASS>": "1" 설정 존재 여부
  • "hw:pci_numa_affinity_policy": "preferred" 설정 존재 여부

2) Instance 상세 정보 조회

curl -s -X GET "http://${CONTROLLER_IP}:${NOVA_PORT}/v2.1/servers/${SERVER_ID}" \
  -H "X-Auth-Token: ${OS_TOKEN}" \
  -H "Content-Type: application/json" | json_pp

[확인 포인트]

  • status: "ACTIVE"
  • flavor.id: 위에서 조회한 <FLAVOR_ID>와 일치해야 함