---
title: "OpenStack 수동 설치 8 — Cinder LVM + iSCSI 블록 스토리지 구성"
description: "OpenStack 2026.1 환경에서 Ubuntu 24.04 LTS를 이용해 Cinder LVM + iSCSI 백엔드를 구성하고, RAID 5, LVM, 필터 설정, cinder.conf, iSCSI 타깃 및 서비스 시작까지 단계별로 설치·검증하는 방법을 안내한다."
date: "2026-08-08"
last_modified: "2026-08-28T01:12:00.000Z"
type: "Post"
tags:
  - "openstack"
  - "install"
  - "ubuntu"
  - "LVM"
  - "iSCSI"
  - "storage"
  - "troubleshooting"
categories:
  - "📗 Docs"
series:
  - "오픈스택 설치"
canonical_url: "https://blog.pieroot.xyz/openstack-cinder-lvm"
markdown_url: "https://blog.pieroot.xyz/openstack-cinder-lvm.md"
---

# OpenStack 수동 설치 8 — Cinder LVM + iSCSI 블록 스토리지 구성

OpenStack 2026.1 환경에서 Ubuntu 24.04 LTS를 이용해 Cinder LVM + iSCSI 백엔드를 구성하고, RAID 5, LVM, 필터 설정, cinder.conf, iSCSI 타깃 및 서비스 시작까지 단계별로 설치·검증하는 방법을 안내한다.

![image](https://blog.pieroot.xyz/api/image-proxy?id=627ea53d-62ba-423a-aa3b-40ea3bac0199&kind=s3&pageId=30d067c0-15d0-800e-a8fa-c565cd7236bb&source=block&blockId=30d067c0-15d0-801b-a6d8-d9d0647e79cc)

Neutron으로 첫 인스턴스 부팅까지 확인했다면, 다음 단계는 인스턴스에 영구 디스크를 제공하는 **Cinder(Block Storage)** 다. 이 글은 **Ubuntu 24.04 LTS + OpenStack 2026.1 (Gazpacho)** 수동 설치 환경에서 Cinder controller 서비스와 **LVM + iSCSI** 백엔드를 구성하고, 볼륨 생성·attach·마운트까지 검증하는 흐름으로 갱신했다.

실습에서는 controller가 `cinder-api`와 `cinder-scheduler`를, 별도 storage 노드(또는 여유 디스크가 있는 controller)가 `cinder-volume`을 담당한다. 아래 RAID 5 구성과 기존 이미지는 LVM 백엔드 설계·운영 관점의 참고 예시로 그대로 유지한다.

### 노드별 역할과 설정 범위

> 아래 구성은 **controller / Block Storage / Compute가 분리된 3-역할 배치**를 기준으로 한다. 단일 노드 실습이라면 해당 노드에서 모든 역할의 설정을 합쳐 적용하되, 역할별 서비스와 설정 파일을 빠뜨리지 않는 것이 핵심이다.

> **역할을 나누었다면 같은 설정을 한 노드에만 넣으면 안 된다.** 특히 `cinder.conf`의 LVM backend는 Block Storage 노드에, `open-iscsi`와 Nova의 Cinder 연동 설정은 **모든 Compute 노드**에 적용한다.

---

### 수동 설치에 추가되는 controller 구성

먼저 controller에서 Cinder DB, 서비스 사용자, API endpoint를 준비한다. **2026.1 기준으로는 ****`block-storage`**** 서비스 엔터티 하나와 ****`/v3`**** endpoint를 사용한다.** 예전 예제의 `volumev3` 서비스 타입이나 `/v3/%(project_id)s` endpoint 형식은 사용하지 않는다.

```sql
CREATE DATABASE cinder;
CREATE USER 'cinder'@'localhost' IDENTIFIED BY 'CINDER_DBPASS';
GRANT ALL PRIVILEGES ON cinder.* TO 'cinder'@'localhost';
CREATE USER 'cinder'@'%' IDENTIFIED BY 'CINDER_DBPASS';
GRANT ALL PRIVILEGES ON cinder.* TO 'cinder'@'%';
FLUSH PRIVILEGES;
```

```bash
source ~/admin-openrc

openstack user create --domain default --password-prompt cinder
openstack role add --project service --user cinder admin

# Xena 이후 Cinder는 block-storage 서비스 엔터티 하나를 사용한다.
openstack service create --name cinder \
  --description "OpenStack Block Storage" block-storage
openstack endpoint create --region RegionOne \
  block-storage public http://controller:8776/v3
openstack endpoint create --region RegionOne \
  block-storage internal http://controller:8776/v3
openstack endpoint create --region RegionOne \
  block-storage admin http://controller:8776/v3

sudo apt install -y cinder-api cinder-scheduler
```

`/etc/cinder/cinder.conf`에는 DB, RabbitMQ, Keystone 인증과 management IP를 설정한다.

```
[database]
connection = mysql+pymysql://cinder:CINDER_DBPASS@controller/cinder

[DEFAULT]
my_ip = 192.168.56.101
transport_url = rabbit://openstack:RABBIT_PASS@controller
auth_strategy = keystone

[keystone_authtoken]
www_authenticate_uri = http://controller:5000
auth_url = http://controller:5000
memcached_servers = controller:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = cinder
password = CINDER_PASS

# Nova가 전달하는 service token을 반드시 검증한다.
service_token_roles = service
service_token_roles_required = true

[service_user]
# Cinder가 다른 OpenStack 서비스에 요청할 때 service token을 함께 보낸다.
send_service_user_token = true
project_domain_name = default
project_name = service
user_domain_name = default
username = cinder
password = CINDER_PASS
auth_url = http://controller:5000
auth_type = password

[oslo_concurrency]
lock_path = /var/lib/cinder/tmp
```

> **Service Token은 선택 사항이 아니다.** 2023-05-10 이후 릴리스에서는 CVE-2023-2088 대응을 위해 Nova가 Cinder에 service token을 보내고, Cinder가 이를 검증하도록 구성해야 한다. 실제 운영 환경에서는 `CINDER_PASS`, `NOVA_PASS`를 별도 Secret 관리 체계로 보관한다.

관리자 권한으로 `service` role의 존재와 할당을 확인한다. role이 없다면 먼저 생성한다.

```bash
openstack role show service
# 위 명령이 실패할 때만 실행
openstack role create service

openstack role add --user cinder --project service service
openstack role add --user nova --project service service
openstack role assignment list --user cinder --project service --names
openstack role assignment list --user nova --project service --names
```

Nova도 Cinder를 사용할 region과 service token 발급 정보를 가져야 한다. `/etc/nova/nova.conf`에서 **`nova-api`****가 실행되는 controller와 ****`nova-compute`****가 실행되는 모든 Compute 노드**에 아래 항목을 적용한다. 기존 섹션이 있다면 **섹션을 중복하지 말고 항목만 병합**한다.

```
[cinder]
os_region_name = RegionOne

[service_user]
send_service_user_token = true
project_domain_name = default
project_name = service
user_domain_name = default
username = nova
password = NOVA_PASS
auth_url = http://controller:5000
auth_type = password
```

> `[cinder]`은 Nova가 Cinder endpoint의 region을 선택하게 하고, `[service_user]`는 Nova가 Cinder API 호출에 service token을 함께 보내게 한다. Compute 노드 하나라도 이 설정이 빠지면 해당 노드에서의 volume attach가 인증 오류로 실패할 수 있다.

```bash
sudo su -s /bin/sh -c "cinder-manage db sync" cinder
sudo systemctl restart nova-api cinder-scheduler apache2

source ~/admin-openrc
openstack endpoint list --service block-storage
```

이후 storage 노드에 `cinder-volume`, `lvm2`, `thin-provisioning-tools`, `tgt`를 설치하고, Compute 노드에는 `open-iscsi` initiator를 준비한다. 아래 LVM·iSCSI 백엔드 설정을 적용한 뒤, `openstack volume create` → 인스턴스 attach → 게스트 OS에서 파일시스템 생성·마운트까지 검증한다.

> **이 글에서 다루는 내용**
> 
> - 하드웨어 RAID 5 구성 및 확인
> 
> - LVM Physical Volume / Volume Group 생성
> 
> - `/etc/lvm/lvm.conf` 필터 설정 (중요!)
> 
> - `/etc/cinder/cinder.conf` LVM 백엔드 설정
> 
> - iSCSI 타겟 데몬(tgt) 구성
> 
> - Kolla Ansible 환경에서의 설정 방법
> 
> - 동작 확인 및 트러블슈팅

![OpenStack Cinder LVM + iSCSI 아키텍처](https://blog.pieroot.xyz/api/image-proxy?id=2b134b1e-866c-402a-954d-851ca4e79060&kind=s3&pageId=30d067c0-15d0-800e-a8fa-c565cd7236bb&source=block&blockId=3bce4aac-b6f0-44ed-90d2-ed8159ca2cce)

---

### 🤔 왜 LVM + iSCSI인가?

Cinder의 스토리지 백엔드로는 Ceph RBD, NFS, 상용 SAN 등 다양한 옵션이 있다. 그런데 **LVM + iSCSI**는 Cinder의 **레퍼런스 드라이버**로, 추가적인 외부 스토리지 시스템 없이 **로컬 디스크만으로** 블록 스토리지를 제공할 수 있다는 장점이 있다.

> **LVM + iSCSI 구조 한눈에 보기**
> 
> 1. **LVM**: 물리 디스크를 논리 볼륨으로 관리. Cinder가 볼륨을 생성하면 LVM에서 Logical Volume을 하나 만든다
> 
> 1. **iSCSI**: 네트워크를 통해 블록 디바이스를 공유하는 프로토콜. Compute 노드의 VM이 Storage 노드의 LV에 접근할 수 있게 해준다
> 
> 1. **tgt(iSCSI Target)**: Storage 노드에서 LV를 iSCSI 타겟으로 노출시키는 데몬

```javascript
┌─────────────────────┐         iSCSI          ┌──────────────────────────┐
│    Compute Node     │◀══════════════════════▶│     Storage Node         │
│                     │    (TCP/IP Network)    │                          │
│  ┌───────────────┐  │                        │  ┌────────────────────┐  │
│  │  VM Instance  │  │                        │  │  tgt (iSCSI target)│  │
│  │   /dev/vdb    │  │                        │  │         │          │  │
│  └───────────────┘  │                        │  │         ▼          │  │
│                     │                        │  │  ┌──────────────┐  │  │
│  iSCSI Initiator    │                        │  │  │  LVM (LV)    │  │  │
│  (open-iscsi)       │                        │  │  │  cinder-vol  │  │  │
│                     │                        │  │  └──────┬───────┘  │  │
└─────────────────────┘                        │  │         │          │  │
                                               │  │         ▼          │  │
                                               │  │  ┌──────────────┐  │  │
                                               │  │  │  /dev/md126  │  │  │
                                               │  │  │  (RAID 5)    │  │  │
                                               │  │  └──────────────┘  │  │
                                               │  └────────────────────┘  │
                                               └──────────────────────────┘
```

> **LVM 백엔드의 한계**
> 
> LVM 백엔드는 **단일 스토리지 노드**에 의존하기 때문에 **Single Point of Failure**가 된다. 고가용성이 필요한 프로덕션 환경에서는 Ceph RBD 같은 분산 스토리지를 권장한다. 하지만 소규모 환경이나 테스트, 연구용으로는 충분히 괜찮은 선택이다.

---

### 🔧 1단계: 하드웨어 RAID 구성

cinder에서 사용할 디스크를 우선 구성해야 한다. 연구실에 남는 디스크 **2TB × 4개**를 구했으므로, RAID 5로 구성하여 약 **6TB**의 볼륨을 사용할 생각이다.

> **RAID 레벨 선택 기준**
> 
> - **RAID 0**: 속도 최우선, 안정성 없음. ~~디스크 하나 죽으면 전부 날아간다~~
> 
> - **RAID 1**: 미러링. 안정성 좋지만 용량 50%만 사용 가능
> 
> - **RAID 5**: 패리티 1개. 디스크 1개 장애까지 허용. **용량 대비 안정성 밸런스가 좋다**
> 
> - **RAID 6**: 패리티 2개. 디스크 2개 장애까지 허용. 쓰기 성능이 좀 떨어짐
> 
> 4개의 디스크에 RAID 5를 적용하면 (4-1) × 2TB = **약 6TB** 사용 가능

메인보드에서 하드웨어 RAID 5를 구성하고 서버를 부팅한 뒤, `lsblk`로 디스크 상태를 확인한다.

```bash
lsblk
```

![image](https://blog.pieroot.xyz/api/image-proxy?id=024f07c2-14c8-406e-836e-27eaad73172c&kind=s3&pageId=30d067c0-15d0-800e-a8fa-c565cd7236bb&source=block&blockId=30d067c0-15d0-8078-8232-e9103a24408f)

디스크 4개(sda, sdb, sdc, sdd)가 RAID 5로 잘 구성되었으며, `md126`이라는 이름으로 묶여있다.

![RAID 5에서 Cinder Volume Group까지](https://blog.pieroot.xyz/api/image-proxy?id=d3246686-9c1d-488f-8765-ca3b8749373c&kind=s3&pageId=30d067c0-15d0-800e-a8fa-c565cd7236bb&source=block&blockId=7145f654-50d1-424d-b096-f6996bd7a1a1)

#### RAID 상태 확인

RAID 어레이의 상태를 좀 더 자세히 확인하려면 `mdadm`을 사용한다.

```bash
sudo mdadm --detail /dev/md126
```

![image](https://blog.pieroot.xyz/api/image-proxy?id=003b1665-9243-4541-9f3f-1912caac919c&kind=s3&pageId=30d067c0-15d0-800e-a8fa-c565cd7236bb&source=block&blockId=30d067c0-15d0-80de-971d-c5b29f22114e)

> **mdadm 출력에서 확인해야 할 포인트**
> 
> - **State**: `active` 또는 `clean`이면 정상
> 
> - **Active Devices / Working Devices**: 구성한 디스크 수와 일치하는지 확인
> 
> - **Failed Devices**: 0이어야 한다. 1 이상이면 디스크 교체가 필요
> 
> - **Rebuild Status**: 리빌드 중이라면 완료될 때까지 기다린 후 다음 작업을 진행하자

---

### 🔧 2단계: LVM 구성

디스크가 정상적으로 RAID 구성된 것을 확인했으니, 이제 LVM으로 Cinder에서 사용할 볼륨 그룹을 만들어야 한다.

#### 필수 패키지 설치

LVM 도구가 설치되어 있지 않다면 먼저 설치한다.

```bash
sudo apt install lvm2 thin-provisioning-tools
```

> **thin-provisioning-tools란?**
> 
> Cinder의 LVM 드라이버는 **Thin Provisioning**을 지원한다. Thin Provisioning은 실제로 데이터를 쓸 때만 디스크 공간을 할당하는 방식이다. 예를 들어 100GB 볼륨을 만들어도 실제로 10GB만 사용 중이면 10GB만 차지한다. 이 도구가 있어야 thin provisioning 기능을 활용할 수 있다.

#### Physical Volume 및 Volume Group 생성

```bash
# Physical Volume 생성
sudo pvcreate /dev/md126

# Volume Group 생성 (cinder-volumes라는 이름으로)
sudo vgcreate cinder-volumes /dev/md126
```

> **Volume Group 이름이 중요하다!**
> 
> 여기서 설정한 Volume Group 이름(`cinder-volumes`)은 나중에 `cinder.conf`의 `[lvm]` 섹션에서 **정확히 동일하게** 지정해야 한다. 이름이 다르면 Cinder가 볼륨을 생성할 수 없다.

#### 생성 확인

```bash
# Physical Volume 확인
sudo pvs

# Volume Group 확인
sudo vgs

# 상세 정보 확인
sudo vgdisplay cinder-volumes
```

`vgs` 출력에서 `cinder-volumes` VG가 보이고, `VSize`가 약 6TB로 표시되면 성공이다.

---

### 🔒 3단계: lvm.conf 필터 설정

이 단계가 **은근히 중요한데 자주 빠뜨리는** 부분이다. LVM은 기본적으로 `/dev` 디렉토리의 모든 블록 디바이스를 스캔한다. 문제는 Cinder가 생성한 LV를 Compute 노드에서 iSCSI로 연결했을 때, **Compute 노드의 LVM도 해당 볼륨을 감지해서 캐싱**하려고 시도한다는 것이다. 이렇게 되면 OS와 VM 볼륨 사이에 충돌이 발생할 수 있다.

> **필터 미설정 시 발생할 수 있는 문제**
> 
> - Compute 노드의 LVM이 VM 볼륨을 스캔하여 메타데이터 충돌 발생
> 
> - 볼륨 생성/삭제 시 예상치 못한 오류
> 
> - 최악의 경우 OS 디스크의 LVM 메타데이터가 손상될 수 있다 😭

#### Storage 노드 필터 설정

`/etc/lvm/lvm.conf` 파일을 편집한다.

```bash
sudo vi /etc/lvm/lvm.conf
```

`devices` 섹션에서 `filter` 항목을 찾아 다음과 같이 설정한다.

```bash
devices {
    ...
    filter = [ "a/md126/", "r/.*/" ]
}
```

> **필터 문법 해설**
> 
> - `a`: **Accept** - 해당 디바이스를 LVM 스캔에 포함
> 
> - `r`: **Reject** - 해당 디바이스를 LVM 스캔에서 제외
> 
> - `a/md126/`: RAID 어레이 디바이스를 허용
> 
> - `r/.*/`: 나머지 모든 디바이스를 거부
> 
> - 배열의 **마지막은 반드시** `r/.*/`로 끝나야 한다

만약 OS 디스크도 LVM을 사용하고 있다면(예: `/dev/sda`), OS 디스크도 필터에 추가해야 한다.

```bash
# OS 디스크가 /dev/sda인 경우
filter = [ "a/sda/", "a/md126/", "r/.*/" ]
```

#### Compute 노드 필터 설정

Compute 노드에서도 `/etc/lvm/lvm.conf`의 필터를 설정해야 한다. Compute 노드에서는 **OS 디스크만 허용**하고 나머지는 전부 거부한다.

```bash
# Compute 노드의 /etc/lvm/lvm.conf
filter = [ "a/sda/", "r/.*/" ]
```

#### 필터 테스트

설정 후 `vgs` 명령으로 필터가 제대로 동작하는지 확인한다.

```bash
# -vvvv 옵션으로 상세 로그 확인
sudo vgs -vvvv 2>&1 | grep "filter"
```

![LVM Device Filter Rules](https://blog.pieroot.xyz/api/image-proxy?id=067a8360-115d-4c66-a1ca-fa6a03cc1818&kind=s3&pageId=30d067c0-15d0-800e-a8fa-c565cd7236bb&source=block&blockId=64adc16d-ae8d-4f64-a4c6-9b67b55c40d7)

---

### ⚙️ 4단계: cinder.conf 설정

이제 Cinder의 설정 파일에서 LVM 백엔드를 구성한다.

#### 수동 설치 환경

`/etc/cinder/cinder.conf`를 편집한다. storage 노드도 DB, RabbitMQ, Keystone 인증을 모두 설정해야 하며, backend 이름·volume type·extra spec의 값은 하나로 맞춰야 한다.

```
[database]
connection = mysql+pymysql://cinder:CINDER_DBPASS@controller/cinder

[DEFAULT]
# Storage 노드의 Management IP
my_ip = 172.30.0.11

# 활성화할 백엔드 이름 (아래 섹션명과 일치해야 함)
enabled_backends = lvm

# type 미지정 볼륨이 사용할 기본 type
# 사전에 `openstack volume type create lvm`을 실행해야 한다.
default_volume_type = lvm

# Glance API 주소
glance_api_servers = http://controller:9292

# RabbitMQ 설정
transport_url = rabbit://openstack:RABBIT_PASS@controller

# 인증 방식
auth_strategy = keystone

[lvm]
# LVM 볼륨 드라이버
volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver

# 볼륨 그룹 이름 (위에서 만든 VG 이름과 동일해야 함!)
volume_group = cinder-volumes

# volume type의 volume_backend_name과 동일해야 한다.
volume_backend_name = lvm

# iSCSI 프로토콜 사용
target_protocol = iscsi

# iSCSI 타겟 헬퍼 (tgt 사용)
target_helper = tgtadm

# iSCSI 타겟이 리슨할 IP (Storage 네트워크 IP)
target_ip_address = 172.30.0.11

[keystone_authtoken]
www_authenticate_uri = http://controller:5000
auth_url = http://controller:5000
memcached_servers = controller:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = cinder
password = CINDER_PASS
service_token_roles = service
service_token_roles_required = true

[service_user]
send_service_user_token = true
project_domain_name = default
project_name = service
user_domain_name = default
username = cinder
password = CINDER_PASS
auth_url = http://controller:5000
auth_type = password

[oslo_concurrency]
lock_path = /var/lib/cinder/tmp
```

> **설정 항목 상세 해설**
> 
> - **`volume_driver`**: LVM 볼륨 드라이버 클래스 경로. 이건 고정값이다
> 
> - **`volume_group`**: `vgcreate`로 만든 볼륨 그룹 이름. **대소문자 구분하니 주의**
> 
> - **`target_protocol`**: `iscsi` 또는 `iser`(RDMA 기반). 일반적으로 `iscsi`를 사용한다
> 
> - **`target_helper`**: iSCSI 타겟 관리 도구. Ubuntu에서는 `tgtadm`, RHEL/CentOS에서는 `lioadm`을 사용
> 
> - **`target_ip_address`**: Compute 노드가 iSCSI로 접근할 IP. 별도 스토리지 네트워크가 있다면 해당 네트워크 IP를 사용하는 것이 좋다

> **`enabled_backends`**** 네이밍 주의**
> 
> `enabled_backends`에 지정한 이름이 곧 설정 섹션의 이름이 된다. 예를 들어 `enabled_backends = lvm`이면 `[lvm]` 섹션을 읽는다. `enabled_backends = my-storage`로 했다면 `[my-storage]` 섹션을 만들어야 한다. 이름은 자유지만 **일관성**이 중요하다.

#### Kolla Ansible 환경

Kolla Ansible을 사용하고 있다면 설정 방법이 조금 다르다. `/etc/kolla/config/cinder/cinder-volume.conf` 파일을 생성하여 커스텀 설정을 추가한다.

```
# /etc/kolla/config/cinder/cinder-volume.conf

[DEFAULT]
enabled_backends = lvm

[lvm]
volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver
volume_group = cinder-volumes
target_protocol = iscsi
target_helper = tgtadm
target_ip_address = 172.30.0.11
volume_backend_name = lvm
```

> **Kolla Ansible + LVM 주의사항**
> 
> Kolla Ansible은 기본적으로 서비스를 **컨테이너로 배포**한다. 하지만 iSCSI 기반 LVM 드라이버는 **컨테이너 환경과 호환성 문제**가 있을 수 있다. LXC/Docker의 제한으로 인해 iSCSI 타겟 관리가 정상 동작하지 않는 경우, `cinder-volume` 서비스를 **호스트에 직접 배포**하는 방식을 고려해야 한다.

---

### 🌐 5단계: iSCSI 타겟 데몬 설정

Cinder가 생성한 LV를 네트워크를 통해 Compute 노드에 노출하려면 **iSCSI 타겟 데몬**이 필요하다. Ubuntu에서는 `tgt`를 사용한다.

#### 패키지 설치

공식 설치 절차 기준으로 Storage 노드에는 Cinder volume service와 target daemon을 함께 설치한다.

```bash
# Storage 노드에서
sudo apt install -y cinder-volume tgt

# Compute 노드에서 (iSCSI Initiator)
sudo apt install -y open-iscsi
```

#### tgt include 설정 및 서비스 시작

`tgtadm` helper를 사용할 때는 Cinder가 생성하는 target 정의를 tgt가 읽도록 include 파일을 만든다. 이 파일이 빠지면 volume 생성은 되어도 attach 단계에서 iSCSI target을 찾지 못할 수 있다.

```bash
# Storage 노드에서
sudo install -d -m 0755 /etc/tgt/conf.d
printf 'include /var/lib/cinder/volumes/*\n' | \
  sudo tee /etc/tgt/conf.d/cinder.conf

sudo systemctl enable --now tgt

# 상태와 include 파일 확인
sudo systemctl status tgt --no-pager
sudo cat /etc/tgt/conf.d/cinder.conf
```

> **iSCSI 구성 요소 정리**
> 
> - **Target (타겟)**: 스토리지를 제공하는 쪽. Storage 노드에서 `tgt` 데몬이 담당
> 
> - **Initiator (이니시에이터)**: 스토리지를 사용하는 쪽. Compute 노드에서 `open-iscsi`가 담당
> 
> - **IQN (iSCSI Qualified Name)**: 각 타겟/이니시에이터의 고유 식별자. 예: `iqn.2010-10.org.openstack:volume-xxxxx`
> 
> - **LUN (Logical Unit Number)**: 타겟이 노출하는 논리 디스크 번호

Cinder가 볼륨을 생성하면, **자동으로** tgt에 타겟을 등록하고 LV를 LUN으로 매핑한다. 수동으로 tgt 설정을 건드릴 필요는 없다. ~~이건 참 편하다~~

#### Compute 노드의 Initiator 및 Nova 연동 설정

이 절차는 **모든 Compute 노드에서 각각** 수행한다. iSCSI initiator IQN은 노드별로 고유해야 하며, VM이 실행되는 Compute 노드가 Block Storage 노드의 target에 접속한다.

```bash
# Initiator 이름 확인: 각 Compute 노드에서 서로 다른 IQN인지 확인
cat /etc/iscsi/initiatorname.iscsi

# iSCSI initiator daemon 시작 및 부팅 시 자동 시작
sudo systemctl enable --now iscsid
sudo systemctl status iscsid --no-pager
```

Compute 노드의 `/etc/nova/nova.conf`에도 controller에서 설명한 `[cinder]`, `[service_user]` 섹션이 있어야 한다. 누락 여부는 다음처럼 확인한다.

```bash
sudo grep -A 12 '^\[cinder\]\|^\[service_user\]' /etc/nova/nova.conf

# nova-compute가 변경된 Cinder 연동 설정을 읽도록 재시작
sudo systemctl restart nova-compute
sudo systemctl status nova-compute --no-pager
```

마지막으로 각 Compute 노드에서 controller의 Cinder API(TCP 8776)와 Block Storage의 iSCSI target(TCP 3260)에 도달할 수 있어야 한다. 방화벽을 사용하는 경우 두 통신 경로를 허용한다.

```bash
# 이름 해석·API 도달성 확인
getent hosts controller
curl -sS http://controller:8776/ | head

# attach 후 iSCSI session 확인
sudo iscsiadm -m session
```

---

### 🚀 6단계: 서비스 시작 및 동작 확인

모든 설정이 완료되었으면 서비스를 재시작한다.

#### 서비스 재시작

```bash
# Storage 노드에서
sudo service tgt restart
sudo service cinder-volume restart
```

#### 서비스 상태 확인

```bash
# Cinder 볼륨 서비스 목록 확인
openstack volume service list
```

출력에서 Storage 노드의 `cinder-volume` 서비스가 **enabled / up** 상태인지 확인한다.

```bash
+------------------+-------------------------------+------+---------+-------+---
| Binary           | Host                          | Zone | Status  | State | ...
+------------------+-------------------------------+------+---------+-------+---
| cinder-scheduler | controller                    | nova | enabled | up    | ...
| cinder-volume    | storage-node@lvm              | nova | enabled | up    | ...
+------------------+-------------------------------+------+---------+-------+---
```

#### 볼륨 타입 생성 및 기본 타입 지정

Train 이후에는 모든 볼륨이 volume type을 가져야 한다. 따라서 LVM backend에 연결할 type을 만들고, `default_volume_type = lvm`과 같은 이름으로 맞춘다. type을 지정하지 않은 생성 요청도 안전하게 LVM backend로 가도록 하는 설정이다.

```bash
# 볼륨 타입 생성
openstack volume type create lvm

# backend 매핑: [lvm]의 volume_backend_name과 정확히 일치해야 한다.
openstack volume type set lvm --property volume_backend_name=lvm

# Cinder가 인식하는 기본 type 확인
openstack volume type list --default
```

#### 테스트 볼륨 생성

```bash
# 1GB 테스트 볼륨 생성
openstack volume create --size 1 --type lvm test-volume

# 상태 확인
openstack volume show test-volume
```

`status`가 `available`이면 성공이다! 🎉

#### Storage 노드에서 LV 확인

```bash
# LV 목록 확인
sudo lvs

# 예상 출력
#   LV                                   VG              Attr       LSize
#   volume-xxxxxxxx-xxxx-xxxx-xxxx-xxxx  cinder-volumes  -wi-a-----  1.00g
```

볼륨 ID에 해당하는 LV가 생성된 것을 확인할 수 있다. Cinder가 `cinder-volumes` VG에서 Logical Volume을 잘 만들어낸 것이다.

![OpenStack Cinder Volume Creation and Attach Flow](https://blog.pieroot.xyz/api/image-proxy?id=792f93dd-fb8e-4ccb-b5e1-62a4f968ef3d&kind=s3&pageId=30d067c0-15d0-800e-a8fa-c565cd7236bb&source=block&blockId=9bb28fc1-86db-4c76-a53f-20260fb1c176)

#### iSCSI 타겟 확인

```bash
# tgt에 등록된 타겟 확인
sudo tgtadm --mode target --op show
```

Cinder가 볼륨을 인스턴스에 attach하면, tgt에 해당 볼륨의 iSCSI 타겟이 자동으로 등록된다.

---

### 🔍 트러블슈팅

#### 볼륨 생성이 `error` 상태로 떨어질 때

```bash
# cinder-volume 로그 확인
sudo tail -f /var/log/cinder/cinder-volume.log

# Kolla Ansible 환경에서는
docker logs cinder_volume
```

> **자주 만나는 에러와 해결법**
> 
> - **`VG cinder-volumes not found`**: Volume Group 이름이 `cinder.conf`와 불일치. `vgs`로 실제 이름 확인 후 수정
> 
> - **`Failed to create iscsi target`**: tgt 서비스가 동작하지 않거나 권한 문제. `systemctl status tgt` 확인
> 
> - **`No valid host was found`**: 스케줄러가 적절한 백엔드를 찾지 못함. `volume_backend_name`이 볼륨 타입의 extra-spec과 일치하는지 확인
> 
> - **`tgtadm: command not found`**: `tgt` 패키지가 설치되지 않음. `apt install tgt`

#### Compute 노드에서 볼륨 attach가 안 될 때

```bash
# Compute 노드에서 iSCSI 연결 확인
sudo iscsiadm -m session

# Storage 노드 검색
sudo iscsiadm -m discovery -t sendtargets -p 172.30.0.11
```

네트워크 연결 문제인 경우가 많다. **Storage 노드와 Compute 노드 간 3260 포트(iSCSI 기본 포트)**가 열려 있는지 방화벽을 확인하자.

---

### 핵심 정리

✅ **RAID 구성**: 물리 디스크를 RAID로 묶어 안정성과 용량 확보. `mdadm --detail`로 상태 확인

✅ **LVM 구성**: `pvcreate` → `vgcreate cinder-volumes`로 Cinder 전용 볼륨 그룹 생성

✅ **lvm.conf 필터**: Storage/Compute 노드 모두 설정 필수. 미설정 시 볼륨 충돌 위험

✅ **cinder.conf**: `[lvm]` 섹션에서 드라이버, VG 이름, iSCSI 프로토콜 지정

✅ **iSCSI 타겟**: Storage 노드에 `tgt`, Compute 노드에 `open-iscsi` 설치

✅ **동작 확인**: `openstack volume create`로 테스트 볼륨 생성 후 `lvs`로 LV 확인

### 주의사항

⚠️ **Single Point of Failure**: LVM 백엔드는 단일 노드 의존. 프로덕션에서는 Ceph RBD 등 분산 스토리지를 고려하자

⚠️ **lvm.conf 필터 필수**: Compute 노드에서도 반드시 설정해야 한다. 안 하면 나중에 고생한다

⚠️ **VG 이름 일관성**: `vgcreate`와 `cinder.conf`의 `volume_group` 값이 정확히 일치해야 한다

⚠️ **iSCSI 포트**: 방화벽에서 TCP 3260 포트가 열려 있어야 Compute ↔ Storage 간 통신이 가능하다

⚠️ **디스크 모니터링**: RAID 상태를 주기적으로 확인하자. `mdadm --detail /dev/md126`으로 Failed Devices가 0인지 체크

⚠️ **Thin Provisioning 주의**: 활성화 시 실제 디스크 사용량을 모니터링해야 한다. 오버커밋하면 디스크 풀 나서 전체 장애로 이어질 수 있다

### 참고 자료

- [OpenStack Cinder Installation Guide — 2026.1](https://docs.openstack.org/cinder/2026.1/install/)

- [Cinder LVM Driver 공식 문서](https://docs.openstack.org/cinder/latest/configuration/block-storage/drivers/lvm-volume-driver.html)

- [Rackspace Cinder LVM iSCSI Operator Guide](https://docs.rackspacecloud.com/openstack-cinder-lvmisci/)

- [LVM 공식 문서](https://sourceware.org/lvm2/)
