Cinder可用域问题分析Word下载.docx
《Cinder可用域问题分析Word下载.docx》由会员分享,可在线阅读,更多相关《Cinder可用域问题分析Word下载.docx(11页珍藏版)》请在冰豆网上搜索。
![Cinder可用域问题分析Word下载.docx](https://file1.bdocx.com/fileroot1/2023-1/24/e98a0685-fa5f-4fff-8082-98aa0e7eba9d/e98a0685-fa5f-4fff-8082-98aa0e7eba9d1.gif)
#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:
availability_zone=snapshot['
volume'
]['
ifsource_volumeandavailability_zoneisNone:
availability_zone=source_volume['
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})
msg=_("
isinvalid."
)
msg=msg%{'
availability_zone}
raiseexception.InvalidInput(reason=msg)
#Iftheconfigurationonlyallowscloningtothesameavailability
#zonethenweneedtoenforcethat.
cloned_volume_same_az表示创建卷时是否要求源的Zone和输入Zone一致(主要针对从快照创建和卷创建),默认为True!
!
ifCONF.cloned_volume_same_az:
snap_az=None
snap_az=snapshot['
ifsnap_azandsnap_az!
=availability_zone:
Volumemustbeinthesame"
availabilityzoneasthesnapshot"
source_vol_az=None
source_vol_az=source_volume['
ifsource_vol_azandsource_vol_az!
availabilityzoneasthesourcevolume"
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'
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(
flow_engine=create_volume.get_flow(self.db,
self.image_service,
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
cache_age=timeutils.delta_seconds(
self.availability_zones_last_fetched,
timeutils.utcnow())
ifcache_age>
=CONF.az_cache_duration:
从数据库获取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,'
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))
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依然合法呢?
通过在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['
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