Neutron 理解(5):Neutron 是如何向 Nova 虛機分配固定IP地址的 (How Neutron Allocates Fixed IPs to Nova Instance)

Nova 虛機獲取固定IP (Fixed IP)主要分爲兩個步驟:

(1)在創建虛機過程中,Neutron 隨機生成 MAC 和 從配置數據中分配一個固定IP 地址,並保存到 Dnsmasq 的 hosts 文件中,讓 Dnsmasq 做好準備。

(2)虛機在啓動時向 Dnsmasq 獲取 IP 地址

 

本文將分析該過程。整個過程涉及不同節點的幾個模塊:

下面將具體分析該過程。

1. 創建虛機時的數據流

Nova-compute 在創建虛機時,需要 Neutron 所做的主要事情之一就是分配一個 MAC 和 一個或者多個固定 IP 地址,該過程從 Nova-compute 向 Neutron 申請 Port 開始:

REQ: curl -i http://controller:9696/v2.0/ports.json -X POST -H "X-Auth-Token: ...=" -H "User-Agent: python-neutronclient" -d '{"port": {"binding:host_id": "compute1", "admin_state_up": true, "network_id": "0a4cd030-d951-401a-8202-937b788bea43", "tenant_id": "43f66bb82e684bbe9eb9ef6892bd7fd6", "device_owner": "compute:nova", "security_groups": ["8c0dc337-0a6d-4ad7-94bf-a400ee32b2ac"], "device_id": "8671c14e-9ee4-4338-bcc5-8a5f0ea6e1d5"}}'

Controller 節點上的 Neutron Server 接到該請求後,會開始下面的過程:

步驟 2 ~ 6:Neutron Server 生成 MAC 和 IP。 其中 MAC 是由任意數組成的;Fixed IP 是從保存在數據庫中的管理員配置的網絡和地址數據生成的。

步驟 7 ~ 10: 調用 L3 Agent 和 OVS 執行一些操作。

步驟 12 ~ 14:通過 AMQP 的 cast 消息給 Neutron 節點上的 DHCP Agent,告訴它 Port 創建結束以及 新分配的 Port 的數據。

步驟 13:返回Port 給 nova-compute,數據示例如下:

{"port": {"status": "DOWN", "binding:host_id": "compute1", "allowed_address_pairs": [], "extra_dhcp_opts": [], "device_owner": "compute:nova", "binding:profile": {}, "fixed_ips": [{"subnet_id": "5598bdf9-2de4-4a4e-9054-2070102e0f1f", "ip_address": "10.0.0.132"}], "id": "a9ab8ebf-a0b4-4599-867c-95518f069a10", "security_groups": ["8c0dc337-0a6d-4ad7-94bf-a400ee32b2ac"], "device_id": "8671c14e-9ee4-4338-bcc5-8a5f0ea6e1d5", "name": "", "admin_state_up": true, "network_id": "0a4cd030-d951-401a-8202-937b788bea43", "tenant_id": "43f66bb82e684bbe9eb9ef6892bd7fd6", "binding:vif_details": {"port_filter": true, "ovs_hybrid_plug": true}, "binding:vnic_type": "normal", "binding:vif_type": "ovs", "mac_address": "fa:16:3e:f2:e0:23"}

步驟 15:Neturon 節點上的 DHCP Agent 根據接收到的 Port 創建完成通知,重新生成 Dnsmasq 的 hosts 文件,然後讓 Dnsmasq 重新加載該文件。該 hosts 文件的示例如下:

root@network:/home/s1# cat /var/lib/neutron/dhcp/0a4cd030-d951-401a-8202-937b788bea43/host
fa:16:3e:f2:e0:23,host-10-0-0-132.openstacklocal,10.0.0.132 #剛創建的 Port 對應的項,包括 MAC 地址、host FQDN、IP 地址
fa:16:3e:9d:e9:11,host-10-0-0-135.openstacklocal,10.0.0.135fa:16:3e:45:14:34,host-10-0-0-1.openstacklocal,10.0.0.1
fa:16:3e:9d:e9:17,host-10-0-0-141.openstacklocal,10.0.0.141
fa:16:3e:9d:e9:18,host-10-0-0-142.openstacklocal,10.0.0.142

Nova 拿到 Port 的數據後,會寫入虛機的 libvirt.xml 文件。下面的虛機配了兩塊 NIC,所有它有兩個 interface 塊:

複製代碼
<devices>
    <disk type="file" device="disk">
      <driver name="qemu" type="qcow2" cache="none"/>
      <source file="/var/lib/nova/instances/199f9e78-96aa-4d31-b250-6626b88723f5/disk"/>
      <target bus="virtio" dev="vda"/>
    </disk>
    <interface type="bridge">
      <mac address="fa:16:3e:0f:13:7e"/>
      <model type="virtio"/>
      <driver name="qemu"/>
      <source bridge="qbrf3aeba46-04"/>
      <target dev="tapf3aeba46-04"/>
    </interface>
    <interface type="bridge">
      <mac address="fa:16:3e:a2:47:46"/>
      <model type="virtio"/>
      <driver name="qemu"/>
      <source bridge="qbr04ab89a9-10"/>
      <target dev="tap04ab89a9-10"/>
    </interface>    
  </devices>
複製代碼

關於該過程,詳細的代碼說明可以看 這裏

2. Neutron 中的網絡概念和 DHCP Agent

2.1 Neutron 網絡概念

  • Network:一個具有 tenant 隔離性的虛擬 2 層網絡,它使用一個虛擬交換機。除了用於與外網連接的網絡外,其它的 network 都只屬於創建它的 tenant。 虛機在創建時必須選擇至少一個 network,也可以選擇使用多塊網卡和多個 network 連接。
  • Subnet:表示一個 IPv4 或者 IPv6 地址區間,該區間內的地址可以被分配給虛機。 一個 Subnet 可以使用一個 DHCP Server 用於分配指定區間內的 IP 地址給虛機。 
  • Port:表示給定 network 上的一個虛擬交換端口,一個 Port 和虛機的一個網卡直接連接。
  • Router: 在 subnet IP 段之間轉發 IP 包,使用一個 external gate 和外網連接,以及連接若干個 subnet。

關係:

(1)tenant ---- 1:n ----- network ------- 1:n ------- subnet (一個 tenant 可以擁有多個 network,一個 network 可以包含多個 subnet)

(2)network ------- 1: n ------- port ------ 1:1 --- subnet(一個network 可以有多個 port, 每個 port 連接一個 subnet)(若創建虛機時指定的是 net-id,那麼虛機將隨機地從該 network 包含的 subnet 中分配 IP)

(3)VM ----- 1 : n ---- NIC ----- 1:1 --- port(一個 VM 可以有多個 NIC,每個 NIC 連接一個 port)(可以在創建虛機時指定一個或者多個 port)

(4)Tenant  ----- 1 : n ---- Router ----- 1 : n ------ subnet/ext-network (一個 tenant 可以擁有多個 router,每個 router 在 Neutron network 節點上使用一個 Linux network namespace,其 ID 就是 neutron router-list 得到的 router 的 ID; 一個 router 連接一個通向外網的 gateway 和多個該 tenant 的 subnet)

(5)network ---- 1 : 1 ---- Dnamasq  ----- 1: n ----- subnet (一個 network 有一個 Dnsmasq 進程,該進程爲多個啓動了 DHCP 的 subnet 服務,分配它們擁有的 IP 給虛機)

示例:

綜上:

Neutron 向 OpenStack 提供一個虛擬的大二層網絡。在使用 Open vSwitch 時,它類似於一個跨 Neutron 節點和 Nova-compute 節點的虛擬交換機。Neutron 中的 network 是這個大二層網絡中使用 VLAN Tag 分割的子網,而 Subnet 是 network 中一段 IP 地址的集合,Port 是 OVS 交換機上的一個端口(上圖中步驟7、9、10就是在 OVS 上配置 Port),它連接虛機的 NIC,使用來自 subnet 的 IP 地址。network 具有租戶隔離性,它包含一個自己的 DHCP Agent 來將它所包含的 subnet 的 IP 分給虛機的NIC;它還擁有一個自己的 L3 Agent 來提供 subnet 之間的 IP 包路由以及 subnet 和 external network 之間 IP 包的路由。可以參考我的另一篇文章中的示意圖。

2.2 Neutron DHCP Agent

該 Agent 用戶提供 DHCP 服務。它:

(1)在其所在的節點上的 /var/lib/neutron/dhcp/ 目錄下,爲每個 network 創建了一個子目錄,目錄名即 network id;每個子目錄下,包含若干文件,比如 host 文件。比如:

root@network:/var/lib/neutron/dhcp# ls
0a4cd030-d951-401a-8202-937b788bea43  d04a0a06-7206-4d05-9432-3443843bc199
c359d42b-2a75-4764-bba9-be76b45f64d8  d24963da-5221-481e-adf5-fe033d6e0b4e

(2)爲每個 network 啓動一個 Dnsmasq 進程,該進程爲該 network 中啓動了 DHCP 的 subnet 提供服務。每一個 subnet 對應於一個 dhcp-range, 從 tag0 開始,一次 tag1,tag2....

nobody    7087     1  0 22:57 ?        00:00:00 dnsmasq --no-hosts --no-resolv --strict-order --bind-interfaces --interface=tap6356d532-32 --except-interface=lo --pid-file=/var/lib/neutron/dhcp/0a4cd030-d951-401a-8202-937b788bea43/pid --dhcp-hostsfile=/var/lib/neutron/dhcp/0a4cd030-d951-401a-8202-937b788bea43/host --addn-hosts=/var/lib/neutron/dhcp/0a4cd030-d951-401a-8202-937b788bea43/addn_hosts --dhcp-optsfile=/var/lib/neutron/dhcp/0a4cd030-d951-401a-8202-937b788bea43/opts --leasefile-ro --dhcp-range=set:tag0,10.0.0.0,static,86400s --dhcp-range=set:tag1,10.0.50.0,static,86400s --dhcp-lease-max=512 --conf-file=/etc/neutron/dnsmasq.conf --domain=openstacklocal

關於 set::tag<#>,官方的解釋是 The optional set:<tag> sets an alphanumeric label which marks this network so that dhcp options may be specified on a per-network basis. When it is prefixed with 'tag:' instead, then its meaning changes from setting a tag to matching it. Only one tag may be set, but more than one tag may be matched. 不過還不理解它的意思.....

(3)在 Port 或者 Subnet 有變化時,該 Dnsmasq 進程會重新讀取新的配置,包括新的 host 文件,新的 dhcp-range 等。

3. 關於 Dnsmasq

3.1 Dnsmasq 進程

Dnsmasq 是被 Neutron 用來提供 DHCP 和 DNS 服務的一個開源程序。它提供 DNS 緩存和 DHCP 服務功能。作爲域名解析服務器(DNS),dnsmasq可以通過緩存 DNS 請求來提高對訪問過的網址的連接速度。作爲DHCP 服務器,dnsmasq 可以爲局域網電腦提供內網ip地址和路由。DNS和DHCP兩個功能可以同時或分別單獨實現。dnsmasq輕量且易配置,適用於主機較少的網絡。這裏是它的 man page。這裏是中文wiki page

Neutron 爲每個 network 啓動一個 Dnsmasq 進程,比如:

複製代碼
root@network:/home/s1# ps -ef | grep dnsmasq
nobody    1198     1  0 18:51 ?        00:00:00 dnsmasq --no-hosts --no-resolv --strict-order --bind-interfaces --interface=tap8dfd0bd8-45 --except-interface=lo --pid-file=/var/lib/neutron/dhcp/d04a0a06-7206-4d05-9432-3443843bc199/pid --dhcp-hostsfile=/var/lib/neutron/dhcp/d04a0a06-7206-4d05-9432-3443843bc199/host --addn-hosts=/var/lib/neutron/dhcp/d04a0a06-7206-4d05-9432-3443843bc199/addn_hosts --dhcp-optsfile=/var/lib/neutron/dhcp/d04a0a06-7206-4d05-9432-3443843bc199/opts --leasefile-ro --dhcp-range=set:tag0,10.0.11.0,static,86400s --dhcp-lease-max=256 --conf-file=/etc/neutron/dnsmasq.conf --domain=openstacklocal
nobody    1201     1  0 18:51 ?        00:00:00 dnsmasq --no-hosts --no-resolv --strict-order --bind-interfaces --interface=tap6356d532-32 --except-interface=lo --pid-file=/var/lib/neutron/dhcp/0a4cd030-d951-401a-8202-937b788bea43/pid --dhcp-hostsfile=/var/lib/neutron/dhcp/0a4cd030-d951-401a-8202-937b788bea43/host --addn-hosts=/var/lib/neutron/dhcp/0a4cd030-d951-401a-8202-937b788bea43/addn_hosts --dhcp-optsfile=/var/lib/neutron/dhcp/0a4cd030-d951-401a-8202-937b788bea43/opts --leasefile-ro --dhcp-range=set:tag0,10.0.0.0,static,86400s --dhcp-lease-max=256 --conf-file=/etc/neutron/dnsmasq.conf --domain=openstacklocal
複製代碼

用到的幾個參數的意義如下:

--no-hosts:  Don't read the hostnames in /etc/hosts.
--bind-interfaces:  Setting this option also enables multiple instances of dnsmasq which provide DHCP service to run in the same machine.
--interface: Listen only on the specified interface(s). 在指定的 interface 上監聽 DHCP 請求。
--dhcp-hostsfile: Read DHCP host information from the specified file. The advantage of storing DHCP host information in this file is that it can be changed without re-starting dnsmasq: the file will be re-read when dnsmasq receives SIGHUP. DHCP host 文件,dnsmasq 收到 SIGHUP 後會重新讀入。沒看到 Neutron code 發出該信息,而似乎每次都重啓dnsmasq 進程。

--addn-hosts: Additional hosts file. The file will be re-read when dnsmasq receives SIGHUP.

--dhcp-optsfile: Read DHCP option information from the specified file when dnsmasq receiving SIGHUP.

--dhcp-range: Enable the DHCP server. This option may be repeated, with different addresses, to enable DHCP service to more than one network. dnsmasq 默認關閉DHCP功能,該選項開啓該功能。每個開啓了 DHCP 的 subnet 擁有一個該項。
--dhcp-lease-max: Limits dnsmasq to the specified maximum number of DHCP leases to prevent DoS attacks from hosts.
--domain: Specifies DNS domains for the DHCP server.

這些數據皆由數據庫中數據計算得出。 

3.2 Dnsmasq log

dnsmasq 默認地將日誌寫到 /var/log/syslog 中。可以在 Neutron 節點上做如下配置,使得它使用別的log 文件以便調試:
(1)創建文件  /etc/neutron/dnsmasq.conf,在其中添加 
log-facility = /var/log/neutron/dnsmasq.log
log-dhcp
(2)添加下面行到 /etc/neutron/dhcp_agent.ini:
dnsmasq_config_file = /etc/neutron/dnsmasq.conf
(3)運行下面命令重啓 Neutron DHCP agent:
sudo service neutron-dhcp-agent restart 

4. 虛機啓動時向 Dnsmasq 申請固定 IP

經過以上步驟,Dnsmasq 準備好相應虛機的IP 申請請求了,它:準備好了 host 文件,裏面有每個虛機的 MAC 地址 和 IP 對照表;綁定了 interface,可以收到請求;啓動好了進程,可以爲指定的 subnet 服務。

獲取 IP 的過程如下:

(1)虛機 VM_1 開機,發出 DHCPDISCOVER 廣播,該廣播消息在整個 network 中都可以被收到。

(2)廣播到達 tap6356d532-32,Dnsmasq 在它上面監聽。它檢查其 host 文件,發現有對應項,它以  DHCPOFFER 消息將 IP 和 gateway IP 發回到 VM_1。如果有其他DHCP Server的話,它們也可能會發回IP 地址。

(3)VM_1 發回 DHCPREQUEST 消息確認只接受第二步發的 DHCPOFFER,別的 DHCP Server 給的 IP 可以自行收回了。

(4)Dnsmasq 發回確認消息 DHCPACK,整個過程結束。 

參考創建一個虛機在 dnsmasq 的日誌的整個過程:

複製代碼
Apr 11 23:42:14 dnsmasq[7087]: read /var/lib/neutron/dhcp/0a4cd030-d951-401a-8202-937b788bea43/addn_hosts - 14 addresses #讀取更新後的文件
Apr 11 23:42:14 dnsmasq-dhcp[7087]: read /var/lib/neutron/dhcp/0a4cd030-d951-401a-8202-937b788bea43/host
Apr 11 23:42:14 dnsmasq-dhcp[7087]: read /var/lib/neutron/dhcp/0a4cd030-d951-401a-8202-937b788bea43/opts
Apr 11 23:42:15 dnsmasq[7092]: read /var/lib/neutron/dhcp/c359d42b-2a75-4764-bba9-be76b45f64d8/addn_hosts - 3 addresses #讀取更新後的文件
Apr 11 23:42:15 dnsmasq-dhcp[7092]: read /var/lib/neutron/dhcp/c359d42b-2a75-4764-bba9-be76b45f64d8/host
Apr 11 23:42:15 dnsmasq-dhcp[7092]: read /var/lib/neutron/dhcp/c359d42b-2a75-4764-bba9-be76b45f64d8/opts
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 available DHCP subnet: 10.0.50.0/255.255.255.0 #第一個 subnet
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 available DHCP subnet: 10.0.0.0/255.255.255.0 #第二個 subnet
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 vendor class: udhcp 1.20.1
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 DHCPDISCOVER(tap6356d532-32) fa:16:3e:0f:13:7e #收到虛機的 DHCPDISCOVER 消息
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 tags: tag0, known, tap6356d532-32 #從 10.0.0.0/255.255.255.0 中分配地址 (爲什麼只是 tag0 呢?
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 DHCPOFFER(tap6356d532-32) 10.0.0.143 fa:16:3e:0f:13:7e #發回IP地址
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 requested options: 1:netmask, 3:router, 6:dns-server, 12:hostname,
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 requested options: 15:domain-name, 28:broadcast, 42:ntp-server,
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 requested options: 121:classless-static-route
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 next server: 10.0.0.116
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 sent size:  1 option: 53 message-type  2
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 sent size:  4 option: 54 server-identifier  10.0.0.116
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 sent size:  4 option: 51 lease-time  1d
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 sent size:  4 option: 58 T1  12h
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 sent size:  4 option: 59 T2  21h
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 sent size:  4 option:  1 netmask  255.255.255.0
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 sent size:  4 option: 28 broadcast  10.0.0.255
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 sent size: 14 option: 15 domain-name  openstacklocal
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 sent size: 15 option: 12 hostname  host-10-0-0-143
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 sent size:  4 option:  3 router  10.0.0.1
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 sent size:  4 option:  6 dns-server  192.168.1.1
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 available DHCP subnet: 10.0.50.0/255.255.255.0
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 available DHCP subnet: 10.0.0.0/255.255.255.0
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 vendor class: udhcp 1.20.1
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 DHCPREQUEST(tap6356d532-32) 10.0.0.143 fa:16:3e:0f:13:7e #確認虛機只接受該IP。別的 DHCP Service 可以收回它們廢品的 IP 地址了。
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 tags: tag0, known, tap6356d532-32
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 DHCPACK(tap6356d532-32) 10.0.0.143 fa:16:3e:0f:13:7e host-10-0-0-143 #Dnsmasq 確認該 OFFER,以及發回其它info,整個過程結束。
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 requested options: 1:netmask, 3:router, 6:dns-server, 12:hostname,
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 requested options: 15:domain-name, 28:broadcast, 42:ntp-server,
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 requested options: 121:classless-static-route
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 next server: 10.0.0.116
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 sent size:  1 option: 53 message-type  5
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 sent size:  4 option: 54 server-identifier  10.0.0.116
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 sent size:  4 option: 51 lease-time  1d
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 sent size:  4 option: 58 T1  12h
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 sent size:  4 option: 59 T2  21h
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 sent size:  4 option:  1 netmask  255.255.255.0
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 sent size:  4 option: 28 broadcast  10.0.0.255
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 sent size: 14 option: 15 domain-name  openstacklocal
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 sent size: 15 option: 12 hostname  host-10-0-0-143
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 sent size:  4 option:  3 router  10.0.0.1
Apr 11 23:42:41 dnsmasq-dhcp[7087]: 116908156 sent size:  4 option:  6 dns-server  192.168.1.1
複製代碼

 5. DHCP Agent 的性能和可靠性

一方面,DHCP Agent 在一個 network 內使用一個 Dnsmasq 提供 DHCP 服務,在 network 很大的時候,可能會有性能問題,比如虛機無法及時獲取IP 地址,這時候就需要做性能優化的工作了。而且它依賴於 Neutron Server 發來的 notification,在 AMQP 遇到性能問題的時候,它由可能無法及時收到通知,導致無法提供服務。Marintas 有篇文章談這個問題 https://www.mirantis.com/blog/improving-dhcp-performance-openstack/

另一方面,DHCP Agent 可能因爲一些不可預測的原因不能提供服務,那會造成虛機就無法獲取IP 地址。DHCP 協議天然就支持多個使用多個 DHCP Server。這一塊,以後在 OpenStack 高可靠性(HA)分析部分會進行分析。

原文地址:http://www.cnblogs.com/sammyliu/p/4419195.html

發佈了18 篇原創文章 · 獲贊 6 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章