Cinder可用域问题分析.docx
- 文档编号:7680641
- 上传时间:2023-01-25
- 格式:DOCX
- 页数:11
- 大小:90.66KB
Cinder可用域问题分析.docx
《Cinder可用域问题分析.docx》由会员分享,可在线阅读,更多相关《Cinder可用域问题分析.docx(11页珍藏版)》请在冰豆网上搜索。
Cinder可用域问题分析
Cinder创建磁盘过程的中的可用域分析
1.Cinder_api在创建Volume时进行的Zone检查
在Cinder创建Volume时,cinder_api会创建一个名为“create_volume_api”的TaskFlow,该TaskFlow中的ExtractVolumeRequestTask,会对传入的Zone名称进行过滤,如果过滤结果与预期不符,创建Volume将会失败。
cinder.volume.flows.api.create_volume.ExtractVolumeRequestTask的execute方法:
defexecute(self,context,size,snapshot,image_id,source_volume,
availability_zone,volume_type,metadata,key_manager,
source_replica,consistencygroup,cgsnapshot,group):
...........
availability_zone=self._extract_availability_zone(availability_zone,
snapshot,
source_volume,
group)
...........
从当前的日志分析,如果在Cinder创建磁盘时传入错误的可用域ExtractVolumeRequestTask中的_extract_availability_zone会抛出异常,导致ExtractVolumeRequestTask执行失败,整个创建Vol流程被终止
分析_extract_availability_zone方法的代码:
def_extract_availability_zone(self,availability_zone,snapshot,
source_volume,group):
"""Extractsandreturnsavalidatedavailabilityzone.
Thisfunctionwillextracttheavailabilityzone(ifnotprovided)from
thesnapshotorsource_volumeandthenperformsasetofvalidation
checksontheprovidedorextractedavailabilityzoneandthenreturns
thevalidatedavailabilityzone.
"""
#Ifthevolumewillbecreatedinagroup,itshouldbeplacedin
#insameavailabilityzoneasthegroup.
"""
group指的是cinder的consistencygroups特性(https:
//docs.openstack.org/admin-guide/blockstorage-consistency-groups.html)
该参数传入值当前情况下一般为None
"""
ifgroup:
try:
availability_zone=group['availability_zone']
except(TypeError,KeyError):
pass
#Trytoextracttheavailabilityzonefromthecorrespondingsnapshot
#orsourcevolumeifeitherisvalidsothatwecanbeinthesame
#availabilityzoneasthesource.
"""
如果不指定创建卷时的Zone,那么:
方案1.从快照创建时,指定为快照的Zone,从已有卷创建时,指定为已有卷Zone,由于Image时没有zone信息的,因此如果从Image创建时一般参考方案2!
方案2.如果方案1任然不能指定出Zone,那么依次取default_availability_zone,storage_availability_zone
默认情况下default_availability_zone的值为None;
而storage_availability_zone的值为Nova
"""
ifavailability_zoneisNone:
ifsnapshot:
try:
availability_zone=snapshot['volume']['availability_zone']
except(TypeError,KeyError):
pass
ifsource_volumeandavailability_zoneisNone:
try:
availability_zone=source_volume['availability_zone']
except(TypeError,KeyError):
pass
ifavailability_zoneisNone:
ifCONF.default_availability_zone:
availability_zone=CONF.default_availability_zone
else:
#Forbackwardscompatibilityusethestorage_availability_zone
availability_zone=CONF.storage_availability_zone
"""
从环境上打印的信息来看self.availability_zones里只包含“nova”一个Zone,
allow_availability_zone_fallback的值为False时会抛出异常(allow_availability_zone_fallback默认为False)。
"""
ifavailability_zonenotinself.availability_zones:
"""
allow_availability_zone_fallback的作用是,当输入的Zone不满足情形时,对输入进行回退!
默认为False!
!
回退为default_availability_zone或者storage_availability_zone(default_availability_zone优先级更高)!
!
"""
ifCONF.allow_availability_zone_fallback:
original_az=availability_zone
availability_zone=(
CONF.default_availability_zoneor
CONF.storage_availability_zone)
LOG.warning(_LW("Availabilityzone'%(s_az)s'"
"notfound,fallingbackto"
"'%(s_fallback_az)s'."),
{'s_az':
original_az,
's_fallback_az':
availability_zone})
else:
msg=_("Availabilityzone'%(s_az)s'isinvalid.")
msg=msg%{'s_az':
availability_zone}
raiseexception.InvalidInput(reason=msg)
#Iftheconfigurationonlyallowscloningtothesameavailability
#zonethenweneedtoenforcethat.
"""
cloned_volume_same_az表示创建卷时是否要求源的Zone和输入Zone一致(主要针对从快照创建和卷创建),默认为True!
!
"""
ifCONF.cloned_volume_same_az:
snap_az=None
try:
snap_az=snapshot['volume']['availability_zone']
except(TypeError,KeyError):
pass
ifsnap_azandsnap_az!
=availability_zone:
msg=_("Volumemustbeinthesame"
"availabilityzoneasthesnapshot")
raiseexception.InvalidInput(reason=msg)
source_vol_az=None
try:
source_vol_az=source_volume['availability_zone']
except(TypeError,KeyError):
pass
ifsource_vol_azandsource_vol_az!
=availability_zone:
msg=_("Volumemustbeinthesame"
"availabilityzoneasthesourcevolume")
raiseexception.InvalidInput(reason=msg)
returnavailability_zone
从上面的分析可以看出ExtractVolumeRequestTask.availability_zones中不包含输入的Zone!
因此需要打开allow_availability_zone_fallback,以防流程报错。
2.ExtractVolumeRequestTask.availability_zones是如何生成的?
!
回到create_volume.py中可以看到ExtractVolumeRequestTask在get_flow方法中创建:
defget_flow(db_api,image_service_api,availability_zones,create_what,
scheduler_rpcapi=None,volume_rpcapi=None):
.......
api_flow.add(ExtractVolumeRequestTask(
image_service_api,
availability_zones,
rebind={'size':
'raw_size',
'availability_zone':
'raw_availability_zone',
'volume_type':
'raw_volume_type'}))
.......
returntaskflow.engines.load(api_flow,store=create_what)
cinder.volume.flows.api.create_volume.get_flow方法
在cinder.volume.api.API.create方法中被调用,其入参availability_zones通过storage_availability_zone和list_availability_zones方法的返回值组装:
create方法:
raw_zones=self.list_availability_zones(enable_cache=True)
availability_zones=set([az['name']forazinraw_zones])
ifCONF.storage_availability_zone:
availability_zones.add(CONF.storage_availability_zone)
……
try:
sched_rpcapi=(self.scheduler_rpcapiif(
notcgsnapshotandnotsource_cgand
notgroup_snapshotandnotsource_group)
elseNone)
volume_rpcapi=(self.volume_rpcapiif(
notcgsnapshotandnotsource_cgand
notgroup_snapshotandnotsource_group)
elseNone)
flow_engine=create_volume.get_flow(self.db,
self.image_service,
availability_zones,
create_what,
sched_rpcapi,
volume_rpcapi)
exceptException:
msg=_('Failedtocreateapivolumeflow.')
LOG.exception(msg)
raiseexception.CinderException(msg)
list_availability_zones方法:
1.Cinder对Zone信息进行了缓存,list_availability_zones方法在调用时可以指定是否直接从缓存获取信息!
2.内存中的Zone信息会每隔一段时间更新(az_cache_duration,默认3600s)!
3.内存中Zone的值来自数据库表services,选取规则如下:
A.获取所有topic字段为cinder-volume的记录;
B.将记录中的availability_zone和disabled封装为{name:
available},返回。
(这里disabled=0时,available取值为True)
deflist_availability_zones(self,enable_cache=False):
refresh_cache=False
"""
是否从内存获取Zone信息,创建Volume时该值为True。
"""
ifenable_cache:
"""
availability_zones_last_fetched是上一次更新Cache的时间戳,判断是否需要进行更新
"""
ifself.availability_zones_last_fetchedisNone:
refresh_cache=True
else:
cache_age=timeutils.delta_seconds(
self.availability_zones_last_fetched,
timeutils.utcnow())
ifcache_age>=CONF.az_cache_duration:
refresh_cache=True
"""
从数据库获取Zone的值!
"""
ifrefresh_cacheornotenable_cache:
topic=constants.VOLUME_TOPIC
ctxt=context.get_admin_context()
services=objects.ServiceList.get_all_by_topic(ctxt,topic)
az_data=[(s.availability_zone,s.disabled)
forsinservices]
disabled_map={}
for(az_name,disabled)inaz_data:
tracked_disabled=disabled_map.get(az_name,True)
disabled_map[az_name]=tracked_disabledanddisabled
azs=[{'name':
name,'available':
notdisabled}
for(name,disabled)indisabled_map.items()]
ifrefresh_cache:
now=timeutils.utcnow()
self.availability_zones=azs
self.availability_zones_last_fetched=now
LOG.debug("Availabilityzonecacheupdated,nextupdatewill"
"occuraround%s.",now+datetime.timedelta(
seconds=CONF.az_cache_duration))
else:
azs=self.availability_zones
LOG.info(_LI("AvailabilityZonesretrievedsuccessfully."))
returntuple(azs)
回到cinder.volume.api.API.create中,我们看到list_availability_zones返回值中所有的Zone都被利用了,但是从上面的分析可以看出,raw_zones中的字典构成为:
{name:
available},available决定了当前cinder_volume服务的状态是否为disable?
为啥一个服务已经disable了,他的zone依然合法呢?
raw_zones=self.list_availability_zones(enable_cache=True)
availability_zones=set([az['name']forazinraw_zones])
ifCONF.storage_availability_zone:
availability_zones.add(CONF.storage_availability_zone)
通过在volume节点配置storage_availability_zone可以修改services表中的zone信息,该值默认为nova!
3.Nova创建虚机时Zone信息的传递
Nova创建虚机时可以指定Zone,但是这里的Zone是Nova使用的和Cinder的Zone没有直接关系,可以在主机聚合页面查看。
n-compute创建虚机时调用
nova.virt.block_device.DriverVolumeBlockDevice
的attached方法挂载到磁盘。
根据创建实例时源选择的不同,DriverVolumeBlockDevice,有不同的派生。
由于只有从Image创建VM时,有可能需要创建Vol,因此先分析DriverImageBlockDevice的attach方法。
该方法很简单,调用cinder_api创建一个Volume,之后调用DriverVolumeBlockDevice执行attach。
值得注意的是nova请求cinder创建vol时传递的zone,及_get_volume_create_az_value方法!
defattach(self,context,instance,volume_api,
virt_driver,wait_func=None,do_check_attach=True):
LOG.info("bylinqingrunDriverImageBlockDeviceattach")
ifnotself.volume_id:
av_zone=_get_volume_create_az_value(instance)
vol=volume_api.create(context,self.volume_size,
'','',image_id=self.image_id,
availability_zone=av_zone)
ifwait_func:
self._call_wait_func(context,wait_func,volume_api,vol['id'])
self.volume_id=vol['id']
super(DriverImageBlockDevice,self).attach(
context,instance,volume_api,virt_driver,
do_check_attach=do_check_attach)
_get_volume_create_az_value方法控制nova创建的vol的zone是否需要和虚机相同,且通过配置项cross_az_attach来控制,改配置项默认为True,表示不需要相同(nova.conf.cinder.py中定义了这个配置项)!
def_get_volume_create_az_value(instance):
"""Determineaztousewhencreatingavolume
Usesthecinder.cross_az_attachconfigoptiontodeterminetheavailability
zonevaluetousewhencreatingavolume.
:
paramnova.objects.Instanceinstance:
Theinstanceforwhichthevolume
willbecreatedandattached.
:
returns:
Theavailability_zonevaluetopasstovolume_api.create
"""
#Ifwe'reallowedtoattachavolumeinanyAZtoaninstanceinanyAZ,
#thenwedon'tcarewhatAZthevolumeisinsodon'tspecifyanything.
ifCONF.cinder.cross_az_attach:
returnNone
#ElsethevolumehastobeinthesameAZastheinstanceotherwisewe
#fail.IftheAZisnotinCinderthevolumecreatewillfail.Butonthe
#otherhandifthe
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Cinder 可用 问题 分析