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
log-facility = /var/log/neutron/dnsmasq.log
log-dhcp
dnsmasq_config_file = /etc/neutron/dnsmasq.conf
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