Windows的iSCSI连接通过iSCSI Initiator组件完成,可以通过界面操作,从Server Manager -> Tools -> iSCSI Initiator即可进入iSCSI Initiator配置界面。
界面操作也可通过对应的PowerShell命令操作,完全通过PowerShell则使系统上电自动挂载iSCSI卷成为可能。
本文记录Windows 2012R2挂载iSCSI的操作步骤及PowerShell脚本实现,最后探讨云盘挂载的方案实现。
Windows 7也提供了iSCSI Initiator,本文内容理论上也适用于Windows 7及之后的系统。
实验环境为配置iSCSI Target的Linux虚机及Windows 2012R2虚机,通过virbr0连接。
Linux虚机地址为192.168.122.250,Target配置:
o- / ..................................................................... [...]
o- backstores .......................................................... [...]
| o- block .............................................. [Storage Objects: 0]
| o- fileio ............................................. [Storage Objects: 1]
| | o- testfile ................ [/tmp/fileio (500.0MiB) write-thru activated]
| | o- alua ............................................... [ALUA Groups: 1]
| | o- default_tg_pt_gp ................... [ALUA state: Active/optimized]
| o- pscsi .............................................. [Storage Objects: 0]
| o- ramdisk ............................................ [Storage Objects: 0]
o- iscsi ........................................................ [Targets: 1]
| o- iqn.2018-01.com.example:target ................................ [TPGs: 1]
| o- tpg1 ...................................... [no-gen-acls, auth per-acl]
| o- acls ...................................................... [ACLs: 1]
| | o- iqn.1994-05.com.redhat:f7897073402d .. [1-way auth, Mapped LUNs: 1]
| | o- mapped_lun0 ......................... [lun0 fileio/testfile (rw)]
| o- luns ...................................................... [LUNs: 1]
| | o- lun0 ........... [fileio/testfile (/tmp/fileio) (default_tg_pt_gp)]
| o- portals ................................................ [Portals: 1]
| o- 0.0.0.0:3260 ................................................. [OK]
o- loopback ..................................................... [Targets: 0]
/iscsi/iqn.20...e:target/tpg1>
1. Windows系统iSCSI连接的基本要素
1.1 iSCSI服务
iSCSI Initiator依赖Microsoft iSCSI Initiator服务运行,该服务默认不运行,因此系统首次配置时,需将其启动,并设为自动启动。
界面配置路径:Services -> Microsoft iSCSI Initiator Service
PowerShell查询服务状态:
PS C:\Users\Administrator> Get-Service MSiSCSI Status Name DisplayName ------ ---- ----------- Running MSiSCSI Microsoft iSCSI Initiator Service PS C:\Users\Administrator> $service = Get-Service MSiSCSI PS C:\Users\Administrator> $service.Status Running PS C:\Users\Administrator>
启动iSCSI服务:
PS C:\Users\Administrator> Set-Service MSiSCSI -StartupType Automatic -Status Running
Windows的命名习惯是CamelCase,不区分大小写,PowerShell里也一样,$service.Status写成$service.status也行,如有特别之处再注明。
1.2 本机IQN设置
界面配置:iSCSI Initiator配置界面 -> Configuration页 -> Initiator Name字段
通过PowerShell命令,必须指定旧的IQN号再更新其IQN号,因此需分两步操作:
PS C:\Users\Administrator> Get-InitiatorPort InstanceName NodeAddress PortAddress ConnectionType ------------ ----------- ----------- -------------- ROOT\ISCSIPRT\0000_0 iqn.1991-05.com.microsoft:... ISCSI ANY PORT iSCSI PS C:\Users\Administrator> $initiator = Get-InitiatorPort PS C:\Users\Administrator> $initiator.NodeAddress iqn.1991-05.com.microsoft:win-3ehflk7iomd PS C:\Users\Administrator> Set-InitiatorPort iqn.1991-05.com.microsoft:win-3ehflk7iomd -NewNodeAddress iqn.1994-05.com.redhat:f7897073402d
1.3 添加Portal
界面配置:iSCSI Initiator配置界面 -> Discovery页,这里可以添加/删除Portal。
PowerShell命令:
PS C:\Users\Administrator> New-IscsiTargetPortal -TargetPortalAddress 192.168.122.250 InitiatorInstanceName : InitiatorPortalAddress : IsDataDigest : False IsHeaderDigest : False TargetPortalAddress : 192.168.122.250 TargetPortalPortNumber : 3260 PSComputerName :
如果不是默认的3260端口,用-TargetPortalPortNumber参数指定。
1.4 连接Target
界面配置:iSCSI Initiator配置界面 -> Target页 -> Connect
通过PowerShell命令,在连接Target前,需查看当前Target,如果一个Target已连接,再次连接会报错:
PS C:\Users\Administrator> Get-IscsiTarget IsConnected NodeAddress PSComputerName ----------- ----------- --------------
False iqn.2018-01.com.example:target
连接Target:
PS C:\Users\Administrator> Connect-IscsiTarget -NodeAddress iqn.2018-01.com.example:target AuthenticationType : NONE InitiatorInstanceName : ROOT\ISCSIPRT\0000_0 InitiatorNodeAddress : iqn.1994-05.com.redhat:f7897073402d InitiatorPortalAddress : 0.0.0.0 InitiatorSideIdentifier : 400001370000 IsConnected : True IsDataDigest : False IsDiscovered : True IsHeaderDigest : False IsPersistent : False NumberOfConnections : 1 SessionIdentifier : ffffe000c714d020-4000013700000004 TargetNodeAddress : iqn.2018-01.com.example:target TargetSideIdentifier : 0300 PSComputerName :
重启系统后是否自动重连由-IsPersistent参数指定。是否打开MultiPath由-IsMultipathEnabled参数指定。
1.5 CHAP认证
iSCSI Target可以配置发现认证和登录认证,同时认证还分为单向认证和双向认证。
因为双向认证需要在Windows中配置密码,并将该密码配置到Target,从metadata提供的数据来看,应该是不支持的,
否则应该提供Initiator CHAP相关信息,故未做测试。
对于单向认证,发现和登录道理是相同的,因此只测试了登录认证的情况。
通过界面连接Target出现的对话框,点Advanced进入高级设置对话框,勾选Enable CHAP log on,
在Name和Target secret中填写Target配置的帐号信息。Perform mutual authentication用于双向验证,不要勾选。
通过PowerShell连接带CHAP认证的Target:
Connect-IscsiTarget -NodeAddress iqn.2018-01.com.example:target -IsPersistent $true -AuthenticationType ONEWAYCHAP -ChapUsername guest -ChapSecret targetsecret
AuthenticationType是字符串类型,填错就无法通过认证,官方文档写取值为None, OneWayCHAP和MutualCHAP,但在命令里必须全部大写,非常坑爹!
发现阶段的认证相同,New-IscsiTargetPortal也支持校验参数:
PS C:\Users\Administrator> Get-Help New-IscsiTargetPortal NAME New-IscsiTargetPortal SYNTAX New-IscsiTargetPortal -TargetPortalAddress <string> [-TargetPortalPortNumber <uint16>] [-InitiatorPortalAddress <string>] [-IsHeaderDigest <bool>] [-IsDataDigest <bool>] [-AuthenticationType <string>] [-InitiatorInstanceName <string>] [-ChapUsername <string>] [-ChapSecret <string>] [-CimSession <CimSession[]>] [-ThrottleLimit <int>] [-AsJob] [<CommonParameters>]
查看当前连接和会话:
PS C:\Users\Administrator> Get-IscsiTarget IsConnected NodeAddress PSComputerName ----------- ----------- --------------
True iqn.2018-01.com.example:target PS C:\Users\Administrator> get-iscsiconnection ConnectionIdentifier : ffffe0018793f020-1 InitiatorAddress : 0.0.0.0 InitiatorPortNumber : 3264 TargetAddress : 192.168.122.250 TargetPortNumber : 3260 PSComputerName : PS C:\Users\Administrator> Get-IscsiSession AuthenticationType : NONE InitiatorInstanceName : ROOT\ISCSIPRT\0000_0 InitiatorNodeAddress : iqn.1994-05.com.redhat:f7897073402d InitiatorPortalAddress : 0.0.0.0 InitiatorSideIdentifier : 400001370001 IsConnected : True IsDataDigest : False IsDiscovered : True IsHeaderDigest : False IsPersistent : True NumberOfConnections : 1 SessionIdentifier : ffffe000f70f7020-4000013700000001 TargetNodeAddress : iqn.2018-01.com.example:target TargetSideIdentifier : 0500 PSComputerName :
挂载iSCSI卷后,Windows磁盘管理可见磁盘,可以对其进行分区,格式化,分配卷标并读写文件。
2. iSCSI自动挂载实现
Windows系统的上电配置没有好的选择,仍通过Cloudbase-init来配置,有两种方式:
- 使用LocalScriptsPlugin,制作用户镜像过程中将脚本放置在Cloudbase-init安装目录下的LocalScripts目录。
- 使用UserDataPlugin,脚本通过元数据注入。
注意:插件执行成功,Cloudbase-init将注册表对应项置1,下次启动不会再执行。
典型的OpenStack metadata数据源如下,修改了连接数据来测试:
{
"admin_pass": "XkmAkLJxAx8y",
"random_seed": "...",
"uuid": "7d631f44-00ec-4503-a113-cb616d0fd81c",
"availability_zone": "nova",
"hostname": "centos-cloud.novalocal",
"launch_index": 0,
"devices": [],
"volumes": [
{
"driver_volume_type": "iscsi",
"connector": {
"platform": "x86_64",
"initiator": "iqn.1994-05.com.redhat:f7897073402d",
"multipath": false,
"os_type": "baremetal"
},
"serial": "5d30b37e-d113-49e1-b991-16b9d7d33d3e",
"data": {
"auth_password": "targetsecret",
"target_discovered": false,
"encrypted": false,
"qos_specs": null,
"target_iqn": "iqn.2018-01.com.example:target",
"target_portal": "192.168.122.250:3260",
"volume_id": "5d30b37e-d113-49e1-b991-16b9d7d33d3e",
"target_lun": 0,
"access_mode": "rw",
"auth_username": "guest",
"auth_method": "CHAP"
}
}
],
"project_id": "ac9cab947db74c0c999380a4f306693b",
"name": "centos-cloud"
}
对应PowerShell的实现脚本如下:
# iSCSI Volume Connection
# Copyright 2018
# All Rights Reserved.
# Get volume list from metadata
$metadata = Get-Content "instance.json" -Raw | ConvertFrom-Json if (-not $metadata.volumes) { Write-Host "No volume data found."
return } $volumes = $metadata.volumes Write-Host "[DBG] Found volume data:" $volumes
# Validates initiator
foreach ($vol in $volumes) { $initiator = $vol.connector.initiator if ($initiator) { break } } if ($initiator) { Write-Host "Using $initiator as initiator" } else { throw "Initiator IQN not found, could not proceed." } # Checks and brings up Microsoft iSCSI Initiator Service if it's not.
$ServiceInfo = Get-Service MSiSCSI Write-Host "iSCSI Initiator Service is " $ServiceInfo.Status if ("Running" -ne $ServiceInfo.Status) { Set-Service MSiSCSI -StartupType Automatic -Status Running } # Setup Initiator for host
$current_initiator_port = Get-InitiatorPort Set-InitiatorPort $current_initiator_port.NodeAddress -NewNodeAddress $initiator
foreach ($vol in $volumes) { $data = $vol.data $data.target_iqn = "iqn.2018-01.com.example:target"
# Get/Set target portal
$target_portal_address = $data.target_portal -Split ":"
# Check target
$portal_exists = $false
$current_target_portal = Get-IscsiTargetPortal foreach ($portal in $current_target_portal) { if ($portal.TargetPortalAddress -eq $target_portal_address[0] -and $portal.TargetPortalPortNumber -eq $target_portal_address[1]) { Write-Host "[DBG] Portal" $target_portal_address[0] "already exist"
$portal_exists = $true } } if ( -not $portal_exists) { New-IscsiTargetPortal -TargetPortalAddress $target_portal_address[0] -TargetPortalPortNumber $target_portal_address[1] } # Start: Check status for debugging
Write-Host "[DBG] CHECKING SESSIONS"
$session = Get-IscsiSession $isconnected = $false
foreach ($s in $session) { Write-Host "Look for session " $s
if (($s.TargetNodeAddress -eq $data.target_iqn) -and ($s.IsConnected -eq $true)) { Write-Host "[DBG] Target" $data.target_iqn "is connected"
$isconnected = $true
break } } Write-Host "[DBG] Check Session Is Connected" $isconnected Write-Host "[DBG] CHECKING TARGETS"
$current_targets = Get-IscsiTarget $isconnected = $false
foreach ($t in $current_targets) { Write-Host "Look for session " $s
if (($t.NodeAddress -eq $data.target_iqn) -and ($t.IsConnected -eq $true)) { Write-Host "[DBG] Target" $data.target_iqn "is connected"
$isconnected = $true
break } } Write-Host "[DBG] Check target Is Connected" $isconnected
# End: Check status for debugging
try { Disconnect-IscsiTarget -NodeAddress $data.target_iqn -Confirm $false } catch { Write-Host "[WARN] Target might not have been connected yet." } if (-not $isconnected) { # Args used for CHAP:
# -AuthenticationType: None, OneWayCHAP, MutualCHAP (MUST BE CAPITALIZED!)
# -ChapUsername
# -ChapSecret
if ($data.auth_method -eq "CHAP") { Connect-IscsiTarget -NodeAddress $data.target_iqn -IsPersistent $true -AuthenticationType ONEWAYCHAP -ChapUsername $data.auth_username -ChapSecret $data.auth_password } else { Connect-IscsiTarget -NodeAddress $data.target_iqn -IsPersistent $true } } }
注意:如果元数据有调整,则需相应地修改脚本。
3. 存储网络
在Windows系统支持自动挂载后,剩下即网络的支持。将存储服务部署在租户网络,挂载iSCSI在技术上没有限制,存储网络须由neutron管理,这是前提条件。
需要考虑两种场景:
- 租户网络在底层是同一物理网络,这种最简单,裸机任一端口都可以用,根据binding profile,端口会被切换到对应租户的VLAN网络。
- 存储网络与普通租户网络不在同一物理网络,这就涉及到物理网络感知的功能了。
对于后者,假设存储网络所在的逻辑网络为storage-network,某租户所在网络为tenant1,在裸机配置端口数据时,还需将storage-network和tenant1分别配置到对应端口的physical_network字段,这个信息无法自动收集,需要人工设置。