1)用 namspace 隔離 DHCP 服務node
Neutron 經過 dnsmasq 提供 DHCP 服務,而 dnsmasq 經過 Linux Network Namespace 獨立的爲每一個 network 服務隔離python
在二層網絡上,VLAN 能夠將一個物理交換機分割成幾個獨立的虛擬交換機。相似地,在三層網絡上,Linux network namespace 能夠將一個物理三層網絡分割成幾個獨立的虛擬三層網絡。mysql
每一個 namespace 都有本身獨立的網絡棧,包括 route table,firewall rule,network interface device 等。linux
Neutron 經過 namespace 爲每一個 network 提供獨立的 DHCP 和路由服務,從而容許租戶建立重疊的網絡。若是沒有 namespace,網絡就不能重疊,這樣就失去了不少靈活性。sql
每一個 dnsmasq 進程都位於獨立的 namespace, 命名爲 qdhcp-<network id>,例如 flat_net:數據庫
ip netns list 命令列出全部的 namespace ip netns exec <network namespace name> <command> 管理 namespace
2)root namespacevim
其實,宿主機自己也有一個 namespace,叫 root namespace,擁有全部物理和虛擬 interface device。物理 interface 只能位於 root namespace。api
新建立的 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 鏈接。app
Neutron 使用 veth pair 解決了這個問題。
veth pair 是一種成對出現的特殊網絡設備,它們象一根虛擬的網線,可用於鏈接兩個 namespace。向 veth pair 一端輸入數據,在另外一端就能讀到此數據。
tap19a0ed3d-fe 與 ns-19a0ed3d-fe 就是一對 veth pair,它們將 qdhcp-f153b42f-c3a1-4b6c-8865-c09b5b2aa274 鏈接到 brqf153b42f-c3。
以下圖所示:
能夠經過 ip netns exec qdhcp-7bf09be4-8653-4869-84f0-33494f238627 ip a命令查看ns-ba07bb93配置。
3)獲取 dhcp IP 過程分析
在建立 instance 時,Neutron 會爲其分配一個 port,裏面包含了 MAC 和 IP 地址信息。這些信息會同步更新到 dnsmasq 的 host 文件。以下圖所示:
同時 nova-compute 會設置虛機 VIF 的 MAC 地址。
一切準備就緒,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,整個過程結束。
1)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。
2)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 表中記錄虛擬機的信息。
3)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 包的格式以下
如上圖所示,VXLAN 引入了 8-byte VXLAN header,其中 VNI 佔 24-bit。VXLAN 和原始的 L2 frame 被封裝到 UDP 包中。這 24-bit 的 VNI 用於標示不一樣的二層網段,可以支持 16777216 個 LAN。
4)VXLAN Tunnel Endpoint
VXLAN 使用 VXLAN tunnel endpoint (VTEP) 設備處理 VXLAN 的封裝和解封。每一個 VTEP 有一個 IP interface,配置了一個 IP 地址。VTEP 使用該 IP 封裝 Layer 2 frame,並經過該 IP interface 傳輸和接收封裝後的 VXLAN 數據包。
下面是 VTEP 的示意圖
VXLAN 獨立於底層的網絡拓撲;反過來,兩個 VTEP 之間的底層 IP 網絡也獨立於 VXLAN。VXLAN 數據包是根據外層的 IP header 路由的,該 header 將兩端的 VTEP IP 做爲源和目標 IP。
VXLAN 封裝和轉發包的過程,以及 Linux 對 VXLAN 的原生支持
VXLAN 包轉發流程
VXLAN 在 VTEP 間創建隧道,經過 Layer 3 網絡傳輸封裝後的 Layer 2 數據。下面例子演示了數據如何在 VXLAN 上傳輸
(1)圖中 Host-A 和 Host-B 位於 VNI 10 的 VXLAN,經過 VTEP-1 和 VTEP-2 之間創建的 VXLAN 隧道通訊。數據傳輸過程以下:
a)Host-A 向 Host-B 發送數據時,Host-B 的 MAC 和 IP 做爲數據包的目標 MAC 和 IP,Host-A 的 MAC 做爲數據包的源 MAC 和 IP,而後經過 VTEP-1 將數據發送出去。
b)VTEP-1 從本身維護的映射表中找到 MAC-B 對應的 VTEP-2,而後執行 VXLAN 封裝,加上 VXLAN 頭,UDP 頭,以及外層 IP 和 MAC 頭。此時的外層 IP 頭,目標地址爲 VTEP-2 的 IP,源地址爲 VTEP-1 的 IP。同時因爲下一跳是 Router-1,因此外層 MAC 頭中目標地址爲 Router-1 的 MAC。
c)數據包從 VTEP-1 發送出後,外部網絡的路由器會依據外層 IP 頭進行路由,最後到達與 VTEP-2 鏈接的路由器 Router-2。
d)Router-2 將數據包發送給 VTEP-2。VTEP-2 負責解封數據包,依次去掉外層 MAC 頭,外層 IP 頭,UDP 頭 和 VXLAN 頭。VTEP-2 依據目標 MAC 地址將數據包發送給 Host-B。
上面的流程咱們看到 VTEP 是 VXLAN 的最核心組件,負責數據的封裝和解封。隧道也是創建在 VTEP 之間的,VTEP 負責數據的傳送。
(2)VTEP 是如何提早獲知 IP -- MAC -- VTEP 相關信息的呢?
a)Neutron 知道每個 port 的狀態和信息; port 保存了 IP,MAC 相關數據。
b)instance 啓動時,其 port 狀態變化過程爲:down -> build -> active。
c)每當 port 狀態發生變化時,Neutron 都會經過 RPC 消息通知各節點上的 Neutron agent,使得 VTEP 可以更新 VM 和 port 的相關信息。VTEP 能夠根據這些信息判斷出其餘 Host 上都有哪些 VM,以及它們的 MAC 地址,這樣就能直接與之通訊,從而避免了沒必要要的隧道鏈接和廣播。
(3)Linux 對 VXLAN 的支持
VTEP 能夠由專有硬件來實現,也可使用純軟件實現。目前比較成熟的 VTEP 軟件實現包括:
a)帶 VXLAN 內核模塊的 Linux
b)Open vSwitch
咱們先來看 Linux 如何支持 VXLAN
實現方式:
a)Linux vxlan 建立一個 UDP Socket,默認在 8472 端口監聽。
b)Linux vxlan 在 UDP socket 上接收到 vxlan 包後,解包,而後根據其中的 vxlan ID 將它轉給某個 vxlan interface,而後再經過它所鏈接的 linux bridge 轉給虛機。
c)Linux vxlan 在收到虛機發來的數據包後,將其封裝爲多播 UDP 包,從網卡發出。
網卡分配示例
a)控制節點三個網卡(eth0, eth1, eth2),計算節點兩網卡(eth0, eth1)。
b)合併 Management 和 API 網絡,使用 eth0,IP 段爲 192.168.104.0/24。
c)VM 網絡使用 eht1。
d)控制節點的 eth2 與 External 網絡鏈接,IP 段爲 10.10.10.0/24。
ML2 mechanism driver: Linux Bridge 和 Open vSwitch
Linux Bridge
Open vSwitch
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)虛擬機訪問外網:
(1)虛擬機中訪問一個外網地址192.168.253.3,並用 traceroute 命令跟蹤路由查看
(2)根據網絡拓撲,因爲虛機訪問外網要通過本網段的網關192.168.101.1,而後通過路由的外網接口轉發出去,到達192.168.253.3
查看路由命名空間
ip netns list
(3)查看路由命名空間的網絡配置,查到路由鏈接外網的端口和ip
ip netns exec qrouter-176bd7e0-6427-46a5-906a-be6a373a29a1 ip a
路由上的外網端口正好接到外網網橋br-ex上:ovs-vsctl show 查看
(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
規則解釋: -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
在路由中,抓取路由的外網接口qg-8df29d32-d6的icmp包:
ip netns exec qrouter-176bd7e0-6427-46a5-906a-be6a373a29a1 tcpdump -i qg-8df29d32-d6 -n icmp
2)外網訪問虛機——floating ip原理
SNAT 讓 instance 可以直接訪問外網,但外網還不能直接訪問 instance。由於 instance 沒有外網 IP。這裏 「直接訪問 instance」 是指通訊鏈接由外網發起,例如從外網 SSH 實例。
(1)首先將實例綁定浮動 ip192.168.253.66, floating IP 是配置在 router 的外網 interface 上的,再查看 router 的 interface 配置:
(2)在實例中ping 192.168.253.3 外網地址,在路由的qr-7b56f58b-b5 接口上,實例訪問外網ip,外網ip將數據包轉發回實例ip;但在路由的qg-8df29d32-d6 接口上,始終是經過 floating IP 192.168.253.66 與外網通訊。
(3) 緣由是在路由中iptables作了DNA T(基於目的地址轉發),查看 router 的 NAT 規則
當 router 接收到從外網發來的包,若是目的地址是 floating IP 192.168.254.66,將目的地址修改成實例的 IP 192.168.101.3。這樣外網的包就能送達到實例;
當實例發送數據到外網,源地址 192.168.101.3 將被修改成 floating IP 192.168.253.66;
4.搭建neutron服務
1)環境準備
(1)數據庫準備
create database neutron; grant all privileges on neutron.* to 'neutron'@'localhost' identified by 'NEUTRON_DBPASS'; grant all privileges on neutron.* to 'neutron'@'%' identified by 'NEUTRON_DBPASS';
(2)建立用戶、服務
建立neutron用戶
openstack user create --domain default --password=neutron neutron
+---------------------+----------------------------------+
| Field | Value |
+---------------------+----------------------------------+
| domain_id | default |
| enabled | True |
| id | 99d0fc3a849a4951b92135799fed0673 |
| name | neutron |
| options | {} |
| password_expires_at | None |
+---------------------+----------------------------------+
將cinder用戶角色設置爲admin
openstack role add --project service --user neutron admin
建立cinder服務
openstack service create --name neutron --description "OpenStack Networking" network +-------------+----------------------------------+ | Field | Value | +-------------+----------------------------------+ | description | OpenStack Networking | | enabled | True | | id | 3e79c5a9080043d2b49d06e58affeb76 | | name | neutron | | type | network | +-------------+----------------------------------+
(3)建立neutron服務的endpoint
openstack endpoint create --region RegionOne network public http://node1:9696 +--------------+----------------------------------+ | Field | Value | +--------------+----------------------------------+ | enabled | True | | id | 14cf89b4812a44e9ba657bb04f4b058d | | interface | public | | region | RegionOne | | region_id | RegionOne | | service_id | 3e79c5a9080043d2b49d06e58affeb76 | | service_name | neutron | | service_type | network | | url | http://node1:9696 | +--------------+----------------------------------+ openstack endpoint create --region RegionOne network internal http://node1:9696 +--------------+----------------------------------+ | Field | Value | +--------------+----------------------------------+ | enabled | True | | id | e521a19f51f44a9a823361cb570b982f | | interface | internal | | region | RegionOne | | region_id | RegionOne | | service_id | 3e79c5a9080043d2b49d06e58affeb76 | | service_name | neutron | | service_type | network | | url | http://node1:9696 | +--------------+----------------------------------+ openstack endpoint create --region RegionOne network admin http://node1:9696 +--------------+----------------------------------+ | Field | Value | +--------------+----------------------------------+ | enabled | True | | id | b2a4f6dc0289426291317b80265145fc | | interface | admin | | region | RegionOne | | region_id | RegionOne | | service_id | 3e79c5a9080043d2b49d06e58affeb76 | | service_name | neutron | | service_type | network | | url | http://node1:9696 | +--------------+----------------------------------+
2)配置網絡相關
(1)安裝相關軟件包
yum install openstack-neutron openstack-neutron-ml2 openvswitch openstack-neutron-openvswitch ebtables -y
(2)修改neutron配置文件
vim /etc/neutron/neutron.conf [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@node1 ... [database] connection = mysql+pymysql://neutron:NEUTRON_DBPASS@node1/neutron ... [keystone_authtoken] auth_uri = http://node1:5000 auth_url = http://node1:35357 memcached_servers = node1:11211 auth_type = password project_domain_name = default user_domain_name = default project_name = service username = neutron password = neutron ... [nova] region_name = RegionOne auth_url = http://node1: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 ...
(3)修改Modular Layer 2 (ML2) plug-in配置文件
vim /etc/neutron/plugins/ml2/ml2_conf.ini [ml2] type_drivers = flat,vxlan tenant_network_types = vxlan mechanism_drivers = openvswitch,l2population extension_drivers = port_security ... [ml2_type_vxlan] vni_ranges = 1:1000 ... [securitygroup] enable_ipset = true
(4)修改openvswitch_agent配置文件
vim /etc/neutron/plugins/ml2/openvswitch_agent.ini ... [agent] tunnel_types = vxlan l2_population = True ... [ovs] tunnel_bridge = br-tun local_ip = 192.168.192.134(租戶網的網卡ip) bridge_mappings = ... [securitygroup] firewall_driver = iptables_hybrid enable_security_group = true ...
(5)修改layer-3 agent配置文件
vim /etc/neutron/l3_agent.ini [DEFAULT] interface_driver = openvswitch external_network_bridge = br-ex ...
(6)修改metadata_agent配置文件
vim /etc/neutron/metadata_agent.ini [DEFAULT] nova_metadata_ip = node1 metadata_proxy_shared_secret = METADATA_SECRET ...
(7)修改dhcp_agent配置文件
vim /etc/neutron/dhcp_agent.ini [DEFAULT] interface_driver = openvswitch dhcp_driver = neutron.agent.linux.dhcp.Dnsmasq enable_isolated_metadata = true ...
3)配置計算服務使用網絡服務
vim /etc/nova/nova.conf ... [neutron] url = http://node1:9696 auth_url = http://node1:35357 auth_type = password project_domain_name = default user_domain_name = default region_name = RegionOne project_name = service username = neutron password = neutron service_metadata_proxy = true metadata_proxy_shared_secret = METADATA_SECRET ...
4)建立軟鏈接
ln -s /etc/neutron/plugins/ml2/ml2_conf.ini /etc/neutron/plugin.ini
5)同步數據庫
su -s /bin/sh -c "neutron-db-manage --config-file /etc/neutron/neutron.conf \ --config-file /etc/neutron/plugins/ml2/ml2_conf.ini upgrade head" neutron
6)啓動服務
systemctl restart openstack-nova-api.service systemctl start neutron-server.service neutron-dhcp-agent.service openvswitch \ neutron-openvswitch-agent neutron-metadata-agent.service systemctl enable neutron-server.service neutron-dhcp-agent.service openvswitch \ neutron-openvswitch-agent neutron-metadata-agent.service
7)添加一塊網卡並設置禁止獲取IP、創建網橋
vim /etc/sysconfig/network-scripts/ifcfg-ens38 TYPE=Ethernet NAME=ens38 UUID=be119028-7b80-312f-85cd-ed1ea343254e ONBOOT=yes DEVICE=ens38 IPV6INIT=no
ovs-vsctl add-br br-ex ovs-vsctl add-port br-ex ens38 ovs-vsctl show f6f8d962-bbe0-4dc8-9582-a5d041145cc8 Manager "ptcp:6640:127.0.0.1" is_connected: true Bridge br-tun Controller "tcp:127.0.0.1:6633" is_connected: true fail_mode: secure Port br-tun Interface br-tun type: internal Port patch-int Interface patch-int type: patch options: {peer=patch-tun} Bridge br-int Controller "tcp:127.0.0.1:6633" is_connected: true fail_mode: secure Port patch-tun Interface patch-tun type: patch options: {peer=patch-int} Port br-int Interface br-int type: internal Bridge br-ex Port "ens38" Interface "ens38" Port br-ex Interface br-ex type: internal ovs_version: "2.9.0"
8)配置計算節點
(1)安裝相關軟件包
yum install openvswitch openstack-neutron-openvswitch ebtables ipset -y
(2)配置neutron配置文件
vim /etc/neutron/neutron.conf [DEFAULT] auth_strategy = keystone transport_url = rabbit://openstack:admin@node1 ... [keystone_authtoken] auth_uri = http://node1:5000 auth_url = http://node1:35357 memcached_servers = node1:11211 auth_type = password project_domain_name = default user_domain_name = default project_name = service username = neutron password = neutron ... [oslo_concurrency] lock_path = $state_path/lock ...
(3)配置網絡相關服務
vim /etc/neutron/plugins/ml2/openvswitch_agent.ini ... [agent] tunnel_types = vxlan l2_population = True ... [ovs] tunnel_bridge = br-tun local_ip = 192.168.192.135 bridge_mappings = ... [securitygroup] firewall_driver = iptables_hybrid enable_security_group = true
(4)配置計算服務使用網絡服務
vim /etc/nova/nova.conf ... [neutron] url = http://node1:9696 auth_url = http://node1:35357 auth_type = password project_domain_name = default user_domain_name = default region_name = RegionOne project_name = service username = neutron password = neutron service_metadata_proxy = true metadata_proxy_shared_secret = METADATA_SECRET ...
(5)啓動相關服務
systemctl restart openstack-nova-compute.service systemctl enable openvswitch neutron-openvswitch-agent systemctl start openvswitch neutron-openvswitch-agent