深挖Openstack Nova - evacuate疏散函数

一. 当实例所在的节点发生故障不可用时,可执行evacuate操作,在另外一个新节点rebuild该实例,实现高可用。

这可以是OpenStack计算节点HA的一种实现方案


二. API调用

nova.servers.evacuate(server=fm['id']), on_shared_storage=True

1. on_shared_storage参数在2.14版本后废除,自动检查是否为共享存储。

    共享存储能够保证实例在另外新节点重建后数据不丢失

2. 可以设置目的主机host

    如果不设置host,nova会通过scheduler选择一个新的主机(不会分到原主机,因为rebuild函数中过滤了原主机)

3. 这个调用只是发送了evacuate操作命令,具体是否真正疏散成功,无法知道


三. 源码分析

对应的是/nova/compute/api.py

@check_instance_state(vm_state=[vm_states.ACTIVE, vm_states.STOPPED,
                                vm_states.ERROR])
def evacuate(self, context, instance, host, on_shared_storage,
            admin_password=None)
1. 函数上方有装饰符 @check_instance_state

表示在执行evacuate方法前先执行check_instance_state:检测传入的instancevm_state是否为ACTIVESTOPPEDERROR。如果不是这三种状态,不能执行evacuate方法。


2. 首先检测instance所在主机的状态是否为down,如果不是down(比如up),执行会出错。

LOG.debug('vm evacuation scheduled', instance=instance)
# 原实例所在主机
inst_host = instance.host
service = objects.Service.get_by_compute_host(context, inst_host)
# 首先确保compute主机的状态为down
if self.servicegroup_api.service_is_up(service):
    LOG.error(_LE('Instance compute service state on %s '
                  'expected to be down, but it was up.'), inst_host)
    raise exception.ComputeServiceInUse(host=inst_host)


3. 记录action执行操作

# 实例的任务状态设置为REBUILDING
instance.task_state = task_states.REBUILDING
instance.save(expected_task_state=[None])
self._record_action_start(context, instance, instance_actions.EVACUATE)


4. 初始化迁移类

migration = objects.Migration(context,
                              source_compute=instance.host,
                              source_node=instance.node,
                              instance_uuid=instance_uuid,
                              status='accepted',
                              migration_type='evacuation')

5. 创建迁移(这里为什么要创建migration,并没有执行迁移)
# 如果提供了目的主机
if host:
    migration.dest_compute = host
migration.create()


6. 发送消息通知实例的使用配额

compute_utils.notify_about_instance_usage(
    self.notifier, context, instance, "evacuate")


7. 最后执行task任务:rebuild_instance

所以evacuate的本质是在新节点上执行rebuild操作

return self.compute_task_api.rebuild_instance(context,
            instance=instance,
            new_pass=admin_password,
            injected_files=None,
            image_ref=None,
            orig_image_ref=None,
            orig_sys_metadata=None,
            bdms=None,
            recreate=True,
            on_shared_storage=on_shared_storage,
            host=host)

深入分析rebuild_instance方法,通过各种rpc调用,最终具体执行的是/nova/conductor/manager.py

def rebuild_instance(self, context, instance, orig_image_ref, image_ref,
                    injected_files, new_pass, orig_sys_metadata,
                    bdms, recreate, on_shared_storage,
                    preserve_ephemeral=False, host=None):

(1)在选择新目的主机时先排除instance所在主机

这样能确保不会在原主机上执行rebuild操作

# 排除原实例所在的主机,即不能在同一个主机里进行rebuild
filter_properties = {'ignore_hosts': [instance.host]}
hosts = self.scheduler_client.select_destinations(context,
                                        request_spec,
                                        filter_properties)

(2)接下来会通过scheduler模块筛选出合适的新主机

(3)如果没有选出足够的合适新主机,则抛出异常

except exception.NoValidHost as ex:
    with excutils.save_and_reraise_exception():
        self._set_vm_state_and_notify(context, instance.uuid,
            'rebuild_server',
            {'vm_state': instance.vm_state,
            'task_state': None}, ex, request_spec)
        LOG.warning(_LW("No valid host found for rebuild"),
                    instance=instance)

不能选出合适的新主机,有可能是除了原节点外,其他节点都不可用(computer service status:disabled)或网络不通(computer service state:down),导致没有合适的新主机。



  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值