黑入neutron-l3-agent消息系统

​在进行云计算网络功能开发时,经常需要在现有网络基础上进行网络功能定制或者开发新的插件。此时,就需要我们对Neutron的设计和功能有足够的认识。下面以Neutorn的l3-agent插件为例,讲解第三方服务如何实现对l3-agent服务状态的监控。

l3-agent是Neutron家族众多Agent中的一员。从名称就可以推知,该Agent肯定与三层路由有着密不可分的关系。实际情况也的确如此。l3-agent是一个进程,同时它也是一个RPC Consumer,接收来自neutron-server的RPC消息。它向租户提供路由和NAT功能。l3扩展包含两种资源:

  • router:在不同内部子网中转发数据包,通过指定内部网关做NAT。每个子网对应router上的一个端口,这个端口的IP就是该子网的网关地址。

  • floating ip:代表一个外部网络的IP,映射到内部网络的端口上。当网络的router:external属性为True时,floating ip才能定义。

整个Neutron架构如下所示:

从上图可知,l3-agent通过MQ与neutron-server进行通信。所以如果想监听l3-agent相关操作,理论上只需要订阅l3-agent相关主题即可。

通过具体分析l3-agent源码,我们可以找出所有l3-agent相关的主题。

  • l3-agent启动代码

    代码位置neutron/agent/l3_agent.py

def main(manager='neutron.agent.l3.agent.L3NATAgentWithStateReport'):
  register_opts(cfg.CONF)
  common_config.init(sys.argv[1:])
  config.setup_logging()
  config.setup_privsep()
  server = neutron_service.Service.create(
      binary='neutron-l3-agent',
      topic=topics.L3_AGENT,
      report_interval=cfg.CONF.AGENT.report_interval,
      manager=manager)
  service.launch(cfg.CONF, server).wait()

从上可知,l3-agent实际服务是由neutron.agent.l3.agent.L3NATAgentWithStateReport类提供的。

  • L3NATAgentWithStateReport关键代码

class L3NATAgentWithStateReport(L3NATAgent):

  def __init__(self, host, conf=None):
      super(L3NATAgentWithStateReport, self).__init__(host=host, conf=conf)
      self.state_rpc = agent_rpc.PluginReportStateAPI(topics.REPORTS)
      self.agent_state = {
          'binary': 'neutron-l3-agent',
          'host': host,
          'availability_zone': self.conf.AGENT.availability_zone,
          'topic': topics.L3_AGENT,
          'configurations': {
              'agent_mode': self.conf.agent_mode,
              'handle_internal_only_routers':
              self.conf.handle_internal_only_routers,
              'external_network_bridge': self.conf.external_network_bridge,
              'gateway_external_network_id':
              self.conf.gateway_external_network_id,
              'interface_driver': self.conf.interface_driver,
              'log_agent_heartbeats': self.conf.AGENT.log_agent_heartbeats},
          'start_flag': True,
          'agent_type': lib_const.AGENT_TYPE_L3}
      report_interval = self.conf.AGENT.report_interval
      if report_interval:
          self.heartbeat = loopingcall.FixedIntervalLoopingCall(
              self._report_state)
          self.heartbeat.start(interval=report_interval)

从方法名称就可知道该Agent必然与NAT有关系。这里我们不再详细分析每一个方法。从init方法可知,l3-agent上报自身的当前状态是通过定时任务实现。loopingcall.FixedIntervalLoopingCall会周期性回调self._report_state方法。

  • _report_state方法

def _report_state(self):
      num_ex_gw_ports = 0
      num_interfaces = 0
      num_floating_ips = 0
      router_infos = self.router_info.values()
      num_routers = len(router_infos)
      for ri in router_infos:
          ex_gw_port = ri.get_ex_gw_port()
          if ex_gw_port:
              num_ex_gw_ports += 1
          num_interfaces += len(ri.router.get(lib_const.INTERFACE_KEY,
                                              []))
          num_floating_ips += len(ri.router.get(lib_const.FLOATINGIP_KEY,
                                                []))
      configurations = self.agent_state['configurations']
      configurations['routers'] = num_routers
      configurations['ex_gw_ports'] = num_ex_gw_ports
      configurations['interfaces'] = num_interfaces
      configurations['floating_ips'] = num_floating_ips
      try:
          agent_status = self.state_rpc.report_state(self.context,
                                                      self.agent_state,
                                                      True)
          if agent_status == agent_consts.AGENT_REVIVED:
              LOG.info('Agent has just been revived. '
                        'Doing a full sync.')
              self.fullsync = True
          self.agent_state.pop('start_flag', None)
      except AttributeError:
          # This means the server does not support report_state
          LOG.warning("Neutron server does not support state report. "
                      "State report for this agent will be disabled.")
          self.heartbeat.stop()
          return
      except Exception:
          LOG.exception("Failed reporting state!")

其中,self.state_rpc.report_state是一个消息生产者,作用是向订阅的队列发送agent状态。该agent状态最终被neutron-server接收,并入库到neutron数据库的agents表。agents表有一个configurations字段,保存的信息就是agent_state对象中的configurations的json对象。

  • 编写第三方服务server.py监听agent状态

#!/usr/bin/python
from oslo_config import cfg
import oslo_messaging
import sys
import time

class TestEndpoint(object):

  def report_agent(self, ctx, **kwargs):
      print "receive client access"
      return 'alive'

transport_url = 'rabbit://guest:guest@192.168.90.26:5672/'
server = sys.argv[1]
oslo_messaging.set_transport_defaults(control_exchange='neutron')
transport = oslo_messaging.get_transport(cfg.CONF,transport_url)
target = oslo_messaging.Target(topic='q-reports-plugin', server=server, fanout=False, version='1.0')
endpoints = [
  TestEndpoint(),
]
server = oslo_messaging.get_rpc_server(transport, target, endpoints)
try:
  server.start()
  while True:
      time.sleep(1)
except KeyboardInterrupt:
  print("Stopping server")
server.stop()
server.wait()

其中,q-reports-plugin是l3-agent上报的topic,Neutron默认的交换器配置是'neutron'。

  • 启动服务,即可监听到l3-agent上报到neutron-server的消息

python server.py myserver

上述服务仅仅作为学习测试之用。从代码的配置可知,l3-agent状态上报是非fanout模式。在这种模式下,如果同一队列存在多个消费者时,RabbitMQ会以轮询的方式调用消费者。在实际生产过程中,需要注意到此点,否者冒然通过以上方式监听q-reports-plugin队列,会影响到Neutron本身的业务逻辑。

小结

在实际生产过程中使用第三方服务监听l3-agent相关消息队列时,需要注意消息队列使用的模式,否者很可能影响到Neutron的正常业务。另外,在获取transport对象之前,一定需要把Neutron的默认交换器配置为neutron,否则监听消息一定失败。

 

如果对云计算感兴趣,可以关注我的微信公众号:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是部署 OpenStack 环境的命令: 1. 安装 OpenStack 发行版(例如 Ubuntu 或 CentOS)。 2. 执行以下命令以安装基本软件包和 OpenStack 组件: ``` sudo apt-get update sudo apt-get install -y python-openstackclient sudo apt-get install -y python-pip sudo pip install python-openstackclient sudo apt-get install -y python-neutronclient sudo apt-get install -y neutron-plugin-ml2 neutron-plugin-openvswitch-agent neutron-l3-agent neutron-dhcp-agent neutron-metadata-agent sudo apt-get install -y nova-compute-kvm sudo apt-get install -y cinder-volume sudo apt-get install -y glance sudo apt-get install -y keystone sudo apt-get install -y horizon sudo apt-get install -y heat sudo apt-get install -y ceilometer sudo apt-get install -y aodh sudo apt-get install -y gnocchi sudo apt-get install -y swift ``` 3. 配置 OpenStack 环境。 4. 启动 OpenStack 服务: ``` sudo service neutron-plugin-openvswitch-agent restart sudo service neutron-l3-agent restart sudo service neutron-dhcp-agent restart sudo service neutron-metadata-agent restart sudo service nova-compute restart sudo service cinder-volume restart sudo service glance-api restart sudo service glance-registry restart sudo service keystone restart sudo service apache2 restart sudo service heat-api restart sudo service heat-api-cfn restart sudo service heat-engine restart sudo service ceilometer-agent-central restart sudo service ceilometer-agent-notification restart sudo service ceilometer-api restart sudo service aodh-api restart sudo service aodh-evaluator restart sudo service aodh-notifier restart sudo service aodh-listener restart sudo service gnocchi-api restart sudo service gnocchi-metricd restart sudo service swift-proxy restart sudo service swift-account restart sudo service swift-container restart sudo service swift-object restart ``` 这是一个基本的命令,可以根据具体的部署需求进行调整。如果您需要更详细的部署指导,请参阅 OpenStack 官方文档。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值