openstack Neutron分析(3)—— neutron-dhcp-agent源碼分析


1.neutron dhcp3個主要部件分別為什么?
2.dhcp模塊包含哪些內容?
3.Dnsmasq配置文件是如何創建和更新的?
4.DHCP agent的信息存放在neutron數據庫的哪個表中?

擴展: neutron-dhcp-agent在neutron的作用是什么?




一.概述

neutron dhcp為租戶網絡提供DHCP服務,即IP地址動態分配,另外還會提供metadata請求服務。
3個主要的部件:
DHCP agent scheduler:負責DHCP agent與network的調度
DHCP agent:為租戶網絡提供DHCP的功能,提供metadata request服務。
DHCP driver:即dnsmasq,用於管理DHCP server。


二.REST API

neutron dhcp提供2類REST API接口,這兩類API都是extension API。



一種是 Agent Management Extension API:

<ignore_js_op>  



另一種是agent調度:

<ignore_js_op>  



三.總體架構


根據整個dhcp處理的流程,dhcp模塊主要由Neutron api、core plugin(如linux bridge plugin,ovs plugin等)、dhcp agent scheduler、dhcp agent、dhcp driver(dnsmasq)構成。
架構圖如下:

<ignore_js_op>  

 

對應架構圖中數字,有以下幾個接口:

1.network/subnet/port的操作
2.agent management/agent scheduler的操作
3.network/subnet/port操作會發送rpc請求到dhcp agent。
4.agentscheduler db發送rpc請求到dhcp agent。
5.dhcp agent通過DhcpPluginApi發送rpc請求到core plugin,操作相應的數據庫。
6.dhcp agent調用dhcp driver進行dhcp相關操作。

 

四.代碼分析
neutron-dhcp-agent的入口為neutron.agent.dhcp_agent:main,跟l3-agent的啟動方式是類似的,都是以Service啟動;Manager類為DhcpAgentWithStateReport,匯報DHCPAgent的狀態。
  1. def main():
  2.     register_options()
  3.     common_config.init(sys.argv[1:])
  4.     config.setup_logging(cfg.CONF)
  5.     server = neutron_service.Service.create(
  6.         binary='neutron-dhcp-agent',
  7.         topic=topics.DHCP_AGENT,
  8.         report_interval=cfg.CONF.AGENT.report_interval,
  9.         manager='neutron.agent.dhcp_agent.DhcpAgentWithStateReport')
  10.     service.launch(server).wait()
復制代碼

DhcpAgentWithStateReport繼承自DhcpAgent,用於匯報DHCPAgent的狀態
  1.     if report_interval:
  2.             self.heartbeat = loopingcall.FixedIntervalLoopingCall(
  3.                 self._report_state)
  4.             self.heartbeat.start(interval=report_interval)
復制代碼
_report_state就是從self.cache中取出當前狀態,然后構造一個report_state的message發到q-plugin topic的消息隊列上。


下面看下DhcpAgent初始化過程:

  1. def __init__(self, host=None):
  2.         super(DhcpAgent, self).__init__(host=host)
  3.         self.needs_resync_reasons = []
  4.         self.conf = cfg.CONF
  5.         # Agent cache of the current network state
  6.         self.cache = NetworkCache()
  7.         self.root_helper = config.get_root_helper(self.conf)
  8.         # dhcp_driver currently is neutron.agent.linux.dhcp.Dnsmasq
  9.         self.dhcp_driver_cls = importutils.import_class(self.conf.dhcp_driver)
  10.         ctx = context.get_admin_context_without_session()
  11.         # init plugin rpc
  12.         self.plugin_rpc = DhcpPluginApi(topics.PLUGIN,  # topic is q-plugin,提供DHCP相關的創建、查詢、更新、刪除接口
  13.                                         ctx, self.conf.use_namespaces)
  14.         # create dhcp dir to store dhcp info: /var/lib/neutron/dhcp/
  15.         # these files are used for Dnsmasq
  16.         dhcp_dir = os.path.dirname("/%s/dhcp/" % self.conf.state_path)
  17.         if not os.path.isdir(dhcp_dir):
  18.             os.makedirs(dhcp_dir, 0o755)
  19.         self.dhcp_version = self.dhcp_driver_cls.check_version()
  20.         # query existing_dhcp_networks from driver and then save them into self.cache
  21.         self._populate_networks_cache()
復制代碼

DhcpPluginApi創建了topic為q-plugin的處理方法,dhcp-agent外部可以通過DhcpAgentNotifyAPI來調用這些接口:
  1. class DhcpAgentNotifyAPI(n_rpc.RpcProxy):
  2.     """API for plugin to notify DHCP agent."""
  3.     BASE_RPC_API_VERSION = '1.0'
  4.     # It seems dhcp agent does not support bulk operation
  5.     VALID_RESOURCES = ['network', 'subnet', 'port']
  6.     VALID_METHOD_NAMES = ['network.create.end',
  7.                           'network.update.end',
  8.                           'network.delete.end',
  9.                           'subnet.create.end',
  10.                           'subnet.update.end',
  11.                           'subnet.delete.end',
  12.                           'port.create.end',
  13.                           'port.update.end',
  14.                           'port.delete.end']
復制代碼

neutron.agent.linux.dhcp.Dnsmasq

DhcpAgent通過self.dhcp_driver_cls = importutils.import_class(self.conf.dhcp_driver)注冊了Dnsmasq這個Driver,並在需要的時候調用driver的相應接口:
  1. def call_driver(self, action, network, **action_kwargs):
  2.         """Invoke an action on a DHCP driver instance."""
  3.         LOG.debug(_('Calling driver for network: %(net)s action: %(action)s'),
  4.                   {'net': network.id, 'action': action})
  5.         try:
  6.             # the Driver expects something that is duck typed similar to
  7.             # the base models.
  8.             driver = self.dhcp_driver_cls(self.conf,
  9.                                           network,
  10.                                           self.root_helper,
  11.                                           self.dhcp_version,
  12.                                           self.plugin_rpc)
  13.             getattr(driver, action)(**action_kwargs)
  14.             return True
復制代碼

Dnsmasq會通過/var/lib/neutron/dhcp/目錄下的配置文件啟動dnsmasq進程,在DHCP更新的時候,更新這些配置文件並reload配置。
  1. dnsmasq --no-hosts --no-resolv --strict-order  
  2. --bind-interfaces --interface=tap746570b9-2b --except-interface=lo  
  3. --pid-file=/var/lib/quantum/dhcp/3e16cd2f-c693-49b4-91a7-2a65912ec152/pid  
  4. --dhcp-hostsfile=/var/lib/quantum/dhcp/3e16cd2f-c693-49b4-91a7-2a65912ec152/host  
  5. --dhcp-optsfile=/var/lib/quantum/dhcp/3e16cd2f-c693-49b4-91a7-2a65912ec152/opts  
  6. --dhcp-script=/usr/bin/quantum-dhcp-agent-dnsmasq-lease-update --leasefile-ro  
  7. --dhcp-range=set:tag0,12.0.0.192,static,120s  
  8. --conf-file= --domain=openstacklocal 
  9. --bind-interfaces --interface=tap746570b9-2b 
  10. 主要選項:
  11. --except-interface=lo 使多個dnsmasq實例可以同時運行在同一台主機上並監聽不同的interface
  12. --dhcp-hostsfile=/var/lib/quantum/dhcp/3e16cd2f-c693-49b4-91a7-2a65912ec152/host 讀取IP與虛擬機的靜態映射關系,該文件改變后dnsmasq會自動重新加載,不需要重啟
  13. --dhcp-optsfile=/var/lib/quantum/dhcp/3e16cd2f-c693-49b4-91a7-2a65912ec152/opts  指定DNS服務器地址等選項
  14. --dhcp-script=/usr/bin/quantum-dhcp-agent-dnsmasq-lease-update --leasefile-ro  lease信息更新與通知
  15. --dhcp-range=set:tag0,12.0.0.192,static,120s  重點在於static參數,該參數限制dnsmasq只能為dhcp-hostsfile包含的主機提供DHCP服務
復制代碼
既然Dnsmasq是根據/var/lib/neutron/dhcp/目錄下的配置文件啟動的,那么這些配置文件是如何創建和更新的呢?
(1)創建過程
dhcp agent在收到network_create_end后,會啟動一個dhcp(dnsmasq)進程服務這個新網絡。
(2)更新過程

dhcp agent會調用dhcp_driver.reload_allocations來更新配置文件。reload_allocations會根據新網絡配置重新生成配置文件。

dhcp agent會在收到如下4種消息時調用reload_allocations

  • port_update_end
  • port_delete_end
  • subnet_update_end
  • subnet_delete_end
上面這些通知消息在neturon rest API的前端實現中發出,具體代碼在neutron.api.v2.base.py中
  1. #Controller
  2. notifier_method = self._resource + '.create.end'
  3. notifier_method = self._resource + '.delete.end'
  4. notifier_method = self._resource + '.update.end'
復制代碼
可以看到針對每種resource(network, subnet, port),都會有相應的消息發出。dhcp agent根據這些消息來決定何時重新加載dnsmasp配置文件。


dhcp agent scheduler

通過dhcp agent scheduler,系統中可以部署多個dhcp agent:
1)增加可用性(HA, high availability),避免單點失敗(SOF, single point of failure)
2)增加性能,多個dhcp agent可以安裝在多台機器上,同時服務。

如何調度dhcp agent

調度算法通過network_scheduler_driver配置,默認是neutron.scheduler.dhcp_agent_scheduler.ChanceScheduler
class ChanceScheduler(object):
    """Allocate a DHCP agent for a network in a random way.
    More sophisticated scheduler (similar to filter scheduler in nova?)
    can be introduced later.
    """
可以看出,這個實現采用了隨機分配算法。

如何調用dhcp agent scheduler

通過neutron.api.rpc.agentnotifiers.dhcp_rpc_agent_api.py中
def notify(self, context, data, method_name): 發送消息時,會調用
self._notify_agents,有代碼
            schedule_required = method == 'port_create_end'
            if schedule_required:
                agents = self._schedule_network(admin_ctx, network, agents)

可以看到當系統中有新的port創建后,會調用dhcp agent scheduler分配dhcp agent。


dhcp服務的啟動

  1. def after_start(self):
  2.         self.run()
  3.         LOG.info(_("DHCP agent started"))
  4.     def run(self):
  5.         """Activate the DHCP agent."""
  6.         # 根據系統中的網絡配置,啟動dhcp服務器進程(dnsmasq)。
  7.         # sync_state()在dhcp agent啟動后運行一次。
  8.         self.sync_state()
  9.         # 周期性調用sync_state()
  10.         # dhcp agent會緩存一些網路的信息,通過該任務和neutron同步網絡信息,更新本地緩存。
  11.         self.periodic_resync()
復制代碼
neutron的各種插件實現(core plugin or service plugin)都繼承於db包下的對象,這些object實現了對相應資源數據模型的操作。



五.類圖

<ignore_js_op>  



六.數據庫
DHCP agent的信息會存放在neutron數據庫的agents表中:
  1. mysql> desc agents;
  2. +---------------------+---------------+------+-----+---------+-------+
  3. | Field               | Type          | Null | Key | Default | Extra |
  4. +---------------------+---------------+------+-----+---------+-------+
  5. | id                  | varchar(36)   | NO   | PRI | NULL    |       |
  6. | agent_type          | varchar(255)  | NO   |     | NULL    |       |
  7. | binary              | varchar(255)  | NO   |     | NULL    |       |
  8. | topic               | varchar(255)  | NO   |     | NULL    |       |
  9. | host                | varchar(255)  | NO   |     | NULL    |       |
  10. | admin_state_up      | tinyint(1)    | NO   |     | NULL    |       |
  11. | created_at          | datetime      | NO   |     | NULL    |       |
  12. | started_at          | datetime      | NO   |     | NULL    |       |
  13. | heartbeat_timestamp | datetime      | NO   |     | NULL    |       |
  14. | description         | varchar(255)  | YES  |     | NULL    |       |
  15. | configurations      | varchar(4095) | NO   |     | NULL    |       |
  16. +---------------------+---------------+------+-----+---------+-------+
復制代碼

DHCP agent和network綁定關系存儲在networkdhcpagentbindings中:
  1. mysql> desc networkdhcpagentbindings;
  2. +---------------+-------------+------+-----+---------+-------+
  3. | Field         | Type        | Null | Key | Default | Extra |
  4. +---------------+-------------+------+-----+---------+-------+
  5. | network_id    | varchar(36) | NO   | PRI | NULL    |       |
  6. | dhcp_agent_id | varchar(36) | NO   | PRI | NULL    |       |
  7. +---------------+-------------+------+-----+---------+-------+
復制代碼
agents和networkdhcpagentbindings通過dhcp agent id建立引用關系。
網絡,子網和端口信息分別存儲在數據庫的networks,subnets和ports表中。dhcp agent需要獲取這些信息生成dnsmasq的配置信息,並將這些信息存儲在/var/lib/neutron/dhcp/目錄下。 當neutron-server有需要添加/修改/刪除dhcp相關配置時,會將消息發送到隊列dhcp_agent.hostname或dhcp_agent_fanout_id,dhcp agent收到消息后進行相應dhcp的配置。



相關文章

openstack Neutron分析(2)—— neutron-l3-agent


openstack Neutron分析(4)—— neutron-l3-agent中的iptables

openstack Neutron分析(5)-- neutron openvswitch agent


Openstack之neutron入門


Openstack之neutron入門二 


Openstack之neutron入門三 

http://www.aboutyun.com/thread-9533-1-1.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM