還記得在Day-09: 在OpenStack 上建立Network時,我們在建立instance時,有特別指定IP給instance。但大多數時候,我們都是用DHCP對instance分配IP。在OpenStack要讓DHCP分配IP給instance非常簡單,把原先的指令裡的v4-fixed-ip=aaa.bbb.ccc.ddd
拿掉就可以囉。如果OpneStack是採用Linux Bridge 或 OVS做為Network的backend的話,是利用在不同的namespace裡的dnsmasq 對不同的OpenStack的Network提供DHCP服務。Linux Birdge/OVS的作法和我們今天要介紹的利用OVN提供DHCP是非常不同的,讓我們來看看OVN如何達到吧.
首先,先建立一個用DHCP取得IP的instance吧
IMAGE_ID=$(openstack image show cirros --format json | jq -r .id)
# static ip
openstack server create --nic net-id=n1,v4-fixed-ip=172.16.100.20 --flavor m1.nano --image $IMAGE_ID vm_2
# dynamic ip through dhcp
openstack server create --nic net-id=n1 --flavor m1.nano --image $IMAGE_ID vm_3
照我們在Day-03: 透過DHCP分配IP的logical switch裡介紹的,OVN會透過dhcp-options
物件,得知要分配的IP相關資訊。因為instance可以透過DHCP取得IP,就表示,OpenStack 建立Network時,就有建立dhcp-options
,讓我們來把這個資訊找出來吧。
port_list=$(openstack port list --network n1 --device-owner compute:nova -f json | jq -rc .[].ID)
for port in $port_list; do
ovn-nbctl --no-heading --column dhcpv4_options find logical_switch_port name=$port
done | uniq
9c7674f7-749d-4558-96d4-51e1564d0b5c
dhcpv4_options
的id來查詢 NB DB裡的dhcp_options
TABLE, 可以看到DHCP的option, 每個OpenStack subnet會共用一個optionovn-nbctl list dhcp_options 9c7674f7-749d-4558-96d4-51e1564d0b5c
_uuid : 9c7674f7-749d-4558-96d4-51e1564d0b5c
cidr : "172.16.100.0/24"
external_ids : {"neutron:revision_number"="0", subnet_id="363f1cbb-ec9e-4a97-a059-33e02b351e59"}
options : {classless_static_route="{169.254.169.254/32,172.16.100.2, 0.0.0.0/0,172.16.100.1}", dns_server="{192.168.121.1}", lease_time="43200", mtu="1500", router="172.16.100.1", server_id="172.16.100.1", server_mac="fa:16:3e:e8:9a:84"}
我們仿照Day-03: 透過DHCP分配IP的logical switch的作法,再一次使用ovn-trace來追蹤一個VM發出的dhcp request,會得到怎樣的dhcp response吧。
$ NETWORK1_NAME=n1
$ VM1_NAME=vm_3
# 由openstack network 查OVN logical switch 的name
$ lsw=neutron-`openstack network list --name ${NETWORK1_NAME} -f value -c ID`
# 由openstack port 查OVN logical switch 上 VM1接的port
$ lsp=`openstack port list --network ${NETWORK1_NAME} --server ${VM1_NAME} -f value -c ID`
# 由openstack port 查 VMs的 mac address
$ vm_mac=`openstack port list --network ${NETWORK1_NAME} --server ${VM1_NAME} -f value -c mac_address`
$ ovn-trace --minimal ${lsw} \
"inport == \"${lsp}\" &&
eth.src == $vm1_mac &&
eth.dst == ff:ff:ff:ff:ff:ff &&
ip4.dst == 255.255.255.255 &&
udp.src == 68 &&
udp.dst == 67 &&
ip.ttl == 1"
從ovn-trace的結果可以看出來:
ingress(dp="n1", inport="54b53a")
-----------------------------
...
20. ls_in_dhcp_options (northd.c:8165): inport == "54b53a" && eth.src == fa:16:3e:a3:c6:19 && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 67, priority 100, uuid 82afde2c
reg0[3] = put_dhcp_opts(offerip = 172.16.100.185, classless_static_route = {169.254.169.254/32, 172.16.100.2, 0.0.0.0/0, 172.16.100.1}, dns_server = {192.168.121.1}, lease_time = 43200, mtu = 1500, netmask = 255.255.255.0, router = 172.16.100.1, server_id = 172.16.100.1);
/* We assume that this packet is DHCPDISCOVER or DHCPREQUEST. */
next;
21. ls_in_dhcp_response (northd.c:8212): inport == "54b53a" && eth.src == fa:16:3e:a3:c6:19 && ip4 && udp.src == 68 && udp.dst == 67 && reg0[3], priority 100, uuid b52e3e98
eth.dst = eth.src;
eth.src = fa:16:3e:e8:9a:84;
ip4.src = 172.16.100.1;
udp.src = 67;
udp.dst = 68;
outport = inport;
flags.loopback = 1;
output;
egress(dp="n1", inport="54b53a", outport="54b53a")
------------------------------------------
...
9. ls_out_apply_port_sec (northd.c:5736): 1, priority 0, uuid 850c161b
output;
/* output to "54b53a", type "" */
今天的概念,和Day-03: 透過DHCP分配IP的logical switch機乎是完全相同的,想必大家一定不默生吧。也再一次讓大家知道,OpenStack Network裡的許多網路功能,都是直接用OVN的機制來實現,這和早期的Linux Bridge或 OVS的方案是有很大的不同唷。