雲計算openstack核心組件——neutron網絡服務(9)

一、虛擬機獲取 ip:

用 namspace 隔離 DHCP 服務

Neutron 通過 dnsmasq 提供 DHCP 服務,而 dnsmasq 通過 Linux Network Namespace 獨立的為每個 network 服務隔離

在二層網絡上,VLAN 可以將一個物理交換機分割成幾個獨立的虛擬交換機。類似地,在三層網絡上,Linux network namespace 可以將一個物理三層網絡分割成幾個獨立的虛擬三層網絡。

每個 namespace 都有自己獨立的網絡棧,包括 route table,firewall rule,network interface device 等。

Neutron 通過 namespace 為每個 network 提供獨立的 DHCP 和路由服務,從而允許租戶創建重疊的網絡。如果沒有 namespace,網絡就不能重疊,這樣就失去了很多靈活性。

每個 dnsmasq 進程都位於獨立的 namespace, 命名為 qdhcp-,例如 flat_net:

雲計算openstack核心組件——neutron網絡服務(9)

ip netns list 命令列出所有的 namespace

ip netns exec 管理 namespace

root namespace:

其實,宿主機本身也有一個 namespace,叫 root namespace,擁有所有物理和虛擬 interface device。物理 interface 只能位於 root namespace。

新創建的 namespace 默認只有一個 loopback device。管理員可以將虛擬 interface,例如 bridge,tap 等設備添加到某個 namespace。

對於 flat_net 的 DHCP 設備 tap19a0ed3d-fe,需要將其放到 namespace
qdhcp-7bf09be4-8653-4869-84f0-33494f238627 中,但這樣會帶來一個問題:tap19a0ed3d-fe 將無法直接與 root namespace 中的 bridge 設備 brqf153b42f-c3 連接。

Neutron 使用 veth pair 解決了這個問題。

veth pair 是一種成對出現的特殊網絡設備,它們象一根虛擬的網線,可用於連接兩個 namespace。向 veth pair 一端輸入數據,在另一端就能讀到此數據。

tap19a0ed3d-fe 與 ns-19a0ed3d-fe 就是一對 veth pair,它們將
qdhcp-f153b42f-c3a1-4b6c-8865-c09b5b2aa274 連接到 brqf153b42f-c3。

如下圖所示:

雲計算openstack核心組件——neutron網絡服務(9)

可以通過 ip netns exec
qdhcp-7bf09be4-8653-4869-84f0-33494f238627 ip a命令查看ns-ba07bb93配置:

雲計算openstack核心組件——neutron網絡服務(9)

獲取 dhcp IP 過程分析

在創建 instance 時,Neutron 會為其分配一個 port,裡面包含了 MAC 和 IP 地址信息。這些信息會同步更新到 dnsmasq 的 host 文件。如下圖所示:

雲計算openstack核心組件——neutron網絡服務(9)

同時 nova-compute 會設置虛機 VIF 的 MAC 地址。

雲計算openstack核心組件——neutron網絡服務(9)

雲計算openstack核心組件——neutron網絡服務(9)

一切準備就緒,instance 獲取 IP 的過程如下:

1. vm 開機啟動,發出 DHCPDISCOVER 廣播,該廣播消息在整個 net 中都可以被收到。

2. 廣播到達 veth tap19a0ed3d-fe,然後傳送給 veth pair 的另一端 ns-19a0ed3d-fe。dnsmasq 在它上面監聽,dnsmasq 檢查其 host 文件,發現有對應項,於是dnsmasq 以 DHCPOFFER 消息將 IP(192.168.254.18)、子網掩碼(255.255.255.0)、地址租用期限等信息發送給 vm。

3. vm 發送 DHCPREQUEST 消息確認接受此 DHCPOFFER。

4. dnsmasq 發送確認消息 DHCPACK,整個過程結束。

二、VXLAN簡介:

overlay network概念:

overlay network 是指建立在其他網絡上的網絡。overlay network 中的節點可以看作通過虛擬(或邏輯)鏈路連接起來的。overlay network 在底層可能由若干物理鏈路組成,但對於節點,不需要關心這些底層實現。

例如 P2P 網絡就是 overlay network,隧道也是。vxlan 和 gre 都是基於隧道技術實現的,它們也都是 overlay network。

目前 linux bridge 只支持 vxlan,不支持 gre;

open vswitch 兩者都支持。vxlan 與 gre 實現非常類似,而且 vxlan 用得較多,所以本教程只介紹 vxlan。


VXLAN簡介:

VXLAN 為 Virtual eXtensible Local Area Network。正如名字所描述的,VXLAN 提供與 VLAN 相同的以太網二層服務,但擁有更強的擴展性和靈活性。與 VLAN 相比,

VXLAN 有下面幾個優勢:

1. 支持更多的二層網段。

VLAN 使用 12-bit 標記 VLAN ID,最多支持 4094 個 VLAN,這對大型雲部署會成為瓶頸。VXLAN 的 ID (VNI 或者 VNID)則用 24-bit 標記,支持 16777216 個二層網段。

2. 能更好地利用已有的網絡路徑。

VLAN 使用 Spanning Tree Protocol 避免環路,這會導致有一半的網絡路徑被 block 掉。VXLAN 的數據包是封裝到 UDP 通過三層傳輸和轉發的,可以使用所有的路徑。

3. 避免物理交換機 MAC 表耗盡。

由於採用隧道機制,TOR (Top on Rack) 交換機無需在 MAC 表中記錄虛擬機的信息。


VXLAN 封裝和包格式:

VXLAN 是將二層建立在三層上的網絡。通過將二層數據封裝到 UDP 的方式來擴展數據中心的二層網段數量。

VXLAN 是一種在現有物理網絡設施中支持大規模多租戶網絡環境的解決方案。VXLAN 的傳輸協議是 IP + UDP。

VXLAN 定義了一個 MAC-in-UDP 的封裝格式。在原始的 Layer 2 網絡包前加上 VXLAN header,然後放到 UDP 和 IP 包中。通過 MAC-in-UDP 封裝,VXLAN 能夠在 Layer 3 網絡上建立起了一條 Layer 2 的隧道。

VXLAN 包的格式如下:

雲計算openstack核心組件——neutron網絡服務(9)

如上圖所示,VXLAN 引入了 8-byte VXLAN header,其中 VNI 佔 24-bit。VXLAN 和原始的 L2 frame 被封裝到 UDP 包中。這 24-bit 的 VNI 用於標示不同的二層網段,能夠支持 16777216 個 LAN。


VXLAN Tunnel Endpoint

VXLAN 使用 VXLAN tunnel endpoint (VTEP) 設備處理 VXLAN 的封裝和解封。每個 VTEP 有一個 IP interface,配置了一個 IP 地址。VTEP 使用該 IP 封裝 Layer 2 frame,並通過該 IP interface 傳輸和接收封裝後的 VXLAN 數據包。

下面是 VTEP 的示意圖:

雲計算openstack核心組件——neutron網絡服務(9)

VXLAN 獨立於底層的網絡拓撲;反過來,兩個 VTEP 之間的底層 IP 網絡也獨立於 VXLAN。VXLAN 數據包是根據外層的 IP header 路由的,該 header 將兩端的 VTEP IP 作為源和目標 IP。


VXLAN 封裝和轉發包的過程,以及 Linux 對 VXLAN 的原生支持

VXLAN 包轉發流程

VXLAN 在 VTEP 間建立隧道,通過 Layer 3 網絡傳輸封裝後的 Layer 2 數據。下面例子演示了數據如何在 VXLAN 上傳輸:

雲計算openstack核心組件——neutron網絡服務(9)

圖中 Host-A 和 Host-B 位於 VNI 10 的 VXLAN,通過 VTEP-1 和 VTEP-2 之間建立的 VXLAN 隧道通信。數據傳輸過程如下:

1. Host-A 向 Host-B 發送數據時,Host-B 的 MAC 和 IP 作為數據包的目標 MAC 和 IP,Host-A 的 MAC 作為數據包的源 MAC 和 IP,然後通過 VTEP-1 將數據發送出去。

2. VTEP-1 從自己維護的映射表中找到 MAC-B 對應的 VTEP-2,然後執行 VXLAN 封裝,加上 VXLAN 頭,UDP 頭,以及外層 IP 和 MAC 頭。此時的外層 IP 頭,目標地址為 VTEP-2 的 IP,源地址為 VTEP-1 的 IP。同時由於下一跳是 Router-1,所以外層 MAC 頭中目標地址為 Router-1 的 MAC。

3. 數據包從 VTEP-1 發送出後,外部網絡的路由器會依據外層 IP 頭進行路由,最後到達與 VTEP-2 連接的路由器 Router-2。

4. Router-2 將數據包發送給 VTEP-2。VTEP-2 負責解封數據包,依次去掉外層 MAC 頭,外層 IP 頭,UDP 頭 和 VXLAN 頭。VTEP-2 依據目標 MAC 地址將數據包發送給 Host-B。

上面的流程我們看到 VTEP 是 VXLAN 的最核心組件,負責數據的封裝和解封。隧道也是建立在 VTEP 之間的,VTEP 負責數據的傳送。

VTEP 是如何提前獲知 IP -- MAC -- VTEP 相關信息的呢?

答案是:

1. Neutron 知道每一個 port 的狀態和信息; port 保存了 IP,MAC 相關數據。

2. instance 啟動時,其 port 狀態變化過程為:down -> build -> active。

3. 每當 port 狀態發生變化時,Neutron 都會通過 RPC 消息通知各節點上的 Neutron agent,使得 VTEP 能夠更新 VM 和 port 的相關信息。

VTEP 可以根據這些信息判斷出其他 Host 上都有哪些 VM,以及它們的 MAC 地址,這樣就能直接與之通信,從而避免了不必要的隧道連接和廣播。

Linux 對 VXLAN 的支持

VTEP 可以由專有硬件來實現,也可以使用純軟件實現。目前比較成熟的 VTEP 軟件實現包括:

1. 帶 VXLAN 內核模塊的 Linux

2. Open vSwitch

我們先來看 Linux 如何支持 VXLAN

雲計算openstack核心組件——neutron網絡服務(9)

實現方式:

1. Linux vxlan 創建一個 UDP Socket,默認在 8472 端口監聽。

2. Linux vxlan 在 UDP socket 上接收到 vxlan 包後,解包,然後根據其中的 vxlan ID 將它轉給某個 vxlan interface,然後再通過它所連接的 linux bridge 轉給虛機。

3. Linux vxlan 在收到虛機發來的數據包後,將其封裝為多播 UDP 包,從網卡發出。


ML2 mechanism driver: Linux Bridge 和 Open vSwitch

網卡分配示例:

雲計算openstack核心組件——neutron網絡服務(9)

  1. 控制節點三個網卡(eth0, eth1, eth2),計算節點兩網卡(eth0, eth1)。
  2. 合併 Management 和 API 網絡,使用 eth0,IP 段為 192.168.104.0/24。
  3. VM 網絡使用 eht1。
  4. 控制節點的 eth2 與 External 網絡連接,IP 段為 10.10.10.0/24。

Linux Bridge :


雲計算openstack核心組件——neutron網絡服務(9)

Open vSwitch:

雲計算openstack核心組件——neutron網絡服務(9)

Open vSwitch 中的網絡設備:

br-ex:連接外部(external)網絡的網橋。

br-int:集成(integration)網橋,所有 instance 的虛擬網卡和其他虛擬網絡設備都將連接到該網橋。

br-tun:隧道(tunnel)網橋,基於隧道技術的 VxLAN 和 GRE 網絡將使用該網橋進行通信。

tap interface:命名為 tapXXXX。

linux bridge:命名為 qbrXXXX。

veth pair:命名為 qvbXXXX, qvoXXXX

OVS integration bridge:命名為 br-int。

OVS patch ports:命名為 int-br-ethX 和 phy-br-ethX(X 為 interface 的序號)。

OVS provider bridge:命名為 br-ethX(X 為 interface 的序號)。

物理 interface:命名為 ethX(X 為 interface 的序號)。

OVS tunnel bridge:命名為 br-tun。


三、三層網絡介紹:

虛擬機訪問外網

(1)虛擬機中訪問一個外網地址192.168.253.3,並用 traceroute 命令跟蹤路由查看:

雲計算openstack核心組件——neutron網絡服務(9)

(2)根據網絡拓撲,由於虛機訪問外網要經過本網段的網關192.168.101.1,然後經過路由的外網接口轉發出去,到達192.168.253.3

雲計算openstack核心組件——neutron網絡服務(9)

查看路由命名空間:

ip netns list

雲計算openstack核心組件——neutron網絡服務(9)

(3)查看路由命名空間的網絡配置,查到路由連接外網的端口和ip:

ip netns exec qrouter-176bd7e0-6427-46a5-906a-be6a373a29a1 ip a

雲計算openstack核心組件——neutron網絡服務(9)

路由上的外網端口正好接到外網網橋br-ex上:ovs-vsctl show 查看

雲計算openstack核心組件——neutron網絡服務(9)

(4)查看路由iptables NAT 轉發規則,記錄對私網做的SNAT

ip netns exec qrouter-176bd7e0-6427-46a5-906a-be6a373a29a1 iptables -t nat -L

ip netns exec qrouter-176bd7e0-6427-46a5-906a-be6a373a29a1 iptables -t nat -S

雲計算openstack核心組件——neutron網絡服務(9)

規則解釋: -A neutron-l3-agent-snat -o qg-8df29d32-d6 -j SNAT --to-source 192.168.253.65 記錄了流入接口qg-8df29d32-d6 的數據包做SNAT(基於源地址轉發),將源地址修改為192.168.253.65

(5)驗證:

在虛機 ping 192.168.253.3 時, 可以通過 tcpdump 分別觀察 router 兩個 interface 的 icmp 數據包來驗證 SNAT 的行為:

在路由
qrouter-176bd7e0-6427-46a5-906a-be6a373a29a1,可查到私有網絡的網關接口qr-7b56f58b-b5,並在路由中抓取網關接口的icmp包:

ip netns exec qrouter-176bd7e0-6427-46a5-906a-be6a373a29a1 tcpdump -i qr-7b56f58b-b5 -n icmp

雲計算openstack核心組件——neutron網絡服務(9)

在路由中,抓取路由的外網接口qg-8df29d32-d6的icmp包:

ip netns exec qrouter-176bd7e0-6427-46a5-906a-be6a373a29a1 tcpdump -i qg-8df29d32-d6 -n icmp

雲計算openstack核心組件——neutron網絡服務(9)

外網訪問虛機——floating ip原理

SNAT 讓 instance 能夠直接訪問外網,但外網還不能直接訪問 instance。因為 instance 沒有外網 IP。這裡 “直接訪問 instance” 是指通信連接由外網發起,例如從外網 SSH 實例。

(1)首先將實例綁定浮動 ip192.168.253.66, floating IP 是配置在 router 的外網 interface 上的,再查看 router 的 interface 配置:

雲計算openstack核心組件——neutron網絡服務(9)

(2)在實例中ping 192.168.253.3 外網地址,在路由的qr-7b56f58b-b5 接口上,實例訪問外網ip,外網ip將數據包轉發回實例ip;但在路由的qg-8df29d32-d6 接口上,始終是通過 floating IP 192.168.253.66 與外網通信。

雲計算openstack核心組件——neutron網絡服務(9)

(3) 原因是在路由中iptables做了DNA T(基於目的地址轉發),查看 router 的 NAT 規則:

雲計算openstack核心組件——neutron網絡服務(9)

當 router 接收到從外網發來的包,如果目的地址是 floating IP 192.168.254.66,將目的地址修改為實例的 IP 192.168.101.3。這樣外網的包就能送達到實例;

當實例發送數據到外網,源地址 192.168.101.3 將被修改為 floating IP 192.168.253.66;


四:neutron配置文件:

neutron.conf

<code>[DEFAULT]

state_path = /var/lib/neutron

auth_strategy = keystone

core_plugin = ml2

service_plugins = router

dhcp_agent_notification = true

allow_overlapping_ips = True

notify_nova_on_port_status_changes = true

notify_nova_on_port_data_changes = true

transport_url = rabbit://openstack:admin@controller

[agent]

[cors]

[cors.subdomain]

[database]

connection = mysql+pymysql://neutron:NEUTRON_DBPASS@controller/neutron

[keystone_authtoken]

auth_uri = http://controller:5000

auth_url = http://controller:35357

memcached_servers = controller:11211

auth_type = password

project_domain_name = default

user_domain_name = default

project_name = service

username = neutron

password = neutron

[matchmaker_redis]

[nova]

region_name = RegionOne

auth_url = http://controller:35357

auth_type = password

project_domain_name = default

project_name = service

user_domain_name = default

username = nova

password = nova

[oslo_concurrency]

lock_path = $state_path/lock

[oslo_messaging_amqp]

[oslo_messaging_kafka]

[oslo_messaging_notifications]

[oslo_messaging_rabbit]

[oslo_messaging_zmq]

[oslo_middleware]

[oslo_policy]

[qos]

[quotas]

[ssl]/<code>


ml2_conf.ini

<code>[DEFAULT]

[ml2]

type_drivers = flat,vxlan

tenant_network_types = vxlan

mechanism_drivers = openvswitch,l2population

extension_drivers = port_security

[ml2_type_flat]

[ml2_type_geneve]

[ml2_type_gre]

[ml2_type_vlan]

[ml2_type_vxlan]

vni_ranges = 1:1000

[securitygroup]

enable_ipset = true/<code>


openvswitch_agent.ini

<code>[DEFAULT]

[agent]

tunnel_types = vxlan

l2_population = True

[ovs]

tunnel_bridge = br-tun

local_ip = 192.168.254.63

bridge_mappings =

[securitygroup]

firewall_driver = iptables_hybrid

enable_security_group = true

[xenapi]

/<code>


l3_agent.ini

<code>[DEFAULT]

interface_driver = openvswitch

external_network_bridge = br-ex

[agent]

[ovs]/<code>


metadata_agent.ini

<code>[DEFAULT]

nova_metadata_ip = controller

metadata_proxy_shared_secret = METADATA_SECRET

[agent]

[cache]/<code>


dhcp_agent.ini

<code>[DEFAULT]

interface_driver = openvswitch

dhcp_driver = neutron.agent.linux.dhcp.Dnsmasq

enable_isolated_metadata = true

[agent]

[ovs]/<code>


注意:配置完配置文件後,提前準備ovs外網用的網橋,之後同步數據庫,啟動服務:

(控制)

<code>yum install openstack-neutron openstack-neutron-ml2 openvswitch openstack-neutron-openvswitch ebtables -y

systemctl enable neutron-server.service neutron-dhcp-agent.service openvswitch neutron-openvswitch-agent neutron-metadata-agent.service

systemctl start neutron-server.service neutron-dhcp-agent.service openvswitch neutron-openvswitch-agent neutron-metadata-agent.service

ovs-vsctl add-br br-ex

ovs-vsctl add-port br-ex eth2

systemctl enable neutron-l3-agent.service

systemctl start neutron-l3-agent.service/<code>

(計算)

<code>yum install openvswitch openstack-neutron-openvswitch ebtables ipset

systemctl enable openvswitch neutron-openvswitch-agent

systemctl start openvswitch neutron-openvswitch-agent

systemctl stop openvswitch neutron-openvswitch-agent/<code>


分享到:


相關文章: