OpenStack por dentro. Volúmenes
OpenStack soporta un buen número de tecnologías para proporcionar almacenamiento de bloques, en este caso vamos a explicar la utilización de LVM + iSCSI que es la tecnología utilizada por defecto y quizás la más adecuada para explicar el funcionamiento de OpenStack gracias a su sencillez. A diferencia del caso de KVM, que es sin duda ninguna el hipervisor más utilizado en despliegues de OpenStack, LVM + iSCSI no es la combinación más extendida ya que hay múltiples opciones (Ceph RBD, GlusterFS, sistemas de almacenamiento de múltiples fabricantes, etc.), de entre todas es Ceph RBD la opción preferida de acuerdo a la última encuesta de uso de OpenStack.
LVM
Logical Volume Manager 2 (LVM2) o simplemente LVM es una implementación de volúmenes lógicos para el kérnel de linux. Permite abstraer los dispositivos de bloques lógicos utilizados por el sistema o los usuarios de los dispositivos físicos de la máquina, permitiendo una gestión más adecuada y dinámica de los recursos.
LVM en sí mismo no proporciona redundancia, ésta habitualmente se proporciona utilizando RAID por debajo.
iSCSI
iSCSI es un estándar que permite utilizar la interfaz de transferencia de datos de bus SCSI a través de una red TCP/IP. Es un protocolo de la capa de transporte que básicamente permite la utilización de un dispositivo de bloques en un equipo remoto.
Creación de un volumen
Utilizamos el cliente cinder para crear un nuevo volumen:
$ cinder create --display-name vol3 1
+---------------------+--------------------------------------+
| Property | Value |
+---------------------+--------------------------------------+
| attachments | [] |
| availability_zone | nova |
| bootable | false |
| created_at | 2014-05-29T09:54:39.441869 |
| display_description | None |
| display_name | vol3 |
| id | d61284c3-4daa-48e1-9731-cd6d4361b4c6 |
| metadata | {} |
| size | 1 |
| snapshot_id | None |
| source_volid | None |
| status | creating |
| volume_type | None |
+---------------------+--------------------------------------+
Desde el nodo de almacenamiento (equipo en el que se encuentra instalado cinder o que está configurado como backend) veremos la creación de un nuevo volumen lógico del tamaño solicitado:
# lvs
...
volume-d61284c3-4daa-48e1-9731-cd6d4361b4c6 cinder-volumes -wi-ao---- 1,00g
...
Este volumen se ha creado sobre el grupo de volúmenes cinder-volumes y se identifica con el nombre volume- seguido del UUID del volumen de OpenStack.
Aunque el volumen ya esté creado, el target iSCSI correspondiente no se creará hasta que se realice la asociación del volumen a una determinada instancia.
Asociación de un volumen a una instancia
Para asociar un volumen a una instancia utilizamos el cliente nova:
$ nova volume-attach f69ab4d9-ed28-406e-8a78-67f62a5e4bc2 d61284c3-4daa-48e1-9731-cd6d4361b4c6
+----------+--------------------------------------+
| Property | Value |
+----------+--------------------------------------+
| device | /dev/vdb |
| id | d61284c3-4daa-48e1-9731-cd6d4361b4c6 |
| serverId | f69ab4d9-ed28-406e-8a78-67f62a5e4bc2 |
| volumeId | d61284c3-4daa-48e1-9731-cd6d4361b4c6 |
+----------+--------------------------------------+
En ese momento se crea un nuevo target iSCSI asociado a este volumen lógico que podemos ver con la siguiente instrucción:
# tgtadm --lld iscsi --op show --mode target
...
Target 7: iqn.2010-10.org.openstack:volume-d61284c3-4daa-48e1-9731-cd6d4361b4c6
System information:
Driver: iscsi
State: ready
I_T nexus information:
LUN information:
LUN: 0
Type: controller
SCSI ID: IET 00070000
SCSI SN: beaf70
Size: 0 MB, Block size: 1
Online: Yes
Removable media: No
Prevent removal: No
Readonly: No
Backing store type: null
Backing store path: None
Backing store flags:
LUN: 1
Type: disk
SCSI ID: IET 00070001
SCSI SN: beaf71
Size: 1074 MB, Block size: 512
Online: Yes
Removable media: No
Prevent removal: No
Readonly: No
Backing store type: rdwr
Backing store path: /dev/cinder-volumes/volume-d61284c3-4daa-48e1-9731-cd6d4361b4c6
Backing store flags:
Account information:
ACL information:
ALL
Y en el nodo de computación correspondiente podemos ver la conexión realizada con detalle:
# iscsiadm -m session -P 3
Target: iqn.2010-10.org.openstack:volume-d61284c3-4daa-48e1-9731-cd6d4361b4c6 (non-flash)
Current Portal: 192.168.222.11:3260,1
Persistent Portal: 192.168.222.11:3260,1
**********
Interface:
**********
Iface Name: default
Iface Transport: tcp
Iface Initiatorname: iqn.1993-08.org.debian:01:cab427965c1
Iface IPaddress: 192.168.222.23
Iface HWaddress: <empty>
Iface Netdev: <empty>
SID: 121
iSCSI Connection State: LOGGED IN
iSCSI Session State: LOGGED_IN
Internal iscsid Session State: NO CHANGE
*********
Timeouts:
*********
Recovery Timeout: 120
Target Reset Timeout: 30
LUN Reset Timeout: 30
Abort Timeout: 15
*****
CHAP:
*****
username: ZQg9H5oC5b5rHBthfSFf
password: ********
username_in: <empty>
password_in: ********
************************
Negotiated iSCSI params:
************************
HeaderDigest: None
DataDigest: None
MaxRecvDataSegmentLength: 262144
MaxXmitDataSegmentLength: 8192
FirstBurstLength: 65536
MaxBurstLength: 262144
ImmediateData: Yes
InitialR2T: Yes
MaxOutstandingR2T: 1
************************
Attached SCSI devices:
************************
Host Number: 127 State: running
scsi127 Channel 00 Id 0 Lun: 0
scsi127 Channel 00 Id 0 Lun: 1
Attached scsi disk sdj State: running
Si volcamos la salida del “kernel ring buffer” con la instrucción dmesg del nodo de computación donde se encuentra ejecutándose la instancia, vemos una salida como la siguiente:
scsi5 : iSCSI Initiator over TCP/IP
scsi 5:0:0:0: RAID IET Controller 0001 PQ: 0 ANSI: 5
scsi 5:0:0:0: Attached scsi generic sg7 type 12
scsi 5:0:0:1: Direct-Access IET VIRTUAL-DISK 0001 PQ: 0 ANSI: 5
sd 5:0:0:1: Attached scsi generic sg8 type 0
sd 5:0:0:1: [sdj] 2097152 512-byte logical blocks: (1.07 GB/1.00 GiB)
sd 5:0:0:1: [sdj] Write Protect is off
sd 5:0:0:1: [sdj] Mode Sense: 49 00 00 08
sd 5:0:0:1: [sdj] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
sdg: unknown partition table
sd 5:0:0:1: [sdj] Attached SCSI disk
Es decir, el que realiza la conexión iSCSI es el nodo de computación y el dispositivo de bloques remoto aparece como un dispositivo de bloques local asociado a /dev/sdj. Sin embargo este dispositivo de bloques no lo utiliza directamente el nodo de computación sino que se lo transfiere a la máquina virtual modificando el fichero /etc/libvirt/qemu/instance-0000001c.xml con las líneas:
<disk type='block' device='disk'>
<driver name='qemu' type='raw' cache='none'/>
<source dev='/dev/disk/by-path/ip-192.168.0.68:3260-iscsi-iqn.2010-10.org.openstack:volume-d61284c3-4daa-48e1-9731-cd6d4361b4c6-lun-1'/>
<target dev='vdb' bus='virtio'/>
<serial>d61284c3-4daa-48e1-9731-cd6d4361b4c6</serial>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
</disk>
Instantáneas
Si hacemos una instantánea de un volumen:
$ cinder snapshot-create vol3
+---------------------+--------------------------------------+
| Property | Value |
+---------------------+--------------------------------------+
| created_at | 2014-05-29T10:39:24.806930 |
| display_description | None |
| display_name | None |
| id | 9236ca13-0b71-4050-8ac0-467827719327 |
| metadata | {} |
| size | 1 |
| status | creating |
| volume_id | d61284c3-4daa-48e1-9731-cd6d4361b4c6 |
+---------------------+--------------------------------------+
Se utiliza directamente una instantánea de LVM:
# lvs
LV VG Attr LSize Pool Origin Data% Move Log Cpy%Sync Convert
_snapshot-3546a39f-fc32-42ea-9c51-2d6959f9798a cinder-volumes swi-a-s--- 1,00g volume-70ba58bf-1201-4b27-8de3-a1f2f1bf49ed 0,00
Pero no se ha creado ningún target nuevo ya que las instantáneas de volumen no son directamente utilizables como volúmenes sino que es necesario crear un nuevo volumen desde ellas para poder asociarlo posteriormente a una instancia.
Borrado seguro de volúmenes
Puesto que estamos en un sistema de recursos compartidos el mecanismo que utiliza por defecto OpenStack para borrar los volúmenes es seguro porque antes de eliminar el volumen lógico procede a llenarlo de ceros para evitar que los datos que allí hubieran los pueda leer posteriormente otro usuario.
Para ver este comportamiento bien es preciso tener configurado cinder en modo debug y proceder a eliminar un volumen cualquiera:
$ cinder delete 70ba58bf-1201-4b27-8de3-a1f2f1bf49ed
Si vemos los registros de cinder-volume podemos extraer los siguientes mensajes:
2014-05-29 12:50:26.023 13973 DEBUG cinder.openstack.common.processutils [req-1f17dc86-1de6-4483-b106-d09cd2ab70be 0f94f0bbcdee4715ba2750502bb0d63f 0912c80bef254d7b9352632793cf75b9] Running cmd (subprocess): sudo cinder-rootwrap /etc/cinder/rootwrap.conf dd count=0 if=/dev/zero of=/dev/mapper/cinder--volumes-volume--70ba58bf--1201--4b27--8de3--a1f2f1bf49ed iflag=direct oflag=direct execute /usr/lib/python2.6/site-packages/cinder/openstack/common/processutils.py:142
...
2014-05-29 12:50:43.121 13973 INFO cinder.volume.manager [req-1f17dc86-1de6-4483-b106-d09cd2ab70be 0f94f0bbcdee4715ba2750502bb0d63f 0912c80bef254d7b9352632793cf75b9] volume 70ba58bf-1201-4b27-8de3-a1f2f1bf49ed: deleted successfully