iT邦幫忙

2023 iThome 鐵人賽

DAY 3
0
DevOps

在OpenStack Neutron的ovn-networking裡挖呀挖呀挖系列 第 3

Day-03: 透過DHCP分配IP的logical switch

  • 分享至 

  • xImage
  •  

前天我們已經建立了一個logical switch, 並驗證二組veth pair是能透過logical switch連通。我們在建立這二組veth pair時,我們是採用static IP,所以在veth一端所在的namespace裡,可以查到所指定的IP。OVN也支援透過DHCP動態分配IP給namespace。要完成動態分配IP,在namespace並不需要做什麼特別的事,只要如同往常一般,透過DHCP client取得IP即可;但是,在logical switch上,則必需加以設定。今天,就讓我們來理解OVN的logical swicth是如何支援DHCP吧


使用 DHCP 分配IP

先讓我們來看一下今天想要完成的設定,與昨天的區別在那裡吧。今天的範例要使用DHCP的話,與昨天的差別主要在二個地方:

  1. logical switch 必需加上other_config:subnet,指定DHCP所要使用的subnet
  2. 在logical switch要使用DHCP的port, address要特別宣告要使用dynamic;以及要指定要使用的dhcp-options

這裡的dhcp-options 指向的是一個事先透過ovn-nbctl 建立的一個dhcp-options 物件,而這個物件主要的作用是用來描述要使用的dhcp 服務的屬性。我們可以用ovn-nbctl create dhcp_options 建立。

例如: 建立一個subnet是10.0.0.0/24,gateway是10.0.0.1的dhcp

ovn-nbctl create dhcp_options \
  cidr=10.0.0.0/24 \
  options='"lease_time"="3600" "router"="10.0.0.1" "server_id"="10.0.0.1" "server_mac"="c0:ff:ee:00:00:01"'

也可以透過 ovn-nbctl list dhcp-options 查看,以及 ovn-nbctl destroy dhcp-options <id> 刪除。

gh

有了基本的認識後,再來看一下整個範例的過程吧

建立沒有 IP 的namespace

和昨天的差別,建立namespace,不指定使用的IP, 稍等會用dhcp分配IP

git clone https://github.com/ogre0403/iTHome-2023.git
sudo su
cd /opt/iTHome-2023/day-03
source helper.sh

create-ns ns1
create-ns ns2

建立DHCP-options

建立一個subnet是 10.0.0.0/24,gateway是10.0.0.1的dhcp-options。再將代表這個dhcp-options的uuid,用來建立logical switch。

uuid=$(create-dhcp-options 10.0.0.0/24 10.0.0.1)
create-ovn-ls-and-lsp ls0 $uuid 10.0.0.0/24
assign-iface-to-ovn-lsp ls0

如果深入去看 今天和昨天使用的create-ovn-ls-and-lsp,就可以發現,基本上都是相同的,差別只在於每個要用dhcp的port, 要將address設為dynamic, 以及要指定dhcp-options的uuid.

namespace 透過DHCP取得 IP

最後,分別在ns1與ns2 裡,用dhclient 取得IP後,再試看看二個namespace是否能夠互連。

ip netns exec ns1 dhclient
ip netns exec ns1 ip a


ip netns exec ns2 dhclient
ip netns exec ns2 ip a

OVN 怎麼分配 IP

在一般的區域網路裡,要透過DHCP分配IP,需要有DHCP server處理DHCP client發出的 dhcp request。但我們到目前也沒有安裝DHCP server, OVN 是如何透過DHCP分配IP呢? OVN所使用的DHCP server又在那裡呢? 讓我們來進一步了解OVN的DHCP流程吧。

OVN 提供ovn-trace 了一個工具,可以用於模擬和跟踪虛擬網絡中的封包的路徑。我們使用ovn-trace來追蹤一個namespace發出的dhcp request,會得到怎樣的結果。

NS=ns1
NS_MAC=$(ip netns exec $NS ip link show eth0 |grep link/ether | awk '{print $2}')
LS=ls0

ovn-trace $LS "
  inport==\"$LS-$NS\" &&
  eth.src==$NS_MAC &&
  ip4.src==0.0.0.0 &&
  ip.ttl==1 &&
  ip4.dst==255.255.255.255 &&
  udp.src==68 &&
  udp.dst==67"
ingress(dp="net0", inport="port2")
----------------------------------
...
14. ls_in_dhcp_options (ovn-northd.c:6426): inport == "ls0-ns1" && eth.src == de:8a:77:8e:ca:db && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 67, priority 100, uuid 9eb9c08d
    reg0[3] = put_dhcp_opts(offerip = 10.0.0.3, lease_time = 3600, netmask = 255.255.255.0, router = 10.0.0.1, server_id = 10.0.0.1);
    /* We assume that this packet is DHCPDISCOVER or DHCPREQUEST. */
    next;

15. ls_in_dhcp_response (ovn-northd.c:6474): inport == "ls0-ns1" && eth.src == de:8a:77:8e:ca:db && ip4 && udp.src == 68 && udp.dst == 67 && reg0[3], priority 100, uuid 87c28faa
    eth.dst = eth.src;
    eth.src = 02:00:f2:99:cf:f8;
    ip4.src = 10.0.0.1;
    udp.src = 67;
    udp.dst = 68;
    outport = inport;
    flags.loopback = 1;
    output;

egress(dp="ls0", inport="ls0-ns1", outport="ls0-ns1")
-----------------------------------------------------
 4. ls_out_acl (ovn-northd.c:5401): outport == "ls0-ns1" && eth.src == 02:00:f2:99:cf:f8 && ip4.src == 10.0.0.1 && udp && udp.src == 67 && udp.dst == 68, priority 34000, uuid 30ef0e29
    next;

 9. ls_out_port_sec_l2 (ovn-northd.c:4613): outport == "ls0-ns1", priority 50, uuid 014a78b3
    output;
    /* output to "ls0-ns1", type "" */

從ovn-trace的結果,我們可以看到

  1. ingress 的 #14: 接收到dhcp request後,準備提供 10.0.0.3做為回覆
  2. ingress 的 #15: 將dhcp response 回覆給來源的mac
  3. engress 的 #9 : 最後由一開始進來的port(ls0-ns1)送回去給ns1

由這個流程可以得知OVN在實作DHCP時,namesapce送出的dhcp request,並沒有被任何傳統意義上的DHCP server處理,完全由 hypervisor上的ovn-controller 在收到dhcp request 後,分配一個IP後,就馬上由原來的port送回去給namespace。


logical switch 與 veth 之間的綁定

從昨天到今天為止,目前我們已經完成了二個OVN的實驗,二個實驗都是在logical switch上,讓二個namespace互通,只是昨天是用static ip,而今天是用DHCP取得IP。也知道建立出來的邏輯交換器的長像以及相對應在主機的br-int上的interafce為何。但OVN到底是如何知道logical switch上的port,是對應至那一個hypervisor上的br-int的那一個interface呢? 如果沒有這種資訊,OVN不太可能知道br-int上收到封包後,要往那一個目的端發送。

讓我們深入看一下 helper.sh裡的create-ovn-ls-and-lsp & assign-iface-to-ovn-lsp,下面是將這個二個function裡用的for loop 展開後的一個例子。

# create-ovn-ls-and-lsp ls0
ovn-nbctl ls-add ls0

ovn-nbctl lsp-add ls0 ls0-ns1
ovn-nbctl lsp-set-addresses ls0-ns1 e6:3c:39:39:3d:f4

ovn-nbctl lsp-add ls0 ls0-ns2
ovn-nbctl lsp-set-addresses ls0-ns2 d6:ba:2e:b8:65:da

# assign-iface-to-ovn-lsp ls0
ovs-vsctl add-port br-int veth-ns1-br
ovs-vsctl set Interface veth-ns1-br external_ids:iface-id=ls0-ns1

ovs-vsctl add-port br-int veth-ns2-br
ovs-vsctl set Interface veth-ns2-br external_ids:iface-id=ls0-ns2

可以看到create-ovn-ls-and-lsp的function裡, 是透過ovn-nbctl建立logical switch上的logical port之後;還必需再使用ovs-vsctl將hypervisor的br-int的某一個interface與logical switch的logical port做綁定,即 ovs-vsctl set Interface veth-ns1-br external_ids:iface-id=ls0-ns1 這一行所在做的事;這就是代表圖中的controller和logical switch的那二個綠色鍵頭。

gh


Reference

  1. OVN AND DHCP: A MINIMAL EXAMPLE
  2. Dynamic IP Address Management in Open Virtual Network (OVN): Part One

上一篇
Day-02: 虛擬機器網路卡連至邏輯交換器
下一篇
Day-04: 跨節點的logical switch 與 GEVEVE Overlay Network
系列文
在OpenStack Neutron的ovn-networking裡挖呀挖呀挖30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言