Nova 虚机获取固定IP (Fixed IP)主要分为两个步骤:
(1)在创建虚机过程中,Neutron 随机生成 MAC 和 从配置数据中分配一个固定IP 地址,并保存到 Dnsmasq 的 hosts 文件中,让 Dnsmasq 做好准备。
(2)虚机在启动时向 Dnsmasq 获取 IP 地址
1、创建虚拟机时的数据流
Nova-compute 在创建虚机时,需要 Neutron 所做的主要事情之一就是分配一个 MAC 和 一个或者多个固定 IP 地址,该过程从 Nova-compute 向 Neutron 申请 Port 开始:
步骤2-6:nova-compute向neutron-server申请port,neutron-server是用NeutronDbPlugin创建port,创建port时,生成了随机的mac地址,然后用这MAC地址创建port,同时IP是数据库中取出一个预配置的
ps:创建port时,需要指定网络和mac
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"}}
'
步骤7-10:创建port,并绑定到ovs
步骤12-14:通过消息队列告知DHCP Agent,port创建结束,并通知新分配的port信息
步骤15-17:DHCP Agent重新生成hosts文件,并重启dnsmasq进程,以供dhcp获取
步骤13返回的port信息示例如下:此时已经带有ip信息
{
"
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"
}
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.135
fa:
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 文件
2、Neutron中网络的概念整理
:
关系:
(1)tenant ---- 1:n ----- network ------- 1:n ------- subnet (一个 tenant 可以拥有多个 network,一个 network 可以包含多个 subnet)
(2)network ------- 1: n ------- port ------ n: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 给虚机)
(6)一个网络内的所有子网的VLAN tag一样,所以广播都能收到
关于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
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
其中interface为在br-int上监听的tap设备
dnsmasq默认日志写到/var/log/syslog
3、vm启东时向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,整个过程结束。
整理参考:http://www.cnblogs.com/sammyliu/p/4419195.html