声明:
本博客欢迎转载,但请保留原作者信息,并请注明出处!
作者:林凯
团队:华为杭州OpenStack团队
在OpenStack Grizzly版本中,Neutron(当时叫Quantum)组件引入了一个新的网络服务:LoadBalancer(LBaaS),关于LoadBalancer的框架和基础知识方面网上已经有了一些好文章,在此不再赘述。本文将对LoadBalancer的代码流程及实现进行初步解析,肯定会有错误和不严谨的地方,需要大家给予指正。
首先我们来看下我们在创建这些pool、member、healthmonitor和vip的时候,代码都做了哪些事情。
# pool作为LB v1的根对象,是工作流的起点
def create_pool(self, context, pool):
provider_name = self._get_provider_name(context, pool['pool'])
# DB中创建pool对象
p = super(LoadBalancerPlugin, self).create_pool(context, pool)
self.service_type_manager.add_resource_association(
context,
constants.LOADBALANCER,
provider_name, p['id'])
#need to add provider name to pool dict,
#because provider was not known to db plugin at pool creation
p['provider'] = provider_name
driver = self.drivers[provider_name]
try:
# 调用默认provider中的驱动创建pool
driver.create_pool(context, p)
except loadbalancer.NoEligibleBackend:
# that should catch cases when backend of any kind
# is not available (agent, appliance, etc)
self.update_status(context, ldb.Pool,
p['id'], constants.ERROR,
"No eligible backend")
raise loadbalancer.NoEligibleBackend(pool_id=p['id'])
return p在neutron.conf中可以看到默认的设置为:
service_provider=LOADBALANCER:Haproxy:neutron.services.loadbalancer.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default
class HaproxyOnHostPluginDriver(agent_driver_base.AgentDriverBase):
device_driver = namespace_driver.DRIVER_NAMEdef create_pool(self, context, pool):
# 首先通过agent scheduler分配agent
agent = self.pool_scheduler.schedule(self.plugin, context, pool,
self.device_driver)
if not agent:
raise lbaas_agentscheduler.NoEligibleLbaasAgent(pool_id=pool['id'])
self.agent_rpc.create_pool(context, pool, agent['host'],
self.device_driver)def schedule(self, plugin, context, pool, device_driver):
# 为pool分配一个active的loadbalancer agent,如果其上没有已经使能的agent
with context.session.begin(subtransactions=True):
lbaas_agent = plugin.get_lbaas_agent_hosting_pool(
context, pool['id'])
if lbaas_agent:
LOG.debug(_('Pool %(pool_id)s has already been hosted'
' by lbaas agent %(agent_id)s'),
{'pool_id': pool['id'],
'agent_id': lbaas_agent['id']})
return
# 获取active的agent
active_agents = plugin.get_lbaas_agents(context, active=True)
if not active_agents:
LOG.warn(_('No active lbaas agents for pool %s'), pool['id'])
return
# 根据device_driver筛选候选的agent
candidates = plugin.get_lbaas_agent_candidates(device_driver,
active_agents)
if not candidates:
LOG.warn(_('No lbaas agent supporting device driver %s'),
device_driver)
return
# 随机选取一个合适的候选agent
chosen_agent = random.choice(candidates)
# 与pool进行绑定
binding = PoolLoadbalancerAgentBinding()
binding.agent = chosen_agent
binding.pool_id = pool['id']
context.session.add(binding)
LOG.debug(_('Pool %(pool_id)s is scheduled to '
'lbaas agent %(agent_id)s'),
{'pool_id': pool['id'],
'agent_id': chosen_agent['id']})
return chosen_agentdevice_driver = namespace_driver.DRIVER_NAME
def create_pool(self, context, pool, driver_name):
if driver_name not in self.device_drivers:
LOG.error(_('No device driver on agent: %s.'), driver_name)
self.plugin_rpc.update_status('pool', pool['id'], constants.ERROR)
return
# 获取相应的driver(根据设置默认为HaproxyNSDriver)
driver = self.device_drivers[driver_name]
try:
driver.create_pool(pool)
except Exception:
self._handle_failed_driver_call('create', 'pool', pool['id'],
driver.get_name())
else:
self.instance_mapping[pool['id']] = driver_name
# 之后更新数据库中的状态
self.plugin_rpc.update_status('pool', pool['id'], constants.ACTIVE)def create_pool(self, pool):
# nothing to do here because a pool needs a vip to be useful
# 当没有vip的情况下,不做操作。
PassOpenStack Neutron LoadBalance源码解析(一)
原文地址:http://blog.csdn.net/canxinghen/article/details/42144347