OpenStack中实现混合Hypervisor原理剖析(by quqi99)

时间:2022-03-05 08:44:48

作者:张华  发表于:2014-01-15
版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明

( http://blog.csdn.net/quqi99 )

先搞清楚nova及neutron相关组件的关联关系:
1,当创建network时,neutron-api在DB里仅仅就是记录一下;
2,然后l3-agent会周期性的扫描router, 然后调用vif(通过l3_agent.ini中的interface_driver参数可配)为和它关联的subnet创建该子网的内部网关,若关联外网也创建外部网络相应的tap设备;
3,当nova-compute创建虚机时,同样会调用vif(同样可配置)为虚机创建tap设备;
4,neutron l2 agent周期性检测到物理tap设备,然后从DB中检索到和tap设备相关联的port信息(包括vlan及security group信息),然后就去做vlan及security group相关的设置;

再瞧瞧neutron中的port binding功能:
port binding是nova及neutron交互信息的一种手段,目前包括这五个字段: port_id, binding_host, vif_type, cap_port_filter, driver, segment
先说binding_host:
1,在通过"nova boot"命令创建虚机时,nova-schedule在调度的时候能根据images或者flavor或者instance的种种手段添加元数据信息,与nova compute_nodes表中的hypervisor_type, cpu_info等信息调度vm到相应类型(x86,power etc)的计算节点上(nova-compute).
2,nova-compute(nova-compute和l2 agent部署在同一台机器上, 反过来在nuetron端又会根据host找到对应的l2agent了)会把binding_host传给neutron (port_req_body['port']['binding:host_id'] = instance.get('host') )
3,neutron api首先会记录binding_host到ml2_port_bindings表中, 然后会循环调用各种Mech driver的bind_port方法,但每个mech driver会调用PortContext类中的host_agents方法会根据自身的agent_type和binding_host找到和自身对应的agent信息,代码如下:
 def host_agents(self, agent_type):
        return self._plugin.get_agents(self._plugin_context,
                                       filters={'agent_type': [agent_type],
                                                'host': [self._binding.host]})
  然后继续在binding表记录segment及vif_type信息,代码如下:
  def bind_port(self, context):
        for agent in context.host_agents(self.agent_type):
            if agent['alive']:
                for segment in context.network.network_segments:
                    if self.check_segment_for_agent(segment, agent):
                        context.set_binding(segment[api.ID], self.vif_type, self.cap_port_filter)
                        return
4,segment实际上是指每个neutron l2 agent提供的如vlan, tunnel及外部物理网络(bridge_mappings)的能力, 由每个neutron l2 agent汇报状态时通过configurations指定,这样mech driver就可以知道哪个agent能够提供什么样的能力了,这些信息都可以反馈到nova边去如果它需要的话.
      self.agent_state = {
            'binary': 'neutron-openvswitch-agent',
            'host': cfg.CONF.host,
            'topic': q_const.L2_AGENT_TOPIC,
            'configurations': {'bridge_mappings': bridge_mappings,
                               'tunnel_types': self.tunnel_types,
                               'tunneling_ip': local_ip,
                               'l2_population': self.l2_pop},
            'agent_type': q_const.AGENT_TYPE_OVS,
            'start_flag': True}
5,对于nova设置的vif_type信息,nova是需要用到它们去设置相关的桥信息的,如下,在$nova/network/neutronv2/api.py中的_nw_info_build_network方法中:
          vif_type = port.get('binding:vif_type')
        # TODO(berrange) Neutron should pass the bridge name
        # in another binding metadata field
        if vif_type == network_model.VIF_TYPE_OVS:
            bridge = CONF.neutron_ovs_bridge
            ovs_interfaceid = port['id']
        elif vif_type == network_model.VIF_TYPE_BRIDGE:
            bridge = "brq" + port['network_id']
            should_create_bridge = True

其它想到的:
1,l3-agent依赖于neutron l2 agent去创建port
2,l3-agent的multi-host特性与此port-binding是无关的,它应该是逻辑router与agent的binding,即将一个router下的某些subnet的网关仅仅设置到某一agent上,理由很简单,因为路由中的子网是不能够重的.