- 가상 머신 1대를 준비하여 단일 노드(All-in-One) 환경으로 OpenStack 설치
- 설치 도구는 OpenStack 공식 개발/평가용 도구인
DevStack사용 - OpenStack 릴리스는
2026.1 Gazpacho(최신 안정 버전) - DevStack은 빠른 설치 및 개발을 위한 도구로, 운영 환경에서는
Packstack,Kolla,Ansible등 다른 설치 방법 권장
- SOLID CLOUD 환경에서 아래 사양의 가상 머신을 1대 준비
- 단일 NIC, 정적 IP 권장
| 항목 | 권장 사양 |
|---|---|
| OS | Ubuntu 24.04 LTS (Noble) |
| vCPU | 4 core 이상 |
| RAM | 16 GB 이상 |
| Disk | 80 GB 이상 |
| Network | 외부 통신 가능한 단일 NIC |
- DevStack은 시스템에 광범위한 변경을 가하므로 반드시
실습 전용 VM에서만 사용 - SOLID CLOUD의 KVM 위에 OpenStack의 KVM이 동작하므로
Nested Virtualization구조 - Nested 미지원 시 QEMU 에뮬레이션 모드로 동작 가능 (성능 저하)
# 호스트 KVM 모듈의 nested 가상화 허용 여부 확인
cat /sys/module/kvm_intel/parameters/nested# 현재 VM에서 KVM 디바이스 노출 여부 확인
ls /dev/kvmY(또는1) 출력 시 nested 가상화 허용됨/dev/kvm이 존재하면 현재 VM에서 KVM 가속 사용 가능- 둘 중 하나라도 만족하지 않으면
local.conf에LIBVIRT_TYPE=qemu로 설정하여 QEMU 에뮬레이션 모드로 진행 (성능 저하)
# 패키지 인덱스 업데이트
sudo apt update && sudo apt -y upgrade
# 기본 도구 설치
sudo apt install -y git net-tools curl vim- DevStack은 보안상 root가 아닌 별도의 일반 사용자로 실행해야 함
- 해당 사용자에게 비밀번호 없는 sudo 권한 부여 필요
# stack 사용자 생성 (홈 디렉토리: /opt/stack)
sudo useradd -s /bin/bash -d /opt/stack -m stack
# 홈 디렉토리에 실행 권한 부여 (Ubuntu 21.04+ 기본 700 → 755로 조정)
sudo chmod +x /opt/stack
# sudoers에 stack 사용자 추가
echo "stack ALL=(ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/stack
sudo chmod 0440 /etc/sudoers.d/stack
# stack 사용자로 전환
sudo -u stack -i# stack 사용자 홈 디렉토리에서 수행
cd /opt/stack
pwd # /opt/stack
# DevStack 공식 저장소 클론
git clone https://opendev.org/openstack/devstack
cd devstack
# 2026.1 Gazpacho 안정 브랜치로 체크아웃
git checkout stable/2026.1- DevStack 브랜치 종류
master- 매일 변동되는 개발 버전 (실험용)stable/2026.1- Gazpacho 안정 버전 (실습 권장)stable/2025.2- Flamingo 이전 안정 버전
- DevStack은
local.conf파일을 통해 설치 동작을 제어 - 비밀번호 4종(
ADMIN/DATABASE/RABBIT/SERVICE)이 최소 필수 항목
# devstack 디렉토리에서 수행
# [VM_IP]는 현재 VM의 실제 IP 주소로 변경
cat > /opt/stack/devstack/local.conf <<EOF
[[local|localrc]]
# 비밀번호 (영문 + 숫자만 사용, 특수문자 금지)
ADMIN_PASSWORD=secret
DATABASE_PASSWORD=\$ADMIN_PASSWORD
RABBIT_PASSWORD=\$ADMIN_PASSWORD
SERVICE_PASSWORD=\$ADMIN_PASSWORD
# 네트워크 설정
HOST_IP=[VM_IP]
FLOATING_RANGE=172.24.4.0/24
FIXED_RANGE=192.168.100.0/24
Q_FLOATING_ALLOCATION_POOL=start=172.24.4.100,end=172.24.4.200
PUBLIC_NETWORK_GATEWAY=172.24.4.1
# 추가 서비스: Swift (오브젝트 스토리지)
enable_service s-proxy s-object s-container s-account
SWIFT_HASH=66a3d6b56c1f479c8b4e70ab5c2b9a08
SWIFT_REPLICAS=1
# 추가 서비스: Heat (오케스트레이션)
enable_plugin heat https://opendev.org/openstack/heat stable/2026.1
# 차세대 대시보드 Skyline (Horizon과 함께 동작)
enable_plugin skyline-apiserver https://opendev.org/openstack/skyline-apiserver stable/2026.1
# Nested 미지원 시 주석 해제 (KVM → QEMU 폴백)
# LIBVIRT_TYPE=qemu
# 로그 설정
LOGFILE=/opt/stack/logs/stack.sh.log
LOGDAYS=2
EOFADMIN_PASSWORD: Horizon/Skyline 로그인(admin,demo공통) 및 모든 API 접근에 사용되는 마스터 비밀번호FLOATING_RANGE: VM에 매핑할 외부 통신용 IP 대역. DevStack VM 내부의br-ex가상 브리지에서만 통하므로, CloudStack 호스트 대역(10.0.0.0/16)과 겹치지 않도록172.24.4.0/24사용FIXED_RANGE: 테넌트 VM 내부 사설 IP 대역. Neutron이 network namespace로 격리SWIFT_REPLICAS=1: 단일 노드 환경에서는 복제본 1개 (운영 환경은 기본 3)
# devstack 디렉토리에서 수행
cd /opt/stack/devstack
# 설치 실행 (약 20~40분 소요 -> VM 사양과 네트워크 속도에 따라 달라짐)
./stack.sh- 설치 오류 발생 시
/opt/stack/logs/stack.sh.log확인 - 부분 재시도가 필요한 경우
./unstack.sh후./stack.sh재실행 - 완전 초기화는
./clean.sh후 진행 - 설치 시간은 VM 사양과 외부 네트워크 속도에 크게 영향받음
- DevStack은
openrc파일로 OpenStack 인증 환경 변수를 셸에 주입 - 첫 번째 인자는 사용자명, 두 번째는 프로젝트명
cd /opt/stack/devstack
# admin 계정으로 환경 변수 로드 (관리자 권한)
source openrc admin admin
# 현재 인증 토큰 발급 및 확인
openstack token issue# OpenStack 서비스 카탈로그(엔드포인트) 확인
openstack catalog list
# 등록된 서비스 목록 확인
openstack service listopenstack token issue응답의id값이Fernet Token이며, 약 255바이트 크기의 암호화 문자열- 토큰의 기본 유효기간(TTL)은 1시간
- demo 사용자로 전환 시
source openrc demo demo
Keystone은 OpenStack의 인증/인가 서비스로, 멀티테넌시 계층 구조를 통해 자원을 격리
- Domain : 가장 상위 격리 경계 (조직 단위)
- Project : 자원이 실제 할당되는 단위 (팀 단위)
- User : 시스템 접근 주체
- Role : 권한 집합 (
admin,member,reader)
# admin 권한 로드
source openrc admin admin# 1. 도메인 생성 (조직 단위)
openstack domain create --description "Dankook University" dku
# 2. 프로젝트 생성 (해당 도메인 내 팀 단위)
openstack project create --domain dku \
--description "Cloud Virtualization Lab" cloud-lab
# 3. 사용자 생성
openstack user create --domain dku \
--project cloud-lab --project-domain dku \
--password "userpass" \
--description "Lab student" student
# 4. 역할(Role) 부여
openstack role add --project cloud-lab --project-domain dku \
--user student --user-domain dku \
member# 생성된 자원 확인
openstack domain list
openstack project list --domain dku
openstack user list --domain dku
openstack role assignment list --user student --user-domain dku --names- 도메인을 명시하지 않으면 기본 도메인(
default)에 생성됨 - 한 사용자가 여러 프로젝트에 다양한 역할로 매핑 가능
- 운영 환경에서는 LDAP/AD를 Identity Backend로 연동하여 사용자 정보를 외부에서 관리
- Fernet Token은 DB 저장 없이 토큰 자체에 정보를 포함하는 상태 비저장(Stateless) 방식
- 대칭키(Fernet Key)로 암호화/복호화되며, 보안을 위해 주기적인 키 교체(Rotation) 필요
# Keystone Fernet 키 저장소 확인
sudo ls -la /etc/keystone/fernet-keys/출력 예시
-rw------- 1 keystone keystone 44 May 14 10:00 0 # Staged Key (대기 키)
-rw------- 1 keystone keystone 44 May 14 10:00 1 # Primary Key (주 키)
# 현재 토큰 발급 후 길이 확인
TOKEN=$(openstack token issue -f value -c id)
echo "Token length: ${#TOKEN}"
echo "Token prefix: ${TOKEN:0:50}..."# Key Rotation 수행
sudo keystone-manage fernet_rotate --keystone-user stack --keystone-group stack
# 키 목록 재확인 (Staged → Primary로 승격, 기존 Primary는 Secondary로 강등)
sudo ls -la /etc/keystone/fernet-keys/# 회전 전 발급된 기존 토큰이 여전히 검증 가능한지 확인
curl -s -o /dev/null -w "HTTP %{http_code}\n" \
-H "X-Auth-Token: $TOKEN" \
-H "X-Subject-Token: $TOKEN" \
http://10.0.11.10/identity/v3/auth/tokens
# HTTP 200 → 유효 (Secondary 키로 정상 검증됨)
# HTTP 401 → 무효- Primary Key (주 키) : 새 토큰을 암호화/발급할 때 사용 (가장 큰 인덱스)
- Secondary Key (보조 키) : 이전에 발급된 토큰을 복호화/검증할 때만 사용
- Staged Key (대기 키) : 다음 회전에서 Primary로 승격될 후보 (항상 인덱스
0) - DevStack 환경에서는 모든 OpenStack 서비스가
stack사용자 계정으로 동작하므로
--keystone-user stack --keystone-group stack사용 (운영 환경 표준 패키지는keystone:keystone) - 다중 노드 환경에서는 모든 Keystone 노드가 동일한 키 셋을 유지해야 함
- 토큰 검증은 Keystone의
/v3/auth/tokens엔드포인트에X-Auth-Token(요청자 인증)과X-Subject-Token(검증 대상 토큰) 헤더로 GET 요청하여 수행 - NTP 동기화가 필수 (노드 간 시간 차이로 인한 토큰 만료 판단 오류 방지)
- 운영 환경에서는
cron으로 자동 회전 권장 (예:0 */6 * * *)
Glance는 VM 부팅용 디스크 이미지를 검색, 등록, 조회하는 서비스
source openrc admin admin
# 기본 등록된 이미지 확인 (DevStack이 CirrOS 자동 등록)
openstack image list# Ubuntu 24.04 Cloud 이미지 다운로드 (QCOW2 포맷)
cd /tmp
wget https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img
# Glance에 이미지 등록
openstack image create "ubuntu-24.04" \
--file noble-server-cloudimg-amd64.img \
--disk-format qcow2 \
--container-format bare \
--public
# 이미지 상세 정보 확인
openstack image show ubuntu-24.04# 이미지 메타데이터 추가
openstack image set ubuntu-24.04 \
--property os_distro=ubuntu \
--property os_version=24.04 \
--property hw_disk_bus=virtio- 지원 이미지 포맷
QCOW2: KVM 권장. 스냅샷 및 압축 효율적RAW: 압축 없음. I/O 성능 우수, 용량 큼VMDK: VMware 호환ISO: 설치 미디어 형태
--public: 모든 프로젝트에서 사용 가능 (관리자 권한 필요)--private: 소속 프로젝트 전용- DevStack 기본 백엔드는 로컬 파일시스템(
/opt/stack/data/glance/images/)
Placement는 클라우드 내 자원(CPU, 메모리, 디스크)의 인벤토리와 사용량을 추적하는 API 서비스
# 자원 공급자(Resource Provider) 목록
openstack resource provider list# 특정 공급자(컴퓨트 노드)의 자원 인벤토리 확인
RP_UUID=$(openstack resource provider list -f value -c uuid | head -1)
openstack resource provider inventory list $RP_UUID# 현재 자원 할당(Allocation) 상태 확인
openstack resource provider show $RP_UUID --allocations
# 공급자의 특성(Trait) 확인
openstack resource provider trait list $RP_UUID- Resource Class : 추적 가능한 자원의 종류
- 기본 제공:
VCPU(가상 CPU 코어),MEMORY_MB(메모리 MB),DISK_GB(디스크 GB) - 표준 확장:
PCPU(전용 물리 코어),PGPU(가상 GPU),NET_BW_EGR_KILOBIT_PER_SEC(네트워크 대역폭) - 사용자 정의:
CUSTOM_접두사로 자유롭게 추가 (예:CUSTOM_GPU_A100,CUSTOM_FPGA,CUSTOM_NVME)
- 기본 제공:
- Allocation Ratio : 물리 자원 대비 가상 자원 할당 배수 (오버커밋)
VCPU: 16.0→ 물리 코어 1개를 가상 코어 16개로 할당 가능. CPU는 시분할 가능하므로 대부분 오버커밋 설정MEMORY_MB: 1.5→ 물리 RAM 100GB를 150GB로 할당 가능. 과도하면 OOM 발생 위험DISK_GB: 1.0→ 디스크는 오버커밋 안 함이 일반적 (실제 데이터 점유)- 운영 환경에서는 워크로드 특성에 따라 조정 (예: 일반 웹 서비스
VCPU: 4.0, AI 학습VCPU: 1.0)
- Trait : 자원의 정성적 특성 (있다/없다 형태의 boolean)
- 표준 Trait:
HW_CPU_X86_AVX2(AVX2 명령어 지원),HW_CPU_HYPERTHREADING,STORAGE_DISK_SSD,COMPUTE_VOLUME_MULTI_ATTACH - 보안/규제:
HW_CPU_X86_INTEL_VTX(Intel VT-x),COMPUTE_SECURITY_TPM_2_0(TPM 2.0 탑재) - 사용자 정의:
CUSTOM_접두사 (예:CUSTOM_RACK_A1,CUSTOM_GPU_NVIDIA_A100)
- 표준 Trait:
- Inventory vs Allocation : 인벤토리는 노드가 보유한 자원 총량, 할당은 특정 VM(소비자)에게 실제로 부여된 양
openstack resource provider inventory list: 노드별 자원 총량/오버커밋/사용 가능 단위openstack resource provider show --allocations: 현재 어떤 소비자가 얼마나 점유 중인지 추적
- Nova Scheduler 연동 : VM 생성 시 다음 흐름으로 동작
- Nova가 사용자 요청(예: VCPU=2, RAM=4GB,
trait:HW_CPU_X86_AVX2=required)을 Placement에 전달 - Placement가 조건을 만족하는 Resource Provider만 추려서 후보 목록 반환
- Nova가 후보 중 가중치(Weigher) 계산 후 최종 노드 선정
- 선정된 노드에 자원 할당(Allocation) 기록
- Nova가 사용자 요청(예: VCPU=2, RAM=4GB,
- 모든 노드를 일일이 조회하지 않고 Placement가 1차 필터링하므로 수백~수천 노드 환경에서도 빠르게 스케줄링 가능
VM 생성 전 인스턴스 크기 정의(Flavor)와 SSH 접속용 키페어 준비
cd /opt/stack/devstack
source openrc admin admin
# 기본 Flavor 목록 확인
openstack flavor list
# 실습용 Flavor 생성 (1 vCPU, 1GB RAM, 10GB Disk)
openstack flavor create --vcpus 1 --ram 1024 --disk 10 lab.small# 일반 사용자(demo)로 전환
source openrc demo demo
# SSH 키페어 생성
ssh-keygen -t rsa -b 2048 -N "" -f ~/.ssh/id_rsa_lab
# Nova에 공개키 등록
openstack keypair create --public-key ~/.ssh/id_rsa_lab.pub lab-keypair
# 등록 확인
openstack keypair list- Flavor는 인스턴스 템플릿으로 vCPU/RAM/Disk 외에도
--ephemeral,--swap,--property등 부여 가능 - DevStack 기본 Flavor :
m1.tiny,m1.small,m1.medium,m1.large,m1.xlarge - 키페어는 사용자별로 등록되며, 동일 키페어를 여러 VM에 재사용 가능
Neutron은 SDN 기반으로 가상 네트워크를 프로비저닝하는 서비스. 다음 5단계로 테넌트 네트워크를 구성
source openrc demo demo
# 내부 네트워크 생성
openstack network create internal-net# 서브넷 생성
openstack subnet create internal-subnet \
--network internal-net \
--subnet-range 192.168.100.0/24 \
--dns-nameserver 8.8.8.8# 가상 라우터 생성
openstack router create lab-router# 라우터에 내부 서브넷 인터페이스 추가
openstack router add subnet lab-router internal-subnet# 외부 네트워크 확인 (DevStack이 기본 생성한 'public')
openstack network list --external
# 라우터의 외부 게이트웨이 설정
openstack router set lab-router --external-gateway public# 구성 결과 종합 확인
openstack network list
openstack subnet list
openstack router show lab-router- 서브넷 생성 시 자동으로 DHCP 서버가 활성화되어 VM 부팅 시 자동 IP 할당
- 라우터는 내부적으로 L3 에이전트(또는 OVN의 분산 라우팅)로 동작
- DevStack은 설치 시
public외부 네트워크와shared내부 네트워크를 자동 생성 - 프로젝트 간 IP 대역이 겹쳐도(
192.168.100.0/24공통 사용) 테넌트별 네트워크 네임스페이스로 격리됨
source openrc demo demo
# 보안 그룹 생성
openstack security group create lab-secgroup --description "Lab access"
# SSH(22), ICMP 허용 규칙 추가
openstack security group rule create lab-secgroup --protocol tcp --dst-port 22 --remote-ip 0.0.0.0/0
openstack security group rule create lab-secgroup --protocol icmp --remote-ip 0.0.0.0/0# 내부 네트워크 ID 확인(internal-net 네트워크 이름 대신 ID 사용 권장)
NET_ID=$(openstack network show internal-net -f value -c id)
# VM 인스턴스 생성
openstack server create lab-vm-01 \
--flavor lab.small \
--image cirros-0.6.3-x86_64-disk \
--network $NET_ID \
--key-name lab-keypair \
--security-group lab-secgroup# 상태가 BUILD → ACTIVE로 변하는 과정 모니터링
watch -n 1 'openstack server show lab-vm-01 -f value -c status -c OS-EXT-STS:vm_state'- VM 상태 전환 흐름
BUILD: 리소스 스케줄링, 이미지 다운로드, 네트워크 포트 바인딩 진행 중ACTIVE: 정상 실행PAUSED: 메모리 유지, CPU만 정지 (빠른 재개 가능)SHUTOFF: 완전 종료, 리소스 일부 회수ERROR: 호스트 장애 또는 스케줄링 실패
# 일시 정지 (메모리 유지)
openstack server pause lab-vm-01
openstack server show lab-vm-01 -f value -c status
# 재개
openstack server unpause lab-vm-01
openstack server show lab-vm-01 -f value -c status
# 전원 종료
openstack server stop lab-vm-01
openstack server show lab-vm-01 -f value -c status
# 재시작
openstack server start lab-vm-01
openstack server show lab-vm-01 -f value -c status
# 스냅샷 생성 (현재 디스크 상태를 Glance 이미지로 저장)
openstack server image create --name lab-vm-01-snap lab-vm-01
openstack image list
# 다른 Glance 이미지와 함께 snap 이미지가 출력됨- VM 생성 실패 시 트러블슈팅
NoValidHost오류 → Placement에 가용 자원 부족,nova-scheduler로그 확인- 이미지 다운로드 실패 →
glance-api로그 확인 - 네트워크 바인딩 실패 →
neutron-server로그 및 OVN/OVS 상태 확인
Floating IP는 외부 네트워크와 통신하기 위한 공인 IP로, 가상 라우터에서 NAT를 통해 VM 사설 IP와 1:1 매핑
# 외부 네트워크(public)에서 플로팅 IP 할당
FLOATING_IP=$(openstack floating ip create public -f value -c floating_ip_address)
echo "Allocated Floating IP: $FLOATING_IP"
# VM에 플로팅 IP 매핑
openstack server add floating ip lab-vm-01 $FLOATING_IP
# 매핑 확인
openstack server show lab-vm-01 -f value -c addresses# DevStack VM 내부에서 직접 접속 테스트
# CirrOS 기본 계정: cirros / gocubsgo
ping -c 3 $FLOATING_IP
ssh -i ~/.ssh/id_rsa_lab cirros@$FLOATING_IP# 외부 PC(학생 노트북 등)에서 접속 시 SSH 터널 사용
# [DevStack_VM_IP]는 OpenStack이 설치된 VM의 IP
# (1) 외부 PC에서 실행 - DevStack VM 경유하여 Floating IP의 22번 포트를 노트북 2222 포트로 포워딩
ssh -L 2222:[FLOATING_IP]:22 ubuntu@[DevStack_VM_IP]
# (2) 다른 터미널에서 실행 - 터널을 통해 CirrOS 접속 (1번 터미널을 종료하면 연결 끊김)
ssh -p 2222 cirros@localhost
# password : gocubsgo# 두 번째 VM 생성 후 동일 Floating IP를 이동
openstack server create lab-vm-02 \
--flavor lab.small \
--image cirros-0.6.3-x86_64-disk \
--network $NET_ID \
--key-name lab-keypair \
--security-group lab-secgroup
# 기존 VM에서 Floating IP 해제
openstack server remove floating ip lab-vm-01 $FLOATING_IP
# 새 VM으로 Floating IP 매핑
openstack server add floating ip lab-vm-02 $FLOATING_IP
# 매핑 확인
openstack server show lab-vm-02 -f value -c addresses
# 이후 이 Floating IP로 lab-vm-02에 접속 가능- 보안 그룹은 VM의 vNIC 레벨에서 적용되는 stateful 방화벽
- 기본 정책 : 모든 인바운드 차단, 모든 아웃바운드 허용
Allow Rule만 추가 가능 (Deny Rule은 지원하지 않음)
- 웹 서버 표준 규칙 : TCP 22 (SSH), TCP 80 (HTTP), TCP 443 (HTTPS)
- Floating IP는 서비스 중단 없이 다른 VM으로 동적 이동 가능
- Floating IP에 호스트와 동일한 네트워크 대역을 할당하면 외부에서 직접 접근 가능하나, 실제 IP 자원을 차지하므로 본 실습에서는 격리된 가상 대역(
172.24.4.0/24)을 사용 - Floating IP 대역(
172.24.4.0/24)은 DevStack VM 내부에서만 통하므로, 외부에서 접속하려면 SSH 포트 포워딩(ssh -L) 사용 - 위 패턴은 실무에서 Bastion Host(점프 서버)를 통해 사설 클라우드 VM에 접속하는 방식과 동일
- 왜 사설 IP + Floating IP 구조를 쓰는가
VM에게 회사 네트워크 IP를 직접 부여하는 방식(provider network)도 기술적으로 가능하지만, 일반적으로 다음 이점 때문에 사설 IP + Floating IP 구조를 사용- IP 자원 절약 : 외부 노출이 필요한 VM에만 공인 IP 할당, 나머지는 사설 대역 자유롭게 사용
- 보안 격리 : 외부 네트워크와 VM 사이를 NAT로 분리, 명시적으로 노출한 포트 외에는 접근 차단
- 멀티 테넌트 : 프로젝트 A와 B가 동일한 사설 대역(
192.168.10.0/24)을 충돌 없이 사용 가능 - VM 이동성 : VM을 다른 호스트로 마이그레이션해도 사설 IP 그대로 유지, Floating IP는 외부 사용자 모르게 다른 VM으로 이동 가능
- 동적 노출 제어 : VM은 그대로 둔 채
add floating ip/remove floating ip명령으로 외부 노출만 토글
Cinder는 VM 인스턴스에 영구적인 블록 스토리지(볼륨)를 제공. 인스턴스가 삭제되어도 볼륨 데이터는 보존됨
source openrc demo demo
# 1GB 볼륨 생성
openstack volume create --size 1 lab-volume-01
# available 상태로 전환 확인
openstack volume list# 실행 중인 VM에 볼륨 연결 (Attach)
openstack server add volume lab-vm-01 lab-volume-01
# VM 내부에서 새 디바이스 인식 확인
# FLOATING_IP를 다시 lab-vm-01에 매핑한 후 접속
ssh -i ~/.ssh/id_rsa_lab cirros@$FLOATING_IP "lsblk"# VM 내부에서 파일시스템 생성 및 마운트
ssh -i ~/.ssh/id_rsa_lab cirros@$FLOATING_IP <<'EOF'
sudo mkfs.ext4 /dev/vdb
sudo mkdir /mnt/cinder
sudo mount /dev/vdb /mnt/cinder
echo "Cinder persistent storage test" | sudo tee /mnt/cinder/test.txt
sudo umount /mnt/cinder
EOF# 볼륨 분리
openstack server remove volume lab-vm-01 lab-volume-01
# 다시 연결
openstack server add volume lab-vm-01 lab-volume-01
# VM에서 다시 마운트하고 파일 확인
ssh -i ~/.ssh/id_rsa_lab cirros@$FLOATING_IP <<'EOF'
sudo mount /dev/vdb /mnt/cinder
sudo cat /mnt/cinder/test.txt
sudo umount /mnt/cinder
EOF# 스냅샷 생성(사용중인 볼륨이므로 --force 옵션 필요)
openstack volume snapshot create --volume lab-volume-01 --force lab-snap-01
openstack volume snapshot list
# 스냅샷으로부터 새 볼륨 복제(lab-volume-02 생성)
openstack volume create --snapshot lab-snap-01 --size 1 lab-volume-02# 새로 만든 lab-volume-02를 VM에 붙여서 확인 가능
openstack server add volume lab-vm-01 lab-volume-02
ssh -i ~/.ssh/id_rsa_lab cirros@$FLOATING_IP <<'EOF'
sudo mount /dev/vdb /mnt
ls /mnt
sudo cat /mnt/test.txt
sudo umount /mnt
EOF# 확장 전 볼륨을 VM에서 분리
openstack server remove volume lab-vm-01 lab-volume-01
# 1GB → 2GB로 확장
openstack volume set --size 2 lab-volume-01
# 다시 연결
openstack server add volume lab-vm-01 lab-volume-01# VM 내부에서 확장된 볼륨 인식 및 파일시스템 크기 조정
ssh -i ~/.ssh/id_rsa_lab cirros@$FLOATING_IP <<'EOF'
sudo mount /dev/vdb /mnt/cinder
sudo resize2fs /dev/vdb
df -h /mnt/cinder
sudo umount /mnt/cinder
EOF- DevStack의 기본 Cinder 백엔드는
LVM이며, 운영 환경에서는 Ceph RBD / NetApp 등으로 교체 - VM 삭제와 무관하게 데이터가 보존되므로 DB, 파일시스템 등
Stateful워크로드에 적합 - 볼륨 백업(
openstack volume backup create)은 Swift 등 외부 오브젝트 스토리지에 저장 - Multi-attach 활성화 시 동일 볼륨을 여러 VM에 동시 연결 가능 (클러스터 파일시스템 필수)
Swift는 페타바이트 규모의 비정형 데이터를 저장하는 오브젝트 스토리지 서비스
계층 구조 : Account → Container → Object
cd /opt/stack/devstack
source openrc demo demo
# Swift 서비스 동작 확인
openstack object store account show# 컨테이너 생성 (폴더 개념)
openstack container create lab-data
# 컨테이너 목록 확인
openstack container list# 오브젝트(파일) 업로드
echo "Storage Virtualization test data" > dataset.txt
openstack object create lab-data dataset.txt
# 오브젝트 목록 및 메타데이터 확인
openstack object list lab-data
openstack object show lab-data dataset.txt# 오브젝트 다운로드
openstack object save lab-data dataset.txt --file /tmp/dataset-downloaded.txt
cat /tmp/dataset-downloaded.txt# 컨테이너 내 모든 오브젝트 삭제
openstack object delete lab-data dataset.txt
# 빈 컨테이너 확인
openstack object list lab-data
# 컨테이너 삭제 (비어있어야 삭제 가능)
openstack container delete lab-data
# 삭제 확인
openstack container list- Swift는 REST API 기반이므로
curl로 직접 접근 가능 (X-Auth-Token헤더에 토큰 전달) - 운영 환경 특성
- 3벌 복제 (replicas=3) : 단일 노드 환경에서는
SWIFT_REPLICAS=1로 축소 - 자가 치유 (auditor/replicator) : 손상된 오브젝트 자동 복구
- 리밸런싱 : 노드 추가/제거 시 데이터 분포 자동 재조정
- 3벌 복제 (replicas=3) : 단일 노드 환경에서는
- 컨테이너는 비어있어야 삭제 가능. 내부에 오브젝트가 남아있으면
Conflict에러 발생 openstack container delete --recursive lab-data옵션으로 안의 오브젝트까지 한 번에 삭제 가능 (위험하므로 운영 환경에서 주의)
Heat는 텍스트 템플릿(HOT)을 사용하여 복합 자원을 스택(Stack) 단위로 일괄 생성/관리하는 서비스
cd /opt/stack/devstack
source openrc demo demo
# Heat 템플릿 파일 작성
cat > /tmp/lab-stack.yaml <<'EOF'
heat_template_version: 2021-04-16
description: Simple lab stack - VM with network and volume
parameters:
image_name:
type: string
default: cirros-0.6.3-x86_64-disk
flavor_name:
type: string
default: lab.small
network_name:
type: string
default: internal-net
keypair_name:
type: string
default: lab-keypair
resources:
lab_volume:
type: OS::Cinder::Volume
properties:
size: 1
name: heat-managed-volume
lab_instance:
type: OS::Nova::Server
properties:
name: heat-managed-vm
image: { get_param: image_name }
flavor: { get_param: flavor_name }
key_name: { get_param: keypair_name }
networks:
- network: { get_param: network_name }
lab_attachment:
type: OS::Cinder::VolumeAttachment
properties:
volume_id: { get_resource: lab_volume }
instance_uuid: { get_resource: lab_instance }
outputs:
instance_ip:
description: VM의 사설 IP 주소
value: { get_attr: [lab_instance, first_address] }
EOF# 스택 생성
openstack stack create -t /tmp/lab-stack.yaml lab-stack
# 스택 상태 추적
openstack stack list
openstack stack show lab-stack# 스택이 생성한 리소스 목록
openstack stack resource list lab-stack
# 출력값 조회
openstack stack output show lab-stack instance_ip# 스택 업데이트 (변경분만 반영)
openstack stack update -t /tmp/lab-stack.yaml lab-stack \
--parameter flavor_name=lab.small- HOT 핵심 섹션
heat_template_version: 템플릿 문법 버전parameters: 사용자 입력 변수resources: 생성할 자원 정의outputs: 생성 후 반환할 값
- 주요 리소스 타입
OS::Nova::Server: VM 인스턴스OS::Cinder::Volume: 블록 볼륨OS::Neutron::Net/Subnet/Router: 가상 네트워크OS::Heat::AutoScalingGroup: 자동 확장 그룹
- AutoScaling 구성은
Heat+Aodh(알람) +Ceilometer(메트릭) 조합 필요
OpenStack은 두 가지 공식 웹 대시보드 제공
Horizon: Django 기반의 전통적인 서버 사이드 렌더링 UISkyline: Vue.js + FastAPI 기반의 SPA(Single Page Application) 구조 차세대 UI
두 대시보드 동시 활성화 시 Skyline 플러그인이 자동으로 URI를 분리하여 충돌 없이 함께 동작
| 대시보드 | 접속 URL |
|---|---|
| Skyline | http://[VM_IP]:9999 |
| Horizon | http://[VM_IP]/dashboard(설치 방법에 따라 horizon일 수 있음) |
웹 브라우저에서 http://[VM_IP]/dashboard 접속
| 계정 | 비밀번호 |
|---|---|
admin |
ADMIN_PASSWORD (예: secret) |
demo |
동일 |
# Skyline 서비스 동작 확인
sudo systemctl status devstack@skyline.service
# Skyline 포트(9999) 바인딩 확인
sudo ss -tlnp | grep 9999웹 브라우저에서 http://[VM_IP]:9999 접속 (계정은 Horizon과 동일)
CLI로 수행한 작업을 두 대시보드에서 동일하게 수행하며 UX 차이 비교
| 작업 | 대응 CLI |
|---|---|
| 인스턴스 생성 | openstack server create |
| 이미지 목록 / 등록 | openstack image list/create |
| 볼륨 생성 | openstack volume create |
| 네트워크 토폴로지 확인 | openstack network list |
| 보안 그룹 설정 | openstack security group ... |
| 프로젝트 / 사용자 / 역할 관리 | openstack project/user/role ... |
| 하이퍼바이저 현황 | openstack hypervisor list |
- 두 대시보드는 동일한 OpenStack REST API를 호출하므로, 어느 쪽에서 자원을 생성하든 다른 쪽에서 즉시 조회 가능
Horizon은 페이지 이동 시마다 서버에서 HTML을 렌더링하여 응답 (Django 기반 SSR)Skyline은 SPA 구조로 초기 1회 로딩 후 브라우저에서 화면 전환, 백엔드(FastAPI)는 비동기로 API 중계- Skyline의 Network Topology, 하이퍼바이저 선택 등 일부 기능은 Horizon보다 직관적으로 시각화됨
OpenStack의 모든 서비스는 X-Auth-Token 헤더로 전달된 토큰을 Keystone에 검증한 후 API 요청 처리
# Nova API 엔드포인트 확인 (admin 권한 필요)
source openrc admin admin
NOVA_URL=$(openstack endpoint list --service compute --interface public -f value -c URL)
echo "Nova endpoint: $NOVA_URL"# 1. 로그인 요청 → demo 사용자로 Fernet Token 발급
# [VM_IP]는 현재 VM의 IP 주소로 변경
TOKEN=$(curl -si -X POST http://[VM_IP]/identity/v3/auth/tokens \
-H "Content-Type: application/json" \
-d '{
"auth": {
"identity": {
"methods": ["password"],
"password": {
"user": {
"name": "demo",
"domain": {"name": "Default"},
"password": "secret"
}
}
},
"scope": {
"project": {
"name": "demo",
"domain": {"name": "Default"}
}
}
}
}' | grep -i "^x-subject-token" | awk '{print $2}' | tr -d '\r')
echo "Issued token: ${TOKEN:0:60}..."
echo "Token length: ${#TOKEN}"# 2. 발급받은 토큰으로 Nova API 직접 호출 (demo 프로젝트의 VM 목록 조회)
curl -s -H "X-Auth-Token: $TOKEN" $NOVA_URL/servers | python3 -m json.tool# 3. 잘못된 토큰으로 호출 시도 (검증 실패 확인)
curl -s -o /dev/null -w "HTTP %{http_code}\n" \
-H "X-Auth-Token: invalid-token-xxx" \
$NOVA_URL/servers- Keystone은 Fernet 키로 토큰을 복호화하여 (1) 만료 시각 (2) 사용자/프로젝트/역할 (3) 정책 기반 인가 결정
- 토큰 검증 결과는
Memcached에 캐싱되어 반복 호출 시 DB I/O 절감 - 토큰 유효기간(TTL)은 기본 1시간
identity:list_services,identity:list_endpoints등 서비스 카탈로그 조회는 기본 정책상 admin 권한 필요. 일반 사용자(demo)는 자신의 프로젝트 내 자원만 조회/관리 가능- API 응답으로 받는 자원 목록은 토큰의 scope(프로젝트)에 따라 달라짐. demo 토큰으로 조회 시 §15에서 생성한
lab-vm-01,lab-vm-02가 표시되며, 같은 API 엔드포인트라도 admin 토큰으로 조회하면 다른 결과가 반환됨 - 잘못된 토큰으로 호출 시 HTTP 401(Unauthorized) 응답. 모든 OpenStack 서비스가 동일하게 Keystone 검증을 거치므로 인증 우회 불가
# 시스템 상태 종합 확인
openstack hypervisor list
openstack compute service list
openstack network agent list
openstack volume service list# 서비스 로그 확인 (systemd 기반)
sudo journalctl -u devstack@n-api.service --since "1 hour ago" | tail -20
sudo journalctl -u devstack@n-sch.service --since "1 hour ago" | tail -20
sudo journalctl -u devstack@n-cpu.service --since "1 hour ago" | tail -20
sudo journalctl -u devstack@q-svc.service --since "1 hour ago" | tail -20
sudo journalctl -u devstack@keystone.service --since "1 hour ago" | tail -20| 서비스 | systemd 유닛 | 주요 로그 내용 |
|---|---|---|
| Nova API | devstack@n-api.service |
REST API 요청 처리 |
| Nova Scheduler | devstack@n-sch.service |
VM 배치 결정 |
| Nova Compute | devstack@n-cpu.service |
libvirt 호출, VM lifecycle |
| Nova Conductor | devstack@n-cond.service |
DB 중계 작업 |
| Neutron | devstack@q-svc.service |
가상 네트워크 프로비저닝 |
| Keystone | devstack@keystone.service |
인증/인가, 토큰 발급 |
| Glance | devstack@g-api.service |
이미지 등록/배포 |
| Cinder | devstack@c-api.service |
볼륨 API |
- 운영 체크리스트
- 일일 : 컴퓨트 노드 상태 확인, 스토리지 용량 모니터링
- 주간 : MariaDB 백업 확인, 만료 토큰 정리(
keystone-manage token_flush) - 보안/성능 : NTP 시간 동기화, Fernet Key Rotation 수행
- 트러블슈팅 시나리오
VM 생성 실패 (NoValidHost)→n-sch.service로그, Placement 인벤토리 점검이미지 다운로드 오류→g-api.service로그, Glance 백엔드 용량 확인네트워크 통신 불가→ 보안 그룹 규칙, OVN 컨트롤러 상태(ovn-nbctl show), 외부 게이트웨이 확인
OpenStack 자원은 의존성이 있으므로 역순으로 정리. VM → Floating IP → 볼륨/스냅샷 → 네트워크 → 사용자/도메인 순서
하위요소가 남아있는 요소들은 삭제 시 Conflict 또는 ResourceInUse 에러 발생
스택 단위로 한 번에 정리 가능 (Heat이 만든 모든 자원 자동 삭제)
source openrc demo demo
# Heat 스택 삭제
openstack stack delete lab-stack --yes
# 삭제 확인
openstack stack listsource openrc demo demo
# Floating IP 해제 후 반환
openstack server remove floating ip lab-vm-02 $FLOATING_IP
openstack floating ip delete $FLOATING_IP
# VM 삭제 (연결된 볼륨은 자동 분리됨)
openstack server delete lab-vm-01 lab-vm-02
# 삭제 확인
openstack server list스냅샷이 존재하는 볼륨은 삭제 불가. 스냅샷 먼저 삭제
# 스냅샷 삭제
openstack volume snapshot delete lab-snap-01
# 볼륨 삭제
openstack volume delete lab-volume-01 lab-volume-02
# 삭제 확인
openstack volume list
openstack volume snapshot list# 컨테이너 내 모든 오브젝트 삭제
for obj in $(openstack object list lab-data -f value -c Name); do
openstack object delete lab-data "$obj"
done
# 빈 컨테이너 확인 후 삭제
openstack container delete lab-data
# 삭제 확인
openstack container listsource openrc admin admin
# 추가 등록한 Ubuntu 이미지 삭제
openstack image delete ubuntu-24.04
# 삭제 확인 (CirrOS 등 DevStack 기본 이미지만 남음)
openstack image list라우터의 외부 게이트웨이 해제 → 서브넷 인터페이스 분리 → 라우터 삭제 → 서브넷/네트워크 삭제 순서
source openrc demo demo
# 라우터 외부 게이트웨이 해제
openstack router unset --external-gateway lab-router
# 라우터에서 내부 서브넷 인터페이스 분리
openstack router remove subnet lab-router internal-subnet
# 라우터 삭제
openstack router delete lab-router
# 서브넷 및 네트워크 삭제
openstack subnet delete internal-subnet
openstack network delete internal-net
# 삭제 확인
openstack router list
openstack network list# 보안 그룹 삭제
openstack security group delete lab-secgroup
# 키페어 삭제
openstack keypair delete lab-keypairsource openrc admin admin
# 실습용 Flavor 삭제
openstack flavor delete lab.small사용자 → 프로젝트 → 도메인 순서로 정리. 도메인 삭제 시 먼저 비활성화 필요
# 사용자 삭제
openstack user delete student --domain dku
# 프로젝트 삭제
openstack project delete cloud-lab --domain dku
# 도메인 비활성화 후 삭제
openstack domain set --disable dku
openstack domain delete dku
# 삭제 확인
openstack domain list- 자원 삭제는 항상 의존성 역순으로 진행
- VM이 볼륨에 연결되어 있으면 → VM 먼저 삭제
- 스냅샷이 볼륨 참조 중이면 → 스냅샷 먼저 삭제
- 라우터가 네트워크에 연결되어 있으면 → 라우터 인터페이스 먼저 분리
- 도메인은 비활성화 후에만 삭제 가능. 활성 상태의 도메인 삭제 시도 시
Cannot delete a domain that is enabled에러 - 자원이 많아 일일이 삭제하기 번거로우면
./unstack.sh또는./clean.sh로 DevStack 환경 자체를 초기화하는 것이 빠름
OpenStack 자원이 아닌 DevStack 자체를 초기화하는 명령어
# 실행 중인 OpenStack 서비스 중지 (DB 등 영구 데이터는 보존)
cd /opt/stack/devstack
./unstack.sh# 완전 초기화 (재설치 전 모든 데이터 삭제)
./clean.shunstack.sh- 서비스만 중지. 이후stack.sh재실행 시 빠르게 복구clean.sh- DB / 설정 / 패키지 일부 잔여물 제거. 완전 재설치 시 사용- DevStack은 시스템에 광범위한 변경을 가하므로, 가장 안전한 정리 방법은
VM 자체 재생성




























































