欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報(bào)邀請(qǐng)碼778899分享:云計(jì)算之OpenStack核心

柚子快報(bào)邀請(qǐng)碼778899分享:云計(jì)算之OpenStack核心

http://yzkb.51969.com/

云計(jì)算之OpenStack核心

一、OpenStack架構(gòu)1.1 OpenStack概念架構(gòu)1.2 OpenStack邏輯架構(gòu)1.3 拓?fù)洳渴?.4 使用OpenStack CLI1.4.1 OpenStack 服務(wù)都有自己的 CLI

二、OpenStack核心服務(wù)2.1 認(rèn)證服務(wù)Keystone2.1.1 基本功能2.1.2 基本概念2.1.3 舉例說明:admin用戶查看Project中的image

2.2 鏡像服務(wù)Image2.2.1 基本概念2.2.2 Glance架構(gòu)2.2.2.1 glance-api2.2.2.2 glance-registry2.2.2.3 Database2.2.2.4 Store backend

2.2.3 Glance操作2.2.3.1 Web UI操作2.2.3.1.1 Web UI 創(chuàng)建 image2.2.3.1.2 Web UI 刪除 image

2.2.3.2 CLI操作2.2.3.2.1 CLI 創(chuàng)建 image2.2.3.2.2 CLI 刪除 image

2.2.4 如何 Troubleshooting

2.3 計(jì)算服務(wù)Nova2.3.1 Nova架構(gòu)2.3.1.1 API2.3.1.2 Compute Core2.3.1.3 Console Interface2.3.1.4 Database2.3.1.5 Message Queue

2.3.2 Nova 物理部署方案2.3.3 從虛機(jī)創(chuàng)建流程看 nova-* 子服務(wù)如何協(xié)同工作2.3.4 OpenStack 通用設(shè)計(jì)思路2.3.4.1 API 前端服務(wù)2.3.4.2 Scheduler 調(diào)度服務(wù)2.3.4.3 Worker工作服務(wù)2.3.4.4 Driver 框架2.3.4.5 Messaging 服務(wù)2.3.4.6 Database

2.3.5 Nova 組件詳解2.3.5.1 nova-api2.3.5.2 nova-conductor2.3.5.3 nova-scheduler2.3.5.4 nova-compute

2.3.6 看懂 OpenStack 日志2.3.6.1 日志位置2.3.6.2 日志類型2.3.6.3 日志格式2.3.6.4 日志說明

2.3.7 虛擬機(jī)生命周期管理2.3.7.1 Launch-部署虛擬機(jī)2.3.7.2 Shut Off-關(guān)閉虛擬機(jī)2.3.7.3 Start-啟動(dòng)虛擬機(jī)2.3.7.4 Soft/Hard Reboot-軟/硬重啟虛擬機(jī)2.3.7.5 Lock/Unlock-加鎖/解鎖虛擬機(jī)2.3.7.6 Terminate -刪除虛擬機(jī)2.3.7.7 Pause/Resume-暫停(短時(shí)間)/恢復(fù)(暫停后的恢復(fù),非故障時(shí)恢復(fù))虛擬機(jī)2.3.7.8 Suspend/Resume-暫停(長時(shí)間)/恢復(fù)(暫停后的恢復(fù),非故障時(shí)恢復(fù))虛擬機(jī)2.3.7.9 Rescue/Unrescue-恢復(fù)(發(fā)生故障時(shí)恢復(fù))/重新引導(dǎo)虛擬機(jī)2.3.7.10 Snapshot -創(chuàng)建虛擬機(jī)快照2.3.7.11 Rebuild -通過快照恢復(fù)虛擬機(jī)2.3.7.12 Shelve-擱置虛擬機(jī)2.3.7.13 Unshelve-取消擱置虛擬機(jī)2.3.7.14 Migrate -遷移虛擬機(jī)2.3.7.15 Resize-調(diào)整虛擬機(jī)的vCPU、內(nèi)存和磁盤資源2.3.7.16 Live Migrate-在線遷移虛擬機(jī)2.3.7.17 Evacuate-撤離虛擬機(jī)2.3.7.18 Nova操作總結(jié)

2.4 塊存儲(chǔ)服務(wù)Cinder:為 instance 提供虛擬磁盤2.4.1 Cider架構(gòu)2.4.2 物理部署方案2.4.3 Cinder設(shè)計(jì)思想2.4.4 Cinder 組件詳解2.4.4.1 cinder-api2.4.4.2 cinder-scheduler2.4.4.3 cinder-volume

2.4.5 通過場(chǎng)景學(xué)習(xí)Cinder2.4.5.1 準(zhǔn)備LVM Volume Provider2.4.5.2 創(chuàng)建volume2.4.5.3 Attach附加磁盤2.4.5.4 Detach卸載磁盤2.4.5.5 Extend擴(kuò)展磁盤2.4.5.6 Delete刪除磁盤2.4.5.7 Snapshot磁盤快照2.4.5.8 Backup磁盤備份2.4.5.9 restore磁盤恢復(fù)2.4.5.10 Boot From Volume 將Volume作為虛擬機(jī)的啟動(dòng)盤2.4.5.11 NFS Volume Provider

2.5 網(wǎng)絡(luò)服務(wù)Neutron2.5.1 Neutron概述2.5.1.1 Neutron功能2.5.1.2 Neutron網(wǎng)絡(luò)基本概念

2.5.2 Neutron架構(gòu)2.5.2.1 Neutron組件概括2.5.2.2 Neutron物理部署方案

2.5.3 Neutron組件詳細(xì)說明2.5.3.1 Neutron Server2.5.3.2 Neutron如何支持多種network provider2.5.3.3 ML2 Core Plugin2.5.3.4 Service Plugin/Agent2.5.3.5 小結(jié)

2.5.4 為Neutron準(zhǔn)備底層基礎(chǔ)設(shè)施2.5.5 Linux Bridge實(shí)現(xiàn)Neutron網(wǎng)絡(luò)2.5.5.1 配置 Linux-Bridge Mechanism Driver2.5.5.2 初始網(wǎng)絡(luò)狀態(tài)2.5.5.3 local network2.5.5.4 flat network2.5.5.5 DHCP服務(wù)2.5.5.6 vlan network2.5.5.7 Routing2.5.5.8 vxlan network2.5.5.9 Security Group2.5.5.10 Firewall as a Service2.5.5.11 Load Balancing as a Service

2.5.6 Open vSwitch實(shí)現(xiàn)Neutron網(wǎng)絡(luò)2.5.6.1 local network2.5.6.2 flat network2.5.6.3 vlan network2.5.6.4 Routing2.5.6.5 vxlan network

一、OpenStack架構(gòu)

1.1 OpenStack概念架構(gòu)

中間菱形:是虛擬機(jī),圍繞 VM 的那些長方形代表 OpenStack 不同的模塊或服務(wù);Nova(計(jì)算服務(wù),核心服務(wù)):管理 管理計(jì)算資源,是 OpenStack 中最核心的服務(wù);Neutron(網(wǎng)絡(luò)服務(wù),核心服務(wù)):為 OpenStack 提供網(wǎng)絡(luò)連接服務(wù),負(fù)責(zé)創(chuàng)建和管理L2、L3 網(wǎng)絡(luò), 為 VM 提供虛擬網(wǎng)絡(luò)和物理網(wǎng)絡(luò)連接;Glance(鏡像服務(wù),核心服務(wù)):管理 VM 的啟動(dòng)鏡像,Nova 創(chuàng)建 VM 時(shí)將使用 Glance 提供的鏡像;Cinder(塊存儲(chǔ),核心服務(wù)):為 VM 提供塊存儲(chǔ)服務(wù)。Cinder 提供的每一個(gè) Volume 在 VM 看來是一塊虛擬硬盤,一般用作數(shù)據(jù)盤;Swift(對(duì)象存儲(chǔ),可選服務(wù)):提供對(duì)象存儲(chǔ)服務(wù)。VM 可以通過 RESTful API 存放對(duì)象數(shù)據(jù);作為可選的方案,Glance 可以將鏡像存放在 Swift 中;Cinder 也可以將 Volume 備份到 Swift 中;Keystone(認(rèn)證服務(wù),核心服務(wù)):為 OpenStack 的各種服務(wù)提供認(rèn)證和權(quán)限管理服務(wù)。簡單的說,OpenStack 上的每一個(gè)操作都必須通過 Keystone 的審核;Ceilometer(監(jiān)控服務(wù),可選服務(wù)):提供 OpenStack監(jiān)控和計(jì)量服務(wù),為報(bào)警、統(tǒng)計(jì)或計(jì)費(fèi)提供數(shù)據(jù);Horizon:為 OpenStack 用戶提供一個(gè) Web操作界面;

1.2 OpenStack邏輯架構(gòu)

在邏輯架構(gòu)中,可以看到每個(gè)服務(wù)又由若干組件組成: 上圖邏輯架構(gòu)中,以 Neutron 服務(wù)為例,描述了各個(gè)組成部分以及各組件之間的邏輯關(guān)系。 而在實(shí)際的部署方案上,各個(gè)組件可以部署到不同的物理節(jié)點(diǎn)上。OpenStack 本身是一個(gè)分布式系統(tǒng),不但各個(gè)服務(wù)可以分布部署,服務(wù)中的組件也可以分布部署。 這種分布式特性讓 OpenStack 具備極大的靈活性、伸縮性和高可用性。

1.3 拓?fù)洳渴?/p>

OpenStack 是一個(gè)分布式系統(tǒng),由若干不同功能的節(jié)點(diǎn)(Node)組成: 1)控制節(jié)點(diǎn)(Controller Node):管理 OpenStack,其上運(yùn)行的服務(wù)有 Keystone、Glance、Horizon 以及 Nova 和 Neutron 中管理相關(guān)的組件。 控制節(jié)點(diǎn)也運(yùn)行支持 OpenStack 的服務(wù),例如 SQL 數(shù)據(jù)庫(通常是 MySQL)、消息隊(duì)列(通常是 RabbitMQ)和網(wǎng)絡(luò)時(shí)間服務(wù) NTP。 2)計(jì)算節(jié)點(diǎn)(Compute Node):其上運(yùn)行 Hypervisor(默認(rèn)使用 KVM)。 同時(shí)運(yùn)行 Neutron 服務(wù)的 agent,為虛擬機(jī)提供網(wǎng)絡(luò)支持。 3) 網(wǎng)絡(luò)節(jié)點(diǎn)(Network Node):其上運(yùn)行的服務(wù)為 Neutron。 為 OpenStack 提供 L2 和 L3 網(wǎng)絡(luò)。 包括虛擬機(jī)網(wǎng)絡(luò)、DHCP、路由、NAT 等。 4) 存儲(chǔ)節(jié)點(diǎn)(Storage Node):提供塊存儲(chǔ)(Cinder)或?qū)ο蟠鎯?chǔ)(Swift)服務(wù)。這幾類節(jié)點(diǎn)是從功能上進(jìn)行的邏輯劃分,在實(shí)際部署時(shí)可以根據(jù)需求靈活配置,比如:在大規(guī)模OpenStack生產(chǎn)環(huán)境中,每類節(jié)點(diǎn)都分別部署在若干臺(tái)物理服務(wù)器上,各司其職并互相協(xié)作。 這樣的環(huán)境具備很好的性能、伸縮性和高可用性。在最小的實(shí)驗(yàn)環(huán)境中,可以將 4 類節(jié)點(diǎn)部署到一個(gè)物理的甚至是虛擬服務(wù)器上,通常也稱為 All-in-One 部署。在我們的實(shí)驗(yàn)環(huán)境中,為了使得拓?fù)浜啙嵧瑫r(shí)功能完備,我們用兩個(gè)虛擬機(jī): devstack-controller: 控制節(jié)點(diǎn) + 網(wǎng)絡(luò)節(jié)點(diǎn) + 塊存儲(chǔ)節(jié)點(diǎn) + 計(jì)算節(jié)點(diǎn) devstack-compute: 計(jì)算節(jié)點(diǎn) 物理資源需求,可根據(jù)實(shí)際需求動(dòng)態(tài)調(diào)整: 網(wǎng)絡(luò)規(guī)劃: 網(wǎng)絡(luò)上規(guī)劃了三個(gè)網(wǎng)絡(luò) 1)Management Network:用于 OpenStack 內(nèi)部管理用,比如各服務(wù)之間通信。 這里使用 eth0; 2)VM(Tenant)Network:OpenStack 部署的虛擬機(jī)所使用的網(wǎng)絡(luò)。OpenStack 支持多租戶(Tenant),虛機(jī)是放在 Tenant 下的,所以叫 Tenant Network。 這里使用 eth1; 3)External Network:一般來說,Tenant Network 是內(nèi)部私有網(wǎng)絡(luò),只用于 VM 之間通信,與其他非 VM 網(wǎng)絡(luò)是隔離的。這里我們規(guī)劃了一個(gè)外部網(wǎng)絡(luò)(External Network),通過 devstak-controller 的 eth2 連接。 Neutron 通過 L3 服務(wù)讓 VM 能夠訪問到 External Network。對(duì)于公有云,External Network 一般指的是 Internet。對(duì)于企業(yè)私有云,External Network 則可以是 Intranet 中的某個(gè)網(wǎng)絡(luò)。創(chuàng)建虛擬機(jī):按照物理資源需求創(chuàng)建 devstack-controller 和 devstak-compute 虛擬機(jī): 安裝操作系統(tǒng) 安裝 Ubuntu 14.04,并配置 eth0 的 IP,如下所示:

控制節(jié)點(diǎn) devstack-controller 192.168.104.10

計(jì)算節(jié)點(diǎn) devstak-compute 192.168.104.11

參考:https://www.xjimmy.com/openstack-5min-17.html

1.4 使用OpenStack CLI

1.4.1 OpenStack 服務(wù)都有自己的 CLI

命令很好記,就是服務(wù)的名字,比如 Glance 就是 glance,Nova 就是 nova。但 Keystone 比較特殊,現(xiàn)在是用 openstack 來代替老版的 keystone 命令。比如查詢用戶列表,如果用 keystone user-list: 會(huì)提示 keystone 已經(jīng) deprecated 了,用 openstack user list 命令代替: 執(zhí)行命令之前,需要設(shè)置環(huán)境變量: 這些變量包含用戶名、Project、密碼等; 如果不設(shè)置,每次執(zhí)行命令都必須設(shè)置相關(guān)的命令行參數(shù)各個(gè)服務(wù)的命令都有增、刪、改、查的操作,其格式是:

CMD -create [parm1] [parm2]…

CMD -delete [parm]

CMD -update [parm1] [parm2]…

CMD -list

CMD -show [parm]

例如 glance 管理的是 image,那么:CMD 就是 glance;obj 就是 image,對(duì)應(yīng)的命令就有:

glance image-create

glance image-delete

glance image-update

glance image-list

glance image-show

再比如 neutron 管理的是網(wǎng)絡(luò)和子網(wǎng)等,那么: CMD 就是 neutron;obj 就是 net 和 subnet :

# 網(wǎng)絡(luò)相關(guān)操作

neutron net-create

neutron net -delete

neutron net -update

neutron net -list

neutron net –show

# 子網(wǎng)相關(guān)操作

neutron subnet-create

neutron subnet -delete

neutron subnet -update

neutron subnet -list

neutron subnet–show

有的命令 可以省略,比如 nova,下面的操作都是針對(duì) instance:

nova boot

nova delete

nova list

nova show

沒個(gè)對(duì)象都有ID:delete,show 等操作都以 ID 為參數(shù),例如: 可用 help 查看命令的用法,除了 delete,show 等操作只需要 ID 一個(gè)參數(shù),其他操作可能需要更多的參數(shù),用 help 查看所需的參數(shù),格式是:

CMD help [SUB-CMD]

例如查看 glance 都有哪些 SUB-CMD: 查看 glance image-update 的用法:

二、OpenStack核心服務(wù)

2.1 認(rèn)證服務(wù)Keystone

2.1.1 基本功能

作為 OpenStack 的基礎(chǔ)支持服務(wù),Keystone 做下面這幾件事情: 1)管理用戶及其權(quán)限; 2)維護(hù) OpenStack Services 的 Endpoint; 3)Authentication(認(rèn)證)和 Authorization(鑒權(quán))。

2.1.2 基本概念

user:指代任何使用 OpenStack 的實(shí)體,可以是真正的用戶,其他系統(tǒng)或者服務(wù),當(dāng) User 請(qǐng)求訪問 OpenStack 時(shí),Keystone 會(huì)對(duì)其進(jìn)行驗(yàn)證; Horizon 在 Identity->Users 管理 User: 除了 admin 和 demo,OpenStack 也為 nova、cinder、glance、neutron 服務(wù)創(chuàng)建了相應(yīng)的 User。 admin 也可以管理這些 User。 Credentials:Credentials 是 User 用來證明自己身份的信息,可以是: 1. 用戶名/密碼 2. Token 3. API Key 4. 其他高級(jí)方式。Authentication: 是 Keystone 驗(yàn)證 User 身份的過程。User 訪問 OpenStack 時(shí)向 Keystone 提交用戶名和密碼形式的 Credentials,Keystone 驗(yàn)證通過后會(huì)給 User 簽發(fā)一個(gè) Token 作為后續(xù)訪問的 Credential。Token:Token 是由數(shù)字和字母組成的字符串,User 成功 Authentication 后由 Keystone 分配給 User。Token 用做訪問 Service 的 Credential;Service 會(huì)通過 Keystone 驗(yàn)證 Token 的有效性;Token 的有效期默認(rèn)是 24 小時(shí)。Project: 用于將 OpenStack 的資源(計(jì)算、存儲(chǔ)和網(wǎng)絡(luò))進(jìn)行分組和隔離。根據(jù) OpenStack 服務(wù)的對(duì)象不同,Project 可以是一個(gè)客戶(公有云,也叫租戶)、部門或者項(xiàng)目組(私有云)。這里請(qǐng)注意:資源的所有權(quán)是屬于 Project 的,而不是 User。在 OpenStack 的界面和文檔中,Tenant / Project / Account 這幾個(gè)術(shù)語是通用的,但長期看會(huì)傾向使用 Project。每個(gè) User(包括 admin)必須掛在 Project 里才能訪問該 Project 的資源。 一個(gè)User可以屬于多個(gè) Project。admin 相當(dāng)于 root 用戶,具有最高權(quán)限 Horizon 在 Identity->Projects 中管理 Project: 通過 Manage Members 將 User 添加到 Project 中: Service:OpenStack 的 Service 包括 Compute (Nova)、Block Storage (Cinder)、Object Storage (Swift)、Image Service (Glance) 、Networking Service (Neutron) 等。每個(gè) Service 都會(huì)提供若干個(gè) Endpoint,User 通過 Endpoint 訪問資源和執(zhí)行操作。Endpoint:Endpoint 是一個(gè)網(wǎng)絡(luò)上可訪問的地址,通常是一個(gè) URL。Service 通過 Endpoint 暴露自己的 API。Keystone 負(fù)責(zé)管理和維護(hù)每個(gè) Service 的 Endpoint。 可以使用下面的命令來查看 Endpoint:

root@devstack-controller:~# source devstack/openrc admin admin //切換用戶

root@devstack-controller:~# openstack catalog list //查詢服務(wù)的Endpoint

Role:安全包含兩部分:Authentication(認(rèn)證)和 Authorization(鑒權(quán))。Keystone 是借助 Role 來實(shí)現(xiàn) Authorization 的。 Keystone定義Role: 可以為 User 分配一個(gè)或多個(gè) Role,Horizon 的菜單為 Identity->Project->Manage Members: Service 決定每個(gè) Role 能做什么事情 Service 通過各自的 policy.json 文件對(duì) Role 進(jìn)行訪問控制。下面是 Nova 服務(wù) /etc/nova/policy.json 中的示例: 上面配置的含義是:對(duì)于 create、attach_network 和 attach_volume 操作,任何Role的 User 都可以執(zhí)行; 但只有 admin 這個(gè) Role 的 User 才能執(zhí)行 forced_host 操作。OpenStack 默認(rèn)配置只區(qū)分 admin 和非 admin Role。 如果需要對(duì)特定的 Role 進(jìn)行授權(quán),可以修改 policy.json。

2.1.3 舉例說明:admin用戶查看Project中的image

登錄:賬號(hào)密碼為admin/admin,點(diǎn)擊“Connect”: 此時(shí)OpenStack 內(nèi)部發(fā)生了哪些事情?請(qǐng)看下面:Token 中包含了 User 的 Role 信息。 顯示操作界面:請(qǐng)注意,頂部顯示 admin 可訪問的 Project 為 “admin” 和 “demo”。 在此之前發(fā)生了什么事情: 同時(shí),admin 可以訪問 Intance, Volume, Image 等服務(wù) 因?yàn)?admin 已經(jīng)從 Keystone 拿到了各 Service 的 Endpoints 顯示image列表:點(diǎn)擊 “Images”,會(huì)顯示 image 列表; 背后發(fā)生了這些事:首先,admin 將請(qǐng)求發(fā)送到 Glance 的 Endpoint: Glance 向 Keystone 詢問 admin 身份的有效性: 接下來 Glance 會(huì)查看 /etc/glance/policy.json,判斷 admin 是否有查看 image 的權(quán)限: 權(quán)限判定通過,Glance 將 image 列表發(fā)給 admin。Troubleshoot :OpenStack 排查問題的方法主要是通過日志,每個(gè) Service 都有自己的日志文件。Keystone 主要有兩個(gè)日志:keystone.log 和 keystone_access.log,保存在 /var/log/apache2/ 目錄里。 devstack 的 screen 窗口已經(jīng)幫我們打開了這兩個(gè)日志。可以直接查看: 如果需要得到最詳細(xì)的日志信息,可以在 /etc/keystone/keystone.conf 中打開 debug 選項(xiàng): 在非 devstack 安裝中,日志可能在 /var/log/keystone/ 目錄里。

2.2 鏡像服務(wù)Image

2.2.1 基本概念

在傳統(tǒng) IT 環(huán)境下,安裝一個(gè)系統(tǒng)是要么從安裝 CD 從頭安裝,要么用 Ghost 等克隆工具恢復(fù),這兩種方式有如下幾個(gè)問題: 1)如果要安裝的系統(tǒng)多了效率就很低; 2)時(shí)間長,工作量大; 3)安裝完還要進(jìn)行手工配置,比如安裝其他的軟件,設(shè)置 IP 等; 4)備份和恢復(fù)系統(tǒng)不靈活。云環(huán)境下需要更高效的解決方案,這就是 Image: Image 是一個(gè)模板,里面包含了基本的操作系統(tǒng)和其他的軟件。 舉例來說,有家公司需要為每位員工配置一套辦公用的系統(tǒng),一般需要一個(gè) Win7 系統(tǒng)再加 MS office 軟件。 OpenStack 是這么玩的,先手工安裝好這么一個(gè)虛機(jī);然后對(duì)虛機(jī)執(zhí)行 snapshot,這樣就得到了一個(gè) image;當(dāng)有新員工入職需要辦公環(huán)境時(shí),立馬啟動(dòng)一個(gè)或多個(gè)該 image 的 instance(虛機(jī))就可以了。在這個(gè)過程中,第 1 步跟傳統(tǒng)方式類似,需要手工操作和一定時(shí)間。但第 2、3 步非???,全自動(dòng)化,一般都是秒級(jí)別。而且 2、3 步可以循環(huán)做。比如公司新上了一套 OA 系統(tǒng),每個(gè)員工的 PC 上都得有客戶端軟件。 那么可以在某個(gè)員工的虛機(jī)中手工安裝好 OA 客戶端,然后執(zhí)行snapshot ,得到新的 image,以后就直接使用新 image 創(chuàng)建虛機(jī)就可以了。另外,snapshot 還有備份的作用,能夠非常方便的恢復(fù)系統(tǒng)。Image Service 的功能是管理 Image,讓用戶能夠發(fā)現(xiàn)、獲取和保存 Image。在 OpenStack 中,提供 Image Service 的是 Glance,其具體功能如下: 1)提供 REST API 讓用戶能夠查詢和獲取 image 的元數(shù)據(jù)和 image 本身; 2)支持多種方式存儲(chǔ) image,包括普通的文件系統(tǒng)、Swift、Amazon S3 等; 3)對(duì) Instance 執(zhí)行 Snapshot 創(chuàng)建新的 image。

2.2.2 Glance架構(gòu)

2.2.2.1 glance-api

glance-api 是系統(tǒng)后臺(tái)運(yùn)行的服務(wù)進(jìn)程。 對(duì)外提供 REST API,響應(yīng) image 查詢、獲取和存儲(chǔ)的調(diào)用。glance-api 不會(huì)真正處理請(qǐng)求。如果是與 image metadata(元數(shù)據(jù))相關(guān)的操作,glance-api 會(huì)把請(qǐng)求轉(zhuǎn)發(fā)給 glance-registry;如果是與 image 自身存取相關(guān)的操作,glance-api 會(huì)把請(qǐng)求轉(zhuǎn)發(fā)給該 image 的 store backend。在控制節(jié)點(diǎn)上可以查看 glance-api 進(jìn)程:

2.2.2.2 glance-registry

glance-registry 是系統(tǒng)后臺(tái)運(yùn)行的服務(wù)進(jìn)程。負(fù)責(zé)處理和存取 image 的 metadata,例如 image 的大小和類型。在控制節(jié)點(diǎn)上可以查看 glance-registry 進(jìn)程: Glance 支持多種格式的 image,包括:

2.2.2.3 Database

Image 的 metadata 會(huì)保存到 database 中,默認(rèn)是 MySQL。在控制節(jié)點(diǎn)上可以查看 glance 的 database 信息:

2.2.2.4 Store backend

Glance 自己并不存儲(chǔ) image。 真正的 image 是存放在 backend 中的。 Glance 支持多種 backend,包括: 1)A directory on a local file system(這是默認(rèn)配置); 2)GridFS; 3)Ceph RBD; 4)Amazon S3; 5)Sheepdog; 6)OpenStack Block Storage (Cinder); 7)OpenStack Object Storage (Swift); 8)VMware ESX。 具體使用哪種 backend,是在 /etc/glance/glance-api.conf 中配置的,在我們的 devstack 環(huán)境中,image 存放在控制節(jié)點(diǎn)本地目錄 /opt/stack/data/glance/images/ 中: 其他 backend 的配置可參考:https://docs.openstack.org/liberty/config-reference/content/configuring-image-service-backends.html查看目前已經(jīng)存在的 image使用glance image-list: 查看保存目錄:每個(gè) image 在目錄下都對(duì)應(yīng)有一個(gè)文件,文件以 image 的 ID 命名。

2.2.3 Glance操作

OpenStack 為終端用戶提供了 Web UI(Horizon)和命令行 CLI 兩種方式創(chuàng)建Image。

2.2.3.1 Web UI操作

2.2.3.1.1 Web UI 創(chuàng)建 image

admin 登錄后,Project -> Compute -> Images: 點(diǎn)擊右上角“Create Image”按鈕,為新 image 命名: 這里我們上傳一個(gè) image。 點(diǎn)擊“瀏覽”,選擇鏡像文件 cirros-0.3.4-x86_64-disk.img。cirros 是一個(gè)很小的 linux 鏡像,非常適合測(cè)試用。 可以到http://download.cirros-cloud.net/下載。 格式選擇 QCOW2: 如果勾選“Public”,該 image 可以被其他 Project 使用;如果勾選“Protected”,該 image 不允許被刪除。 點(diǎn)擊“Create Image”,文件上傳到 OpenStack 并創(chuàng)建新的 image: 點(diǎn)擊 image 的“cirros鏈接”: 顯示詳細(xì)信息

2.2.3.1.2 Web UI 刪除 image

admin 登錄后,Project -> Compute -> Images: 點(diǎn)擊“Delete Images”確認(rèn)刪除,操作成功:

2.2.3.2 CLI操作

2.2.3.2.1 CLI 創(chuàng)建 image

cirros 這個(gè) linux 鏡像很小,通過 Web UI 上傳很快,操作會(huì)很順暢。 但如果我們要上傳的鏡像比較大(比如好幾個(gè) G ),那么操作會(huì)長時(shí)間停留在上傳的 Web 界面,我們也不知道目前到底處于什么狀態(tài)。對(duì)于這樣的操作,CLI 是更好的選擇。將 image 上傳到控制節(jié)點(diǎn)的文件系統(tǒng)中,例如 /tmp/cirros-0.3.4-x86_64-disk.img:設(shè)置環(huán)境變量: Devstack 的安裝目錄下有個(gè) openrc 文件。source 該文件就可以配置 CLI 的環(huán)境變量。這里我們傳入了兩個(gè)參數(shù),第一個(gè)參數(shù)是 OpenStack 用戶名 admin;第二個(gè)參數(shù)是 Project 名 admin。執(zhí)行 image 創(chuàng)建命令:

glance image-create --name cirros --file /tmp/cirros-0.3.4-x86_64-disk.img --disk-format qcow2 --container-format bare --progress

在創(chuàng)建 image 的 CLI 參數(shù)中我們用 –progress 讓其顯示文件上傳的百分比 %。在 /opt/stack/data/glance/images/ 下查看新的 Image:

2.2.3.2.2 CLI 刪除 image

設(shè)置環(huán)境變量: 查詢現(xiàn)有image: 刪除image采用glance image-delete 鏡像ID:

2.2.4 如何 Troubleshooting

OpenStack 排查問題的方法主要是通過日志,Service 都有自己單獨(dú)的日志。Glance 主要有兩個(gè)日志,glance_api.log 和 glance_registry.log,保存在 /opt/stack/logs/ 目錄里。devstack 的 screen 窗口已經(jīng)幫我們打開了這兩個(gè)日志,可以直接查看: g-api 窗口顯示 glance-api 日志,記錄 REST API 調(diào)用情況;g-reg 窗口顯示 glance-registry 日志,記錄 Glance 服務(wù)處理請(qǐng)求的過程以及數(shù)據(jù)庫操作。如果需要得到最詳細(xì)的日志信息,可以在 /etc/glance/*.conf 中打開 debug 選項(xiàng)。devstack 默認(rèn)已經(jīng)打開了 debug。 在非 devstack 安裝中,日志在 /var/log/glance/ 目錄里。

2.3 計(jì)算服務(wù)Nova

Compute Service Nova 是 OpenStack 最核心的服務(wù),負(fù)責(zé)維護(hù)和管理云環(huán)境的計(jì)算資源。OpenStack 作為 IaaS 的云操作系統(tǒng),虛擬機(jī)生命周期管理也就是通過 Nova 來實(shí)現(xiàn)的。 在上圖中可以看到,Nova 處于 Openstak 架構(gòu)的中心,其他組件都為 Nova 提供支持。Glance 為 VM 提供 image;Cinder 和 Swift 分別為 VM 提供塊存儲(chǔ)和對(duì)象存儲(chǔ) ;Neutron 為 VM 提供網(wǎng)絡(luò)連接。

2.3.1 Nova架構(gòu)

2.3.1.1 API

nova-api:接收和響應(yīng)客戶的 API 調(diào)用。 除了提供 OpenStack 自己的API,nova-api 還支持 Amazon EC2 API。也就是說,如果客戶以前使用 Amazon EC2,并且用 EC2 的 API 開發(fā)工具來管理虛機(jī),那么如果現(xiàn)在要換成 OpenStack,這些工具可以無縫遷移到OpenStack,因?yàn)?nova-api 兼容 EC2 API,無需做任何修改。

2.3.1.2 Compute Core

nova-scheduler:虛機(jī)調(diào)度服務(wù),負(fù)責(zé)決定在哪個(gè)計(jì)算節(jié)點(diǎn)上運(yùn)行虛機(jī);nova-compute:管理虛機(jī)的核心服務(wù),通過調(diào)用 Hypervisor API 實(shí)現(xiàn)虛機(jī)生命周期管理;Hypervisor:計(jì)算節(jié)點(diǎn)上跑的虛擬化管理程序,虛機(jī)管理最底層的程序。 不同虛擬化技術(shù)提供自己的 Hypervisor。 常用的 Hypervisor 有 KVM,Xen,VMWare 等;nova-conductor:nova-compute 經(jīng)常需要更新數(shù)據(jù)庫,比如更新虛機(jī)的狀態(tài)。出于安全性和伸縮性的考慮,nova-compute 并不會(huì)直接訪問數(shù)據(jù)庫,而是將這個(gè)任務(wù)委托給 nova-conductor。

2.3.1.3 Console Interface

nova-console:用戶可以通過多種方式訪問虛機(jī)的控制臺(tái): 1)nova-novncproxy,基于 Web 瀏覽器的VNC 訪問; 2)nova-spicehtml5proxy,基于HTML5 瀏覽器的 SPICE 訪問; 3)nova-xvpnvncproxy,基于 Java 客戶端的 VNC 訪問;nova-consoleauth:負(fù)責(zé)對(duì)訪問虛機(jī)控制臺(tái)請(qǐng)求提供 Token 認(rèn)證;nova-cert:提供 x509 證書支持。

2.3.1.4 Database

Nova 會(huì)有一些數(shù)據(jù)需要存放到數(shù)據(jù)庫中,一般使用 MySQL。數(shù)據(jù)庫安裝在控制節(jié)點(diǎn)上。 Nova 使用命名為 “nova” 的數(shù)據(jù)庫。

2.3.1.5 Message Queue

在前面我們了解到 Nova 包含眾多的子服務(wù),這些子服務(wù)之間需要相互協(xié)調(diào)和通信。 為解耦各個(gè)子服務(wù),Nova 通過 Message Queue 作為子服務(wù)的信息中轉(zhuǎn)站。 所以在架構(gòu)圖上我們看到了子服務(wù)之間沒有直接的連線,它們都通過 Message Queue 聯(lián)系。 OpenStack 默認(rèn)是用 RabbitMQ 作為 Message Queue。MQ 是 OpenStack 的核心基礎(chǔ)組件。

2.3.2 Nova 物理部署方案

對(duì)于 Nova,這些服務(wù)會(huì)部署在兩類節(jié)點(diǎn)上:計(jì)算節(jié)點(diǎn)和控制節(jié)點(diǎn)。計(jì)算節(jié)點(diǎn)上安裝了 Hypervisor,上面運(yùn)行虛擬機(jī),由此可知:只有 nova-compute 需要放在計(jì)算節(jié)點(diǎn)上。其他子服務(wù)則是放在控制節(jié)點(diǎn)上的。實(shí)驗(yàn)環(huán)境的具體部署情況 : 通過在計(jì)算節(jié)點(diǎn)和控制節(jié)點(diǎn)上運(yùn)行 ps -elf|grep nova 來查看運(yùn)行的 nova 子服務(wù): 1)計(jì)算節(jié)點(diǎn)上只運(yùn)行了nova-compute自服務(wù): 2)控制節(jié)點(diǎn)上運(yùn)行了若干 nova-* 子服務(wù),RabbitMQ 和 MySQL 也是放在控制節(jié)點(diǎn)上的,我們發(fā)現(xiàn)的控制節(jié)點(diǎn)上也運(yùn)行了 nova-compute:這實(shí)際上也就意味著controller 既是一個(gè)控制節(jié)點(diǎn),同時(shí)也是一個(gè)計(jì)算節(jié)點(diǎn),也可以在上面運(yùn)行虛機(jī)。 這也向我們展示了 OpenStack 這種分布式架構(gòu)部署上的靈活性: 可以將所有服務(wù)都放在一臺(tái)物理機(jī)上,作為一個(gè) All-in-One 的測(cè)試環(huán)境; 也可以將服務(wù)部署在多臺(tái)物理機(jī)上,獲得更好的性能和高可用。 另外,可以用 nova service-list 查看 nova-* 子服務(wù)都分布在哪些節(jié)點(diǎn)上:

2.3.3 從虛機(jī)創(chuàng)建流程看 nova-* 子服務(wù)如何協(xié)同工作

從學(xué)習(xí) Nova 的角度看,虛機(jī)創(chuàng)建是一個(gè)非常好的場(chǎng)景,涉及的 nova-* 子服務(wù)很全,下面是流程圖: 1)客戶(可以是 OpenStack 最終用戶,也可以是其他程序)向 API(nova-api)發(fā)送請(qǐng)求:“幫我創(chuàng)建一個(gè)虛機(jī)”; 2)API 對(duì)請(qǐng)求做一些必要處理后,向 Messaging(RabbitMQ)發(fā)送了一條消息:“讓 Scheduler 創(chuàng)建一個(gè)虛機(jī)”; 3)Scheduler(nova-scheduler)從 Messaging 獲取到 API 發(fā)給它的消息,然后執(zhí)行調(diào)度算法,從若干計(jì)算節(jié)點(diǎn)中選出節(jié)點(diǎn) A; 4)Scheduler 向 Messaging 發(fā)送了一條消息:“在計(jì)算節(jié)點(diǎn) A 上創(chuàng)建這個(gè)虛機(jī)”; 5)計(jì)算節(jié)點(diǎn) A 的 Compute(nova-compute)從 Messaging 中獲取到 Scheduler 發(fā)給它的消息,然后在本節(jié)點(diǎn)的 Hypervisor 上啟動(dòng)虛機(jī); 5)在虛機(jī)創(chuàng)建的過程中,Compute 如果需要查詢或更新數(shù)據(jù)庫信息,會(huì)通過 Messaging 向Conductor(nova-conductor)發(fā)送消息,Conductor 負(fù)責(zé)數(shù)據(jù)庫訪問。

2.3.4 OpenStack 通用設(shè)計(jì)思路

2.3.4.1 API 前端服務(wù)

每個(gè) OpenStack 組件可能包含若干子服務(wù),其中必定有一個(gè) API 服務(wù)負(fù)責(zé)接收客戶請(qǐng)求。以 Nova 為例,nova-api 作為 Nova 組件對(duì)外的唯一窗口,向客戶暴露 Nova 能夠提供的功能。當(dāng)客戶需要執(zhí)行虛機(jī)相關(guān)的操作,能且只能向 nova-api 發(fā)送 REST 請(qǐng)求。這里的客戶包括終端用戶、命令行和 OpenStack 其他組件。設(shè)計(jì) API 前端服務(wù)的好處在于:對(duì)外提供統(tǒng)一接口,隱藏實(shí)現(xiàn)細(xì)節(jié);API 提供 REST 標(biāo)準(zhǔn)調(diào)用服務(wù),便于與第三方系統(tǒng)集成;可以通過運(yùn)行多個(gè) API 服務(wù)實(shí)例輕松實(shí)現(xiàn) API 的高可用,比如運(yùn)行多個(gè) nova-api 進(jìn)程。

2.3.4.2 Scheduler 調(diào)度服務(wù)

對(duì)于某項(xiàng)操作,如果有多個(gè)實(shí)體都能夠完成任務(wù),那么通常會(huì)有一個(gè)scheduler 負(fù)責(zé)從這些實(shí)體中挑選出一個(gè)最合適的來執(zhí)行操作。在前面的例子中,Nova 有多個(gè)計(jì)算節(jié)點(diǎn)。當(dāng)需要?jiǎng)?chuàng)建虛機(jī)時(shí),nova-scheduler 會(huì)根據(jù)計(jì)算節(jié)點(diǎn)當(dāng)時(shí)的資源使用情況選擇一個(gè)最合適的計(jì)算節(jié)點(diǎn)來運(yùn)行虛機(jī)。除了 Nova,塊服務(wù)組件 Cinder 也有 scheduler 子服務(wù),后面我們會(huì)詳細(xì)討論。

2.3.4.3 Worker工作服務(wù)

調(diào)度服務(wù)只管分配任務(wù),真正執(zhí)行任務(wù)的是 Worker 工作服務(wù)。在 Nova 中,這個(gè) Worker 就是 nova-compute 了。 將 Scheduler 和 Worker 從職能上進(jìn)行劃分使得OpenStack 非常容易擴(kuò)展:1)當(dāng)計(jì)算資源不夠了無法創(chuàng)建虛機(jī)時(shí),可以增加計(jì)算節(jié)點(diǎn)(增加 Worker);2)當(dāng)客戶的請(qǐng)求量太大調(diào)度不過來時(shí),可以增加 Scheduler。

2.3.4.4 Driver 框架

OpenStack 作為開放的 Infrastracture as a Service 云操作系統(tǒng),支持業(yè)界各種優(yōu)秀的技術(shù)。那 OpenStack 的這種開放性體現(xiàn)在哪里呢:一個(gè)重要的方面就是采用基于 Driver 的框架。以 Nova 為例,OpenStack 的計(jì)算節(jié)點(diǎn)支持多種 Hypervisor。 包括 KVM, Hyper-V, VMWare, Xen, Docker, LXC 等。Nova-compute 為這些 Hypervisor 定義了統(tǒng)一的接口,hypervisor 只需要實(shí)現(xiàn)這些接口,就可以 driver 的形式即插即用到 OpenStack 中。下面是 nova driver 的架構(gòu)示意圖: 在 nova-compute 的配置文件 /etc/nova/nova.conf 中由 compute_driver 配置項(xiàng)指定該計(jì)算節(jié)點(diǎn)使用哪種 Hypervisor 的 driver。 在我們的環(huán)境中因?yàn)槭?KVM,所以配置的是 Libvirt 的 driver。不知大家是否還記得我們?cè)趯W(xué)習(xí) Glance 時(shí)談到: OpenStack 支持多種 backend 來存放 image??梢允潜镜匚募到y(tǒng),Cinder,Ceph,Swift 等。其實(shí)這也是一個(gè) driver 架構(gòu)。 只要符合 Glance 定義的規(guī)范,新的存儲(chǔ)方式可以很方便的加入到 backend 支持列表中。再后面 Cinder 和 Neutron 中我們還會(huì)看到 driver 框架的應(yīng)用。

2.3.4.5 Messaging 服務(wù)

在前面創(chuàng)建虛機(jī)的流程示意圖中,我們看到 nova-* 子服務(wù)之間的調(diào)用嚴(yán)重依賴 Messaging。Messaging 是 nova-* 子服務(wù)交互的中樞。 以前沒接觸過分布式系統(tǒng)的同學(xué)可能會(huì)不太理解為什么不讓 API 直接調(diào)用Scheduler,或是讓Scheuler 直接調(diào)用 Compute,而是非要通過 Messaging 進(jìn)行中轉(zhuǎn)。程序之間的調(diào)用通常分兩種:同步調(diào)用和異步調(diào)用: 1)同步調(diào)用: API 直接調(diào)用 Scheduler 的接口就是同步調(diào)用。 其特點(diǎn)是 API 發(fā)出請(qǐng)求后需要一直等待,直到 Scheduler 完成對(duì) Compute 的調(diào)度,將結(jié)果返回給 API 后 API 才能夠繼續(xù)做后面的工作。 2)異步調(diào)用: API 通過 Messaging 間接調(diào)用 Scheduler 就是異步調(diào)用。 其特點(diǎn)是 API 發(fā)出請(qǐng)求后不需要等待,直接返回,繼續(xù)做后面的工作。Scheduler 從 Messaging 接收到請(qǐng)求后執(zhí)行調(diào)度操作,完成后將結(jié)果也通過 Messaging 發(fā)送給 API。在 OpenStack 這類分布式系統(tǒng)中,通常采用異步調(diào)用的方式,其好處是:解耦各子服務(wù):子服務(wù)不需要知道其他服務(wù)在哪里運(yùn)行,只需要發(fā)送消息給 Messaging 就能完成調(diào)用;提高性能:異步調(diào)用使得調(diào)用者無需等待結(jié)果返回。這樣可以繼續(xù)執(zhí)行更多的工作,提高系統(tǒng)總的吞吐量;提高伸縮性:子服務(wù)可以根據(jù)需要進(jìn)行擴(kuò)展,啟動(dòng)更多的實(shí)例處理更多的請(qǐng)求,在提高可用性的同時(shí)也提高了整個(gè)系統(tǒng)的伸縮性。而且這種變化不會(huì)影響到其他子服務(wù),也就是說變化對(duì)別人是透明的。

2.3.4.6 Database

OpenStack 各組件都需要維護(hù)自己的狀態(tài)信息。比如 Nova 中有虛機(jī)的規(guī)格、狀態(tài),這些信息都是在數(shù)據(jù)庫中維護(hù)的。每個(gè) OpenStack 組件在 MySQL 中有自己的數(shù)據(jù)庫。

2.3.5 Nova 組件詳解

2.3.5.1 nova-api

Nova-api 是整個(gè) Nova 組件的門戶,所有對(duì) Nova 的請(qǐng)求都首先由 nova-api 處理。 Nova-api 向外界暴露若干 HTTP REST API 接口。在 keystone 中我們采用openstack endpoint show nova命令查詢 nova-api 的 endponits??蛻舳司涂梢詫⒄?qǐng)求發(fā)送到 endponits 指定的地址,向 nova-api 請(qǐng)求操作。 當(dāng)然,作為最終用戶的我們不會(huì)直接發(fā)送 Rest AP I請(qǐng)求。OpenStack CLI,Dashboard 和其他需要跟 Nova 交換的組件會(huì)使用這些 API。 Nova-api 對(duì)接收到的 HTTP API 請(qǐng)求會(huì)做如下處理: 1)檢查客戶端傳入的參數(shù)是否合法有效 ; 2)調(diào)用 Nova 其他子服務(wù)的處理客戶端 HTTP 請(qǐng)求 ; 3)格式化 Nova 其他子服務(wù)返回的結(jié)果并返回給客戶端。 nova-api 接收哪些請(qǐng)求? 簡單的說,只要是跟虛擬機(jī)生命周期相關(guān)的操作,nova-api 都可以響應(yīng)。大部分操作都可以在 Dashboard 上找到。打開Instance管理界面: 點(diǎn)擊下拉箭頭,列表中就是 nova-api 可執(zhí)行的操作。 OpenStack 用術(shù)語 “Instance” 來表示虛擬機(jī)。

2.3.5.2 nova-conductor

nova-compute 需要獲取和更新數(shù)據(jù)庫中 instance 的信息。但 nova-compute 并不會(huì)直接訪問數(shù)據(jù)庫,而是通過 nova-conductor 實(shí)現(xiàn)數(shù)據(jù)的訪問。 這樣做有兩個(gè)顯著好處:更高的系統(tǒng)安全性;更好的系統(tǒng)伸縮性 。更高的安全性: 在 OpenStack 的早期版本中,nova-compute 可以直接訪問數(shù)據(jù)庫,但這樣存在非常大的安全隱患。因?yàn)?nova-compute 這個(gè)服務(wù)是部署在計(jì)算節(jié)點(diǎn)上的,為了能夠訪問控制節(jié)點(diǎn)上的數(shù)據(jù)庫,就必須在計(jì)算節(jié)點(diǎn)的 /etc/nova/nova.conf 中配置訪問數(shù)據(jù)庫的連接信息,比如: 試想任意一個(gè)計(jì)算節(jié)點(diǎn)被黑客入侵,都會(huì)導(dǎo)致部署在控制節(jié)點(diǎn)上的數(shù)據(jù)庫面臨極大風(fēng)險(xiǎn)。為了解決這個(gè)問題,從 G 版本開始,Nova 引入了一個(gè)新服務(wù) nova-conductor,將 nova-compute 訪問數(shù)據(jù)庫的全部操作都放到 nova-conductor 中,而且 nova-conductor 是部署在控制節(jié)點(diǎn)上的。這樣就避免了 nova-compute 直接訪問數(shù)據(jù)庫,增加了系統(tǒng)的安全性。更好的伸縮性: nova-conductor 將 nova-compute 與數(shù)據(jù)庫解耦之后還帶來另一個(gè)好處:提高了 nova 的伸縮性。nova-compute 與 conductor 是通過消息中間件交互的。這種松散的架構(gòu)允許配置多個(gè) nova-conductor 實(shí)例。在一個(gè)大規(guī)模的 OpenStack 部署環(huán)境里,管理員可以通過增加 nova-conductor 的數(shù)量來應(yīng)對(duì)日益增長的計(jì)算節(jié)點(diǎn)對(duì)數(shù)據(jù)庫的訪問。

2.3.5.3 nova-scheduler

重點(diǎn)介紹 nova-scheduler 的調(diào)度機(jī)制和實(shí)現(xiàn)方法:即解決如何選擇在哪個(gè)計(jì)算節(jié)點(diǎn)上啟動(dòng) instance 的問題。 創(chuàng)建 Instance 時(shí),用戶會(huì)提出資源需求,例如 CPU、內(nèi)存、磁盤各需要多少。OpenStack 將這些需求定義在 flavor(配額) 中,用戶只需要指定用哪個(gè) flavor 就可以了。 可用的 flavor 在 System->Flavors 中管理: Flavor 主要定義了 VCPU,RAM,DISK 和 Metadata 這四類。 nova-scheduler 會(huì)按照 flavor 去選擇合適的計(jì)算節(jié)點(diǎn)。VCPU,RAM,DISK 比較好理解,而 Metatdata 比較有意思,我們后面會(huì)具體討論。下面介紹 nova-scheduler 是如何實(shí)現(xiàn)調(diào)度的 在 /etc/nova/nova.conf 中,nova 通過 scheduler_driver,scheduler_available_filters 和 scheduler_default_filters這三個(gè)參數(shù)來配置 nova-scheduler。 Filter scheduler: Filter scheduler 是 nova-scheduler 默認(rèn)的調(diào)度器,調(diào)度過程分為兩步。1)通過過濾器(filter)選擇滿足條件的計(jì)算節(jié)點(diǎn)(運(yùn)行 nova-compute);2)通過權(quán)重計(jì)算(weighting)選擇在最優(yōu)(權(quán)重值最大)的計(jì)算節(jié)點(diǎn)上創(chuàng)建 Instance。 Nova 允許使用第三方 scheduler,配置 scheduler_driver 即可。這又一次體現(xiàn)了OpenStack的開放性。Scheduler 可以使用多個(gè) filter 依次進(jìn)行過濾,過濾之后的節(jié)點(diǎn)再通過計(jì)算權(quán)重選出最適合的節(jié)點(diǎn)。 上圖是調(diào)度過程的一個(gè)示例:最開始有 6 個(gè)計(jì)算節(jié)點(diǎn) Host1-Host6;通過多個(gè) filter 層層過濾,Host2 和 Host4 沒有通過,被刷掉了;Host1,Host3,Host5,Host6 計(jì)算權(quán)重,結(jié)果 Host5 得分最高,最終入選。 Filter: 當(dāng) Filter scheduler 需要執(zhí)行調(diào)度操作時(shí),會(huì)讓 filter 對(duì)計(jì)算節(jié)點(diǎn)進(jìn)行判斷,filter 返回 True 或 False。Nova.conf 中的 scheduler_available_filters 選項(xiàng)用于配置 scheduler 可用的 filter,默認(rèn)是所有 nova 自帶的 filter 都可以用于過濾操作。 另外還有一個(gè)選項(xiàng) scheduler_default_filters,用于指定 scheduler 真正使用的 filter,默認(rèn)值如下 : Filter scheduler 將按照列表中的順序依次過濾。 下面依次介紹每個(gè) filter。 1)RetryFilter: RetryFilter 的作用是刷掉之前已經(jīng)調(diào)度過的節(jié)點(diǎn)。舉個(gè)例子方便大家理解: 假設(shè) A,B,C 三個(gè)節(jié)點(diǎn)都通過了過濾,最終 A 因?yàn)闄?quán)重值最大被選中執(zhí)行操作。但由于某個(gè)原因,操作在 A 上失敗了。 默認(rèn)情況下,nova-scheduler 會(huì)重新執(zhí)行過濾操作(重復(fù)次數(shù)由 scheduler_max_attempts 選項(xiàng)指定,默認(rèn)是 3)。那么這時(shí)候 RetryFilter 就會(huì)將 A 直接刷掉,避免操作再次失敗。RetryFilter 通常作為第一個(gè) filter。 2)AvailabilityZoneFilter: 為提高容災(zāi)性和提供隔離服務(wù),可以將計(jì)算節(jié)點(diǎn)劃分到不同的Availability Zone中。例如把一個(gè)機(jī)架上的機(jī)器劃分在一個(gè) Availability Zone 中。OpenStack 默認(rèn)有一個(gè)命名為 “Nova” 的 Availability Zone,所有的計(jì)算節(jié)點(diǎn)初始都是放在 “Nova” 中。用戶可以根據(jù)需要?jiǎng)?chuàng)建自己的 Availability Zone。 創(chuàng)建 Instance 時(shí),需要指定將 Instance 部署到在哪個(gè) Availability Zone中。 nova-scheduler 在做 filtering 時(shí),會(huì)使用 AvailabilityZoneFilter 將不屬于指定 Availability Zone 的計(jì)算節(jié)點(diǎn)過濾掉。 3)RamFilter: RamFilter 將不能滿足 flavor 內(nèi)存需求的計(jì)算節(jié)點(diǎn)過濾掉。對(duì)于內(nèi)存有一點(diǎn)需要注意: 為了提高系統(tǒng)的資源使用率,OpenStack 在計(jì)算節(jié)點(diǎn)可用內(nèi)存時(shí)允許 overcommit(超配),也就是可以超過實(shí)際內(nèi)存大小。 超過的程度是通過 nova.conf 中 ram_allocation_ratio 這個(gè)參數(shù)來控制的,默認(rèn)值為 1.5。 其含義是:如果計(jì)算節(jié)點(diǎn)的內(nèi)存有 10GB,OpenStack 則會(huì)認(rèn)為它有 15GB(10*1.5)的內(nèi)存。 4)DiskFilter: DiskFilter 將不能滿足 flavor 磁盤需求的計(jì)算節(jié)點(diǎn)過濾掉。Disk 同樣允許 overcommit,通過 nova.conf 中 disk_allocation_ratio 控制,默認(rèn)值為 1。 5)CoreFilter: CoreFilter 將不能滿足 flavor vCPU 需求的計(jì)算節(jié)點(diǎn)過濾掉。vCPU 同樣允許 overcommit,通過 nova.conf 中 cpu_allocation_ratio 控制,默認(rèn)值為 16。 這意味著一個(gè) 8 vCPU 的計(jì)算節(jié)點(diǎn),nova-scheduler 在調(diào)度時(shí)認(rèn)為它有 128 個(gè) vCPU。需要提醒的是: nova-scheduler 默認(rèn)使用的 filter 并沒有包含 CoreFilter。 如果要用,可以將 CoreFilter 添加到 nova.conf 的 scheduler_default_filters 配置選項(xiàng)中。 6)ComputeFilter: ComputeFilter 保證只有 nova-compute 服務(wù)正常工作的計(jì)算節(jié)點(diǎn)才能夠被 nova-scheduler調(diào)度。ComputeFilter 顯然是必選的 filter。 7)ComputeCapabilitiesFilter:ComputeCapabilitiesFilter 根據(jù)計(jì)算節(jié)點(diǎn)的特性來篩選。這個(gè)比較高級(jí),我們舉例說明。例如我們的節(jié)點(diǎn)有 x86_64 和 ARM 架構(gòu)的,如果想將 Instance 指定部署到 x86_64 架構(gòu)的節(jié)點(diǎn)上,就可以利用到ComputeCapabilitiesFilter。還記得 flavor 中有個(gè) Metadata 嗎,Compute 的 Capabilities就在 Metadata中 指定。 “Compute Host Capabilities” 列出了所有可設(shè)置 Capabilities。 點(diǎn)擊 “Architecture” 后面的 “+”,就可以在右邊的列表中指定具體的架構(gòu)。 配置好后,ComputeCapabilitiesFilter 在調(diào)度時(shí)只會(huì)篩選出 x86_64 的節(jié)點(diǎn)。如果沒有設(shè)置 Metadata,ComputeCapabilitiesFilter 不會(huì)起作用,所有節(jié)點(diǎn)都會(huì)通過篩選。 8)ImagePropertiesFilter: ImagePropertiesFilter 根據(jù)所選 image 的屬性來篩選匹配的計(jì)算節(jié)點(diǎn)。 跟 flavor 類似,image 也有 metadata,用于指定其屬性。 例如希望某個(gè) image 只能運(yùn)行在 kvm 的 hypervisor 上,可以通過 “Hypervisor Type” 屬性來指定。 點(diǎn)擊 “+”,然后在右邊的列表中選擇 “kvm”。 配置好后,ImagePropertiesFilter 在調(diào)度時(shí)只會(huì)篩選出 kvm 的節(jié)點(diǎn)。如果沒有設(shè)置 Image 的Metadata,ImagePropertiesFilter 不會(huì)起作用,所有節(jié)點(diǎn)都會(huì)通過篩選。 9)ServerGroupAntiAffinityFilter: ServerGroupAntiAffinityFilter 可以盡量將 Instance 分散部署到不同的節(jié)點(diǎn)上。例如有 inst1,inst2 和 inst3 三個(gè) instance,計(jì)算節(jié)點(diǎn)有 A,B 和 C。為保證分散部署,進(jìn)行如下操作: 創(chuàng)建一個(gè) anti-affinity 策略的 server group “group-1” : 請(qǐng)注意,這里的 server group 其實(shí)是 instance group,并不是計(jì)算節(jié)點(diǎn)的 group。 依次創(chuàng)建 Instance,將inst1, inst2和inst3放到group-1中: 因?yàn)?group-1 的策略是 AntiAffinity,調(diào)度時(shí) ServerGroupAntiAffinityFilter 會(huì)將inst1, inst2 和 inst3 部署到不同計(jì)算節(jié)點(diǎn) A, B 和 C。目前只能在 CLI 中指定 server group 來創(chuàng)建 instance。創(chuàng)建 instance 時(shí)如果沒有指定 server group,ServerGroupAntiAffinityFilter 會(huì)直接通過,不做任何過濾。 10)ServerGroupAffinityFilter: 與 ServerGroupAntiAffinityFilter 的作用相反,ServerGroupAffinityFilter 會(huì)盡量將 instance 部署到同一個(gè)計(jì)算節(jié)點(diǎn)上。方法類似: 創(chuàng)建一個(gè) affinity 策略的 server group “group-2”: 依次創(chuàng)建 instance,將 inst1, inst2 和 inst3 放到 group-2 中: 因?yàn)?group-2 的策略是 Affinity,調(diào)度時(shí) ServerGroupAffinityFilter 會(huì)將 inst1, inst2 和 inst3 部署到同一個(gè)計(jì)算節(jié)點(diǎn)。創(chuàng)建 instance 時(shí)如果沒有指定 server group,ServerGroupAffinityFilter 會(huì)直接通過,不做任何過濾。 Weight: 經(jīng)過前面一堆 filter 的過濾,nova-scheduler 選出了能夠部署 instance 的計(jì)算節(jié)點(diǎn)。如果有多個(gè)計(jì)算節(jié)點(diǎn)通過了過濾,那么最終選擇哪個(gè)節(jié)點(diǎn)呢?Scheduler 會(huì)對(duì)每個(gè)計(jì)算節(jié)點(diǎn)打分,得分最高的獲勝。打分的過程就是 weight,翻譯過來就是計(jì)算權(quán)重值,那么 scheduler 是根據(jù)什么來計(jì)算權(quán)重值呢?目前 nova-scheduler 的默認(rèn)實(shí)現(xiàn)是根據(jù)計(jì)算節(jié)點(diǎn)空閑的內(nèi)存量計(jì)算權(quán)重值:空閑內(nèi)存越多,權(quán)重越大,instance 將被部署到當(dāng)前空閑內(nèi)存最多的計(jì)算節(jié)點(diǎn)上。 日志: 1)整個(gè)過程都被記錄到 nova-scheduler 的日志中。比如當(dāng)我們部署一個(gè) instance 時(shí),打開 nova-scheduler 的日志 /opt/stack/logs/n-sch.log(非 devstack 安裝其日志在 /var/log/nova/scheduler.log): 日志顯示初始有兩個(gè) host(在我們的實(shí)驗(yàn)環(huán)境中就是 devstack-controller 和 devstack-compute1),依次經(jīng)過 9 個(gè) filter 的過濾(RetryFilter,AvailabilityZoneFilter,RamFilter,DiskFilter,ComputeFilter,ComputeCapabilitiesFilter,ImagePropertiesFilter,ServerGroupAntiAffinityFilter, ServerGroupAffinityFilter),兩個(gè)計(jì)算節(jié)點(diǎn)都通過了。 2)那么接下來就該 weight 了: 可以看到因?yàn)?devstack-controller 的空閑內(nèi)存比 devstack-compute1 多(7466 > 3434),權(quán)重值更大(1.0 > 0.4599),最終選擇 devstack-controller。 注:要顯示 DEBUG 日志,需要在 /etc/nova/nova.conf 中打開 debug 選項(xiàng):

2.3.5.4 nova-compute

nova-compute 在計(jì)算節(jié)點(diǎn)上運(yùn)行,負(fù)責(zé)管理節(jié)點(diǎn)上的 instance。OpenStack 對(duì) instance 的操作,最后都是交給 nova-compute 來完成的。nova-compute 與 Hypervisor 一起實(shí)現(xiàn) OpenStack 對(duì) instance 生命周期的管理。通過 Driver 架構(gòu)支持多種 Hypervisor:現(xiàn)在市面上有這么多 Hypervisor,nova-compute 如何與它們配合呢?這就是我們之前討論過的 Driver 架構(gòu)。nova-compute 為這些 Hypervisor 定義了統(tǒng)一的接口,Hypervisor 只需要實(shí)現(xiàn)這些接口,就可以 Driver 的形式即插即用到 OpenStack 系統(tǒng)中。 下面是Nova Driver的架構(gòu)示意圖: 我們可以在 /opt/stack/nova/nova/virt/ 目錄下查看到 OpenStack 源代碼中已經(jīng)自帶了上面這幾個(gè) Hypervisor 的 Driver: 某個(gè)特定的計(jì)算節(jié)點(diǎn)上只會(huì)運(yùn)行一種 Hypervisor,只需在該節(jié)點(diǎn) nova-compute 的配置文件 /etc/nova/nova.conf 中配置所對(duì)應(yīng)的 compute_driver 就可以了。在我們的環(huán)境中因?yàn)槭?KVM,所以配置的是 Libvirt 的 driver: nova-compute 的功能可以分為兩類:1)定時(shí)向 OpenStack 報(bào)告計(jì)算節(jié)點(diǎn)的狀態(tài) ;2)實(shí)現(xiàn) instance 生命周期的管理。 1)定期向 OpenStack 報(bào)告計(jì)算節(jié)點(diǎn)的狀態(tài) : 前面我們看到 nova-scheduler 的很多 Filter 是根據(jù)算節(jié)點(diǎn)的資源使用情況進(jìn)行過濾的。比如 RamFilter 要檢查計(jì)算節(jié)點(diǎn)當(dāng)前可以的內(nèi)存量;CoreFilter 檢查可用的 vCPU 數(shù)量;DiskFilter 則會(huì)檢查可用的磁盤空間。 那這里有個(gè)問題:OpenStack 是如何得知每個(gè)計(jì)算節(jié)點(diǎn)的這些信息呢? 答案就是:nova-compute 會(huì)定期向 OpenStack 報(bào)告。從 nova-compute 的日志 /opt/stack/logs/n-cpu.log 可以發(fā)現(xiàn):每隔一段時(shí)間,nova-compute 就會(huì)報(bào)告當(dāng)前計(jì)算節(jié)點(diǎn)的資源使用情況和 nova-compute 服務(wù)狀態(tài)。 如果我們?cè)偕钊雴栆粋€(gè)問題:nova-compute 是如何獲得當(dāng)前計(jì)算節(jié)點(diǎn)的資源使用信息的? 要得到計(jì)算節(jié)點(diǎn)的資源使用詳細(xì)情況,需要知道當(dāng)前節(jié)點(diǎn)上所有 instance 的資源占用信息。這些信息誰最清楚? 當(dāng)然是 Hypervisor。大家還記得之前我們討論的 Nova Driver 架構(gòu)吧,nova-compute 可以通過 Hypervisor 的 driver 拿到這些信息。舉例來說,在我們的實(shí)驗(yàn)環(huán)境下 Hypervisor 是 KVM,用的 Driver 是 LibvirtDriver。LibvirtDriver 可以調(diào)用相關(guān)的 API 獲得資源信息,這些 API 的作用相當(dāng)于我們?cè)?CLI 里執(zhí)行 virsh nodeinfo、virsh dominfo 等命令。 2)實(shí)現(xiàn) instance 生命周期的管理: OpenStack 對(duì) instance 最主要的操作都是通過 nova-compute 實(shí)現(xiàn)的:包括 instance 的 launch(部署)、shutdown(關(guān)機(jī))、reboot(重啟)、suspend(掛起)、resume(恢復(fù))、terminate(終止)、resize(重新分配配額)、migration(遷移)、snapshot(快照) 等。 本小節(jié)重點(diǎn)學(xué)習(xí) nova-compute 如何實(shí)現(xiàn) instance launch(部署)操作。當(dāng) nova-scheduler 選定了部署 instance 的計(jì)算節(jié)點(diǎn)后,會(huì)通過消息中間件 rabbitMQ 向選定的計(jì)算節(jié)點(diǎn)發(fā)出 launch instance 的命令。該計(jì)算節(jié)點(diǎn)上運(yùn)行的 nova-compute 收到消息后會(huì)執(zhí)行 instance 創(chuàng)建操作。 日志 /opt/stack/logs/n-cpu.log 記錄了整個(gè)操作過程。nova-compute 創(chuàng)建 instance 的過程可以分為 4 步:為 instance 準(zhǔn)備資源;創(chuàng)建 instance 的鏡像文件;創(chuàng)建 instance 的 XML 定義文件 ;創(chuàng)建虛擬網(wǎng)絡(luò)并啟動(dòng)虛擬機(jī)。 第1步-為instance 準(zhǔn)備資源: nova-compute 首先會(huì)根據(jù)指定的 flavor 依次為 instance 分配內(nèi)存、磁盤空間和 vCPU??梢栽谌罩局锌吹竭@些細(xì)節(jié): 網(wǎng)絡(luò)資源也會(huì)提前分配: 第2步-創(chuàng)建 instance 的鏡像文件 : 資源準(zhǔn)備好之后,nova-compute 會(huì)為 instance 創(chuàng)建鏡像文件,OpenStack 啟動(dòng)一個(gè) instance 時(shí),會(huì)選擇一個(gè) image,這個(gè) image 由 Glance 管理。nova-compute會(huì):首先將該 image 下載到計(jì)算節(jié)點(diǎn);然后將其作為 backing file 創(chuàng)建 instance 的鏡像文件。 從 Glance 下載 image:nova-compute 首先會(huì)檢查 image 是否已經(jīng)下載(比如之前已經(jīng)創(chuàng)建過基于相同 image 的 instance)。 如果沒有,就從 Glance 下載 image 到本地。由此可知,如果計(jì)算節(jié)點(diǎn)上要運(yùn)行多個(gè)相同 image 的 instance,只會(huì)在啟動(dòng)第一個(gè) instance 的時(shí)候從 Glance 下載 image,后面的 instance 啟動(dòng)速度就大大加快了。日志如下: 可以看到:image(ID為 917d60ef-f663-4e2d-b85b-e4511bb56bc2)是 qcow2格式,nova-compute 將其下載,然后通過 qemu-img 轉(zhuǎn)換成 raw 格式。 轉(zhuǎn)換的原因是下一步需要將其作為 instance的鏡像文件的 backing file,而 backing file不能是 qcow2 格式。image 的存放目錄是 /opt/stack/data/nova/instances/_base,這是由 /etc/nova/nova.conf 的下面兩個(gè)配置選項(xiàng)決定的。 instances_path = /opt/stack/data/nova/instances base_dir_name = _base 下載的 image 文件被命名為 60bba5916c6c90ed2ef7d3263de8f653111dd35f,這是 image id 的 SHA1 哈希值。 為 instance 創(chuàng)建鏡像文件:有了 image 之后,instance 的鏡像文件直接通過 qemu-img 命令創(chuàng)建,backing file 就是下載的 image: 這里 instance 的鏡像文件位于 /opt/stack/data/nova/instances/f1e22596-6844-4d7a-84a3-e41e6d7618ef/disk,格式為 qcow2,其中 f1e22596-6844-4d7a-84a3-e41e6d7618ef 就是 instance 的 id。 可以通過 qemu-info 查看 disk 文件的屬性: 這里有兩個(gè)容易搞混淆的術(shù)語,在此特別說明一下 image,指的是 Glance 上保存的鏡像,作為 instance 運(yùn)行的模板。 計(jì)算節(jié)點(diǎn)將下載的 image 存放在 /opt/stack/data/nova/instances/_base 目錄下。 鏡像文件,指的是 instance 啟動(dòng)盤所對(duì)應(yīng)的文件。二者的關(guān)系是:image 是鏡像文件 的 backing file。image 不會(huì)變,而鏡像文件會(huì)發(fā)生變化。 比如安裝新的軟件后,鏡像文件會(huì)變大。因?yàn)橛⑽闹袃烧叨冀?“image”,為避免混淆,我們用 “image” 和 “鏡像文件” 作區(qū)分。 第3步-創(chuàng)建 instance 的XML 定義文件 : 創(chuàng)建的 XML 文件會(huì)保存到該 instance 目錄 /opt/stack/data/nova/instances/f1e22596-6844-4d7a-84a3-e41e6d7618ef,命名為 libvirt.xml: 第4步-創(chuàng)建虛擬網(wǎng)絡(luò)并啟動(dòng) instance : 本環(huán)境用的是 linux-bridge 實(shí)現(xiàn)的虛擬網(wǎng)絡(luò),在 Neutron 章節(jié)我們會(huì)詳細(xì)討論 OpenStack 虛擬網(wǎng)絡(luò)的不同實(shí)現(xiàn)方式。一切就緒,接下來可以啟動(dòng) instance 了: 至此,instance 已經(jīng)成功啟動(dòng)。OpenStack 圖形界面和 KVM CLI 都可以查看到 instance 的運(yùn)行狀態(tài): 在計(jì)算節(jié)點(diǎn)上,instance 并不是以 OpenStack上 的名字命名,而是用 instance-xxxxx 的格式。

2.3.6 看懂 OpenStack 日志

2.3.6.1 日志位置

我們實(shí)驗(yàn)環(huán)境使用的是 devstack,日志都統(tǒng)一放在 /opt/stack/logs 目錄下,非 devstack日志在var/log目錄下。每個(gè)服務(wù)有自己的日志文件,從命名上很容易區(qū)分。

2.3.6.2 日志類型

比如 nova-* 各個(gè)子服務(wù)的日志都以 “n-” 開頭。n-api.log 是 nova-api 的日志;n-cpu.log 是 nova-compute 的日志。Glance 的日志文件都是 “g-” 開頭。g-api.log 是 glance-api 的日志;g-reg.log 是 glance-registry 的日志。Cinder、Neutron 的日志分別以 “c-” 和 “q-” 開頭。對(duì)于非 devstack 安裝的 OpenStack,日志一般放在 /var/log/xxx/ 目錄下 比如 Nova 放在 /var/log/nova/ 下,Glance 放在/var/log/glance下……。各個(gè)子服務(wù)的日志文件也是單獨(dú)保存,命名也很規(guī)范,容易區(qū)分。比如 nova-api 的日志一般就命名為 /var/log/nova/api.log,其他日志類似。

2.3.6.3 日志格式

OpenStack 的日志格式都是統(tǒng)一的,如下: <時(shí)間戳><日志等級(jí)><代碼模塊><日志內(nèi)容><源代碼位置> 簡單說明一下: 1)時(shí)間戳:日志記錄的時(shí)間,包括年、月、日、時(shí)、分、秒、毫秒; 2)日志等級(jí):有INFO、WARNING、ERROR、DEBUG等; 3)代碼模塊:當(dāng)前運(yùn)行的模塊Request ID,日志會(huì)記錄連續(xù)不同的操作,為了便于區(qū)分和增加可讀性,每個(gè)操作都被分配唯一的Request ID,便于查找; 4)日志內(nèi)容:這是日志的主體,記錄當(dāng)前正在執(zhí)行的操作和結(jié)果等重要信息; 5)源代碼位置:日志代碼的位置,包括方法名稱,源代碼文件的目錄位置和行號(hào)。這一項(xiàng)不是所有日志都有。下面舉例說明:

2015-12-10 20:46:49.566 DEBUG nova.virt.libvirt.config [req-5c973fff-e9ba-4317-bfd9-76678cc96584 None None] Generated XML ('\n x86_64\n Westmere\n

Intel\n \n

\n \n \n

\n \n \n

\n \n \n

\n\n',) to_xml /opt/stack/nova/nova/virt/libvirt/config.py:82

這條日志我們可以得知:代碼模塊是 nova.virt.libvirt.config,由此可知應(yīng)該是 Hypervisor Libvirt 相關(guān)的操作;日志內(nèi)容是生成 XML;如果要跟蹤源代碼,可以到/opt/stack/nova/nova/virt/libvirt/config.py 的 82 行,方法是 to_xml。

又例如下面這條日志:

2015-12-10 20:46:49.671 ERROR nova.compute.manager[req-5c973fff-e9ba-4317-bfd9-76678cc96584 None None]No compute node record for host devstack-controller

這條日志我們可以得知:這是一個(gè) ERROR 日志;具體內(nèi)容是 “No compute node record for host devstack-controller”;該日志沒有指明源代碼位置。

2.3.6.4 日志說明

學(xué)習(xí) OpenStack 需要看日志嗎?這個(gè)問題的答案取決于你是誰。果你只是 OpenStack 的最終用戶,那么日志對(duì)你不重要。你只需要在 GUI上 操作,如果出問題直接找管理員就可以了。 但如果你是 OpenStack 的運(yùn)維和管理人員,日志對(duì)你就非常重要了。因?yàn)?OpenStack 操作如果出錯(cuò),GUI 上給出的錯(cuò)誤信息是非?;\統(tǒng)和簡要的,日志則提供了大量的線索,特別是當(dāng) debug 選項(xiàng)打開之后。如果你正處于 OpenStack 的學(xué)習(xí)階段,正如我們現(xiàn)在的狀態(tài),那么也強(qiáng)烈建議你多看日志。日志能夠幫助你更加深入理解 OpenStack 的運(yùn)行機(jī)制。日志能夠幫助我們深入學(xué)習(xí) OpenStack 和排查問題。但要想高效的使用日志還得有個(gè)前提:必須先掌握 OpenStack 的運(yùn)行機(jī)制,然后針對(duì)性的查看日志。 就拿 Instance Launch 操作來說,如果之前不了解 nova-* 各子服務(wù)在操作中的協(xié)作關(guān)系,如果沒有理解流程圖,面對(duì)如此多和分散的日志文件,我們也很難下手不是。對(duì)于 OpenStack 的運(yùn)維和管理員來說,在大部分情況下,我們都不需要看源代碼。因?yàn)?OpenStack 的日志記錄得很詳細(xì)了,足以幫助我們分析和定位問題。 但還是有一些細(xì)節(jié)日志沒有記錄,必要時(shí)可以通過查看源代碼理解得更清楚。 即便如此,日志也會(huì)為我們提供源代碼查看的線索,不需要我們大海撈針。

2.3.7 虛擬機(jī)生命周期管理

2.3.7.1 Launch-部署虛擬機(jī)

客戶(可以是 OpenStack 最終用戶,也可以是其他程序)向 API(nova-api)發(fā)送請(qǐng)求:“幫我創(chuàng)建一個(gè) Instance”: 1)API對(duì)請(qǐng)求做一些必要處理后,向 Messaging(RabbitMQ)發(fā)送了一條消息:“讓 Scheduler 創(chuàng)建一個(gè) Instance”; 2)Scheduler(nova-scheduler)從 Messaging 獲取 API 發(fā)給它的消息,然后執(zhí)行調(diào)度算法,從若干計(jì)算節(jié)點(diǎn)中選出節(jié)點(diǎn) A; 3)Scheduler 向 Messaging 發(fā)送了一條消息:“在計(jì)算節(jié)點(diǎn) A 上創(chuàng)建這個(gè) Instance”; 4)計(jì)算節(jié)點(diǎn) A 的 Compute(nova-compute)從 Messaging 中獲取到 Scheduler 發(fā)給它的消息,然后通過本節(jié)點(diǎn)的 Hypervisor Driver 創(chuàng)建 Instance; 5)在 Instance 創(chuàng)建的過程中,Compute 如果需要查詢或更新數(shù)據(jù)庫信息,會(huì)通過 Messaging 向 Conductor(nova-conductor)發(fā)送消息,Conductor 負(fù)責(zé)數(shù)據(jù)庫訪問。

2.3.7.2 Shut Off-關(guān)閉虛擬機(jī)

shut off instance 的流程圖如下所示:1)向 nova-api 發(fā)送請(qǐng)求;2)nova-api 發(fā)送消息;3)nova-compute 執(zhí)行操作。 1)向 nova-api 發(fā)送請(qǐng)求: 客戶(可以是 OpenStack 最終用戶,也可以是其他程序)向 API(nova-api)發(fā)送請(qǐng)求:“幫我關(guān)閉這個(gè) Instance”: 查看日志 /opt/stack/logs/n-api.log: 對(duì)于初學(xué)者,這不是一件容易的事情,因?yàn)槿罩纠飾l目和內(nèi)容很多,特別是 debug 選項(xiàng)打開之后,容易讓人眼花繚亂,無從下手。這里給大家?guī)讉€(gè)小竅門: a)先確定大的范圍,比如在操作之前用 tail -f 打印日志文件,這樣需要查看的日志肯定在操作之后的打印輸出的這些內(nèi)容里。 另外也可以通過時(shí)間戳來確定需要的日志范圍。 b)利用 “代碼模塊” 快速定位有用的信息。 nova-* 子服務(wù)都有自己特定的代碼模塊: nova-api : nova.api.openstack.compute.servers nova.compute.api nova.api.openstack.wsgi nova-compute: nova.compute.manager nova.virt.libvirt.* nova-scheduler: nova.scheduler.* c)利用 Request ID 查找相關(guān)的日志信息。 在上面的日志中,我們可以利用 “req-1758b389-a2d0-44cc-a95a-6f75e4dc07fd” 這個(gè) Request ID 快速定位 n-api.log 中相與 shut off 操作的其他日志條目。 需要補(bǔ)充說明的是,Request ID 是跨日志文件的,這一個(gè)特性能幫助我們?cè)谄渌臃?wù)的日志文件中找到相關(guān)信息,我們后面馬上將會(huì)看到這個(gè)技巧的應(yīng)用。 2)nova-api 發(fā)送消息: nova-api 向 Messaging(RabbitMQ)發(fā)送了一條消息:“關(guān)閉這個(gè) Instance”。nova-api 沒有將發(fā)送消息的操作記錄到日志中,不過我們可以通過查看源代碼來驗(yàn)證。 一提到源代碼,大家可能以為要大海撈針了。其實(shí)很簡單,上面日志已經(jīng)清楚地告訴我們需要查看的源代碼在 /opt/stack/nova/nova/compute/api.py 的 1977 行,方法是 force_stop。 force_stop 方法最后調(diào)用的是對(duì)象 self.compute_rpcapi 的 stop_instance 方法。 在 OpenStack 源碼中,以 xxx_rpcapi 命名的對(duì)象,表示的就是 xxx 的消息隊(duì)列。 xxx_rpcapi.yyy() 方法則表示向 xxx 的消息隊(duì)列發(fā)送 yyy 操作的消息。 所以 self.compute_rpcapi.stop_instance() 的作用就是向 RabbitMQ 上 nova-compute 的消息隊(duì)列里發(fā)送一條 stop instance 的消息。這里補(bǔ)充說明一下: 關(guān)閉 instance 的前提是 instance 當(dāng)前已經(jīng)在某個(gè)計(jì)算節(jié)點(diǎn)上運(yùn)行,所以這里不需要 nova-scheduler 再幫我們挑選合適的節(jié)點(diǎn),這個(gè)跟 launch 操作不同。 3)nova-compute 執(zhí)行操作: 查看計(jì)算節(jié)點(diǎn)上的日志 /opt/stack/logs/n-cpu.log 這里我們利用了 Request ID “req-1758b389-a2d0-44cc-a95a-6f75e4dc07fd”在 n-cpu.log 中快速定位到 nova-compute 關(guān)閉 instance 的日志條目。小結(jié): 分析某個(gè)操作時(shí),我們首先要理清該操作的內(nèi)部流程,然后再到相應(yīng)的節(jié)點(diǎn)上去查看日志 例如shut off 的流程為: 1)向 nova-api 發(fā)送請(qǐng)求; 2)nova-api 發(fā)送消息; 3)nova-compute 執(zhí)行操作。 1,2 兩個(gè)步驟是在控制節(jié)點(diǎn)上執(zhí)行的,查看 nova-api 的日志。第 3 步是在計(jì)算節(jié)點(diǎn)上執(zhí)行的,查看 nova-compute 的日志。

2.3.7.3 Start-啟動(dòng)虛擬機(jī)

下圖是 start instance 的流程圖,包含1) 向 nova-api 發(fā)送請(qǐng)求;2)nova-api 發(fā)送消息;3)nova-compute 執(zhí)行操作。 1)向 nova-api 發(fā)送請(qǐng)求: 客戶(可以是 OpenStack 最終用戶,也可以是其他程序)向API(nova-api)發(fā)送請(qǐng)求:“幫我啟動(dòng)這個(gè) Instance”: 查看日志 /opt/stack/logs/n-api.log : 2)nova-api 發(fā)送消息: nova-api 向 Messaging(RabbitMQ)發(fā)送了一條消息:“啟動(dòng)這個(gè) Instance”。查看源代碼 /opt/stack/nova/nova/compute/api.py 的 2002 行,方法是 start: self.compute_rpcapi.start_instance() 的作用就是向 RabbitMQ 上 nova-compute 的消息隊(duì)列里發(fā)送一條start instance 的消息。 3)nova-compute 執(zhí)行操作: 查看日志 /opt/stack/logs/n-cpu.log。開始啟動(dòng): 準(zhǔn)備虛擬網(wǎng)卡: 準(zhǔn)備 instance 的 XML 文件: 準(zhǔn)備 instance 鏡像文件: 成功啟動(dòng):

2.3.7.4 Soft/Hard Reboot-軟/硬重啟虛擬機(jī)

Soft/Hard Reboot區(qū)別: 1)soft reboot 只是重啟操作系統(tǒng),整個(gè)過程中,instance 依然處于運(yùn)行狀態(tài)。相當(dāng)于在 linux 中執(zhí)行 reboot 命令; 2)hard reboot 是重啟 instance,相當(dāng)于關(guān)機(jī)之后再開機(jī)。提示:soft/hard reboot 在 nova-api 的日志里找不到,這是因?yàn)?/opt/stack/nova/nova/compute/api.py 的 reboot 方法中沒有輸出 log。 可以通過關(guān)鍵字 “nova.api.openstack.wsgi” 或者 “reboot” 搜索;在 nova-compute 的日志中可以看到 “soft reboot” 和 “hard reboot” 二者有明顯的區(qū)別。

2.3.7.5 Lock/Unlock-加鎖/解鎖虛擬機(jī)

為了避免誤操作,比如意外重啟或刪除 instance,可以將 instance 加鎖;對(duì)被加鎖(Lock)的 instance 執(zhí)行重啟等改變狀態(tài)的操作會(huì)提示操作不允許。執(zhí)行解鎖(Unlock)操作后恢復(fù)正常。Lock/Unlock 操作都是在 nova-api 中進(jìn)行的。操作成功后 nova-api 會(huì)更新 instance 加鎖的狀態(tài)。執(zhí)行其他操作時(shí),nova-api 根據(jù)加鎖狀態(tài)來判斷是否允許。Lock/Unlock 不需要 nova-compute 的參與。提示:admin 角色的用戶不受 lock 的影響,即無論加鎖與否都可以正常執(zhí)行操作;根據(jù)默認(rèn) policy 的配置,任何用戶都可以 unlock。也就是說如果發(fā)現(xiàn) instance 被加鎖了,可以通過 unlock 解鎖,然后在執(zhí)行操作。

2.3.7.6 Terminate -刪除虛擬機(jī)

下面是 terminate instance 的流程圖,包含:1)向nova-api 發(fā)送請(qǐng);2)nova-api 發(fā)送消息;3)nova-compute 執(zhí)行操作。 1)向 nova-api 發(fā)送請(qǐng)求 : 客戶(可以是 OpenStack 最終用戶,也可以是其他程序)向 API(nova-api)發(fā)送請(qǐng)求:“幫我刪除這個(gè) Instance”: 查看日志 /opt/stack/logs/n-api.log: 2)nova-api 發(fā)送消息: nova-api 向 Messaging(RabbitMQ)發(fā)送了一條消息:“刪除這個(gè) Instance”。源代碼在 /opt/stack/nova/nova/compute/api.py,方法是 _do_force_delete: 3)nova-compute 執(zhí)行操作 : 查看日志 /opt/stack/logs/n-cpu.log,關(guān)閉 instance: 刪除 instance 的鏡像文件: 釋放虛擬網(wǎng)絡(luò)等其他資源:

2.3.7.7 Pause/Resume-暫停(短時(shí)間)/恢復(fù)(暫停后的恢復(fù),非故障時(shí)恢復(fù))虛擬機(jī)

有時(shí)需要短時(shí)間暫停 instance,可以通過 Pause 操作將 instance 的狀態(tài)保存到宿主機(jī)的內(nèi)存中。當(dāng)需要恢復(fù)的時(shí)候,執(zhí)行 Resume 操作,從內(nèi)存中讀回 instance 的狀態(tài),然后繼續(xù)運(yùn)行 instance。下面是 pause instance 的流程圖,包含:1)向 nova-api 發(fā)送請(qǐng)求;2)nova-api 發(fā)送消息;3)nova-compute 執(zhí)行操作。 1)向nova-api發(fā)送請(qǐng)求: 客戶(可以是 OpenStack 最終用戶,也可以是其他程序)向 API(nova-api)發(fā)送請(qǐng)求:“幫我暫停這個(gè) Instance”: 查看日志 /opt/stack/logs/n-api.log: 注:對(duì)于 Pause 操作,日志沒有前面 Start 記錄得那么詳細(xì)。例如這里就沒有記錄 nova.api.openstack.compute.servers 和 nova.compute.api 代碼模塊的日志,這可能是因?yàn)檫@個(gè)操作邏輯比較簡單,開發(fā)人員在編碼時(shí)沒有加入日志。 2)nova-api 發(fā)送消息: nova-api 向 Messaging(RabbitMQ)發(fā)送了一條消息:“暫停這個(gè) Instance”。查看源代碼 /opt/stack/nova/nova/compute/api.py,方法是 pause: 3)nova-compute 執(zhí)行操作: 查看日志 /opt/stack/logs/n-cpu.log: 暫停操作成功執(zhí)行后,instance 的狀態(tài)變?yōu)?Paused: Resume 操作的日志分析留給大家練習(xí)。 提示:這里的 Resume 操作實(shí)際上是 Unpause 操作,可以通過關(guān)鍵字“unpause”定位日志。

2.3.7.8 Suspend/Resume-暫停(長時(shí)間)/恢復(fù)(暫停后的恢復(fù),非故障時(shí)恢復(fù))虛擬機(jī)

有時(shí)需要長時(shí)間暫停 instance,可以通過 Suspend 操作將 instance 的狀態(tài)保存到宿主機(jī)的磁盤上。當(dāng)需要恢復(fù)的時(shí)候,執(zhí)行 Resume 操作,從磁盤讀回 instance 的狀態(tài),使之繼續(xù)運(yùn)行。這里需要對(duì) Suspend 和 Pause 操作做個(gè)比較: 1)相同點(diǎn):兩者都是暫停 instance 的運(yùn)行,并保存當(dāng)前狀態(tài),之后可以通過 Resume 操作恢復(fù); 2)不同點(diǎn): a)Suspend 將 instance 的狀態(tài)保存在磁盤上;Pause 是保存在內(nèi)存中,所以 Resume 被 Pause 的 instance 要比 Suspend 快。 b)Suspend 之后的 instance,其狀態(tài)是 Shut Down;而被 Pause 的 instance 狀態(tài)是Paused。 c)雖然都是通過 Resume 操作恢復(fù),Pause 對(duì)應(yīng)的 Resume 在 OpenStack 內(nèi)部被叫作 “Unpause”;Suspend 對(duì)應(yīng)的 Resume 才是真正的 “Resume”。這個(gè)在日志中能體現(xiàn)出來。

2.3.7.9 Rescue/Unrescue-恢復(fù)(發(fā)生故障時(shí)恢復(fù))/重新引導(dǎo)虛擬機(jī)

從這節(jié)開始,我們將討論幾種 instance 故障恢復(fù)的方法,不同方法適用于不同的場(chǎng)景。首先我們考慮操作系統(tǒng)故障:有時(shí)候由于誤操作或者突然斷電,操作系統(tǒng)重啟后卻起不來了。為了最大限度挽救數(shù)據(jù),我們通常會(huì)使用一張系統(tǒng)盤將系統(tǒng)引導(dǎo)起來,然后在嘗試恢復(fù)。問題如果不太嚴(yán)重,完全可以通過這種方式讓系統(tǒng)重新正常工作。比如某個(gè)系統(tǒng)文件意外刪除, root 密碼遺忘等。Nova 也提供了這種故障恢復(fù)機(jī)制,叫做 Rescue。 Rescue 用指定的 image 作為啟動(dòng)盤引導(dǎo) instance,將 instance 本身的系統(tǒng)盤作為第二個(gè)磁盤掛載到操作系統(tǒng)上。下面是 rescue instance 的流程圖:包含1)向 nova-api 發(fā)送請(qǐng)求;2)nova-api 發(fā)送消息;3)nova-compute 執(zhí)行操作。 1)向 nova-api 發(fā)送請(qǐng)求: 目前 Rescue 操作只能通過 CLI 執(zhí)行。這里我們沒有指明用哪個(gè) image 作為引導(dǎo)盤,nova 將使用 instance 部署時(shí)使用的 image: 查看日志 /opt/stack/logs/n-api.log: 2)nova-api 發(fā)送消息: nova-api 向 Messaging(RabbitMQ)發(fā)送了一條消息:“Rescue 這個(gè) Instance”。源代碼在 /opt/stack/nova/nova/compute/api.py,方法是 rescue: 3)nova-compute執(zhí)行操作: 查看日志 /opt/stack/logs/n-cpu.log。關(guān)閉 instance: 通過 image 創(chuàng)建新的引導(dǎo)盤,命名為 disk.rescue: 啟動(dòng) instance: Rescue 執(zhí)行成功后,可以通過 virsh edit 查看 instance 的 XML 定義。disk.rescue 作為啟動(dòng)盤 vda,真正的啟動(dòng)盤 disk 作為第二個(gè)磁盤 vdb: 登錄 instance,通過 fdisk 也可確認(rèn),fdisk -l是以列表的形式列出磁盤分區(qū)情況: 此時(shí),instance 處于 Rescue 狀態(tài): Rescue 操作讓我們有機(jī)會(huì)修復(fù)損壞的操作系統(tǒng)。修好之后,使用 Unrescue 操作從原啟動(dòng)盤重新引導(dǎo) instance。

2.3.7.10 Snapshot -創(chuàng)建虛擬機(jī)快照

有時(shí)候操作系統(tǒng)損壞得很嚴(yán)重,通過 Rescue 操作無法修復(fù),那么我們就得考慮通過備份恢復(fù)了。當(dāng)然前提是我們之前對(duì)instance做過備份。Nova 備份的操作叫 Snapshot,其工作原理是對(duì) instance 的鏡像文件(系統(tǒng)盤)進(jìn)行全量備份,生成一個(gè)類型為 snapshot 的 image,然后將其保存到 Glance 上。從備份恢復(fù)的操作叫 Rebuild,將在下一節(jié)重點(diǎn)討論。下面是 snapshot instance 的流程圖,包含1)向 nova-api 發(fā)送請(qǐng)求;2)nova-api 發(fā)送消息;3)nova-compute 執(zhí)行操作。 1)向 nova-api 發(fā)送請(qǐng)求: 客戶(可以是 OpenStack 最終用戶,也可以是其他程序)向 API(nova-api)發(fā)送請(qǐng)求:“對(duì)這個(gè) Instance做個(gè)快照”: 查看日志 /opt/stack/logs/n-api.log: 2)nova-api 發(fā)送消息: nova-api 向 Messaging(RabbitMQ)發(fā)送了一條消息:“對(duì)這個(gè) Instance 做快照”,源代碼在 /opt/stack/nova/nova/compute/api.py,方法是 snapshot: 3)nova-compute 執(zhí)行操作: 查看日志 /opt/stack/logs/n-cpu.log。暫停 instance: 對(duì) instance 的鏡像文件做快照: 恢復(fù) instance: 將快照上傳到 Glance: Snapshot 成功保存在 Glance 中: instance 備份成功,下節(jié)我們討論如何通過 snapshot 恢復(fù)。

2.3.7.11 Rebuild -通過快照恢復(fù)虛擬機(jī)

上一節(jié)我們討論了 snapshot,snapshot 的一個(gè)重要作用是對(duì) instance 做備份。如果 instance 損壞了,可以通過 snapshot 恢復(fù),這個(gè)恢復(fù)的操作就是 Rebuild。 Rebuild 會(huì)用 snapshot 替換 instance 當(dāng)前的鏡像文件,同時(shí)保持 instance 的其他諸如網(wǎng)絡(luò),資源分配屬性不變。下面是 rebuild instance 的流程圖 :1)向 nova-api 發(fā)送請(qǐng)求;2)nova-api 發(fā)送消息;3)nova-compute 執(zhí)行操作。 1)向 nova-api 發(fā)送請(qǐng)求: 客戶(可以是 OpenStack 最終用戶,也可以是其他程序)向 API(nova-api)發(fā)送請(qǐng)求:“Rebuild 這個(gè) Instance”: 選擇用于恢復(fù)的 image: 查看日志/opt/stack/logs/n-api.log : 2)nova-api 發(fā)送消息: nova-api 向 Messaging(RabbitMQ)發(fā)送了一條消息:“Rebuild 這個(gè) Instance”,源代碼在 /opt/stack/nova/nova/compute/api.py,方法是 rebuild: 3)nova-compute 執(zhí)行操作: 查看日志 /opt/stack/logs/n-cpu.log 關(guān)閉 instance: 下載新的 image,并準(zhǔn)備 instance 的鏡像文件 : 啟動(dòng) instance : Rebuild 后,GUI 顯示 instance 已經(jīng)使用新的 image :

2.3.7.12 Shelve-擱置虛擬機(jī)

Instance 被 Suspend 后雖然處于 Shut Down 狀態(tài),但 Hypervisor 依然在宿主機(jī)上為其預(yù)留了資源,以便在以后能夠成功 Resume。如果希望釋放這些預(yù)留資源,可以使用 Shelve 操作。Shelve 會(huì)將 instance 作為 image 保存到 Glance 中,然后在宿主機(jī)上刪除該 instance。下面是 shelve instance 的流程圖 :1)向 nova-api 發(fā)送請(qǐng)求;2)nova-api 發(fā)送消息;3)nova-compute 執(zhí)行操作。 1)客戶(可以是 OpenStack 最終用戶,也可以是其他程序)向API(nova-api)發(fā)送請(qǐng)求:“幫我 shelve 這個(gè) Instance”: 查看日志 /opt/stack/logs/n-api.log: 2)nova-api 發(fā)送消息: nova-api 向 Messaging(RabbitMQ)發(fā)送了一條消息:“shelve 這個(gè) Instance”。查看源代碼 /opt/stack/nova/nova/compute/api.py,方法是 shelve: 3)nova-compute 執(zhí)行操作 : 查看日志 /opt/stack/logs/n-cpu.log。首先,關(guān)閉 instance: 然后對(duì) instance 執(zhí)行 snapshot 操作 : 成功后,snapshot 生成的 image 會(huì)保存在 Glance 上,命名為 -shelved: 最后刪除 instance 在宿主機(jī)上的資源 : 暫停操作成功執(zhí)行后,instance 的狀態(tài)變?yōu)?Shelved Offloaded,電源狀態(tài)是 Shut Down:

2.3.7.13 Unshelve-取消擱置虛擬機(jī)

上一節(jié)我們 shelve instance 到 Glance,本節(jié)討論如何通過 unshelve 操作恢復(fù)該 instance。因?yàn)?Glance 中保存了 instance 的 image,unshelve 的過程其實(shí)就是通過該 image launch 一個(gè)新的 instance,nova-scheduler 也會(huì)調(diào)度合適的計(jì)算節(jié)點(diǎn)來創(chuàng)建該 instance。instance unshelve 后可能運(yùn)行在與 shelve 之前不同的計(jì)算節(jié)點(diǎn)上,但 instance 的其他屬性(比如 flavor,IP 等)不會(huì)改變。下面是 Unshelve instance 的流程圖 :1)向 nova-api 發(fā)送請(qǐng)求;2)nova-api 發(fā)送消息;3)nova-scheduler 執(zhí)行調(diào)度;4)nova-scheduler 發(fā)送消息;5)nova-compute 執(zhí)行操作。 1)向 nova-api 發(fā)送請(qǐng)求 : 客戶(可以是 OpenStack 最終用戶,也可以是其他程序)向 API(nova-api)發(fā)送請(qǐng)求:“幫我 Unshelve 這個(gè) Instance”: 查看日志 /opt/stack/logs/n-api.log: 2)nova-api 發(fā)送消息: nova-api 向 Messaging(RabbitMQ)發(fā)送了一條消息:“unshelve 這個(gè) Instance”。查看源代碼 /opt/stack/nova/nova/compute/api.py,方法是 unshelve: 3)nova-scheduler 執(zhí)行調(diào)度: nova-scheduler 收到消息后,會(huì)為 instance 選擇合適的計(jì)算節(jié)點(diǎn);查看日志 /opt/stack/logs/n-sch.log: 經(jīng)過篩選,最終 devstack-controller 被選中 launch instance。 4)nova-scheduler 發(fā)送消息 : nova-scheduler 發(fā)送消息,告訴被選中的計(jì)算節(jié)點(diǎn)可以 launch instance 了。源代碼在/opt/stack/nova/nova/scheduler/filter_scheduler.py 第 95 行,方法為 select_destinations: 5) nova-compute 執(zhí)行操作 : nova-compute 執(zhí)行 unshelve 的過程與 launch instance 非常類似。一樣會(huì)經(jīng)過如下幾個(gè)步驟:a)為 instance 準(zhǔn)備 CPU、內(nèi)存和磁盤資源;b)創(chuàng)建 instance 鏡像文件;c)創(chuàng)建 instance 的 XML 定義文件;d)創(chuàng)建虛擬網(wǎng)絡(luò)并啟動(dòng) instance。

2.3.7.14 Migrate -遷移虛擬機(jī)

Migrate 操作的作用是將 instance 從當(dāng)前的計(jì)算節(jié)點(diǎn)遷移到其他節(jié)點(diǎn)上。Migrate 不要求源和目標(biāo)節(jié)點(diǎn)必須共享存儲(chǔ),當(dāng)然共享存儲(chǔ)也是可以的。Migrate 前必須滿足一個(gè)條件:計(jì)算節(jié)點(diǎn)間需要配置 nova 用戶無密碼訪問。下面是 Migrate instance 的流程圖:1)向 nova-api 發(fā)送請(qǐng)求;2)nova-api 發(fā)送消息;3)nova-scheduler 執(zhí)行調(diào)度;4)nova-scheduler 發(fā)送消息;5)nova-compute 執(zhí)行操作。 1)向 nova-api 發(fā)送請(qǐng)求 : 客戶(可以是 OpenStack 最終用戶,也可以是其他程序)向 API(nova-api)發(fā)送請(qǐng)求:“幫我遷移這個(gè) Instance”;Migrate 操作是特權(quán)操作,只能在 Admin 的 instance 菜單中執(zhí)行: 查看日志 /opt/stack/logs/n-api.log: 2) nova-api 發(fā)送消息: nova-api 向 Messaging(RabbitMQ)發(fā)送了一條消息:“遷移這個(gè) Instance”;查看源代碼/opt/stack/nova/nova/compute/api.py,方法是 resize。 沒錯(cuò),是 resize 而非 migrate。 這是由于 migrate 實(shí)際上是通過 resize 操作實(shí)現(xiàn)的,至于為什么要這樣設(shè)計(jì),我們會(huì)在下一節(jié) resize 中詳細(xì)分析。 3)nova-scheduler 執(zhí)行調(diào)度 nova-scheduler 收到消息后,會(huì)為 instance 選擇合適的目標(biāo)計(jì)算節(jié)點(diǎn)。查看日志 /opt/stack/logs/n-sch.log可以看到,因?yàn)?devstack-compute1 的權(quán)值比 devstack-controller 大,最終選擇 devstack-compute1 作為目標(biāo)節(jié)點(diǎn)。 看到上面的日志,大家發(fā)現(xiàn)什么問題沒有? 在分析這段日志的時(shí)候,我發(fā)現(xiàn) scheduler 選出來的計(jì)算節(jié)點(diǎn)有可能是當(dāng)前節(jié)點(diǎn)源節(jié)點(diǎn)!因?yàn)?scheduler 并沒在初始的時(shí)候?qū)⒃垂?jié)點(diǎn)剔除掉,而是與其他節(jié)點(diǎn)放在一起做 filter,按照這個(gè)邏輯,只要源節(jié)點(diǎn)的權(quán)值足夠大,是有可能成為目標(biāo)節(jié)點(diǎn)的。 那緊接著的問題是:如果源節(jié)點(diǎn)和目標(biāo)節(jié)點(diǎn)是同一個(gè),migrate 操作會(huì)怎樣進(jìn)行呢? 實(shí)驗(yàn)得知,nova-compute 在做 migrate 的時(shí)候會(huì)檢查目標(biāo)節(jié)點(diǎn),如果發(fā)現(xiàn)目標(biāo)節(jié)點(diǎn)與源節(jié)點(diǎn)相同,會(huì)拋出 UnableToMigrateToSelf 異常。Nova-compute 失敗之后,scheduler 會(huì)重新調(diào)度,由于有 RetryFilter,會(huì)將之前選擇的源節(jié)點(diǎn)過濾掉,這樣就能選到不同的計(jì)算節(jié)點(diǎn)了。 在上面的操作中 sheduler 選擇的目標(biāo)節(jié)點(diǎn)是 devstack-compute1,意味著 instance 將從 devstack-controller 遷移到 devstack-compute1。 4)nova-scheduler 發(fā)送消息: nova-scheduler 發(fā)送消息,通知計(jì)算節(jié)點(diǎn)可以遷移 instance 了 源代碼在/opt/stack/nova/nova/scheduler/filter_scheduler.py 第 95 行,方法為 select_destinations(選擇目標(biāo)節(jié)點(diǎn)): 4)nova-compute 執(zhí)行操作 : nova-compute 會(huì)在源計(jì)算節(jié)點(diǎn)和目標(biāo)計(jì)算節(jié)點(diǎn)上分別執(zhí)行操作。 源計(jì)算節(jié)點(diǎn) devstack-controller: 遷移操作在源節(jié)點(diǎn)上首先會(huì)關(guān)閉 instance,然后將 instance 的鏡像文件傳到目標(biāo)節(jié)點(diǎn)上。日志在 /opt/stack/logs/n-cpu.log,具體步驟如下: a)開始 migrate b)在目標(biāo)節(jié)點(diǎn)上創(chuàng)建 instance 的目錄: nova-compute 首先會(huì)嘗試通過 ssh 在目標(biāo)節(jié)點(diǎn)上的 instance 目錄里 touch 一個(gè)臨時(shí)文件,日志如下: 如果 touch 失敗,說明目標(biāo)節(jié)點(diǎn)上還沒有該 instance 的目錄,也就是說,源節(jié)點(diǎn)和目標(biāo)節(jié)點(diǎn)沒有共享存儲(chǔ)。 那么接下來就要在目標(biāo)節(jié)點(diǎn)上創(chuàng)建 instance 的目錄,日志如下: 關(guān)閉 instance: 將 instance 的鏡像文件通過 scp 傳到目標(biāo)節(jié)點(diǎn)上: 目標(biāo)計(jì)算節(jié)點(diǎn) devstack-compute1: 在目標(biāo)節(jié)點(diǎn)上啟動(dòng) instance,過程與 launch instance 非常類似。會(huì)經(jīng)過如下幾個(gè)步驟:為 instance 準(zhǔn)備 CPU、內(nèi)存和磁盤資源;創(chuàng)建 instance 鏡像文件;創(chuàng)建 instance 的 XML 定義文件;創(chuàng)建虛擬網(wǎng)絡(luò)并啟動(dòng) instance。 5)Confirm 這時(shí),instance 會(huì)處于 “Confirm or Revert Resize/Migrate”狀態(tài),需要用戶確認(rèn)或者回退當(dāng)前的遷移操作,實(shí)際上給了用戶一個(gè)反悔的機(jī)會(huì)。 當(dāng)我們按下 Confirm 按鈕后,會(huì)發(fā)生如下事情,nova-api 接收到 confirm 的消息: 源計(jì)算節(jié)點(diǎn)刪除 instance 的目錄,并在 Hypervisor 上刪除 instance: 目標(biāo)計(jì)算節(jié)點(diǎn)不需要做任何事情。 6)Revert還原 如果執(zhí)行的是 Revert 操作會(huì)發(fā)生什么事情呢? nova-api 接收到 revert 的消息: 在目標(biāo)計(jì)算節(jié)點(diǎn)上關(guān)閉 instance,刪除 instance 的目錄,并在 Hypervisor 上刪除 instance: 源計(jì)算節(jié)點(diǎn)上啟動(dòng) instance: 因?yàn)橹斑w移的時(shí)候只是在源節(jié)點(diǎn)上關(guān)閉了該 instance,revert 操作只需重新啟動(dòng) instance。 以上是 Migrate 操作的完整流程,這里有一點(diǎn)需要特別注意:遷移過程中源和目標(biāo)節(jié)點(diǎn)之前需要使用 ssh 和 scp,為了使操作順利進(jìn)行,必須要保證 nova-compute 進(jìn)程的啟動(dòng)用戶(通常是 nova,也可能是 root,可以通過 ps 命令確認(rèn))能夠在計(jì)算節(jié)點(diǎn)之間無密碼訪問。否則 nova-compute 會(huì)等待密碼輸入,但后臺(tái)服務(wù)是無法輸入密碼的,遷移操作會(huì)一直卡在那里。

2.3.7.15 Resize-調(diào)整虛擬機(jī)的vCPU、內(nèi)存和磁盤資源

Resize 的作用是調(diào)整 instance 的 vCPU、內(nèi)存和磁盤資源。Instance 需要多少資源是定義在 flavor 中的,resize 操作是通過為 instance 選擇新的 flavor 來調(diào)整資源的分配。有了前面對(duì) Migrate 的分析,再來看 Resize 的實(shí)現(xiàn)就非常簡單了。因?yàn)?instance 需要分配的資源發(fā)生了變化,在 resize 之前需要借助 nova-scheduler 重新為 instance 選擇一個(gè)合適的計(jì)算節(jié)點(diǎn),如果選擇的節(jié)點(diǎn)與當(dāng)前節(jié)點(diǎn)不是同一個(gè),那么就需要做 Migrate。所以本質(zhì)上講:Resize 是在 Migrate 的同時(shí)應(yīng)用新的 flavor。 Migrate 可以看做是 resize 的一個(gè)特例:flavor 沒發(fā)生變化的 resize,這也是為什么我們?cè)谏弦还?jié)日志中看到 migrate 實(shí)際上是在執(zhí)行 resize 操作。下面是 Resize instance 的流程圖:1)向 nova-api 發(fā)送請(qǐng)求;2)nova-api 發(fā)送消息;3)nova-scheduler 執(zhí)行調(diào)度;4)nova-scheduler 發(fā)送消息;5)nova-compute 執(zhí)行操作。 Resize 分兩種情況: 1)nova-scheduler 選擇的目標(biāo)節(jié)點(diǎn)與源節(jié)點(diǎn)是不同節(jié)點(diǎn)。操作過程跟上一節(jié) Migrate 幾乎完全一樣,只是在目標(biāo)節(jié)點(diǎn)啟動(dòng) instance 的時(shí)候按新的 flavor 分配資源。 同時(shí),因?yàn)橐绻?jié)點(diǎn)復(fù)制文件,也必須要保證 nova-compute 進(jìn)程的啟動(dòng)用戶(通常是 nova,也可能是 root,可以通過 ps 命令確認(rèn))能夠在計(jì)算節(jié)點(diǎn)之間無密碼訪問。 對(duì)這一種情況我們不再贅述,請(qǐng)參看前面 Migrate 小節(jié)。 2)目標(biāo)節(jié)點(diǎn)與源節(jié)點(diǎn)是同一個(gè)節(jié)點(diǎn)。則不需要 migrate。下面我們重點(diǎn)討論這一種情況。 a) 向 nova-api 發(fā)送請(qǐng)求 客戶(可以是 OpenStack 最終用戶,也可以是其他程序)向 API(nova-api)發(fā)送請(qǐng)求:“幫我 Resize 這個(gè) Instance”: 選擇新的 flavor: 點(diǎn)擊 Resize 按鈕: 查看日志 /opt/stack/logs/n-api.log: b)nova-api 發(fā)送消息: nova-api 向 Messaging(RabbitMQ)發(fā)送了一條消息:“Resize 這個(gè) Instance”。查看源代碼/opt/stack/nova/nova/compute/api.py,方法是 resize_instance: c)nova-scheduler 執(zhí)行調(diào)度: nova-scheduler 收到消息后,會(huì)為 instance 選擇合適的目標(biāo)計(jì)算節(jié)點(diǎn)。查看日志 /opt/stack/logs/n-sch.log: 在本例中,nova-scheduler 選擇了 devstack-compute1 作為的目節(jié)點(diǎn),與源節(jié)點(diǎn)相同。 d)nova-scheduler 發(fā)送消息 : nova-scheduler 發(fā)送消息,通知計(jì)算節(jié)點(diǎn)可以遷移 instance 了。源代碼在 /opt/stack/nova/nova/scheduler/filter_scheduler.py 第 95 行,方法為 select_destinations: e)nova-compute 執(zhí)行操作: 在目標(biāo)節(jié)點(diǎn)上啟動(dòng) instance,過程與 launch instance 非常類似。日志記錄在 /opt/stack/logs/n-cpu.log。會(huì)經(jīng)過如下幾個(gè)步驟: 按新的 flavor 為 instance 準(zhǔn)備 CPU、內(nèi)存和磁盤資源: 關(guān)閉 instance: 創(chuàng)建 instance 鏡像文件: 將 instance 的目錄備份一份,命名為_resize,以便 revert: 創(chuàng)建 instance 的 XML 定義文件: 準(zhǔn)備虛擬網(wǎng)絡(luò): 啟動(dòng) instance: f) Confirm 這時(shí),instance 的狀態(tài)處于“Confirm or Revert Resize/Migrate”狀態(tài),需要用戶確認(rèn)或者回退當(dāng)前的遷移操作,實(shí)際上給了用戶一個(gè)反悔的機(jī)會(huì)。 當(dāng)我們按下 Confirm 按鈕后,會(huì)發(fā)生如下事情:nova-api 接收到 confirm 的消息: 刪除計(jì)算節(jié)上備份的 instance 目錄 _resize: g)revert恢復(fù) 反過來,如果執(zhí)行 Revert 操作會(huì)發(fā)生什么事情呢? nova-api 接收到 revert 的消息: 在計(jì)算節(jié)點(diǎn)上關(guān)閉 instance: 通過備份目錄 _resize 恢復(fù) instance 目錄: 重新啟動(dòng) instance:

2.3.7.16 Live Migrate-在線遷移虛擬機(jī)

Migrate 操作會(huì)先將 instance 停掉,也就是所謂的“冷遷移”。 而 Live Migrate 是“熱遷移”,也叫“在線遷移”,instance不會(huì)停機(jī)。 Live Migrate 分兩種: 1)源和目標(biāo)節(jié)點(diǎn)沒有共享存儲(chǔ),instance 在遷移的時(shí)候需要將其鏡像文件從源節(jié)點(diǎn)傳到目標(biāo)節(jié)點(diǎn),這叫做 Block Migration(塊遷移); 2)源和目標(biāo)節(jié)點(diǎn)共享存儲(chǔ),instance 的鏡像文件不需要遷移,只需要將 instance 的狀態(tài)遷移到目標(biāo)節(jié)點(diǎn)。 源和目標(biāo)節(jié)點(diǎn)需要滿足一些條件才能支持 Live Migration: 1)源和目標(biāo)節(jié)點(diǎn)的 CPU 類型要一致; 2)源和目標(biāo)節(jié)點(diǎn)的 Libvirt 版本要一致; 3)源和目標(biāo)節(jié)點(diǎn)能相互識(shí)別對(duì)方的主機(jī)名稱,比如可以在 /etc/hosts 中加入對(duì)方的條目; 4)在源和目標(biāo)節(jié)點(diǎn)的 /etc/nova/nova.conf 中指明在線遷移時(shí)使用 TCP 協(xié)議; 5)Instance 使用 config driver 保存其 metadata。在 Block Migration 過程中,該 config driver 也需要遷移到目標(biāo)節(jié)點(diǎn)。由于目前 libvirt 只支持遷移 vfat 類型的 config driver,所以必須在 /etc/nova/nova.conf 中明確指明 launch instance 時(shí)創(chuàng)建 vfat 類型的 config driver; 6)源和目標(biāo)節(jié)點(diǎn)的 Libvirt TCP 遠(yuǎn)程監(jiān)聽服務(wù)得打開,需要在下面兩個(gè)配置文件中做一點(diǎn)配置; 非共享存儲(chǔ) Block Migration: 我們先討論非共享存儲(chǔ)的 Block Migration流程圖如下:1)向 nova-api 發(fā)送請(qǐng)求;2)nova-api 發(fā)送消息;3)nova-compute 執(zhí)行操作。 1)向nova-api發(fā)送請(qǐng)求 : 客戶(可以是 OpenStack 最終用戶,也可以是其他程序)向API(nova-api)發(fā)送請(qǐng)求:“幫我將這個(gè) Instance 從節(jié)點(diǎn) A Live Migrate 到節(jié)點(diǎn) B” 這里源節(jié)點(diǎn)是 devstack-compute1,目標(biāo)節(jié)點(diǎn)是 devstack-controller,因?yàn)槭欠枪蚕泶鎯?chǔ),記得將“Block Migration”勾選上。這里還有一個(gè)“Disk Over Commit”選項(xiàng),如果勾選了此選項(xiàng),nova 在檢查目標(biāo)節(jié)點(diǎn)的磁盤空間是否足夠時(shí),是以 instance 磁盤鏡像文件定義的最大容量為準(zhǔn);否則,以磁盤鏡像文件當(dāng)前的實(shí)際大小為準(zhǔn)。 查看日志 /opt/stack/logs/n-api.log: 2)nova-api 發(fā)送消息 : nova-api 向 Messaging(RabbitMQ)發(fā)送了一條消息:“Live Migrate 這個(gè) Instance” ;源代碼在/opt/stack/nova/nova/compute/api.py,方法是 live_migrate: 3)nova-compute 執(zhí)行操作 : 源和目標(biāo)節(jié)點(diǎn)執(zhí)行 Live Migrate 的操作過程如下:目標(biāo)節(jié)點(diǎn)執(zhí)行遷移前的準(zhǔn)備工作,首先將 instance 的數(shù)據(jù)遷移過來,主要包括鏡像文件、虛擬網(wǎng)絡(luò)等資源,日志在 devstack-controller:/opt/stack/logs/n-cpu.log: 源節(jié)點(diǎn)啟動(dòng)遷移操作,暫停 instance: 在目標(biāo)節(jié)點(diǎn)上 Resume instance: 在源節(jié)點(diǎn)上執(zhí)行遷移的后處理工作,刪除 instance: 在目標(biāo)節(jié)點(diǎn)上執(zhí)行遷移的后處理工作,創(chuàng)建 XML,在 Hypervisor 中定義 instance,使之下次能夠正常啟動(dòng)。 Instance 在 Live Migrate 的整個(gè)過程中不會(huì)停機(jī),我們通過 Ping 操作來觀察: 可見在遷移過程中,Ping 進(jìn)程沒有中斷,只是有一個(gè) ping 包的延遲增加了。 共享存儲(chǔ) Live Migration: 有多種方式可以實(shí)現(xiàn)共享存儲(chǔ),比如可以將 instance 的鏡像文件放在 NFS 服務(wù)器上,或者使用 NAS 服務(wù)器,或者分布式文件系統(tǒng)。作為學(xué)習(xí)和實(shí)驗(yàn),這里我們采用 NFS 方案。其他共享存儲(chǔ)方案對(duì)于 Live Migration 本質(zhì)上是一樣的,只是在性能和高可用性上更好。 1)搭建 NFS 環(huán)境 將 devstack-controller 作為 NFS 服務(wù)器,共享其目錄 /opt/stack/data/nova/instances。devstack-compute1 作為 NFS 客戶端將此目錄 mount 到本機(jī),如下所示: 這樣,OpenStack 的 instance 在 devstack-controller 和 devstack-compute1 上就實(shí)現(xiàn)共享存儲(chǔ)了。共享存儲(chǔ)的遷移過程與 Block Migrate 基本上一樣,只是幾個(gè)環(huán)節(jié)有點(diǎn)區(qū)別:向 nova-api 提交請(qǐng)求的時(shí)候,不能勾選“Block Migrate”: 因?yàn)樵春湍繕?biāo)節(jié)點(diǎn)都能直接訪問 instance 的鏡像,所以目標(biāo)節(jié)點(diǎn)在準(zhǔn)備階段不需要傳輸鏡像文件,源節(jié)點(diǎn)在遷移后處理階段也無需刪除 instance 的目錄。只有 instance 的狀態(tài)需要從源節(jié)點(diǎn)傳輸?shù)降哪繕?biāo)節(jié)點(diǎn),整個(gè)遷移速遞比 Block Migration 快很多。

2.3.7.17 Evacuate-撤離虛擬機(jī)

Rebuild 可以恢復(fù)損壞的 instance。那如果是宿主機(jī)壞了怎么辦呢?比如硬件故障或者斷電造成整臺(tái)計(jì)算節(jié)點(diǎn)無法工作,該節(jié)點(diǎn)上運(yùn)行的 instance 如何恢復(fù)呢?用 Shelve 或者 Migrate 可不可以?很不幸,這兩個(gè)操作都要求 instance 所在計(jì)算節(jié)點(diǎn)的 nova-compute 服務(wù)正常運(yùn)行。幸運(yùn)的是,還有 Evacuate 操作。Evacuate 可在 nova-compute 無法工作的情況下將節(jié)點(diǎn)上的 instance 遷移到其他計(jì)算節(jié)點(diǎn)上。但有個(gè)前提是 Instance 的鏡像文件必須放在共享存儲(chǔ)上。下面是 Evacuate instance 的流程圖:1)向 nova-api 發(fā)送請(qǐng)求;2)nova-api 發(fā)送消息;3)nova-scheduler 執(zhí)行調(diào)度;4)nova-scheduler 發(fā)送消息;5)nova-compute 執(zhí)行操作。 1)向 nova-api 發(fā)送請(qǐng)求 : 我們的實(shí)驗(yàn)場(chǎng)景如下: Instance c2 運(yùn)行在 devstack-compute1 上,通過斷電模擬計(jì)算節(jié)點(diǎn)故障,然后執(zhí)行 Evacuate 操作恢復(fù) instance c2,目前 Evacuate 只能通過 CLI 執(zhí)行。 這里需要指定 –on-shared-storage 這個(gè)參數(shù)。 查看日志 /opt/stack/logs/n-api.log: 2)nova-api 發(fā)送消息 nova-api 向 Messaging(RabbitMQ)發(fā)送了一條消息:“Evacuate 這個(gè) Instance”;查看源代碼 /opt/stack/nova/nova/compute/api.py,方法是 evacuate: 大家注意到?jīng)]有,evacuate 實(shí)際上是通過 rebuild 操作實(shí)現(xiàn)的。這是可以理解的,因?yàn)?evacuate 是用共享存儲(chǔ)上 instance 的鏡像文件重新創(chuàng)建虛機(jī) 3) nova-scheduler 執(zhí)行調(diào)度 : nova-scheduler 收到消息后,會(huì)為 instance 選擇合適的計(jì)算節(jié)點(diǎn) 查看日志 /opt/stack/logs/n-sch.log: nova-scheduler 最后選擇在 devstack-controller 計(jì)算節(jié)點(diǎn)上重建 instance。 4) nova-compute 執(zhí)行操作 : 計(jì)算節(jié)點(diǎn)上的工作是用共享存儲(chǔ)上的鏡像文件重建 instance。日志在 devstack-controller:/opt/stack/logs/n-cpu.log。為instance分配資源: 使用共享存儲(chǔ)上的鏡像文件: 啟動(dòng) instance: Evacuate 操作完成后,instance 在 devstack-controller 上運(yùn)行。

2.3.7.18 Nova操作總結(jié)

如上圖所示,我們把對(duì) Instance 的管理按運(yùn)維工作的場(chǎng)景分為兩類:常規(guī)操作和故障處理。

常規(guī)操作:常規(guī)操作中,Launch、Start、Reboot、Shut Off 和 Terminate 都很好理解。 下面幾個(gè)操作重點(diǎn)回顧一下: 1)Resize:通過應(yīng)用不同的 flavor 調(diào)整分配給 instance 的資源。 2)Lock/Unlock:可以防止對(duì) instance 的誤操作。 3)Pause/Suspend/Resume:暫停當(dāng)前 instance,并在以后恢復(fù)。 Pause 和 Suspend 的區(qū)別在于 Pause 將 instance 的運(yùn)行狀態(tài)保存在計(jì)算節(jié)點(diǎn)的內(nèi)存中,而 Suspend 保存在磁盤上。 Pause 的優(yōu)點(diǎn)是 Resume 的速度比 Suspend 快;缺點(diǎn)是如果計(jì)算節(jié)點(diǎn)重啟,內(nèi)存數(shù)據(jù)丟失,就無法 Resume 了,而 Suspend 則沒有這個(gè)問題。 4)Snapshot:備份 instance 到 Glance。產(chǎn)生的 image 可用于故障恢復(fù),或者以此為模板部署新的 instance。故障處理 :故障處理有兩種場(chǎng)景:計(jì)劃內(nèi)和計(jì)劃外。計(jì)劃內(nèi)是指提前安排時(shí)間窗口做的維護(hù)工作,比如服務(wù)器定期的微碼升級(jí),添加更換硬件等。計(jì)劃外是指發(fā)生了沒有預(yù)料到的突發(fā)故障,比如強(qiáng)行關(guān)機(jī)造成 OS 系統(tǒng)文件損壞,服務(wù)器掉電,硬件故障等。 1) 計(jì)劃內(nèi)故障處理:對(duì)于計(jì)劃內(nèi)的故障處理,可以在維護(hù)窗口中將 instance 遷移到其他計(jì)算節(jié)點(diǎn)。 涉及如下操作: a)Migrate:將 instance 遷移到其他計(jì)算節(jié)點(diǎn)。遷移之前,instance 會(huì)被 Shut Off,支持共享存儲(chǔ)和非共享存儲(chǔ)。 b)Live Migrate:與 Migrate 不同,Live Migrate 能不停機(jī)在線地遷移 instance,保證了業(yè)務(wù)的連續(xù)性。也支持共享存儲(chǔ)和非共享存儲(chǔ)(Block Migration)。 c)Shelve/Unshelve:Shelve 將 instance 保存到 Glance 上,之后可通過 Unshelve 重新部署。Shelve 操作成功后,instance 會(huì)從原來的計(jì)算節(jié)點(diǎn)上刪除。Unshelve 會(huì)重新選擇節(jié)點(diǎn)部署,可能不是原節(jié)點(diǎn)。 2) 計(jì)劃外故障處理:計(jì)劃外的故障按照影響的范圍又分為兩類:Instance 故障和計(jì)算節(jié)點(diǎn)故障; a)Instance 故障:Instance故障只限于某一個(gè) instance 的操作系統(tǒng)層面,系統(tǒng)無法正常啟動(dòng)??梢允褂萌缦虏僮餍迯?fù) instance: i)Rescue/Unrescue:用指定的啟動(dòng)盤啟動(dòng),進(jìn)入 Rescue 模式,修復(fù)受損的系統(tǒng)盤。成功修復(fù)后,通過 Unrescue 正常啟動(dòng) instance。 ii)Rebuild:如果 Rescue 無法修復(fù),則只能通過 Rebuild 從已有的備份恢復(fù)。Instance 的備份是通過 snapshot 創(chuàng)建的,所以需要有備份策略定期備份。 b)計(jì)算節(jié)點(diǎn)故障:Instance 故障的影響范圍局限在特定的 instance,計(jì)算節(jié)點(diǎn)本身是正常工作的。如果計(jì)算節(jié)點(diǎn)發(fā)生故障,OpenStack 則無法與節(jié)點(diǎn)的 nova-compute 通信,其上運(yùn)行的所有 instance 都會(huì)受到影響。這個(gè)時(shí)候,只能通過 Evacuate 操作在其他正常節(jié)點(diǎn)上重建 Instance。 i)Evacuate:利用共享存儲(chǔ)上 Instance 的鏡像文件在其他計(jì)算節(jié)點(diǎn)上重建 Instance。 所以提前規(guī)劃共享存儲(chǔ)是關(guān)鍵。

2.4 塊存儲(chǔ)服務(wù)Cinder:為 instance 提供虛擬磁盤

理解 Block Storage 操作系統(tǒng)獲得存儲(chǔ)空間的方式一般有兩種:1)通過某種協(xié)議(SAS,SCSI,SAN,iSCSI 等)掛接裸硬盤,然后分區(qū)、格式化、創(chuàng)建文件系統(tǒng);或者直接使用裸硬盤存儲(chǔ)數(shù)據(jù)(數(shù)據(jù)庫);2)通過 NFS、CIFS 等 協(xié)議,mount 遠(yuǎn)程的文件系統(tǒng)。 第一種裸硬盤的方式叫做 Block Storage(塊存儲(chǔ)),每個(gè)裸硬盤通常也稱作 Volume(卷); 第二種叫做文件系統(tǒng)存儲(chǔ)。NAS 和 NFS 服務(wù)器,以及各種分布式文件系統(tǒng)提供的都是這種存儲(chǔ)。理解 Block Storage Service Block Storage Service提供對(duì) volume 從創(chuàng)建到刪除整個(gè)生命周期的管理。從 instance 的角度看,掛載的每一個(gè) Volume 都是一塊硬盤。OpenStack 提供 Block Storage Service 的是 Cinder,其具體功能是:1)提供 REST API 使用戶能夠查詢和管理 volume、volume snapshot 以及 volume type;2)提供 scheduler 調(diào)度 volume 創(chuàng)建請(qǐng)求,合理優(yōu)化存儲(chǔ)資源的分配;3)通過 driver 架構(gòu)支持多種 back-end(后端)存儲(chǔ)方式,包括 LVM,NFS,Ceph 和其他諸如 EMC、IBM 等商業(yè)存儲(chǔ)產(chǎn)品和方案。

2.4.1 Cider架構(gòu)

上圖是cider的邏輯架構(gòu),包含如下組件: 1)cinder-api:接收 API 請(qǐng)求,調(diào)用 cinder-volume 執(zhí)行操作; 2)cinder-volume:管理 volume 的服務(wù),與 volume provider 協(xié)調(diào)工作,管理 volume 的生命周期。運(yùn)行 cinder-volume 服務(wù)的節(jié)點(diǎn)被稱作為存儲(chǔ)節(jié)點(diǎn); 3)cinder-scheduler:scheduler 通過調(diào)度算法選擇最合適的存儲(chǔ)節(jié)點(diǎn)創(chuàng)建 volume; 4)volume provider:數(shù)據(jù)的存儲(chǔ)設(shè)備,為 volume 提供物理存儲(chǔ)空間。cinder-volume 支持多種 volume provider,每種 volume provider 通過自己的 driver 與cinder-volume 協(xié)調(diào)工作。 5)Message Queue:Cinder 各個(gè)子服務(wù)通過消息隊(duì)列實(shí)現(xiàn)進(jìn)程間通信和相互協(xié)作。因?yàn)橛辛讼㈥?duì)列,子服務(wù)之間實(shí)現(xiàn)了解耦,這種松散的結(jié)構(gòu)也是分布式系統(tǒng)的重要特征。 6)Database:Cinder 有一些數(shù)據(jù)需要存放到數(shù)據(jù)庫中,一般使用 MySQL。數(shù)據(jù)庫是安裝在控制節(jié)點(diǎn)上的,比如在我們的實(shí)驗(yàn)環(huán)境中,可以訪問名稱為“cinder”的數(shù)據(jù)庫。

2.4.2 物理部署方案

Cinder 的服務(wù)會(huì)部署在兩類節(jié)點(diǎn)上,控制節(jié)點(diǎn)和存儲(chǔ)節(jié)點(diǎn)。我們來看看控制節(jié)點(diǎn) devstack-controller 上都運(yùn)行了哪些 cinder-* 子服務(wù): inder-api 和 cinder-scheduler 部署在控制節(jié)點(diǎn)上,這個(gè)很合理。至于 cinder-volume 也在控制節(jié)點(diǎn)上可能有些同學(xué)就會(huì)迷糊了:cinder-volume 不是應(yīng)該部署在存儲(chǔ)節(jié)點(diǎn)上嗎? 要回答這個(gè)問題,首先要搞清楚一個(gè)事實(shí):OpenStack 是分布式系統(tǒng),其每個(gè)子服務(wù)都可以部署在任何地方,只要網(wǎng)絡(luò)能夠連通。無論是哪個(gè)節(jié)點(diǎn),只要上面運(yùn)行了 cinder-volume,它就是一個(gè)存儲(chǔ)節(jié)點(diǎn),當(dāng)然,該節(jié)點(diǎn)上也可以運(yùn)行其他 OpenStack服務(wù)。 cinder-volume 是一頂存儲(chǔ)節(jié)點(diǎn)帽子,cinder-api 是一頂控制節(jié)點(diǎn)帽子。在我們的環(huán)境中,devstack-controller 同時(shí)戴上了這兩頂帽子,所以它既是控制節(jié)點(diǎn),又是存儲(chǔ)節(jié)點(diǎn)。當(dāng)然,我們也可以用一個(gè)專門的節(jié)點(diǎn)來運(yùn)行 cinder-volume。這再一次展示了 OpenStack 分布式架構(gòu)部署上的靈活性:可以將所有服務(wù)都放在一臺(tái)物理機(jī)上,用作一個(gè) All-in-One 的測(cè)試環(huán)境;而在生產(chǎn)環(huán)境中可以將服務(wù)部署在多臺(tái)物理機(jī)上,獲得更好的性能和高可用。RabbitMQ 和 MySQL 通常是放在控制節(jié)點(diǎn)上的。另外,也可以用 cinder service list 查看 cinder-* 子服務(wù)都分布在哪些節(jié)點(diǎn)上: 還有一個(gè)問題:volume provider 放在那里:一般來講,volume provider 是獨(dú)立的。cinder-volume 使用 driver 與 volume provider 通信并協(xié)調(diào)工作。所以只需要將 driver 與 cinder-volume 放到一起就可以了。在 cinder-volume 的源代碼目錄下有很多 driver,支持不同的 volume provider。 后面我們會(huì)以 LVM 和 NFS 這兩種 volume provider 為例討論 cinder-volume 的使用,其他 volume provider 可以查看 OpenStack 的 configuration 文檔。

2.4.3 Cinder設(shè)計(jì)思想

從 volume 創(chuàng)建流程看 cinder-* 子服務(wù)如何協(xié)同工作 ,對(duì)于 Cinder 學(xué)習(xí)來說,Volume 創(chuàng)建是一個(gè)非常好的場(chǎng)景,涉及各個(gè) cinder-* 子服務(wù),下面是流程圖: 1)客戶(可以是 OpenStack 最終用戶,也可以是其他程序)向 API(cinder-api)發(fā)送請(qǐng)求:“幫我創(chuàng)建一個(gè)volume”; 2)API 對(duì)請(qǐng)求做一些必要處理后,向 Messaging(RabbitMQ)發(fā)送了一條消息:“讓 Scheduler 創(chuàng)建一個(gè) volume” ; 3)Scheduler(cinder-scheduler)從 Messaging 獲取到 API 發(fā)給它的消息,然后執(zhí)行調(diào)度算法,從若干計(jì)存儲(chǔ)點(diǎn)中選出節(jié)點(diǎn) A ; 4)Scheduler 向 Messaging 發(fā)送了一條消息:“讓存儲(chǔ)節(jié)點(diǎn) A 創(chuàng)建這個(gè) volume”; 5)存儲(chǔ)節(jié)點(diǎn) A 的 Volume(cinder-volume)從 Messaging 中獲取到 Scheduler 發(fā)給它的消息,然后通過 driver 在 volume provider 上創(chuàng)建 volume。Cinder設(shè)計(jì)思想:Cinder 延續(xù)了 Nova 的以及其他組件的設(shè)計(jì)思想。 1)API 前端服務(wù): cinder-api 作為 Cinder 組件對(duì)外的唯一窗口,向客戶暴露 Cinder 能夠提供的功能,當(dāng)客戶需要執(zhí)行 volume 相關(guān)的操作,只能向 cinder-api 發(fā)送 REST 請(qǐng)求。這里的客戶包括終端用戶、命令行和 OpenStack 其他組件。 設(shè)計(jì) API 前端服務(wù)的好處在于: a)對(duì)外提供統(tǒng)一接口,隱藏實(shí)現(xiàn)細(xì)節(jié); b)API 提供 REST 標(biāo)準(zhǔn)調(diào)用服務(wù),便于與第三方系統(tǒng)集成; c)可以通過運(yùn)行多個(gè) API 服務(wù)實(shí)例輕松實(shí)現(xiàn) API 的高可用,比如運(yùn)行多個(gè) cinder-api 進(jìn)程。 2)Scheduler 調(diào)度服務(wù): Cinder 可以有多個(gè)存儲(chǔ)節(jié)點(diǎn),當(dāng)需要?jiǎng)?chuàng)建 volume 時(shí),cinder-scheduler 會(huì)根據(jù)存儲(chǔ)節(jié)點(diǎn)的屬性和資源使用情況選擇一個(gè)最合適的節(jié)點(diǎn)來創(chuàng)建 volume。 3)Worker 工作服務(wù): 調(diào)度服務(wù)只管分配任務(wù),真正執(zhí)行任務(wù)的是 Worker 工作服務(wù)。 在 Cinder 中,這個(gè) Worker 就是 cinder-volume 了。這種 Scheduler 和 Worker 之間職能上的劃分使得 OpenStack 非常容易擴(kuò)展:當(dāng)存儲(chǔ)資源不夠時(shí)可以增加存儲(chǔ)節(jié)點(diǎn)(增加 Worker)。當(dāng)客戶的請(qǐng)求量太大調(diào)度不過來時(shí),可以增加 Scheduler。 4)Driver 框架: 以 Cinder 為例,存儲(chǔ)節(jié)點(diǎn)支持多種 volume provider,包括 LVM, NFS, Ceph, GlusterFS,以及 EMC, IBM 等商業(yè)存儲(chǔ)系統(tǒng)。cinder-volume 為這些 volume provider 定義了統(tǒng)一的 driver 接口,volume provider 只需要實(shí)現(xiàn)這些接口,就可以 driver 的形式即插即用到 OpenStack 中。 下面是 cinder driver 的架構(gòu)示意圖: 在 cinder-volume 的配置文件 /etc/cinder/cinder.conf 中 volume_driver 配置項(xiàng)設(shè)置該存儲(chǔ)節(jié)點(diǎn)使用哪種 volume provider 的 driver,下面的示例表示使用的是 LVM。

2.4.4 Cinder 組件詳解

2.4.4.1 cinder-api

cinder-api 是整個(gè) Cinder 組件的門戶,所有 cinder 的請(qǐng)求都首先由 cinder-api 處理。cinder-api 向外界暴露若干 HTTP REST API 接口。在 keystone 中我們可以查詢 cinder-api 的 endponits。 客戶端可以將請(qǐng)求發(fā)送到 endponits 指定的地址,向 cinder-api 請(qǐng)求操作。當(dāng)然,作為最終用戶的我們不會(huì)直接發(fā)送 Rest API 請(qǐng)求。OpenStack CLI,Dashboard 和其他需要跟 Cinder 交換的組件會(huì)使用這些 API。cinder-api 對(duì)接收到的 HTTP API 請(qǐng)求會(huì)做如下處理:1)檢查客戶端傳人的參數(shù)是否合法有效;2)調(diào)用 cinder 其他子服務(wù)的處理客戶端請(qǐng)求;3)將 cinder 其他子服務(wù)返回的結(jié)果序列號(hào)并返回給客戶端。cinder-api 接受哪些請(qǐng)求呢? 簡單的說,只要是 Volume 生命周期相關(guān)的操作,cinder-api 都可以響應(yīng)。大部分操作都可以在 Dashboard 上看到。打開 Volume 管理界面: 點(diǎn)擊下拉箭頭,列表中就是 cinder-api 可執(zhí)行的操作:

2.4.4.2 cinder-scheduler

創(chuàng)建 Volume 時(shí),cinder-scheduler 會(huì)基于容量、Volume Type 等條件選擇出最合適的存儲(chǔ)節(jié)點(diǎn),然后讓其創(chuàng)建 Volume。在 /etc/cinder/cinder.conf 中,cinder 通過 scheduler_driver, scheduler_default_filters 和 scheduler_default_weighers 這三個(gè)參數(shù)來配置 cinder-scheduler。 1)Filter scheduler: Filter scheduler 是 cinder-scheduler 默認(rèn)的調(diào)度器 與 Nova 一樣,Cinder 也允許使用第三方 scheduler,配置 scheduler_driver 即可。 scheduler 調(diào)度過程如下: i)通過過濾器(filter)選擇滿足條件的存儲(chǔ)節(jié)點(diǎn)(運(yùn)行 cinder-volume); ii)通過權(quán)重計(jì)算(weighting)選擇最優(yōu)(權(quán)重值最大)的存儲(chǔ)節(jié)點(diǎn)。 可見,cinder-scheduler 的運(yùn)行機(jī)制與 nova-scheduler 完全一樣。 2)Filter : 當(dāng) Filter scheduler 需要執(zhí)行調(diào)度操作時(shí),會(huì)讓 filter 對(duì)存儲(chǔ)節(jié)點(diǎn)進(jìn)行判斷,filter 返回 True 或者 False。cinder.conf 中 scheduler_default_filters 選項(xiàng)指定 filter scheduler 使用的 filter,默認(rèn)值如下: a)AvailabilityZoneFilter: 為提高容災(zāi)性和提供隔離服務(wù),可以將存儲(chǔ)節(jié)點(diǎn)和計(jì)算節(jié)點(diǎn)劃分到不同的 Availability Zone 中。例如把一個(gè)機(jī)架上的機(jī)器劃分在一個(gè) Availability Zone 中。OpenStack 默認(rèn)有一個(gè)命名為“Nova” Availability Zone 的,所有的節(jié)點(diǎn)初始都是放在“Nova”中。用戶可以根據(jù)需要?jiǎng)?chuàng)建自己的 Availability Zone。 創(chuàng)建 Volume 時(shí),需要指定 Volume 所屬的 Availability Zone。 cinder-scheduler 在做 filtering 時(shí),會(huì)使用 AvailabilityZoneFilter 將不屬于指定 Availability Zone 的存儲(chǔ)節(jié)點(diǎn)過濾掉。 b)CapacityFilter: 創(chuàng)建 Volume 時(shí),用戶會(huì)指定 Volume 的大小。CapacityFilter 的作用是將存儲(chǔ)空間不能滿足 Volume 創(chuàng)建需求的存儲(chǔ)節(jié)點(diǎn)過濾掉。 c)CapabilitiesFilter: 不同的 Volume Provider 有自己的特性(Capabilities),比如是否支持 thin provision 等。Cinder 允許用戶創(chuàng)建 Volume 時(shí)通過 Volume Type 指定需要的 Capabilities。 Volume Type 可以根據(jù)需要定義若干 Capabilities,詳細(xì)描述 Volume 的屬性。VolumeVolume Type 的作用與 Nova 的 flavor 類似。Volume Type 在 Admin -> System -> Volume 菜單里管理: 通過 Volume Type 的 Extra Specs 定義 Capabilities: Extra Specs 是用 Key-Value 的形式定義。不同的 Volume Provider 支持的 Extra Specs 不同,需要參考 Volume Provider 的文檔。 上圖所示的 Volume Type 只有一個(gè) Extra Specs “volume_backend_name”,這是最重要也是必須的 Extra Specs。cinder-volume 會(huì)在自己的配置文件 /etc/cinder/cinder.conf 中設(shè)置“volume_backend_name”這個(gè)參數(shù),其作用是為存儲(chǔ)節(jié)點(diǎn)的 Volume Provider 命名。這樣,CapabilitiesFilter 就可以通過 Volume Type 的“volume_backend_name”篩選出指定的 Volume Provider。不同的存儲(chǔ)節(jié)點(diǎn)可以在各自的 cinder.conf 中配置相同的 volume_backend_name,這是允許的。因?yàn)殡m然存儲(chǔ)節(jié)點(diǎn)不同,但它們可能使用的是一種 Volume Provider。如果在第一步 filtering 環(huán)節(jié)選出了多個(gè)存儲(chǔ)節(jié)點(diǎn),那么接下來的 weighting 環(huán)節(jié)會(huì)挑選出最合適的一個(gè)節(jié)點(diǎn)。 3)Weighter : Filter Scheduler 通過 scheduler_default_weighers 指定計(jì)算權(quán)重的 weigher,默認(rèn)為 CapacityWeigher。 如命名所示,CapacityWeigher 基于存儲(chǔ)節(jié)點(diǎn)的空閑容量計(jì)算權(quán)重值,空閑容量最大的勝出。

2.4.4.3 cinder-volume

cinder-volume 在存儲(chǔ)節(jié)點(diǎn)上運(yùn)行,OpenStack 對(duì) Volume 的操作,最后都是交給 cinder-volume 來完成的。cinder-volume 自身并不管理真正的存儲(chǔ)設(shè)備,存儲(chǔ)設(shè)備是由 volume provider 管理的。cinder-volume 與 volume provider 一起實(shí)現(xiàn) volume 生命周期的管理。通過 Driver 架構(gòu)支持多種 Volume Provider 接著的問題是:現(xiàn)在市面上有這么多塊存儲(chǔ)產(chǎn)品和方案(volume provider),cinder-volume 如何與它們配合呢?這就是我們之前討論過的 Driver 架構(gòu)。cinder-volume 為這些 volume provider 定義了統(tǒng)一的接口,volume provider 只需要實(shí)現(xiàn)這些接口,就可以 Driver 的形式即插即用到 OpenStack 系統(tǒng)中。 下面是 Cinder Driver 的架構(gòu)示意圖: 我們可以在 /opt/stack/cinder/cinder/volume/drivers/ 目錄下查看到,OpenStack 源代碼中已經(jīng)自帶了很多 volume provider 的 Driver: 存儲(chǔ)節(jié)點(diǎn)在配置文件 /etc/cinder/cinder.conf 中用 volume_driver 選項(xiàng)配置使用的driver:配置使用的driver 這里 LVM 是我們使用的 volume provider。定期向 OpenStack 報(bào)告計(jì)算節(jié)點(diǎn)的狀態(tài) 在前面 cinder-scheduler 會(huì)用到 CapacityFilter 和 CapacityWeigher,它們都是通過存儲(chǔ)節(jié)點(diǎn)的空閑容量來做篩選。那這里有個(gè)問題:Cinder 是如何得知每個(gè)存儲(chǔ)節(jié)點(diǎn)的空閑容量信息的呢?答案就是:cinder-volume 會(huì)定期向 Cinder 報(bào)告。從 cinder-volume 的日志 /opt/stack/logs/c-vol.log 可以發(fā)現(xiàn)每隔一段時(shí)間,cinder-volume 就會(huì)報(bào)告當(dāng)前存儲(chǔ)節(jié)點(diǎn)的資源使用情況。 因?yàn)樵谖覀兊膶?shí)驗(yàn)環(huán)境中存儲(chǔ)節(jié)點(diǎn)使用的是 LVM,所以在上面的日志看到存儲(chǔ)節(jié)點(diǎn)通過“vgs”和”lvs”這兩個(gè)命令獲取 LVM 的容量使用信息。實(shí)現(xiàn) volume 生命周期管理 Cinder 對(duì) volume 的生命周期的管理最終都是通過 cinder-volume 完成的,包括 volume 的 create、extend、attach、snapshot、delete 等,后面我們會(huì)詳細(xì)討論。

2.4.5 通過場(chǎng)景學(xué)習(xí)Cinder

2.4.5.1 準(zhǔn)備LVM Volume Provider

Cinder 真正負(fù)責(zé) Volume 管理的組件是 volume provider。cinder 支持多種 volume provider,LVM 是默認(rèn)的 volume provider。Devstack 安裝之后,/etc/cinder/cinder 已經(jīng)配置好了 LVM,如下圖所示: 上面的配置定義了名為“l(fā)vmdriver-1”的 volume provider,也稱作 back-end。其 driver 是 LVM,LVM 的 volume group 名為“stack-volumes-lvmdriver-1”。Devstack 安裝時(shí)并沒有自動(dòng)創(chuàng)建 volume group,所以需要我們手工創(chuàng)建。如下步驟演示了在 /dev/sdb 上創(chuàng)建 VG “stack-volumes-lvmdriver-1”: 1)首先創(chuàng)建 physical volume /dev/sdb: Linux 的 lvm 默認(rèn)配置不允許在 /dev/sdb 上創(chuàng)建 PV,需要將 sdb 添加到 /etc/lvm.conf 的 filter 中。 2)然后創(chuàng)建 VG stack-volumes-lvmdriver-1: 打開 Web GUI,可以看到 OpenStack 已經(jīng)創(chuàng)建了 Volume Type “l(fā)vmdriver-1”: 其 Extra Specs volume_backend_name 為 lvmdriver-1:

2.4.5.2 創(chuàng)建volume

Create 操作流程如下: 1)客戶(可以是 OpenStack 最終用戶,也可以是其他程序)向 API(cinder-api)發(fā)送請(qǐng)求:“幫我創(chuàng)建一個(gè) volume”。 2)API 對(duì)請(qǐng)求做一些必要處理后,向 Messaging(RabbitMQ)發(fā)送了一條消息:“讓 Scheduler 創(chuàng)建一個(gè) volume”。 3)Scheduler(cinder-scheduler)從 Messaging 獲取到 API 發(fā)給它的消息,然后執(zhí)行調(diào)度算法,從若干計(jì)存儲(chǔ)點(diǎn)中選出節(jié)點(diǎn) A。 4)Scheduler 向 Messaging 發(fā)送了一條消息:“讓存儲(chǔ)節(jié)點(diǎn) A 創(chuàng)建這個(gè) volume”。 5)存儲(chǔ)節(jié)點(diǎn) A 的 Volume(cinder-volume)從 Messaging 中獲取到 Scheduler 發(fā)給它的消息,然后通過 driver 在 volume provider 上創(chuàng)建 volume。向 cinder-api 發(fā)送請(qǐng)求: 客戶(可以是 OpenStack最終用戶,也可以是其他程序)向 cinder-api發(fā)送請(qǐng)求:“幫我創(chuàng)建一個(gè) volume。GUI 上操作的菜單為 Project -> Compute -> Volumes -> Create Volume: 設(shè)置 volume 的名稱,volume type,大小,Availability Zone 等基本信息。這里我們沒有設(shè)置 Volume Source,這樣會(huì)創(chuàng)建一個(gè)空白的 volume。點(diǎn)擊“Create Volume” 按鈕,cinder-api 將接收到創(chuàng)建 volume 的請(qǐng)求。 查看 cinder-api 日志 /opt/stack/logs/c-api.log: 日志顯示 cinder-api 接收到一個(gè) POST 類型的 REST API,經(jīng)過對(duì) HTTP body 的分析,該請(qǐng)求是:創(chuàng)建一個(gè) 1GB 的 volume。緊接著,cinder-api 啟動(dòng)了一個(gè) Flow(工作流)volume_create_api。Flow 的執(zhí)行狀態(tài)依次為 PENDING(待定), RUNNING 和 SUCCESS。volume_create_api 當(dāng)前的狀態(tài)由 PENDING 變?yōu)?RUNNING。 volume_create_api 工作流包含若干 Task,每個(gè) Task 完成特定的任務(wù) 這些任務(wù)依次為 ExtractVolumeRequestTask, QuotaReserveTask, EntryCreateTask, QuotaCommitTask, VolumeCastTask。Task 的執(zhí)行狀態(tài)也會(huì)經(jīng)歷 PENDING, RUNNING 和 SUCCESS 三個(gè)階段。Task 的名稱基本上說明了任務(wù)的工作內(nèi)容,前面幾個(gè) Task 主要是做一些創(chuàng)建 volume 的準(zhǔn)備工作,比如: 1)ExtractVolumeRequestTask 獲取 request 信息: 2)QuotaReserveTask 預(yù)留配額: 3)EntryCreateTask 在數(shù)據(jù)庫中創(chuàng)建 volume 條目: 4)QuotaCommitTask 確認(rèn)配額: 5)最后 VolumeCastTask 是向 cinder-sheduler 發(fā)送消息,開始調(diào)度工作: 6)至此,F(xiàn)low volume_create_api 已經(jīng)完成,狀態(tài)由 RUNNING 變?yōu)?SUCCESS,volume 創(chuàng)建成功。日志如下: 需要特別注意的是,“volume 創(chuàng)建成功”只是指 cinder-api 已經(jīng)成功處理了 volume create 請(qǐng)求,將消息發(fā)給了 cinder-scheduler,但并不意味 volume 在存儲(chǔ)節(jié)點(diǎn)上已經(jīng)成功創(chuàng)建, 這一點(diǎn)是容易引起誤解的。我們可以通過 cinder-volume 創(chuàng)建 volume 日志的時(shí)間戳驗(yàn)證。 cinder-api 發(fā)送消息: cinder-api 向 RabbitMQ 發(fā)送了一條消息:“讓cinder-scheduler 創(chuàng)建一個(gè) volume”。前面我們提到消息是由 VolumeCastTask 發(fā)出的,因?yàn)?VolumeCastTask 沒有打印相關(guān)日志,我們只能通過源代碼查看 /opt/stack/cinder/cinder/volume/flows/api/create_volume.py ,方法為 create_volume。 cinder-scheduler 執(zhí)行調(diào)度: cinder-scheduler 執(zhí)行調(diào)度算法,通過 Filter 和 Weigher 挑選最優(yōu)的存儲(chǔ)節(jié)點(diǎn),日志為 /opt/stack/logs/c-sch.log。 1)cinder-scheduler 通過 Flow volume_create_scheduler 執(zhí)行調(diào)度工作: 2)該 Flow 依次執(zhí)行 ExtractSchedulerSpecTask 和 ScheduleCreateVolumeTask: 3)主要的 filter 和 weighting 工作由 ScheduleCreateVolumeTask 完成 ScheduleCreateVolumeTask: 經(jīng)過 AvailabilityZoneFilter, CapacityFilter, CapabilitiesFilter 和 CapacityWeigher 的層層篩選,最終選擇了存儲(chǔ)節(jié)點(diǎn) devstack-controller@lvmdriver-1#lvmdriver-1。 4)Flow volume_create_scheduler 完成調(diào)度,狀態(tài)變?yōu)?SUCCESS: 5)cinder-scheduler 發(fā)送消息 : cinder-scheduler 發(fā)送消息給 cinder-volume,讓其創(chuàng)建 volume。源碼 /opt/stack/cinder/cinder/scheduler/filter_scheduler.py,方法為 schedule_create_volume: cinder-volume 的處理過程: cinder-volume 通過 driver 創(chuàng)建 volume,日志為 /opt/stack/logs/c-vol.log。 1)與 cinder-api 和 cinder-scheduler 執(zhí)行方式類似,cinder-volume 也啟動(dòng)了一個(gè) Flow 來完成 volume 創(chuàng)建工作。Flow 的名稱為 volume_create_manager: 2)volume_create_manager 執(zhí)行操作: 首先執(zhí)行ExtractVolumeRefTask, OnFailureRescheduleTask, ExtractVolumeSpecTask, NotifyVolumeActionTask 為 volume 創(chuàng)建做準(zhǔn)備。 3)接下來 CreateVolumeFromSpecTask 執(zhí)行 volume 創(chuàng)建任務(wù) 創(chuàng)建任務(wù): 因?yàn)?volume provider 為 LVM, CreateVolumeFromSpecTask 通過 lvcreate 命令在 VG stack-volumes-lvmdriver-1 中創(chuàng)建了一個(gè) 1G 的 LV,cinder-volume 將這個(gè) LV 作為volume。新創(chuàng)建的 LV 命名為“volume-1e7f6bd7-ce11-4a73-b95e-aabd65a5b188”,其格式為“volume-”。 4)最后,CreateVolumeOnFinishTask 完成掃尾工作: 5)至此,volume 成功創(chuàng)建,F(xiàn)low volume_create_manager 結(jié)束:

2.4.5.3 Attach附加磁盤

本節(jié)討論 cinder-volume 和 nova-compute 如何將 volume attach 到 Instance。

cinder-volume 初始化 volume 的連接: cinder-volume 接收到 initialize_connection 消息后,會(huì)通過 tgt 創(chuàng)建 target,并將 volume 所對(duì)應(yīng)的LV 通過 target export 出來。日志為 /opt/stack/logs/c-vol.log: 下面的日志顯示: 通過命令tgtadm –lld iscsi –op show –mode target 看到已經(jīng)將 1GB(1074MB)的 LV /dev/stack-volumes-lvmdriver-1/volume-1e7f6bd7-ce11-4a73-b95e-aabd65a5b188 通過 Target 1 export 出來了。 Initialize connection 完成: nova-compute 將 volume attach 到 instance: 1)iSCSI是由IBM發(fā)明的基于以太網(wǎng)的存儲(chǔ)協(xié)議,該協(xié)議與SUN的NFS協(xié)議都是為了解決存儲(chǔ)資源共享問題的解決方案。兩者意圖一致,只不過兩者是不同的實(shí)現(xiàn)方式,前者在客戶機(jī)上呈現(xiàn)的是一個(gè)塊設(shè)備,概括的說,iSCSI是一種存儲(chǔ)設(shè)備遠(yuǎn)程映射技術(shù),它可以將一個(gè)遠(yuǎn)程服務(wù)器上的存儲(chǔ)設(shè)備映射到本地,并呈現(xiàn)為一個(gè)塊設(shè)備(大白話就是磁盤)。從普通用戶的角度,映射過來的磁盤與本地安裝的磁盤毫無差異。這種映射方式基于是基于SCSI協(xié)議的,SCSI協(xié)議是計(jì)算機(jī)與外圍設(shè)備(例如硬盤、光盤等)通信的協(xié)議。而iSCSI則是通過TCP協(xié)議對(duì)SCSI進(jìn)行封裝的一種協(xié)議,也就是通過以太網(wǎng)傳輸SCSI協(xié)議的內(nèi)容。 2)計(jì)算節(jié)點(diǎn)作為 iSCSI initiator 訪問存儲(chǔ)節(jié)點(diǎn) Iscsi Target 上的 volume,并將其 attach 到 instance。日志文件為 /opt/stack/logs/n-cpu.log: 3)nova-compute 依次執(zhí)行 iscsiadm 的 new, update, login, rescan 操作訪問 target 上的 volume:(iscsiadm是基于命令行的iscsi管理工具,提供了對(duì)iSCSI節(jié)點(diǎn)、會(huì)話、連接以及發(fā)現(xiàn)記錄的操作。) 4)計(jì)算節(jié)點(diǎn)將 iSCSI target 上的 volume 識(shí)別為一個(gè)磁盤文件: 5)然后通過更新 instance 的 XML 配置文件將 volume 映射給 instance: 6)我們也可以通過 virsh edit 查看更新后的 XML: 可以看到,instance 增加了一個(gè)類型為 block 的虛擬磁盤,source 就是要 attach 的 volume,該虛擬磁盤的設(shè)備名為 vdb。 7)手工 Shut off 并 Start instance,通過 fdisk -l 查看到 volume 已經(jīng) attach 上來,設(shè)備為 vdb: 8)GUI 界面也會(huì)更新相關(guān) attach 信息: 現(xiàn)在如果我們?cè)诖鎯?chǔ)節(jié)點(diǎn)執(zhí)行 tgt-admin –show –mode target,會(huì)看到計(jì)算節(jié)點(diǎn)作為 initiator 已經(jīng)連接到 target 1。cinder-volume 剛剛創(chuàng)建 target 的時(shí)候是沒有 initiator 連接的,大家可以將下面的截圖與之前的日志做個(gè)對(duì)比。

2.4.5.4 Detach卸載磁盤

下圖是Detach操作流程圖,包含1)向 cinder-api 發(fā)送 detach 請(qǐng)求;2)cinder-api 發(fā)送消息;3)nova-compute detach volume;4)cinder-volume 刪除 target。 1)向 cinder-api 發(fā)送 attach 請(qǐng)求: 客戶(可以是 OpenStack 最終用戶,也可以是其他程序)向 cinder-api 發(fā)送請(qǐng)求:“請(qǐng) detach 指定 instance 上的 volume。這里我們將 detach instance “c2”上的 volume “vol-1” 。進(jìn)入 GUI 操作菜單Project -> Compute -> Volumes: 選擇 volume “vol-1”,點(diǎn)擊“Manage Attachments” : 點(diǎn)擊 “Detach Volume”: 再次確認(rèn): cinder-api 將接收到 detach volume 的請(qǐng)求。日志文件在 /opt/stack/logs/c-api.log: 2)cinder-api 發(fā)送消息 cinder-api 發(fā)送消息 detach 消息。cinder-api 沒有打印發(fā)送消息的日志,只能通過源代碼查看 /opt/stack/cinder/cinder/volume/api.py,方法為 detach: Detach 的操作由 nova-compute 和 cinder-volume 共同完成。首先 nova-compute 將 volume 從 instance 上 detach,然后斷開與 iSCSI target 的連接;最后 cinder-volume 刪除 volume 相關(guān)的 iSCSI target。 a)nova-compute detach volume: nova-compute 首先將 volume 從 instance 上 detach,日志為 /opt/stack/logs/n-cpu.log。 這時(shí)通過 virsh edit 可以看到 XML 配置文件中已經(jīng)不在有 volume 的虛擬磁盤: 接下來斷開與 iSCSI target 的連接: 具體步驟如下: i)將緩存中的數(shù)據(jù) Flush 到 volume。 ii)刪除計(jì)算節(jié)點(diǎn)上 volume 對(duì)應(yīng)的 SCSI 設(shè)備。 iii)通過 iscsiadm 的 logout,delete 操作斷開與 iSCSI target 的連接。 compue-nova 完成了 detach 工作,接下來 cinder-volume 就可以刪除 volume 相關(guān)的 target 了。 b)cinder-volume 刪除 target: 存儲(chǔ)節(jié)點(diǎn) cinder-volume 通過 tgt-admin 命令刪除 volume 對(duì)應(yīng)的 target;日志文件為 /opt/stack/logs/c-vol.log。 至此 detach volume 操作已經(jīng)完成,GUI 也會(huì)更新 volume 的 attach 信息:

2.4.5.5 Extend擴(kuò)展磁盤

為了保護(hù)現(xiàn)有數(shù)據(jù),cinder 不允許縮小 volume。Extend 操作用于擴(kuò)大 Volume 的容量,狀態(tài)為 Available 的 volume 才能夠被 extend。如果 volume 當(dāng)前已經(jīng) attach 給 instance,需要先 detach 后才能 extend。Extend 實(shí)現(xiàn)比較簡單,流程圖如下所示:1)向 cinder-api 發(fā)送 extend 請(qǐng)求;2)cinder-api 發(fā)送消息;3)cinder-volume 執(zhí)行 extend 操作。 1)向 cinder-api 發(fā)送 extend 請(qǐng)求: 客戶(可以是 OpenStack 最終用戶,也可以是其他程序)向 cinder-api 發(fā)送請(qǐng)求:“請(qǐng) extend 指定的 volume。這里我們將 extend volume “vol-2”。進(jìn)入 GUI 操作菜單 Project -> Compute -> Volumes: vol-2 當(dāng)前大小為 1GB。其在存儲(chǔ)節(jié)點(diǎn)上對(duì)應(yīng)的 LV 信息如下 LV 信息如下: 選擇 volume “vol-2”,點(diǎn)擊 “Extend Volume”: 指定新的容量為 3GB,點(diǎn)擊 “Extend Volume”: cinder-api 將接收到 extend volume 的請(qǐng)求,日志文件在 /opt/stack/logs/c-api.log: 2)cinder-api 發(fā)送消息: cinder-api 發(fā)送extend 消息。cinder-api 沒有打印發(fā)送消息的日志,只能通過源代碼查看。/opt/stack/cinder/cinder/volume/api.py,方法為 extend: 3) cinder-volume extend volume: cinder-volume 執(zhí)行 lvextend 命令 extend volume。日志為 /opt/stack/logs/c-vol.log: LV 被 extend 到 3GB: Extend 操作完成后,GUI 也會(huì)更新 volume 的狀態(tài)信息:

2.4.5.6 Delete刪除磁盤

今天討論 cinder 如何刪除 volume ,狀態(tài)為 Available 的 volume 才能夠被 delete,如果 volume 當(dāng)前已經(jīng) attach 到 instance,需要先 detach 后才能 delete。Delete操作實(shí)現(xiàn)比較簡單,流程圖如下:1)向 cinder-api 發(fā)送delete 請(qǐng)求;2)cinder-api 發(fā)送消息;3)cinder-volume 執(zhí)行 delete 操作。 1)向 cinder-api 發(fā)送 delete 請(qǐng)求: 客戶(可以是 OpenStack 最終用戶,也可以是其他程序)向 cinder-api 發(fā)送請(qǐng)求:“請(qǐng) delete 指定的 volume。這里我們將 delete volume “vol-2”。進(jìn)入 GUI 操作菜單 Project -> Compute -> Volumes: 選擇volume “vol-2”,點(diǎn)擊“Delete Volume”: 再次確認(rèn): cinder-api 將接收到 delete volume 的請(qǐng)求。日志文件在 /opt/stack/logs/c-api.log: 2)cinder-api 發(fā)送消息: cinder-api 發(fā)送消息 delete 消息。cinder-api 沒有打印發(fā)送消息的日志,只能通過源代碼查看。opt/stack/cinder/cinder/volume/api.py,方法為 extend。 3)cinder-volume delete volume: cinder-volume 執(zhí)行 lvremove 命令 delete volume,日志為 /opt/stack/logs/c-vol.log。 這里比較有意思的是:cinder-volume 執(zhí)行的是“安全”刪除。所謂“安全”實(shí)際上就是將 volume 中的數(shù)據(jù)抹掉,LVM driver 使用的是 dd 操作將 LV 的數(shù)據(jù)清零,日志如下: 然后刪除 LV:

2.4.5.7 Snapshot磁盤快照

Snapshot 可以為 volume 創(chuàng)建快照,快照中保存了 volume 當(dāng)前的狀態(tài),以后可以通過 snapshot 回溯。snapshot 操作實(shí)現(xiàn)比較簡單,流程圖如下所示:1)向 cinder-api 發(fā)送 snapshot 請(qǐng)求;2)cinder-api 發(fā)送消息;3)cinder-volume 執(zhí)行 snapshot 操作。 1)向 cinder-api 發(fā)送 snapshot 請(qǐng)求: 客戶(可以是 OpenStack 最終用戶,也可以是其他程序)向 cinder-api 發(fā)送請(qǐng)求:“請(qǐng) snapshot 指定的 volume。這里我們將 snapshot volume “vol-1”。進(jìn)入 GUI 操作菜單 Project -> Compute -> Volumes: 選擇 volume “vol-1”,點(diǎn)擊 “Create Snapshot”: 為 snapshot 命名: 這里我們看到界面提示當(dāng)前 volume 已經(jīng) attach 到某個(gè) instance,創(chuàng)建 snapshot 可能導(dǎo)致數(shù)據(jù)不一致。我們可以先 pause instance,或者確認(rèn)當(dāng)前 instance 沒有大量的磁盤 IO,處于相對(duì)穩(wěn)定的狀態(tài),則可以創(chuàng)建 snapshot,否則還是建議先 detach volume 再做 sanpshot。 cinder-api 將接收到 snapshot volume 的請(qǐng)求,日志文件在 /opt/stack/logs/c-api.log: 2)cinder-api 發(fā)送消息: cinder-api 發(fā)送消息 snapshot 消息。cinder-api 沒有打印發(fā)送消息的日志,只能通過源代碼查看 /opt/stack/cinder/cinder/volume/api.py,方法為 _create_snapshot: 3)cinder-volume 執(zhí)行 snapshot 操作: cinder-volume 執(zhí)行 lvcreate 命令創(chuàng)建 snapshot。日志為 /opt/stack/logs/c-vol.log: 對(duì)于 LVM volume provider,snapshot 實(shí)際上也是一個(gè) LV,同時(shí)記錄了與源 LV 的 snapshot 關(guān)系,可以通過 lvdisplay 查看: GUI 的 Volume Snapshots 標(biāo)簽中可以看到新創(chuàng)建的 “vol-1-snapshot”: 有了 snapshot,我們就可以將 volume 回溯到創(chuàng)建 snapshot 時(shí)的狀態(tài),方法是通過 snapshot 創(chuàng)建新的 volume: 新創(chuàng)建的 volume 容量必須大于或等于 snapshot 的容量: 其過程與 Create Volume 類似,不同之處在于 LV 創(chuàng)建之后會(huì)通過 dd 將 snapshot 的數(shù)據(jù) copy 到新的 volume。如果一個(gè) volume 存在 snapshot,則這個(gè) volume 是無法刪除的。這是因?yàn)?snapshot 依賴于 volume,snapshot 無法獨(dú)立存在。 在 LVM 作為 volume provider 的環(huán)境中,snapshot 是從源 volume 完全 copy 而來,所以這種依賴關(guān)系不強(qiáng)。但在其他 volume provider(比如商業(yè)存儲(chǔ)設(shè)備或者分布式文件系統(tǒng)),snapshot 通常是源 volume 創(chuàng)建快照時(shí)數(shù)據(jù)狀態(tài)的一個(gè)引用(指針),占用空間非常小,在這種實(shí)現(xiàn)方式里 snapshot 對(duì)源 volume 的依賴就非常明顯了。

2.4.5.8 Backup磁盤備份

本節(jié)我們討論 volume 的 Backup 操作。Backup 是將 volume 備份到別的地方(備份設(shè)備),將來可以通過 restore 操作恢復(fù)。Backup VS Snapshot: 初看 backup 功能好像與 snapshot 很相似,都可以保存 volume 的當(dāng)前狀態(tài),以備以后恢復(fù)。但二者在用途和實(shí)現(xiàn)上還是有區(qū)別的,具體表現(xiàn)在: 1)Snapshot 依賴于源 volume,不能獨(dú)立存在;而 backup 不依賴源 volume,即便源 volume 不存在了,也可以 restore。 2)Snapshot 與源 volume 通常存放在一起,都由同一個(gè) volume provider 管理;而 backup 存放在獨(dú)立的備份設(shè)備中,有自己的備份方案和實(shí)現(xiàn),與 volume provider 沒有關(guān)系。 3)上面兩點(diǎn)決定了 backup 具有容災(zāi)功能;而 snapshot 則提供 volume provider 內(nèi)便捷的回溯功能。配置 cinder-backup: Cinder 的 backup 功能是由 cinder-backup 服務(wù)提供的,devstack 默認(rèn)沒有啟用該服務(wù),需要手工啟用 與 cinder-volume 類似,cinder-backup 也通過 driver 架構(gòu)支持多種備份 backend,包括 POSIX 文件系統(tǒng)、NFS、Ceph、GlusterFS、Swift 和 IBM TSM。支持的driver 源文件放在 /opt/stack/cinder/cinder/backup/drivers/: 本節(jié)我們將以 NFS 為 backend 來研究 backup 操作 : 在實(shí)驗(yàn)環(huán)境中,存放 volume backup 的 NFS 遠(yuǎn)程目錄為 192.168.104.11:/backup,cinder-backup 服務(wù)節(jié)點(diǎn)上 mount point 為 /backup_mount。需要在 /etc/cinder/cinder.conf 中作相應(yīng)配置: 然后手工啟動(dòng) cinder-backup 服務(wù): 一切準(zhǔn)備就緒,下面我們來看 backup 操作的流程:1)向 cinder-api 發(fā)送 backup 請(qǐng)求;2)cinder-api 發(fā)送消息;3)cinder-backup 執(zhí)行 backup 操作。 1)向 cinder-api 發(fā)送 backup 請(qǐng)求: 客戶(可以是 OpenStack 最終用戶,也可以是其他程序)向 cinder-api 發(fā)送請(qǐng)求:“請(qǐng) backup 指定的 volume。這里我們將 backup volume “vol-1”,目前 backup 只能在 CLI 中執(zhí)行,采用cinder backup-create vol-1 --force命令。 這里因?yàn)?vol-1 已經(jīng) attach 到 instance,需要使用 –force 選項(xiàng)。cinder-api 接收到 backup volume 的請(qǐng)求。日志文件在 /opt/stack/logs/c-api.log。

2)cinder-api 發(fā)送消息: cinder-api 發(fā)送 backup 消息。cinder-api 沒有打印發(fā)送消息的日志,只能通過源代碼查看 /opt/stack/cinder/cinder/backup/api.py,方法為 create: 3)cinder-backup 執(zhí)行 backup 操作: cinder-backup 收到消息后,通過如下步驟完成 backup 操作,日志為 /opt/stack/logs/c-vol.log。 i)啟動(dòng) backup 操作,mount NFS。 ii)創(chuàng)建 volume 的臨時(shí)快照。 iii)創(chuàng)建存放 backup 的 container 目錄。 iv)對(duì)臨時(shí)快照數(shù)據(jù)進(jìn)行壓縮,并保存到 container 目錄。 v)創(chuàng)建并保存 sha256(加密)文件和 metadata 文件。 vi)刪除臨時(shí)快照。 Backup 完成后,我們可以查看一下 container 目錄的內(nèi)容:里面有三個(gè)文件,根據(jù)前面的日志我們可以知道:backup-00001,壓縮后的 backup 文件。backup_metadata,metadata 文件。backup_sha256file,加密文件。 可以通過 cinder backup-list 查看當(dāng)前存在的 backup: 另外我們采用cinder help backup-create命令可以查看一下 cinder backup-create 的用法: 這里有--incremental 選項(xiàng),表示可以執(zhí)行增量備份。如果之前做過普通(全量)備份,之后可以通過增量備份大大減少需要備份的數(shù)據(jù)量,是個(gè)很不錯(cuò)的功能。

2.4.5.9 restore磁盤恢復(fù)

前面我們 backup 了 voluem,今天我們將討論如何 restore volume。restore 的過程其實(shí)很簡單,兩步走:1)在存儲(chǔ)節(jié)點(diǎn)上創(chuàng)建一個(gè)空白 volume。2)將 backup 的數(shù)據(jù) copy 到空白 voluem 上。下面我們來看 restore 操作的詳細(xì)流程:1)向 cinder-api 發(fā)送 restore 請(qǐng)求;2)cinder-api 發(fā)送消息;3)cinder-scheduler 挑選最合適的 cinder-volume;4)cinder-volume 創(chuàng)建空白 volume;5)cinder-backup 將 backup 數(shù)據(jù) copy 到空白 volume 上。 1) 向 cinder-api 發(fā)送 restore 請(qǐng)求: 客戶(可以是 OpenStack 最終用戶,也可以是其他程序)向 cinder-api 發(fā)送請(qǐng)求:“請(qǐng) restore 指定的 backup”。這里我們將 restore 之前創(chuàng)建的 backup,目前 restore 只能在 CLI 中執(zhí)行,先采用cinder backup-list命令查看backup,采用cinder backup-restore 備份volume的ID命令進(jìn)行恢復(fù): cinder-api 接收到 restore 請(qǐng)求,日志文件在 /opt/stack/logs/c-api.log: 這里看到 cinder-api 轉(zhuǎn)發(fā)請(qǐng)求,為 restore 創(chuàng)建 volume。 之后 cinder-scheduler 和 cinder-volume 將創(chuàng)建空白 volume,這個(gè)過程與 create volume 一樣,不再贅述。 2)接下來分析數(shù)據(jù)恢復(fù)的過程 a)首先,在 cinder-api 日志中可以看到相關(guān)信息: 這里注意日志中的 volume_id 和 backup_id 與前面 backup-restore 命令的輸出是一致的。 b)下面來看 cinder-backup 是如何恢復(fù)數(shù)據(jù)的。cinder-backup 執(zhí)行 restore 操作:日志為 /opt/stack/logs/c-vol.log。 i)啟動(dòng) restore 操作,mount NFS。 ii)讀取 container 目錄中的 metadata。 iii)將數(shù)據(jù)解壓并寫到 volume 中。 iv)恢復(fù) volume 的 metadata,完成 restore 操作。 c)此時(shí),在 GUI 中已經(jīng)可以看到 restore 創(chuàng)建的 volume:

2.4.5.10 Boot From Volume 將Volume作為虛擬機(jī)的啟動(dòng)盤

Volume 除了可以用作 instance 的數(shù)據(jù)盤,也可以作為啟動(dòng)盤(Bootable Volume)。 那么如何使 volume 成為 bootable 呢?現(xiàn)在我們打開 instance 的 launch 操作界面: 這里有一個(gè)下拉菜單“Instance Boot Source”。以前我們 launch(部署)instance 要么直接從 image launch(Boot from image),要么從 instance 的 snapshot launch(Boot from snapshot)。 這兩種 launch 方式下,instance 的啟動(dòng)盤 vda 均為鏡像文件,存放路徑為計(jì)算節(jié)點(diǎn) /opt/stack/data/nova/instances//disk,例如: 下拉列表的后三項(xiàng)則可以將 volume 作為 instance 的啟動(dòng)盤 vda,分別為: 1)Boot from volume:直接從現(xiàn)有的 bootable volume launch; 2)Boot from image (create a new volume):創(chuàng)建一個(gè)新的 volume,將 image 的數(shù)據(jù) copy 到 volume,然后從該 volume launch; 3)Boot from volume snapshot (create a new volume):通過指定的 volume snapshot 創(chuàng)建 volume,然后從該 volume launch,當(dāng)然前提是該snapshot 對(duì)應(yīng)的源 volume 是 bootable 的。 下面我們以 Boot from image (create a new volume)為例,看如何從 volume 啟動(dòng): 選擇 cirros 作為 image,instance 命名為“c3” ,如果希望 terminate instance 的時(shí)候同時(shí)刪除 volume,可以勾選“Delete on Terminate”。 c3 成功 Launch 后,volume 列表中可以看到一個(gè)新 bootable volume,以 volume ID 命名,并且已經(jīng) attach 到 c3。 該 volume 已經(jīng)配置為 c3 的啟動(dòng)盤 vda: 如果用該 volume 創(chuàng)建 snapshot,之后就可以通過 Boot from volume snapshot (create a new volume) 部署新的instance。boot from volume 的 instance 也可以執(zhí)行 live migrate。前面的實(shí)驗(yàn)使用的是 LVM provider,cinder 當(dāng)然也支持其他 provider。

2.4.5.11 NFS Volume Provider

cinder-volume 支持多種 volume provider,前面我們一直使用的是默認(rèn)的 LVM,本節(jié)我們將增加 NFS volume provider。雖然 NFS 更多地應(yīng)用在實(shí)驗(yàn)或小規(guī)模 cinder 環(huán)境,由于性能和缺乏高可用的原因在生產(chǎn)環(huán)境中不太可能使用。 但是學(xué)習(xí) NFS volume provider 的意義在于: 1)理解 cinder-volume 如何支持多 backend; 2)更重要的,可以理解 cinder-volume,nova-compute 和 volume provider 是如何協(xié)同工作,共同為 instance 提供塊存儲(chǔ); 3)舉一反三,能夠快速理解并接入其他生產(chǎn)級(jí) backend ,比如 Ceph,商業(yè)存儲(chǔ)等。 下圖展示了 cinder、nova 是如何與 NFS volume provider 協(xié)調(diào)工作的: 1)NFS Volume Provider:就是我們通常說的 NFS Server,提供遠(yuǎn)程 NFS 目錄,NFS Clinet 可以 mount 這些遠(yuǎn)程目錄到本地,然后像使用本地目錄一樣創(chuàng)建、讀寫文件以及子目錄。 2)cinder-volume:存儲(chǔ)節(jié)點(diǎn)通過 NFS driver 管理 NFS volume provider 中的 volume,這些 volume 在 NFS 中實(shí)際上是一個(gè)個(gè)文件。 3)nova-compute:計(jì)算節(jié)點(diǎn)將 NFS volume provider 存放 volume 的目錄 mount 到本地,然后將 volume 文件作為虛擬硬盤映射給 instance。 這里有幾點(diǎn)需要強(qiáng)調(diào) 1)在 Cinder 的 driver 架構(gòu)中,運(yùn)行 cinder-volume 的存儲(chǔ)節(jié)點(diǎn)和 Volume Provider 可以是完全獨(dú)立的兩個(gè)實(shí)體。cinder-volume 通過 driver 與 Volume Provider 通信,控制和管理 volume。 2)Instance 讀寫 volume 時(shí),數(shù)據(jù)流不需要經(jīng)過存儲(chǔ)節(jié)點(diǎn),而是直接對(duì) Volume Provider 中的 volume 進(jìn)行讀寫。 正如上圖所示,存儲(chǔ)節(jié)點(diǎn)與 NFS Volume Provider 的連接只用作 volume 的管理和控制(綠色連線);真正的數(shù)據(jù)讀寫,是通過計(jì)算節(jié)點(diǎn)和 NFS Volume Proiver 之間的連接完成的(紫色連線)。這種設(shè)計(jì)減少了中間環(huán)節(jié),存儲(chǔ)節(jié)點(diǎn)不直接參與數(shù)據(jù)傳輸,保證了讀寫效率。 3)其他 Volume Provider(例如 ceph,swift,商業(yè)存儲(chǔ)等)均遵循這種控制流與數(shù)據(jù)流分離的設(shè)計(jì)。 配置 NFS Volume Provider: 在實(shí)驗(yàn)環(huán)境中,NFS volume provider 的 NFS 遠(yuǎn)程目錄為 192.168.104.11:/storage,cinder-volume 服務(wù)節(jié)點(diǎn)上 mount point 為 /nfs_storage。在 /etc/cinder/cinder.conf 中添加 nfs backend: 配置enabled_backends = lvmdriver-1,nfs是 讓 cinder-volume 使用 nfs backend。[nfs]中詳細(xì)配置 nfs backend。包括: a) 使用nfs_mount_point_base = /nfs_storage命令,指定存儲(chǔ)節(jié)點(diǎn)上 /nfs_storage 為 nfs 的 mount point。 b) 查看 /etc/cinder/nfs_shares 活動(dòng) nfs 共享目錄列表。 nfs_shares_config = /etc/cinder/nfs_shares,其內(nèi)容為: 列表中只有 192.168.104.11:/storage。如果希望有多個(gè) nfs 共享目錄存放 volume,則可以添加到該文件中。 c) nfs volume driver。 volume_driver=cinder.volume.drivers.nfs.NfsDriver d) 設(shè)置 volume backend name。在 cinder 中需要根據(jù)這里的 volume_backend_name 創(chuàng)建對(duì)應(yīng)的 volume type,這個(gè)非常重要,volume_backend_name = nfs。 重啟 cinder-volume,cinder service-list 確認(rèn) nfs cinder-volume 服務(wù)正常工作: 創(chuàng)建 nfs volume type 打開GUI頁面Admin -> System -> Volumes -> Volume Types,點(diǎn)擊 “Create Volume Type”: 命名 nfs,點(diǎn)擊“Create Volume Type”: 選擇 nfs volume type,點(diǎn)擊下拉菜單“View Extra Specs”: 點(diǎn)擊“Create”,Key 輸入 volume_backend_name ;Value 輸入 nfs: NFS volume provider 準(zhǔn)備就緒,下一節(jié)我們將創(chuàng)建 NFS 為 backend 的 volume。 創(chuàng)建volume 1)創(chuàng)建 NFS volume 操作方法與 LVM volume 一樣,唯一區(qū)別是在 volume type 的下拉列表中選擇“nfs”: 點(diǎn)擊“Create Volume”,cinder-api,cinder-scheduler 和 cinder-volume 共同協(xié)作創(chuàng)建 volume “nfs-vol-1”。這個(gè)流程與 LVM volume 一樣。 2)分析 cinder-volume 的日志: 看看 NFS volume provider 是如何創(chuàng)建 volume 的,日志在 /opt/stack/logs/c-vol.log。 i)cinder-volume 也會(huì)啟動(dòng) Flow 來完成 volume 創(chuàng)建工作,F(xiàn)low 的名稱為 volume_create_manager: volume_create_manager 首先執(zhí)行 ExtractVolumeRefTask, OnFailureRescheduleTask, ExtractVolumeSpecTask, NotifyVolumeActionTask 為 volume創(chuàng)建做準(zhǔn)備。 ii)然后由 CreateVolumeFromSpecTask 真正創(chuàng)建 volume: iii)首先 mount 遠(yuǎn)程 NFS 目錄: iv)執(zhí)行 stat、du 命令檢查 NFS 目錄: v)執(zhí)行 truncate 創(chuàng)建 volume 文件: vi)采用chmod ugo+rw命令設(shè)置 volume 文件為可讀寫: vii)create 操作完成: viii)Volume 在 NFS 上以文件存在,命名為“volume-”: ix)GUI volume 列表中可以看到新創(chuàng)建的 volume: GUI volume 列表中可以看到新創(chuàng)建的 volume。 nova-compute 如何將“nfs-vol-1” attach 到“c2” : 通過日志分析,nova-compute 會(huì)將存放 volume 文件的 NFS 目錄 mount 到本地 /opt/stack/data/nova/mnt 目錄下,然后修改 instance 的 XML 將 volume 文件配置為虛擬磁盤,日志為 /opt/stack/logs/n-cpu.log。 1)通過 findmnt 和 mkdir 測(cè)試和創(chuàng)建 mount point: 2)mount NFS 目錄: 3)更新 instance 的XML,將 volume 文件映射給 instance: 4)我們也可以通過 virsh edit 查看更新后的XML: 5)GUI 界面也會(huì)更新相關(guān) attach 信息:

2.5 網(wǎng)絡(luò)服務(wù)Neutron

2.5.1 Neutron概述

2.5.1.1 Neutron功能

二層交換 Switching 1)Nova 的 Instance 是通過虛擬交換機(jī)連接到虛擬二層網(wǎng)絡(luò)的。 2)Neutron 支持多種虛擬交換機(jī),包括 Linux 原生的 Linux Bridge 和 Open vSwitch。Open vSwitch(OVS)是一個(gè)開源的虛擬交換機(jī),它支持標(biāo)準(zhǔn)的管理接口和協(xié)議。 3)利用 Linux Bridge 和 OVS,Neutron 除了可以創(chuàng)建傳統(tǒng)的 VLAN 網(wǎng)絡(luò),還可以創(chuàng)建基于隧道技術(shù)的 Overlay 網(wǎng)絡(luò),比如 VxLAN 和 GRE(Linux Bridge 目前只支持 VxLAN)。三層路由 Routing 1)Instance 可以配置不同網(wǎng)段的 IP,Neutron 的 router(虛擬路由器)實(shí)現(xiàn) instance 跨網(wǎng)段通信。 2)router 通過 IP forwarding,iptables 等技術(shù)來實(shí)現(xiàn)路由和 NAT。(IP forwarding是IP轉(zhuǎn)發(fā),一種路由協(xié)議。IP轉(zhuǎn)發(fā)是操作系統(tǒng)的一種選項(xiàng),支持主機(jī)起到路由器的功能。在一個(gè)系統(tǒng)中含有兩塊以上的網(wǎng)卡,并將IP轉(zhuǎn)發(fā)選項(xiàng)打開,這樣該系統(tǒng)就可以作為路由器進(jìn)行使用了)。負(fù)載均衡 Load Balancing 1)Openstack 在 Grizzly 版本第一次引入了 Load-Balancing-as-a-Service(LBaaS),提供了將負(fù)載分發(fā)到多個(gè) instance 的能力。LBaaS 支持多種負(fù)載均衡產(chǎn)品和方案,不同的實(shí)現(xiàn)以 Plugin(插件) 的形式集成到 Neutron,目前默認(rèn)的 Plugin 是 HAProxy。防火墻 Firewalling Neutron 通過下面兩種方式來保障 instance 和網(wǎng)絡(luò)的安全性。 1)Security Group:通過 iptables 限制進(jìn)出 instance 的網(wǎng)絡(luò)包。 2)Firewall-as-a-Service:FWaaS,限制進(jìn)出虛擬路由器的網(wǎng)絡(luò)包,通過 iptables 實(shí)現(xiàn)。

2.5.1.2 Neutron網(wǎng)絡(luò)基本概念

network : network 是一個(gè)隔離的二層廣播域。Neutron 支持多種類型的 network,包括 local, flat, VLAN, VxLAN 和 GRE。 1)local local 網(wǎng)絡(luò)與其他網(wǎng)絡(luò)和節(jié)點(diǎn)隔離。local 網(wǎng)絡(luò)中的 instance 只能與位于同一節(jié)點(diǎn)上同一網(wǎng)絡(luò)的 instance 通信,local 網(wǎng)絡(luò)主要用于單機(jī)測(cè)試。 2)flat flat 網(wǎng)絡(luò)是無 vlan tagging 的網(wǎng)絡(luò)。flat 網(wǎng)絡(luò)中的 instance 能與位于同一網(wǎng)絡(luò)的 instance 通信,并且可以跨多個(gè)節(jié)點(diǎn)。 3)vlan vlan 網(wǎng)絡(luò)是具有 802.1q tagging 的網(wǎng)絡(luò)。vlan 是一個(gè)二層的廣播域,同一 vlan 中的 instance 可以通信,不同 vlan 只能通過 router 通信。vlan 網(wǎng)絡(luò)可以跨節(jié)點(diǎn),是應(yīng)用最廣泛的網(wǎng)絡(luò)類型。 4)vxlan vxlan 是基于隧道技術(shù)的 overlay 網(wǎng)絡(luò)。vxlan 網(wǎng)絡(luò)通過唯一的 segmentation ID(也叫 VNI)與其他 vxlan 網(wǎng)絡(luò)區(qū)分。vxlan 中數(shù)據(jù)包會(huì)通過 VNI 封裝成 UDP 包進(jìn)行傳輸。因?yàn)槎拥陌ㄟ^封裝在三層傳輸,能夠克服 vlan 和物理網(wǎng)絡(luò)基礎(chǔ)設(shè)施的限制。 5)gre gre 是與 vxlan 類似的一種 overlay 網(wǎng)絡(luò)。主要區(qū)別在于使用 IP 包而非 UDP 進(jìn)行封裝。 6)不同 network 之間在二層上是隔離的 以 vlan 網(wǎng)絡(luò)為例,network A 和 network B 會(huì)分配不同的 VLAN ID,這樣就保證了 network A 中的廣播包不會(huì)跑到 network B 中。當(dāng)然,這里的隔離是指二層上的隔離,借助路由器不同 network 是可能在三層上通信的。network 必須屬于某個(gè) Project( Tenant 租戶),Project 中可以創(chuàng)建多個(gè) network。 network 與 Project 之間是 1對(duì)多 關(guān)系。subnet: subnet 是一個(gè) IPv4 或者 IPv6 地址段。instance 的 IP 從 subnet 中分配。每個(gè) subnet 需要定義 IP 地址的范圍和掩碼。subnet 與 network 是 1對(duì)多 關(guān)系。一個(gè) subnet 只能屬于某個(gè) network;一個(gè) network 可以有多個(gè) subnet,這些 subnet 可以是不同的 IP 段,但不能重疊。 下面的配置是有效的: 但下面的配置則無效,因?yàn)?subnet 有重疊: 這里不是判斷 IP 是否有重疊,而是 subnet 的 CIDR 重疊(都是 10.10.1.0/24)。 但是,如果 subnet 在不同的 network 中,CIDR 和 IP 都是可以重疊的,比如: 這里大家不免會(huì)疑惑: 如果上面的IP地址是可以重疊的,那么就可能存在具有相同 IP 的兩個(gè) instance,這樣會(huì)不會(huì)沖突? 簡單的回答是:不會(huì)!具體原因: 因?yàn)?Neutron 的 router 是通過 Linux network namespace 實(shí)現(xiàn)的。network namespace 是一種網(wǎng)絡(luò)的隔離機(jī)制。通過它,每個(gè) router 有自己獨(dú)立的路由表。 上面的配置有兩種結(jié)果: 1)如果兩個(gè) subnet 是通過同一個(gè) router 路由,根據(jù) router 的配置,只有指定的一個(gè) subnet 可被路由。 2)如果上面的兩個(gè) subnet 是通過不同 router 路由,因?yàn)?router 的路由表是獨(dú)立的,所以兩個(gè) subnet 都可以被路由。port: 1)port 可以看做虛擬交換機(jī)上的一個(gè)端口。port 上定義了 MAC 地址和 IP 地址,當(dāng) instance 的虛擬網(wǎng)卡 VIF(Virtual Interface)綁定到 port 時(shí),port 會(huì)將 MAC 和 IP 分配給 VIF。 2)port 與 subnet 是 1對(duì)多 關(guān)系。一個(gè) port 必須屬于某個(gè) subnet;一個(gè) subnet 可以有多個(gè) port。小節(jié) 下面總結(jié)了 Project,Network,Subnet,Port 和 VIF 之間關(guān)系。Project 1 : m Network 1 : m Subnet 1 : m Port 1 : 1 VIF m : 1 Instance,即一個(gè)租戶有多個(gè)網(wǎng)絡(luò),一個(gè)網(wǎng)絡(luò)有多個(gè)子網(wǎng),一個(gè)子網(wǎng)有多個(gè)端口,一個(gè)端口有一個(gè)虛擬網(wǎng)卡,一個(gè)虛擬機(jī)有多個(gè)虛擬網(wǎng)卡。

2.5.2 Neutron架構(gòu)

2.5.2.1 Neutron組件概括

與 OpenStack 的其他服務(wù)的設(shè)計(jì)思路一樣,Neutron 也是采用分布式架構(gòu),由多個(gè)組件(子服務(wù))共同對(duì)外提供網(wǎng)絡(luò)服務(wù)。 Neutron由如下組件構(gòu)成: 1)Neutron Server:對(duì)外提供 OpenStack 網(wǎng)絡(luò) API,接收請(qǐng)求,并調(diào)用 Plugin 處理請(qǐng)求。 2)Plugin:處理 Neutron Server 發(fā)來的請(qǐng)求,維護(hù) OpenStack 邏輯網(wǎng)絡(luò)的狀態(tài), 并調(diào)用 Agent 處理請(qǐng)求。 3)Agent:處理 Plugin 的請(qǐng)求,負(fù)責(zé)在 network provider 上真正實(shí)現(xiàn)各種網(wǎng)絡(luò)功能。 4)network provider:提供網(wǎng)絡(luò)服務(wù)的虛擬或物理網(wǎng)絡(luò)設(shè)備,例如 Linux Bridge,Open vSwitch 或者其他支持 Neutron 的物理交換機(jī)。 5)Queue:Neutron Server,Plugin 和 Agent 之間通過 Messaging Queue 通信和調(diào)用。 6)Database:存放 OpenStack 的網(wǎng)絡(luò)狀態(tài)信息,包括 Network, Subnet, Port, Router 等。 以創(chuàng)建一個(gè) VLAN100 的 network 為例,假設(shè) network provider 是 linux bridge, 流程如下: 1)Neutron Server 接收到創(chuàng)建 network 的請(qǐng)求,通過 Message Queue(RabbitMQ)通知已注冊(cè)的 Linux Bridge Plugin。 2)Plugin 將要?jiǎng)?chuàng)建的 network 的信息(例如名稱、VLAN ID等)保存到數(shù)據(jù)庫中,并通過 Message Queue 通知運(yùn)行在各節(jié)點(diǎn)上的 Agent。 3)Agent 收到消息后會(huì)在節(jié)點(diǎn)上的物理網(wǎng)卡(比如 eth2)上創(chuàng)建 VLAN 設(shè)備(比如 eth2.100),并創(chuàng)建 bridge (比如 brqXXX) 橋接 VLAN 設(shè)備。這里進(jìn)行幾點(diǎn)說明: 1)plugin 解決的是 What 的問題,即網(wǎng)絡(luò)要配置成什么樣子?而至于如何配置 How 的工作則交由 agent 完成。 2)plugin,agent 和 network provider 是配套使用的,比如上例中 network provider 是 linux bridge,那么就得使用 linux bridge 的 plungin 和 agent;如果 network provider 換成了 OVS 或者物理交換機(jī),plugin 和 agent 也得替換。 3)plugin 的一個(gè)主要的職責(zé)是在數(shù)據(jù)庫中維護(hù) Neutron 網(wǎng)絡(luò)的狀態(tài)信息,這就造成一個(gè)問題:所有 network provider 的 plugin 都要編寫一套非常類似的數(shù)據(jù)庫訪問代碼。為了解決這個(gè)問題,Neutron 在 Havana 版本實(shí)現(xiàn)了一個(gè) ML2(Modular Layer 2)plugin,對(duì) plgin 的功能進(jìn)行抽象和封裝。有了 ML2 plugin,各種 network provider 無需開發(fā)自己的 plugin,只需要針對(duì) ML2 開發(fā)相應(yīng)的 driver 就可以了,工作量和難度都大大減少。ML2 會(huì)在后面詳細(xì)討論。 4)plugin 按照功能分為兩類: core plugin 和 service plugin。core plugin 維護(hù) Neutron 的 netowrk, subnet 和 port 相關(guān)資源的信息,與 core plugin 對(duì)應(yīng)的 agent 包括 linux bridge, OVS 等; service plugin 提供 routing, firewall, load balance 等服務(wù),也有相應(yīng)的 agent。

2.5.2.2 Neutron物理部署方案

方案1:控制節(jié)點(diǎn) + 計(jì)算節(jié)點(diǎn): 1)控制節(jié)點(diǎn):部署的服務(wù)包括:neutron server, core plugin 的 agent 和 service plugin 的 agent。 2)計(jì)算節(jié)點(diǎn):部署 core plugin 的agent,負(fù)責(zé)提供二層網(wǎng)絡(luò)功能。 NOTE:這里有幾點(diǎn)需要說明: 1)core plugin 和 service plugin 已經(jīng)集成到 neutron server,不需要運(yùn)行獨(dú)立的 plugin 服務(wù)。 2)控制節(jié)點(diǎn)和計(jì)算節(jié)點(diǎn)都需要部署 core plugin 的 agent,因?yàn)橥ㄟ^該 agent 控制節(jié)點(diǎn)與計(jì)算節(jié)點(diǎn)才能建立二層連接。 3)可以部署多個(gè)控制節(jié)點(diǎn)和計(jì)算節(jié)點(diǎn)。 方案1:控制節(jié)點(diǎn) +網(wǎng)絡(luò)節(jié)點(diǎn)+ 計(jì)算節(jié)點(diǎn): 1)控制節(jié)點(diǎn):部署 neutron server 服務(wù)。 2)網(wǎng)絡(luò)節(jié)點(diǎn):部署的服務(wù)包括:core plugin 的 agent 和 service plugin 的 agent。 3)計(jì)算節(jié)點(diǎn):部署 core plugin 的agent,負(fù)責(zé)提供二層網(wǎng)絡(luò)功能。 這個(gè)方案的要點(diǎn)是將所有的 agent 從控制節(jié)點(diǎn)分離出來,部署到獨(dú)立的網(wǎng)絡(luò)節(jié)點(diǎn)上。控制節(jié)點(diǎn)只負(fù)責(zé)通過 neutron server 響應(yīng) API 請(qǐng)求。由獨(dú)立的網(wǎng)絡(luò)節(jié)點(diǎn)實(shí)現(xiàn)數(shù)據(jù)的交換,路由以及 load balance等高級(jí)網(wǎng)絡(luò)服務(wù)。可以通過增加網(wǎng)絡(luò)節(jié)點(diǎn)承擔(dān)更大的負(fù)載。可以部署多個(gè)控制節(jié)點(diǎn)、網(wǎng)絡(luò)節(jié)點(diǎn)和計(jì)算節(jié)點(diǎn)。該方案特別適合規(guī)模較大的 OpenStack 環(huán)境。

2.5.3 Neutron組件詳細(xì)說明

2.5.3.1 Neutron Server

下圖是 Neutron Server 的分層結(jié)構(gòu),至上而下依次為: 1)Core API:對(duì)外提供管理 network, subnet 和 port 的 RESTful API。 2)Extension API:對(duì)外提供管理 router, load balance, firewall 等資源 的 RESTful API。 3)Commnon Service:認(rèn)證和校驗(yàn) API 請(qǐng)求。 4)Neutron Core:Neutron server 的核心處理程序,通過調(diào)用相應(yīng)的 Plugin 處理請(qǐng)求。 5)Core Plugin API:定義了 Core Plgin 的抽象功能集合,Neutron Core 通過該 API 調(diào)用相應(yīng)的 Core Plgin。 6)Extension Plugin API:定義了 Service Plgin 的抽象功能集合,Neutron Core 通過該 API 調(diào)用相應(yīng)的 Service Plgin。 7)Core Plugin:實(shí)現(xiàn)了 Core Plugin API,在數(shù)據(jù)庫中維護(hù) network, subnet 和 port 的狀態(tài),并負(fù)責(zé)調(diào)用相應(yīng)的 agent 在 network provider 上執(zhí)行相關(guān)操作,比如創(chuàng)建 network。 8)Service Plugin:實(shí)現(xiàn)了 Extension Plugin API,在數(shù)據(jù)庫中維護(hù) router, load balance, security group 等資源的狀態(tài), 并負(fù)責(zé)調(diào)用相應(yīng)的 agent 在 network provider 上執(zhí)行相關(guān)操作,比如創(chuàng)建 router。歸納起來,Neutron Server 包括兩部分:1)提供 API 服務(wù)。2)運(yùn)行 Plugin。 即 Neutron Server = API + Plugins

2.5.3.2 Neutron如何支持多種network provider

根據(jù)我們上一節(jié)討論的 Neutron Server 的分層模型,我們需要實(shí)現(xiàn)兩個(gè)東西:linux bridge core plugin 和 linux bridge agent。linux bridge core plugin 1)與 neutron server 一起運(yùn)行。 2)實(shí)現(xiàn)了 core plugin API。 3)負(fù)責(zé)維護(hù)數(shù)據(jù)庫信息。 4)通知 linux bridge agent 實(shí)現(xiàn)具體的網(wǎng)絡(luò)功能。linux bridge agent 1)在計(jì)算節(jié)點(diǎn)和網(wǎng)絡(luò)節(jié)點(diǎn)(或控制節(jié)點(diǎn))上運(yùn)行。 2)接收來自 plugin 的請(qǐng)求。 3)通過配置本節(jié)點(diǎn)上的 linux bridge 實(shí)現(xiàn) neutron 網(wǎng)絡(luò)功能。 同樣的道理,如果要支持 open vswitch,只需要實(shí)現(xiàn) open vswitch plugin 和 open vswitch agent 由此可見:Neutron 可以通過開發(fā)不同的 plugin 和 agent 支持不同的網(wǎng)絡(luò)技術(shù)。這是一種相當(dāng)開放的架構(gòu)。不過隨著支持的 network provider 數(shù)量的增加,開發(fā)人員發(fā)現(xiàn)了兩個(gè)突出的問題:只能在 OpenStack 中使用一種 core plugin,多種 network provider 無法共存。不同 plugin 之間存在大量重復(fù)代碼,開發(fā)新的 plugin 工作量大。

2.5.3.3 ML2 Core Plugin

Moduler Layer 2(ML2)是 Neutron 在 Havana 版本實(shí)現(xiàn)的一個(gè)新的 core plugin,用于替代原有的 linux bridge plugin 和 open vswitch plugin。ML2 能解決傳統(tǒng) core plugin 的問題。ML2 作為新一代的 core plugin,提供了一個(gè)框架,允許在 OpenStack 網(wǎng)絡(luò)中同時(shí)使用多種 Layer 2 網(wǎng)絡(luò)技術(shù),不同的節(jié)點(diǎn)可以使用不同的網(wǎng)絡(luò)實(shí)現(xiàn)機(jī)制。 如上圖所示,采用 ML2 plugin 后,可以在不同節(jié)點(diǎn)上分別部署 linux bridge agent, open vswitch agent, hyper-v agent 以及其他第三方 agent。(Hyper-V 是 Microsoft 的硬件虛擬化產(chǎn)品。 它用于創(chuàng)建并運(yùn)行虛擬機(jī)。 每個(gè)虛擬機(jī)都像一臺(tái)完整的計(jì)算機(jī)一樣運(yùn)行操作系統(tǒng)和程序。)ML2 不但支持異構(gòu)部署方案,同時(shí)能夠與現(xiàn)有的 agent 無縫集成:以前用的 agent 不需要變,只需要將 Neutron server 上的傳統(tǒng) core plugin 替換為 ML2。有了 ML2,要支持新的 network provider 就變得簡單多了:無需從頭開發(fā) core plugin,只需要開發(fā)相應(yīng)的 mechanism driver,大大減少了要編寫和維護(hù)的代碼。ML2 對(duì)二層網(wǎng)絡(luò)進(jìn)行抽象和建模,引入了 type driver 和 mechanism driver。這兩類 driver 解耦了 Neutron 所支持的網(wǎng)絡(luò)類型(type)與訪問這些網(wǎng)絡(luò)類型的機(jī)制(mechanism),其結(jié)果就是使得 ML2 具有非常好的彈性,易于擴(kuò)展,能夠靈活支持多種 type 和 mechanism。 Type Driver:Neutron 支持的每一種網(wǎng)絡(luò)類型都有一個(gè)對(duì)應(yīng)的 ML2 type driver。type driver 負(fù)責(zé)維護(hù)網(wǎng)絡(luò)類型的狀態(tài),執(zhí)行驗(yàn)證,創(chuàng)建網(wǎng)絡(luò)等。ML2 支持的網(wǎng)絡(luò)類型包括 local, flat, vlan, vxlan 和 gre。Mechanism Driver:Neutron 支持的每一種網(wǎng)絡(luò)機(jī)制都有一個(gè)對(duì)應(yīng)的 ML2 mechanism driver。mechanism driver 負(fù)責(zé)獲取由 type driver 維護(hù)的網(wǎng)絡(luò)狀態(tài),并確保在相應(yīng)的網(wǎng)絡(luò)設(shè)備(物理或虛擬)上正確實(shí)現(xiàn)這些狀態(tài)。type 和 mechanisim 都太抽象,現(xiàn)在我們舉一個(gè)具體的例子:type driver 為 vlan,mechanism driver 為 linux bridge,我們要完成的操作是創(chuàng)建 network vlan100,那么:vlan type driver 會(huì)確保將 vlan100 的信息保存到 Neutron 數(shù)據(jù)庫中,包括 network 的名稱,vlan ID 等。linux bridge mechanism driver 會(huì)確保各節(jié)點(diǎn)上的 linux brige agent 在物理網(wǎng)卡上創(chuàng)建 ID 為 100 的 vlan 設(shè)備 和 brige 設(shè)備,并將兩者進(jìn)行橋接。mechanism driver 有三種類型 1)Agent-based:包括 linux bridge, open vswitch 等。 2)Controller-based:包括 OpenDaylight, VMWare NSX 等。 3)基于物理交換機(jī):包括 Cisco Nexus, Arista, Mellanox 等。 比如前面那個(gè)例子如果換成 Cisco 的 mechanism driver,則會(huì)在 Cisco 物理交換機(jī)的指定 trunk 端口上添加 vlan100。linux bridge 和 open vswitch 的 ML2 mechanism driver 的作用是配置各節(jié)點(diǎn)上的虛擬交換機(jī)。linux bridge driver 支持的 type 包括 local, flat, vlan, and vxlan。open vswitch driver 除了這 4 種 type 還支持 gre。L2 population driver 作用是優(yōu)化和限制 overlay 網(wǎng)絡(luò)中的廣播流量。vxlan 和 gre 都屬于 overlay 網(wǎng)絡(luò)。

2.5.3.4 Service Plugin/Agent

Core Plugin/Agent 負(fù)責(zé)管理核心實(shí)體:net, subnet 和 port。而對(duì)于更高級(jí)的網(wǎng)絡(luò)服務(wù),則由 Service Plugin/Agent 管理。 Service Plugin 及其 Agent 提供更豐富的擴(kuò)展功能,包括路由,load balance,firewall等。Neutron架構(gòu)如圖所示: 1)DHCP:dhcp agent 通過 dnsmasq 為 instance 提供 dhcp 服務(wù)。 2)Routing:l3 agent 可以為 project(租戶)創(chuàng)建 router,提供 Neutron subnet 之間的路由服務(wù)。路由功能默認(rèn)通過 IPtables 實(shí)現(xiàn)。 3)Firewall:l3 agent 可以在 router 上配置防火墻策略,提供網(wǎng)絡(luò)安全防護(hù)。 另一個(gè)與安全相關(guān)的功能是 Security Group,也是通過 IPtables 實(shí)現(xiàn)。Firewall 與 Security Group 的區(qū)別在于:Firewall 安全策略位于 router,保護(hù)的是某個(gè) project 的所有 network。Security Group 安全策略位于 instance,保護(hù)的是單個(gè) instance。 4)Load Balance:Neutron 默認(rèn)通過 HAProxy 為 project 中的多個(gè) instance 提供 load balance 服務(wù)。

2.5.3.5 小結(jié)

與 OpenStack 其他服務(wù)一樣,Neutron 采用的是分布式架構(gòu),包括 Neutorn Server、各種 plugin/agent、database 和 message queue。 1)Neutron server 接收 api 請(qǐng)求。 2)plugin/agent 實(shí)現(xiàn)請(qǐng)求。 3)database 保存 neutron 網(wǎng)絡(luò)狀態(tài)。 4)message queue 實(shí)現(xiàn)組件之間通信。metadata-agent 之前沒有講到,這里做個(gè)補(bǔ)充: instance 在啟動(dòng)時(shí)需要訪問 nova-metadata-api 服務(wù)獲取 metadata 和 userdata,這些 data 是該 instance 的定制化信息,比如 hostname, ip, public key 等。但 instance 啟動(dòng)時(shí)并沒有 ip,如何能夠通過網(wǎng)絡(luò)訪問到 nova-metadata-api 服務(wù)呢? 答案就是 neutron-metadata-agent。該 agent 讓 instance 能夠通過 dhcp-agent 或者 l3-agent 與 nova-metadata-api 通信如果我們將 Neutron 架構(gòu)展開,則會(huì)得到下面第二張圖: 1)Neutron 通過 plugin 和 agent 提供的網(wǎng)絡(luò)服務(wù)。 2)plugin 位于 Neutron server,包括 core plugin 和 service plugin。 3)agent 位于各個(gè)節(jié)點(diǎn),負(fù)責(zé)實(shí)現(xiàn)網(wǎng)絡(luò)服務(wù)。 4)core plugin 提供 L2 功能,ML2 是推薦的 plugin。 5)使用最廣泛的 L2 agent 是 linux bridage 和 open vswitch。 6)service plugin 和 agent 提供擴(kuò)展功能,包括 dhcp, routing, load balance, firewall, vpn 等。

2.5.4 為Neutron準(zhǔn)備底層基礎(chǔ)設(shè)施

1個(gè)控制節(jié)點(diǎn) +1個(gè)計(jì)算節(jié)點(diǎn)的部署方案:控制節(jié)點(diǎn)合并了網(wǎng)絡(luò)節(jié)點(diǎn)的功能,同時(shí)也是一個(gè)計(jì)算節(jié)點(diǎn) 。 配置多個(gè)網(wǎng)卡區(qū)分不同類型的網(wǎng)絡(luò)數(shù)據(jù):Management、API、VM、External。 1)Management 網(wǎng)絡(luò) 用于節(jié)點(diǎn)之間 message queue 內(nèi)部通信以及訪問 database 服務(wù),所有的節(jié)點(diǎn)都需要連接到 management 網(wǎng)絡(luò)。 2)API 網(wǎng)絡(luò) OpenStack 各組件通過該網(wǎng)絡(luò)向用戶暴露 API 服務(wù)。Keystone, Nova, Neutron, Glance, Cinder, Horizon 的 endpoints 均配置在 API 網(wǎng)絡(luò)上。通常,管理員也通過 API 網(wǎng)絡(luò) SSH 管理各個(gè)節(jié)點(diǎn)。 3)VM 網(wǎng)絡(luò) VM 網(wǎng)絡(luò)也叫 tenant 網(wǎng)絡(luò),用于 instance 之間通信。 VM 網(wǎng)絡(luò)可以選擇的類型包括 local, flat, vlan, vxlan 和 gre。 VM 網(wǎng)絡(luò)由 Neutron 配置和管理。 4)External網(wǎng)絡(luò) External 網(wǎng)絡(luò)指的是 VM 網(wǎng)絡(luò)之外的網(wǎng)絡(luò),該網(wǎng)絡(luò)不由 Neutron 管理。 Neutron 可以將 router attach 到 External 網(wǎng)絡(luò),為 instance 提供訪問外部網(wǎng)絡(luò)的能力。 External 網(wǎng)絡(luò)可能是企業(yè)的 intranet,也可能是 internet。我們可以為每種網(wǎng)絡(luò)分配單獨(dú)的網(wǎng)卡; 也可以多種網(wǎng)絡(luò)共同使用一個(gè)網(wǎng)卡;為提高帶寬和硬件冗余,可以使用 bonding 技術(shù)將多個(gè)物理網(wǎng)卡綁定成一個(gè)邏輯的網(wǎng)卡,我們的實(shí)驗(yàn)環(huán)境采用下面的網(wǎng)卡分配方式: 網(wǎng)絡(luò)拓?fù)洌海ü?jié)點(diǎn)安裝配置參考:https://www.xjimmy.com/openstack-5min-76.html)

2.5.5 Linux Bridge實(shí)現(xiàn)Neutron網(wǎng)絡(luò)

2.5.5.1 配置 Linux-Bridge Mechanism Driver

下圖中,br0 是 linux bridge,br0 充當(dāng)虛擬交換機(jī)的作用,負(fù)責(zé)將物理網(wǎng)卡 eth0 和虛擬網(wǎng)卡 tap 設(shè)備 vnet0/vent1 連接到同一個(gè)二層網(wǎng)絡(luò),實(shí)現(xiàn)虛擬機(jī) VM1 和 VM2,以及虛擬機(jī)與外網(wǎng)之間的通信。 配置linux-bridge mechanism driver 1)要在 Neutron 中使用 linux bridge,首先需要配置 linux-bridge mechanism driver: Neutron 默認(rèn)使用 ML2 作為 core plugin,其配置位于 /etc/neutron/neutron.conf。控制節(jié)點(diǎn)和計(jì)算節(jié)點(diǎn)都需要在各自的 neutron.conf 中配置 core_plugin 選項(xiàng)。 2)然后需要讓 ML2 使用 linux-bridge mechanism driver: ML2 的配置文件位于 /etc/neutron/plugins/ml2/ml2_conf.ini。 mechanism_drivers 選項(xiàng)指明當(dāng)前節(jié)點(diǎn)可以使用的 mechanism driver,這里可以指定多種 driver,ML2 會(huì)負(fù)責(zé)加載。上面的配置指明我們只使用 linux-bridge driver??刂乒?jié)點(diǎn)和計(jì)算節(jié)點(diǎn)都需要在各自的 ml2_conf.ini 中配置 mechanism_drivers 選項(xiàng)。 3)Neutron 服務(wù)正常啟動(dòng)后,所有節(jié)點(diǎn)上都會(huì)運(yùn)行 neutron-linuxbridge-agent:

2.5.5.2 初始網(wǎng)絡(luò)狀態(tài)

控制節(jié)點(diǎn): 計(jì)算節(jié)點(diǎn): 在 linux bridge 環(huán)境中,一個(gè)數(shù)據(jù)包從 instance 發(fā)送到物理網(wǎng)卡會(huì)經(jīng)過下面幾個(gè)類型的設(shè)備: 1)tap interface:命名為 tapN (N 為 0, 1, 2, 3……)。 2)linux bridge:命名為 brqXXXX。 3)vlan interface:命名為 ethX.Y(X 為 interface 的序號(hào),Y 為 vlan id)。 4)vxlan interface:命名為 vxlan-Z(z 是 VNI)。 5)物理 interface:命名為 ethX(X 為 interface 的序號(hào))。 linux-bridge 支持 local, flat, vlan 和 vxlan 四種 network type,目前不支持 gre。

2.5.5.3 local network

local 網(wǎng)絡(luò)與其他網(wǎng)絡(luò)和節(jié)點(diǎn)隔離。local 網(wǎng)絡(luò)中的 instance 只能與位于同一節(jié)點(diǎn)上同一網(wǎng)絡(luò)的 instance 通信,local 網(wǎng)絡(luò)主要用于單機(jī)測(cè)試。local network 的特點(diǎn)是不會(huì)與宿主機(jī)的任何物理網(wǎng)卡相連,也不關(guān)聯(lián)任何的 VLAN ID。對(duì)于每個(gè) local netwrok,ML2 linux-bridge 會(huì)創(chuàng)建一個(gè) bridge,instance 的 tap 設(shè)備會(huì)連接到 bridge。位于同一個(gè) local network 的 instance 會(huì)連接到相同的 bridge,這樣 instance 之間就可以通信了。因?yàn)?bridge 沒有與物理網(wǎng)卡連接,所以 instance 無法與宿主機(jī)之外的網(wǎng)絡(luò)通信。同時(shí)因?yàn)槊總€(gè) local network 有自己的 bridge,bridge 之間是沒有連通的,所以兩個(gè) local network 之間也不能通信,即使它們位于同一宿主機(jī)上。下圖是 local network 的示例: 1)創(chuàng)建了兩個(gè) local network,分別對(duì)應(yīng)兩個(gè)網(wǎng)橋 brqXXXX 和 brqYYYY。 2)VM0 和 VM1 通過 tap0 和 tap1 連接到 brqXXXX。 3)VM2 通過 tap2 連接到 brqYYYY。 4)VM0 與 VM1 在同一個(gè) local network中,它們之間可以通信。 5)VM2 位于另一個(gè) local network,由于 brqXXXX 和 brqYYYY 沒有聯(lián)通,所以 VM2 無法與 VM0 和 VM1 通信。在 ML2 配置中 enable local network: 1)創(chuàng)建 local 網(wǎng)絡(luò)之前請(qǐng)先確保 ML2 已經(jīng)加載了 local type driver,ML2 的配置文件位于 /etc/neutron/plugins/ml2/ml2_conf.ini: 2)type_drivers 告訴 ML2 加載所有 5 種網(wǎng)絡(luò)的 type driver。 3)普通用戶和 admin 都可以通過 CLI 或者 Web GUI 創(chuàng)建網(wǎng)絡(luò),但只有 amdin 才能指定網(wǎng)絡(luò)的 type,所以需要用 tenant_network_types 告訴 ML2 當(dāng)普通用戶在自己的 Tenant(Project)中創(chuàng)建網(wǎng)絡(luò)時(shí),默認(rèn)創(chuàng)建哪種 type 的網(wǎng)絡(luò),這里 type 是 local。tenant_network_types 可以指定多種 type,比如: 4)其作用是先創(chuàng)建 vlan 網(wǎng)絡(luò),當(dāng)沒有 vlan 可創(chuàng)建時(shí)(比如 vlan id 用完),便創(chuàng)建 local 網(wǎng)絡(luò)。當(dāng)配置文件發(fā)生了變化,需要重啟 Neutron 相關(guān)服務(wù)使之生效。創(chuàng)建第一個(gè) Local Network: 1)首先確保各個(gè)節(jié)點(diǎn)上的 neutorn agent 狀態(tài)正常。GUI 菜單 為 Admin -> System -> System Infomation -> Neutron Agents: 2)GUI 中有兩個(gè)地方可以創(chuàng)建 network :1)Project -> Network -> Networks這是普通用戶在自己的 tenant 中創(chuàng)建 network 的地方。2)Admin -> Networks 這是 admin 創(chuàng)建 network 的地方。我們先用第一種方式創(chuàng)建,點(diǎn)擊 “Create Network” 按鈕: 3)在創(chuàng)建網(wǎng)絡(luò)的向?qū)ы撁娼o network 命名為 “first_local_net”,點(diǎn)擊 “Next”: 4)創(chuàng)建 subnet,命名為 “subnet_172_16_1_0”,地址為 “172.16.1.0/24”,點(diǎn)擊 “Next”。如果 Gateway IP 不設(shè)置,默認(rèn)為 subnet 的第一個(gè) IP,即 172.16.1.1: 5)設(shè)置 subnet 的 IP 地址范圍為 172.16.1.2-172.16.1.100,instance 的 IP 會(huì)從這里分配,點(diǎn)擊 “Create”。默認(rèn)會(huì)“Enable DHCP”,同時(shí)還可以設(shè)置 subnet 的 DNS 和添加靜態(tài)路由條目。 6)network 創(chuàng)建成功: 7)點(diǎn)擊 “first_local_net” 鏈接,顯示 network 的 subnet 和 port 信息: 8)在 Ports 列表中已經(jīng)創(chuàng)建了一個(gè) port,名稱為 “(a5bd3746-3f89)”,IP 為 172.16.1.2, Attached Device 是 network:dhcp。打開控制節(jié)點(diǎn)的 shell 終端,用 brctl show 查看當(dāng)前 linux bridge 的狀態(tài): 9)可以看到 Neutron 自動(dòng)創(chuàng)建了如下兩個(gè)設(shè)備: brqbb9b6d21-c6 對(duì)應(yīng) local network “first_local_net”,命名規(guī)則為 brqXXX,XXX 為 network ID 的前 11 個(gè)字符。tapa5bd3746-3f 對(duì)應(yīng) port (a5bd3746-3f89),命名規(guī)則為 tapYYY, YYY 為 port ID 的前 11 個(gè)字符。該 tap 設(shè)備已經(jīng)連接到 bridge,即連接到該 local 網(wǎng)絡(luò)。將 instance 連接到 first_local_net: 1)launch 一個(gè) instance,在“Networking”標(biāo)簽頁面選擇 first_local_net 網(wǎng)絡(luò): 2)instance 部署成功,分配的 IP 地址為 172.16.1.3: 3)對(duì)于 instance “cirros-vm1”,Neutron 會(huì)在 subnet 中創(chuàng)建一個(gè) port,分配 IP 和 MAC 地址,并將 port 分配給 cirros-vm1: 4)如上圖所示,port 列表中增加了一個(gè) port “(fa7e090e-a29c)”,IP 為 172.16.1.3。點(diǎn)擊 port 名稱查看 MAC 信息: 5)當(dāng) cirros-vm1 啟動(dòng)時(shí),宿主機(jī)上的 neutron-linuxbridge-agent 會(huì)根據(jù) port 信息創(chuàng)建 tap 設(shè)備,并連接到 local 網(wǎng)絡(luò)所在的 bridge;同時(shí)該 tap 會(huì)映射成 cirros-vm1 的虛擬網(wǎng)卡,即 virtual interface (VIF)。cirros-vm1 部署到了控制節(jié)點(diǎn),通過 brctl show 查看 bridge 的配置: 6)可以看到 bridge brqbb9b6d21-c6 上連接了一個(gè)新的 tap 設(shè)備 tapfa7e090e-a2 從命名上可知 tapfa7e090e-a2 對(duì)應(yīng)著 port “(fa7e090e-a29c)”。virsh list 中顯示的虛擬機(jī) instance-00000001 即為 “cirros-vm1”,命名方式有所不同,需注意。通過 virsh edit 命令查看 cirros-vm1 的配置,確認(rèn) VIF 就是 tapfa7e090e-a2: 7)另外,VIF 的 MAC 地址為 fa:16:3e:c1:66:a5,這個(gè)數(shù)據(jù)就是從 port “(fa7e090e-a29c)” 取過來的。在 cirros-vm1 中執(zhí)行 ifconfig,通過 MAC 地址可以確認(rèn) eth0 與 tapfa7e090e-a2 對(duì)應(yīng)。 8)下圖展示了創(chuàng)建 cirros-vm1 后宿主機(jī)當(dāng)前的網(wǎng)絡(luò)結(jié)構(gòu) : 連接第二個(gè) Insance 到 First_local_net: 1)以同樣的方式 launch instance “cirros-vm2”分配的 IP 為 172.16.1.4: 2)cirros-vm2 也被 schedule 到控制節(jié)點(diǎn)。virsh list 和 brctl show 輸出如下 cirros-vm2 對(duì)于的 tap 設(shè)備為 tapa5bd3746-3f。 3)在 cirros-vm2 的控制臺(tái)運(yùn)行 ifconfig,instance 已經(jīng)拿到了 DCHP 的 IP 地址: 4)能夠 Ping 通 cirros-vm1 的 IP 地址 172.16.1.3: 5)前宿主機(jī)的網(wǎng)絡(luò)結(jié)構(gòu)如下 : 6)兩個(gè) instance 的 VIF 掛在同一個(gè) linux bridge 上,可以相互通信。這里請(qǐng)大家思考一個(gè)問題:如果 cirros-vm2 launch 時(shí)被 schedule 到計(jì)算節(jié)點(diǎn)而非控制節(jié)點(diǎn),它能獲得 DHCP 的 IP 嗎?答案:不能。 因?yàn)?DHCP agent 在控制節(jié)點(diǎn)上運(yùn)行,cirros-vm2 在計(jì)算節(jié)點(diǎn)的 local 網(wǎng)絡(luò)上,兩者位于不同物理節(jié)點(diǎn)。由于 local 網(wǎng)絡(luò)的流量只能局限在本節(jié)點(diǎn)之內(nèi),發(fā)送的 DHCP 請(qǐng)求無法到達(dá)控制節(jié)點(diǎn)。創(chuàng)建第二個(gè) Local Network: 1)GUI 中有兩個(gè)地方可以創(chuàng)建 network:Project -> Network -> Networks這是普通用戶在自己的 tenant 中創(chuàng)建 network 的地方、Admin -> Networks 這是 admin 創(chuàng)建 network 的地方。前面我們已經(jīng)用第一種方式創(chuàng)建了 “first_local_net”。本節(jié)將以第二種方式創(chuàng)建 local network “second_local_net” 。菜單路徑為 Admin -> Networks,此菜單只有 admin 用戶才能夠訪問,點(diǎn)擊 “Create Network” 按鈕: 2)顯示創(chuàng)建頁面,點(diǎn)擊 “Create Network”,second_local_net 創(chuàng)建成功: 3)可以看到幾個(gè)與普通用戶創(chuàng)建 network 不同的地方: a)可以選擇該 network 屬于哪個(gè) Project(租戶)。 b)可以選擇 network type。 c)可以指定 network 是否與其他 Project 共享。 d)可以指定是否為 external network。 可見,這種方式賦予 admin 用戶創(chuàng)建 network 更大的靈活性,后面我們都將采用這種方式創(chuàng)建 network。 4)點(diǎn)擊 second_local_net 鏈接,進(jìn)入 network 配置頁面: 5)目前還沒有 subnet,點(diǎn)擊 “Create Subnet” 按鈕: 6)設(shè)置 IP 地址為 “172.16.1.0/24”,點(diǎn)擊 “Next”: 7)設(shè)置 IP 地址范圍為 172.16.1.101-172.16.1.200,點(diǎn)擊 “Create”: 8)subnet 創(chuàng)建成功: 9)查看控制節(jié)點(diǎn)的網(wǎng)絡(luò)結(jié)構(gòu)。增加了 second_local_net 對(duì)應(yīng)的網(wǎng)橋 brq161e0b25-58,以及 dhcp 的 tap 設(shè)備 tapae547b6b-2a: 將 Instance 連接到 Second_local_net: 1)launch 新的 instance “cirros-vm3”,網(wǎng)絡(luò)選擇 second_local_net: 2)cirros-vm3 分配到的 IP 為 172.16.1.102: 3)cirros-vm3 被 schedule 到控制節(jié)點(diǎn),對(duì)應(yīng)的 tap 設(shè)備為 tap5395d19b-ed: 4)控制臺(tái)顯示 cirros-vm3 已經(jīng)成功從 DHCP 拿到 IP 地址 172.16.1.102: 5)但是 cirros-vm3 無法 Ping 到 cirros-vm1: 6)這是在預(yù)料之中的,因?yàn)?cirros-vm3 和 cirros-vm1 位于不同的 local network,之間沒有連通,即使都位于同一個(gè)宿主機(jī)也不能通信。網(wǎng)絡(luò)結(jié)構(gòu)如下: 小結(jié):位于同一 local network 的 instance 可以通信; 位于不同 local network 的 instance 無法通信;一個(gè) local network 只能位于一個(gè)物理節(jié)點(diǎn),無法跨節(jié)點(diǎn)。

2.5.5.4 flat network

flat network 是不帶 tag 的網(wǎng)絡(luò),要求宿主機(jī)的物理網(wǎng)卡直接與 linux bridge 連接,這意味著:每個(gè) flat network 都會(huì)獨(dú)占一個(gè)物理網(wǎng)卡。下圖中 eth1 橋接到 brqXXX,為 instance 提供 flat 網(wǎng)絡(luò)。 如果需要?jiǎng)?chuàng)建多個(gè) flat network,就得準(zhǔn)備多個(gè)物理網(wǎng)卡,如下圖所示: Flat Network 原理與配置: 1)在 ML2 配置中 enable flat network,在 /etc/neutron/plugins/ml2/ml2_conf.ini 設(shè)置 flat network 相關(guān)參數(shù): 指定普通用戶創(chuàng)建的網(wǎng)絡(luò)類型為 flat。 需要注意的是:因?yàn)?flat 網(wǎng)絡(luò)與物理網(wǎng)卡一一對(duì)應(yīng),一般情況下租戶網(wǎng)絡(luò)不會(huì)采用 flat,這里只是示例。 2)接著需要指明 flat 網(wǎng)絡(luò)與物理網(wǎng)卡的對(duì)應(yīng)關(guān)系: 如上所示:a)在 [ml2_type_flat] 中通過 flat_networks 定義了一個(gè) flat 網(wǎng)絡(luò),label 為 “default”。b)在 [linux_bridge] 中通過 physical_interface_mappings 指明 default 對(duì)應(yīng)的物理網(wǎng)卡為 eth1。 3)理解 label 與 ethX 的關(guān)系:label 是 flat 網(wǎng)絡(luò)的標(biāo)識(shí),在創(chuàng)建 flat 時(shí)需要指定 label(后面演示)。label 的名字可以是任意字符串,只要確保各個(gè)節(jié)點(diǎn) ml2_conf.ini 中的 label 命名一致就可以了。各個(gè)節(jié)點(diǎn)中 label 與物理網(wǎng)卡的對(duì)應(yīng)關(guān)系可能不一樣。這是因?yàn)槊總€(gè)節(jié)點(diǎn)可以使用不同的物理網(wǎng)卡將 instance 連接到 flat network。 例如對(duì)于 label 為 “default” 的 flat network,節(jié)點(diǎn) A 可能使用 eth1,配置為: 而節(jié)點(diǎn) B 則可能使用 eth2,配置為: 4)支持多個(gè) flat :如果要?jiǎng)?chuàng)建多個(gè) flat 網(wǎng)絡(luò),需要定義多個(gè) label,用逗號(hào)隔開,當(dāng)然也需要用到多個(gè)物理網(wǎng)卡,如下所示: 創(chuàng)建 Flat Network: 1)打開菜單 Admin -> Networks,點(diǎn)擊 “Create Network” 按鈕: 2)顯示創(chuàng)建頁面, 點(diǎn)擊 “Create Network”,flat_net 創(chuàng)建成功。Provider Network Type 選擇 “Flat”。Physical Network 填寫 “default”,與 ml2_conf.ini 中 flat_networks 參數(shù)保持一致: 3)點(diǎn)擊 flat_net 鏈接,進(jìn)入 network 配置頁面: 4)目前還沒有 subnet,點(diǎn)擊 “Create Subnet” 按鈕: 5)設(shè)置 IP 地址為 “172.16.1.0/24”,點(diǎn)擊 “Next”: 6)設(shè)置 IP 地址范圍為 172.16.1.101-172.16.1.200,點(diǎn)擊 “Create”: 7)subnet 創(chuàng)建成功: 8)底層網(wǎng)絡(luò)發(fā)生了什么變化 。執(zhí)行 brctl show,查看控制節(jié)點(diǎn)當(dāng)前的網(wǎng)絡(luò)結(jié)構(gòu): Neutron 自動(dòng)新建了 flat_net 對(duì)應(yīng)的網(wǎng)橋 brqf153b42f-c3,以及 dhcp 的 tap 設(shè)備 tap19a0ed3d-fe。另外,tap19a0ed3d-fe 和物理網(wǎng)卡 eth1 都已經(jīng)連接到 bridge。此時(shí) flat_net 結(jié)構(gòu)如圖所示: 將 Instance 連接到 Flat_net: 1)launch 新的 instance “cirros-vm1”,選擇網(wǎng)絡(luò) falt_net: 2)cirros-vm1 分配到的 IP 為 172.16.1.103: 3)cirros-vm1 被 schedule 到控制節(jié)點(diǎn),對(duì)應(yīng)的 tap 設(shè)備為 tapc1875c7f-cb,并且已經(jīng)連接到 bridge : 4)當(dāng)前 flat_net 的結(jié)構(gòu)如下: 5)繼續(xù)用同樣的方式 launch instance cirros-vm2,分配到的 IP 為 172.16.1.104: 6)cirros-vm2 被 schedule 到計(jì)算節(jié)點(diǎn),對(duì)應(yīng)的 tap 設(shè)備為 tapfb3fb197-24,并且連接到 bridge: 這里有兩點(diǎn)需要提醒:因?yàn)橛?jì)算節(jié)點(diǎn)上沒有 dhcp 服務(wù),所以 brctl show 中沒有 dhcp 對(duì)應(yīng)的 tap 設(shè)備。計(jì)算節(jié)點(diǎn)上 bridge 的名稱與控制節(jié)點(diǎn)上一致,都是 brqf153b42f-c3,表明是同一個(gè) network。 7)當(dāng)前 flat_net 的結(jié)構(gòu)如下: 8)cirros-vm1(172.16.1.103) 與 cirros-vm2(172.16.1.104) 位于不同節(jié)點(diǎn),通過 flat_net 相連,下面執(zhí)行 PING 驗(yàn)證連通性。 在 cirros-vm1 控制臺(tái)中執(zhí)行 ping 172.16.1.104:

2.5.5.5 DHCP服務(wù)

Neutron 提供 DHCP 服務(wù)的組件是 DHCP agent。 DHCP agent 在網(wǎng)絡(luò)節(jié)點(diǎn)運(yùn)行上,默認(rèn)通過 dnsmasq 實(shí)現(xiàn) DHCP 功能。 配置 DHCP agent: 1)DHCP agent 的配置文件位于 /etc/neutron/dhcp_agent.ini: dhcp_driver :使用 dnsmasq 實(shí)現(xiàn) DHCP。 interface_driver :使用 linux bridge 連接 DHCP namespace interface。 2)當(dāng)創(chuàng)建 network 并在 subnet 上 enable DHCP: 網(wǎng)絡(luò)節(jié)點(diǎn)上的 DHCP agent 會(huì)啟動(dòng)一個(gè)dnsmasq 進(jìn)程為該network 提供 DHCP 服務(wù),dnsmasq 是一個(gè)提供 DHCP 和 DNS 服務(wù)的開源軟件。dnsmasq 與 network 是一對(duì)一關(guān)系,一個(gè) dnsmasq 進(jìn)程可以為同一 netowrk 中所有 enable 了 DHCP 的 subnet 提供服務(wù)。 3)回到我們的實(shí)驗(yàn)環(huán)境,之前創(chuàng)建了 flat_net,并且在 subnet 上啟用了 DHCP,執(zhí)行 ps 查看 dnsmasq 進(jìn)程,如下圖所示: DHCP agent 會(huì)為每個(gè) network 創(chuàng)建一個(gè)目錄 /opt/stack/data/neutron/dhcp/,用于存放該 network 的 dnsmasq 配置文件。 4)討論 dnsmasq 重要的啟動(dòng)參數(shù): --dhcp-hostsfile:存放 DHCP host 信息的文件,這里的 host 在我們這里實(shí)際上就是 instance。dnsmasq 從該文件獲取 host 的 IP 與 MAC 的對(duì)應(yīng)關(guān)系。每個(gè) host 對(duì)應(yīng)一個(gè)條目,信息來源于 Neutron 數(shù)據(jù)庫。對(duì)于 flat_net,hostsfile 是 /opt/stack/data/neutron/dhcp/f153b42f-c3a1-4b6c-8865-c09b5b2aa274/host,記錄了 DHCP,cirros-vm1 和 cirros-vm2 的 interface 信息。 --interface:指定提供 DHCP 服務(wù)的 interface。dnsmasq 會(huì)在該 interface 上監(jiān)聽 instance 的 DHCP 請(qǐng)求。對(duì)于 flat_net,interface 是 ns-19a0ed3d-fe?;蛟S大家還記得,之前我們看到的 DHCP interface 叫 tap19a0ed3d-fe(如下圖所示),并非 ns-19a0ed3d-fe。 從名稱上看,ns-19a0ed3d-fe 和 tap19a0ed3d-fe 應(yīng)該存在某種聯(lián)系,但那是什么呢?要回答這個(gè)問題,需要先搞懂一個(gè)概念:Linux Network Namespace,我們下一節(jié)詳細(xì)討論。用 Namspace 隔離 DHCP 服務(wù): 1)Neutron 通過 dnsmasq 提供 DHCP 服務(wù),而 dnsmasq 如何獨(dú)立的為每個(gè) network 服務(wù)呢? 2)答案是通過 Linux Network Namespace 隔離。在二層網(wǎng)絡(luò)上,VLAN 可以將一個(gè)物理交換機(jī)分割成幾個(gè)獨(dú)立的虛擬交換機(jī)。 類似地,在三層網(wǎng)絡(luò)上,Linux network namespace 可以將一個(gè)物理三層網(wǎng)絡(luò)分割成幾個(gè)獨(dú)立的虛擬三層網(wǎng)絡(luò)。 3)每個(gè) namespace 都有自己獨(dú)立的網(wǎng)絡(luò)棧,包括 route table,firewall rule,network interface device 等。 4)Neutron 通過 namespace 為每個(gè) network 提供獨(dú)立的 DHCP 和路由服務(wù),從而允許租戶創(chuàng)建重疊的網(wǎng)絡(luò)。如果沒有 namespace,網(wǎng)絡(luò)就不能重疊,這樣就失去了很多靈活性。每個(gè) dnsmasq 進(jìn)程都位于獨(dú)立的 namespace,命名為 qdhcp-,例如 flat_net,我們有: 1)ip netns list 命令列出所有的 namespace。 qdhcp-f153b42f-c3a1-4b6c-8865-c09b5b2aa274 就是 flat_net 的 namespace。 2)其實(shí),宿主機(jī)本身也有一個(gè) namespace,叫 root namespace,擁有所有物理和虛擬 interface device。物理interface 只能位于 root namespace。新創(chuàng)建的 namespace 默認(rèn)只有一個(gè) loopback device。管理員可以將虛擬 interface,例如 bridge,tap 等設(shè)備添加到某個(gè) namespace。對(duì)于 flat_net 的 DHCP 設(shè)備 tap19a0ed3d-fe,需要將其放到 namespace qdhcp-f153b42f-c3a1-4b6c-8865-c09b5b2aa274 中,但這樣會(huì)帶來一個(gè)問題: tap19a0ed3d-fe 將無法直接與 root namespace 中的 bridge 設(shè)備 brqf153b42f-c3 連接。Neutron 使用 veth pair 解決了這個(gè)問題: 1)veth pair 是一種成對(duì)出現(xiàn)的特殊網(wǎng)絡(luò)設(shè)備,它們象一根虛擬的網(wǎng)線,可用于連接兩個(gè) namespace。向 veth pair 一端輸入數(shù)據(jù),在另一端就能讀到此數(shù)據(jù)。 2)tap19a0ed3d-fe 與 ns-19a0ed3d-fe 就是一對(duì) veth pair,它們將 qdhcp-f153b42f-c3a1-4b6c-8865-c09b5b2aa274 連接到 brqf153b42f-c3。 可以通過 ip netns exec 管理 namespace: 1)例如查看 ns-19a0ed3d-fe 的配置: 分析instance如何從dnsmasq獲取IP: 1)在創(chuàng)建 instance 時(shí),Neutron 會(huì)為其分配一個(gè) port,里面包含了 MAC 和 IP 地址信息,這些信息會(huì)同步更新到 dnsmasq 的 host 文件。如下圖所示: 2)同時(shí) nova-compute 會(huì)設(shè)置 cirros-vm1 VIF 的 MAC 地址: 3)一切準(zhǔn)備就緒,instance 獲取 IP 的過程如下: a)cirros-vm1 開機(jī)啟動(dòng),發(fā)出 DHCPDISCOVER 廣播,該廣播消息在整個(gè) flat_net 中都可以被收到。 b)廣播到達(dá) veth tap19a0ed3d-fe,然后傳送給 veth pair 的另一端 ns-19a0ed3d-fe。dnsmasq 在它上面監(jiān)聽,dnsmasq 檢查其 host 文件,發(fā)現(xiàn)有對(duì)應(yīng)項(xiàng),于是dnsmasq 以 DHCPOFFER 消息將 IP(172.16.1.103)、子網(wǎng)掩碼(255.255.255.0)、地址租用期限等信息發(fā)送給 cirros-vm1。 c)cirros-vm1 發(fā)送 DHCPREQUEST 消息確認(rèn)接受此 DHCPOFFER。 d)dnsmasq 發(fā)送確認(rèn)消息 DHCPACK,整個(gè)過程結(jié)束。這個(gè)過程我們可以在 dnsmasq 日志中查看,dnsmasq 默認(rèn)將日志記錄到 /var/log/syslog:

2.5.5.6 vlan network

下圖是 vlan100 網(wǎng)絡(luò)的示例,三個(gè) instance 通過 TAP 設(shè)備連接到名為 “brqXXXX” linux bridge。在物理網(wǎng)卡 eth1 上創(chuàng)建了 eth1.100 的 vlan interface,eth1.100 連接到 brqXXXX。instance 通過 eth1.100 發(fā)送到 eth1 的數(shù)據(jù)包就會(huì)打上 vlan100 的 tag。 如果再創(chuàng)建一個(gè) network vlan101,eth1 上會(huì)相應(yīng)的創(chuàng)建 vlan interface eth1.101,并且連接的新的 lingux bridge “brqYYYY”。 每個(gè) vlan network 有自己的 bridge,從而也就實(shí)現(xiàn)了基于 vlan 的隔離。 這里有一點(diǎn)要特別提醒:因?yàn)槲锢砭W(wǎng)卡 eth1 上面可以走多個(gè) vlan 的數(shù)據(jù),那么物理交換機(jī)上與 eth1 相連的的 port 要設(shè)置成 trunk 模式,而不是 access 模式。在 ML2 中配置 Vlan Network: 1)首先在 /etc/neutron/plugins/ml2/ml2_conf.ini 中設(shè)置 vlan network 相關(guān)參數(shù),指定普通用戶創(chuàng)建的網(wǎng)絡(luò)類型為 vlan: 2)然后指定 vlan 的范圍: 上面配置定義了 label 為 “default” 的 vlan network,vlan id 的范圍是 3001 – 4000。這個(gè)范圍是針對(duì)普通用戶在自己的租戶里創(chuàng)建 network 的范圍。因?yàn)槠胀ㄓ脩魟?chuàng)建 network 時(shí)并不能指定 vlan id,Neutron 會(huì)按順序自動(dòng)從這個(gè)范圍中取值。對(duì)于 admin 則沒有 vlan id 的限制,admin 可以創(chuàng)建 id 范圍為 1-4094 的 vlan network。 3)接著需要指明 vlan network 與物理網(wǎng)卡的對(duì)應(yīng)關(guān)系: 如上所示: 在 [ml2_type_vlan] 中定義了 lable “default”,[linux_bridge] 中則指明 default 對(duì)應(yīng)的物理網(wǎng)卡為 eth1。這里 label 的作用與前面 flat network 中的 label 一樣,只是一個(gè)標(biāo)識(shí),可以是任何字符串。配置完成,重啟 Neutron 服務(wù)后生效。創(chuàng)建第一個(gè) Vlan Network Vlan100: 1)打開菜單 Admin -> Networks,點(diǎn)擊 “Create Network” 按鈕: 2)顯示創(chuàng)建頁面,點(diǎn)擊 “Create Network”,vlan100 創(chuàng)建成功: Provider Network Type 選擇 “VLAN”。Physical Network 填寫 “default”,必須與 ml2_conf.ini中network_vlan_ranges 參數(shù)值保持一致。Segmentation ID 即 VLAN ID,設(shè)置為 100。 3)點(diǎn)擊 vlan100 鏈接,進(jìn)入 network 配置頁面: 4)目前還沒有 subnet,點(diǎn)擊 “Create Subnet” 按鈕: 5)subnet_172_16_100_0,IP 地址為 172.16.100.0/24: 6)底層網(wǎng)絡(luò)發(fā)生了什么變化: 在控制節(jié)點(diǎn)上執(zhí)行 brctl show,查看當(dāng)前網(wǎng)絡(luò)結(jié)構(gòu): Neutron 自動(dòng)新建了三個(gè)設(shè)備:

vlan100 對(duì)應(yīng)的網(wǎng)橋 brq3fcfdb98-9d。vlan interface eth1.100。dhcp 的 tap 設(shè)備 tap1180bbe8-06。 eth1.100 和 tap19a0ed3d-fe 已經(jīng)連接到了 brq3fcfdb98-9d,VLAN 100 的二層網(wǎng)絡(luò)就緒 7)此時(shí) vlan100 結(jié)構(gòu)如圖所示: 將instance連接到vlan100: 1)launch 新的 instance “cirros-vm1”,網(wǎng)絡(luò)選擇 vlan100: 2)cirros-vm1 分配到的 IP 為 172.16.100.3: 3)cirros-vm1 被 schedule 到控制節(jié)點(diǎn),對(duì)應(yīng)的 tap 設(shè)備為 tapc1875c7f-cb,并且連接到 bridge: 4)當(dāng)前 vlan100 的結(jié)構(gòu)如下 : 5)繼續(xù)用同樣的方式 launch instance cirros-vm2,分配到的 IP 為 172.16.100.104: 6)cirros-vm2 被 schedule 到計(jì)算節(jié)點(diǎn),對(duì)應(yīng)的 tap 設(shè)備為 tap238437b8-50,并且連接到 bridge: 因?yàn)橛?jì)算節(jié)點(diǎn)上沒有 hdcp 服務(wù),所以沒有相應(yīng)的 tap 設(shè)備。 另外,bridge 的名稱與控制節(jié)點(diǎn)上一致,都是 brq3fcfdb98-9d,表明是同一個(gè) network。 7)當(dāng)前 vlan100 的結(jié)構(gòu)如下: 8)cirros-vm1(172.16.100.3) 與 cirros-vm2(172.16.100.4) 位于不同節(jié)點(diǎn),通過 vlan100 相連,下面執(zhí)行 PING 驗(yàn)證連通性。 在 cirros-vm1 控制臺(tái)中執(zhí)行 ping 172.16.100.4: 創(chuàng)建第二個(gè) Vlan Network Vlan101: 1)創(chuàng)建第二個(gè) vlan network vlan101: 2)subnet IP 地址為 172.16.101.0/24: 3) 底層網(wǎng)絡(luò)發(fā)生了什么變化: Neutron 自動(dòng)創(chuàng)建了 vlan101 對(duì)應(yīng)的網(wǎng)橋 brq1d7040b8-01,vlan interface eth1.101,以及 dhcp 的 tap 設(shè)備 tap5b1a2247-32。eth1.101 和 tap5b1a2247-32 已經(jīng)連接到 brq1d7040b8-01,VLAN 101 的二層網(wǎng)絡(luò)就緒。 4)網(wǎng)絡(luò)結(jié)構(gòu)如下: 連接 Insance 到 Vlan101: 1)launch 新的 instance “cirros-vm3”,網(wǎng)絡(luò)選擇 vlan101: 2)cirros-vm3 分配到的 IP 為 172.16.101.103: 3)cirros-vm3 被 schedule 到計(jì)算節(jié)點(diǎn),對(duì)應(yīng)的 tap 設(shè)備為 tapadb5cc6a-7a,并且連接到 bridge: 4)當(dāng)前網(wǎng)絡(luò)結(jié)構(gòu)如下: cirros-vm1 位于控制節(jié)點(diǎn),屬于 vlan100。 cirros-vm2 位于計(jì)算節(jié)點(diǎn),屬于 vlan100。 cirros-vm3 位于計(jì)算節(jié)點(diǎn),屬于 vlan101。 cirros-vm1 與 cirros-vm2 都在 vlan100,它們之間能通信。 cirros-vm3 在 vlan101,不能與 cirros-vm1 和 cirros-vm2 通信。 那怎么樣才能讓 vlan100 與 vlan101 中的 instance 通信呢?單靠二層 vlan 是不行的,還得在三層通過路由器轉(zhuǎn)發(fā)。

2.5.5.7 Routing

Routing 功能概述: 1)路由服務(wù)(Routing)提供跨 subnet 互聯(lián)互通功能。例如前面我們搭建了實(shí)驗(yàn)環(huán)境: cirros-vm1 172.16.100.3 vlan100 cirros-vm3 172.16.101.3 vlan101 這兩個(gè) instance 要通信必須借助 router。 可以是物理 router 或者虛擬 router。 2)物理路由: 接入的物理 router 有兩個(gè) interface ip: 172.16.100.1 對(duì)應(yīng) vlan100 的網(wǎng)關(guān)。 172.16.101.1 對(duì)應(yīng) vlan101 的網(wǎng)關(guān)。 當(dāng) cirros-vm1 要跟 cirros-vm3 通信時(shí),數(shù)據(jù)包的流向是這樣的:a)因?yàn)?cirros-vm1 的默認(rèn)網(wǎng)關(guān)指向 172.16.100.1,cirros-vm1 發(fā)送到 cirros-vm3 的數(shù)據(jù)包首先通過 vlan100 的 interface 進(jìn)入物理 router。b)router 發(fā)現(xiàn)目的地址 172.16.101.3 與 172.16.101.1 為同一個(gè) vlan,則從 vlan101 的 interface 發(fā)出。c)數(shù)據(jù)包經(jīng)過 brq1d7040b8-01 最終到達(dá) cirros-vm3。 3)虛擬路由: 虛擬 router 的路由機(jī)制與物理 router 一樣,只是由軟件實(shí)現(xiàn)。Neutron 兩種方案都支持。如果要使用虛擬 router,需要啟用 L3 agent。L3 agent 會(huì)在控制節(jié)點(diǎn)或者網(wǎng)絡(luò)節(jié)點(diǎn)上運(yùn)行虛擬 router,為 subnet 提供路由服務(wù)。 配置 L3 Agent: 1)Neutron 的路由服務(wù)是由 l3 agent 提供的,除此之外,l3 agent 通過 iptables 提供 firewall 和 floating ip 服務(wù)。 2)l3 agent 需要正確配置才能工作,配置文件為 /etc/neutron/l3_agent.ini,位于控制節(jié)點(diǎn)或網(wǎng)絡(luò)節(jié)點(diǎn)上: interface_driver 是最重要的選項(xiàng),如果 mechanism driver 是 linux bridge,則:interface_driver = neutron.agent.linux.interface.BridgeInterfaceDriver;如果選用 open vswitch,則:interface_driver = neutron.agent.linux.interface.OVSInterfaceDriver。 3)l3 agent 運(yùn)行在控制或網(wǎng)絡(luò)節(jié)點(diǎn)上: 可以看到 l3 agnet 已經(jīng)正常啟動(dòng)。 創(chuàng)建 Router 連通 Subnet: 1)創(chuàng)建虛擬路由器“router_100_101”,打通 vlan100 和 vlan101。打開操作菜單 Project -> Network -> Routers: 2)點(diǎn)擊 “Create Router” 按鈕: 3)router 命名為 “router_100_101”,點(diǎn)擊 “Create Router” 按鈕確認(rèn): 4)router_100_101 創(chuàng)建成功: 5)接下來需要將 vlan100 和 vlan101 連接到 router_100_101 。點(diǎn)擊 “router_100_101” 鏈接進(jìn)入 router 的配置頁面,在 “Interfaces” 標(biāo)簽中點(diǎn)擊 “Add Interface” 按鈕 6)選擇 vlan101 的 subnet_172_16_101_0,點(diǎn)擊 “Add Interface” 確認(rèn): 7)用同樣的方法添加 vlan100 的 subnet_172_16_100_0: 完成后,可以看到 router_100_101 有了兩個(gè) interface,其 IP 正好是 subnet 的 Gateway IP 172.16.100.1 和 172.16.101.1。 8)router_100_101 已經(jīng)連接了 subnet_172_16_100_0 和 subnet_172_16_101_0。router_100_101 上已經(jīng)設(shè)置好了兩個(gè) subnet 的 Gateway IP。cirros-vm1 和 cirros-vm3 應(yīng)該可以通信了。通過 PING 測(cè)試一下: 9)查看 cirros-vm1 的路由表,默認(rèn)網(wǎng)關(guān)為 172.16.100.1。同時(shí) traceroute 告訴我們,cirros-vm1 確實(shí)是通過 router_100_101 訪問到 cirros-vm3 的: 虛擬 ?Router 原理分析: 1)首先我們查看控制節(jié)點(diǎn)的 linux bridge 結(jié)構(gòu)發(fā)生了什么變化: vlan101 的 bridge 上多了一個(gè) tape17162c5-00,從命名上可以推斷該 TAP 設(shè)備對(duì)應(yīng) router_100_101 的 interface (e17162c5-00fa)。vlan100 的 bridge 上多了一個(gè) tapd568ba1a-74,從命名上可以推斷該 TAP 設(shè)備對(duì)應(yīng) router_100_101 的 interface (d568ba1a-740e)。 2)當(dāng)前網(wǎng)絡(luò)結(jié)構(gòu)如圖所示: 3)兩個(gè) TAP 設(shè)備上并沒有配置相應(yīng)的 Gateway IP: 4)如果沒有 Gateway IP,router_100_101 是如何完成路由的呢? 答案是:l3 agent 會(huì)為每個(gè) router 創(chuàng)建了一個(gè) namespace,通過 veth pair 與 TAP 相連,然后將 Gateway IP 配置在位于 namespace 里面的 veth interface 上,這樣就能提供路由了。 5)通過 ip netns 查看 namespace:router 對(duì)應(yīng)的 namespace 命名為 qrouter-。 6)通過 ip netns exec ip a 命令查看 router_100_101 namespace 中的 veth interface 配置: namespace 中有兩個(gè) interface:qr-e17162c5-00 上設(shè)置了 Gateway IP 172.16.101.1,與 root namespace 中的 tape17162c5-00 組成 veth pair。qr-d568ba1a-74 上設(shè)置了 Gateway IP 172.16.100.1,與 root namespace 中的 tapd568ba1a-74 組成 veth pair。 7)網(wǎng)絡(luò)結(jié)構(gòu)如圖所示: 8)namespace 中的路由表也保證了 subnet_172_16_100_0 和 subnet_172_16_101_0 之間是可以路由的,命令為ip nets exec IP routing table: 為什么要使用Namespace: 1)為什么不直接在 tape17162c5-00 和 tapd568ba1a-74 上配置 Gateway IP,而是引入一個(gè) namespace,在 namespace 里面配置 Gateway IP 呢?首先考慮另外一個(gè)問題:如果不用 namespace,直接 Gareway IP 配置到 tape17162c5-00 和 tapd568ba1a-74 上,能不能連通 subnet_172_16_100_0 和 subnet_172_16_101_0 呢? 答案是可以的,只要控制節(jié)點(diǎn)上配置了類似下面的路由: 既然不需要 namespace 也可以路由,為什么還要加一層 namespace 增加復(fù)雜性呢?其根本原因是:增加namespace是為了支持網(wǎng)絡(luò)重疊。 云環(huán)境下,租戶可以按照自己的規(guī)劃創(chuàng)建網(wǎng)絡(luò),不同租戶的網(wǎng)絡(luò)是可能重疊的。 將路由功能放到 namespace 中,就能隔離不同租戶的網(wǎng)絡(luò),從而支持網(wǎng)絡(luò)重疊。 2)通過例子進(jìn)一步解釋:A,B 兩個(gè)租戶定義了完全相同的兩個(gè) subnet,網(wǎng)絡(luò)完全重疊。如下圖所示: 3)不使用namespace的場(chǎng)景: 其特征是網(wǎng)關(guān) IP 配置在 TAP interface 上。因?yàn)闆]有 namespace 隔離,router_100_101 和 router_102_103 的路由條目都只能記錄到控制節(jié)點(diǎn)操作系統(tǒng)(root namespace)的路由表中,內(nèi)容如下: 這樣的路由表是無法工作的。按照路由表優(yōu)先匹配原則,Tenant B 的數(shù)據(jù)包總是錯(cuò)誤地被 Tenant A 的 router 路由。例如 vlan102 上有數(shù)據(jù)包要發(fā)到 vlan103。選擇路由時(shí),會(huì)匹配路由表的第二個(gè)條目,結(jié)果數(shù)據(jù)被錯(cuò)誤地發(fā)到了 vlan101。 4) 使用 namespace 的場(chǎng)景:如果使用 namespace,網(wǎng)絡(luò)結(jié)構(gòu)如下: 其特征是網(wǎng)關(guān) IP 配置在 namespace 中的 veth interface 上。每個(gè) namespace 擁有自己的路由表。router_100_101 的路由表內(nèi)容如下: router_102_103 的路由表內(nèi)容如下: 這樣的路由表是可以工作的。例如 vlan102 上有數(shù)據(jù)包要發(fā)到 vlan103。選擇路由時(shí),會(huì)查看 router_102_103 的路由表, 匹配第二個(gè)條目,數(shù)據(jù)通過 qr-4 被正確地發(fā)送到 vlan103。同樣當(dāng) vlan100 上有數(shù)據(jù)包要發(fā)到 vlan101時(shí),會(huì)匹配 router_100_101 路由表的第二個(gè)條目,數(shù)據(jù)通過 qr-2 被正確地發(fā)送到 vlan101。可見,namespace 使得每個(gè) router 有自己的路由表,而且不會(huì)與其他 router 沖突,所以能很好地支持網(wǎng)絡(luò)重疊。 instance訪問外網(wǎng) ML2 的配置: 1)這里的外部網(wǎng)絡(luò)是指的租戶網(wǎng)絡(luò)以外的網(wǎng)絡(luò)。租戶網(wǎng)絡(luò)是由 Neutron 創(chuàng)建和維護(hù)的網(wǎng)絡(luò)。 外部網(wǎng)絡(luò)不由 Neutron 創(chuàng)建。如果是私有云,外部網(wǎng)絡(luò)通常指的是公司 intranet;如果是公有云,外部網(wǎng)絡(luò)通常指的是 internet。具體到我們的實(shí)驗(yàn)網(wǎng)絡(luò)環(huán)境: 計(jì)算節(jié)點(diǎn)和控制節(jié)點(diǎn) eth1 提供的是租戶網(wǎng)絡(luò),IP 段租戶可以自由設(shè)置。 控制節(jié)點(diǎn) eth2 連接的就是外部網(wǎng)絡(luò),IP 網(wǎng)段為 10.10.10.0/24。如下圖所示: 2)配置準(zhǔn)備:為了連接外部網(wǎng)絡(luò),需要在配置文件中告訴 Neutron 外部網(wǎng)絡(luò)的類型以及對(duì)應(yīng)的物理網(wǎng)卡 因?yàn)橥獠烤W(wǎng)絡(luò)是已經(jīng)存在的物理網(wǎng)絡(luò),一般都是 flat 或者 vlan 類型。這里我們將外部網(wǎng)絡(luò)的 label 命名為 “external”。 如果類型為 flat,控制節(jié)點(diǎn) /etc/neutron/plugins/ml2/ml2_conf.ini 配置如下: 如果類型為 vlan,配置如下 修改配置后,需要重啟 neutron 的相關(guān)服務(wù)。在我們的網(wǎng)絡(luò)環(huán)境中,外部網(wǎng)絡(luò)是 flat 類型。 創(chuàng)建外網(wǎng) Ext_net: 1)進(jìn)入 Admin -> Networks 菜單,點(diǎn)擊 “Create Network” 按鈕: 2)顯示創(chuàng)建頁面,點(diǎn)擊 “Create Network”,ext_net 創(chuàng)建成功,其中Provider Network Type 選擇 “Flat”;Physical Network 填寫 “external”,與 ml2_conf.ini 中 flat_networks 參數(shù)的設(shè)置保持一致;勾選 External Network 選擇框。 3)點(diǎn)擊 ext_net 鏈接,進(jìn)入 network 配置頁面: 4)目前還沒有 subnet,點(diǎn)擊 “Create Subnet” 按鈕: 5)創(chuàng)建 subnet_10_10_10_0,IP 地址為 10.10.10.0/24,點(diǎn)擊 “Next”。這里 Gateway 我們使用默認(rèn)地址 10.10.10.1。 通常我們需要詢問網(wǎng)絡(luò)管理員外網(wǎng) subnet 的 Gateway IP,然后填在這里: 6)因?yàn)槲覀儾粫?huì)直接為 instance 分配外網(wǎng) IP,所以一般不需要 enable DHCP,點(diǎn)擊 “Create”: 7)subnet 創(chuàng)建成功,網(wǎng)關(guān)為 10.10.10.1: 8)查看控制節(jié)點(diǎn)網(wǎng)絡(luò)結(jié)構(gòu)的變化,執(zhí)行 brctl show: 增加了一個(gè)網(wǎng)橋 brqe496d3d2-53,物理網(wǎng)卡 eth2 已經(jīng)連接到該 bridge。 外網(wǎng)訪問原理分析: 1)將外網(wǎng)連接到 Neutron 的虛擬路由器,這樣 instance 才能訪問外網(wǎng) 。點(diǎn)擊菜單 Project -> Network -> Routers 進(jìn)入 router 列表,點(diǎn)擊 router_100_101 的 “Set Gateway” 按鈕: 2) “External Network” 下拉列表中選擇 ext_net,點(diǎn)擊 “Set Gateway” : 3)外網(wǎng)設(shè)置成功: 4) 我們需要看看 router 發(fā)生了什么變化 。點(diǎn)擊 “router_100_101” 鏈接,打開 “Interfaces” 標(biāo)簽頁:router 多了一個(gè)新的 interface,IP 為 10.10.10.2。 該 interface 用于連接外網(wǎng) ext_net。 5)查看控制節(jié)點(diǎn)的網(wǎng)絡(luò)結(jié)構(gòu),外網(wǎng) bridge 上已經(jīng)連接了 router 的 tap 設(shè)備 tapb8b32a88-03: 6)ip netns list 命令列出所有的 namespace。在 router 的 namespace 中查看 tapb8b32a88-03 的 veth pair 設(shè)備: 該 veth pair 命名為 qg-b8b32a88-03,上面配置了 IP 10.10.10.2。router 的每個(gè) interface 在 namespace 中都有對(duì)應(yīng)的 veth。如果 veth 用于連接租戶網(wǎng)絡(luò),命名格式為 qr-xxx,比如 qr-d568ba1a-74 和 qr-e17162c5-00。如果 veth 用于連接外部網(wǎng)絡(luò),命名格式為 qg-xxx,比如 qg-b8b32a88-03。 7)查看 router 的路由表信息: 可以看到默認(rèn)網(wǎng)關(guān)為 10.10.10.1。 意味著對(duì)于訪問 vlan100 和 vlan101 租戶網(wǎng)絡(luò)以外的所有流量,router_100_101 都將轉(zhuǎn)發(fā)給 ext_net 的網(wǎng)關(guān) 10.10.10.1。 8)現(xiàn)在 router_100_101 已經(jīng)同時(shí)連接了 vlan100, vlan101 和 ext_net 三個(gè)網(wǎng)絡(luò),如下圖所示: 9)下面我們?cè)?cirros-vm3 上測(cè)試一下:irros-vm3 位于計(jì)算節(jié)點(diǎn),現(xiàn)在已經(jīng)可以 Ping 到 ext_net 網(wǎng)關(guān) 10.10.10.1 了。 10)通過 traceroute 查看一下 cirros-vm3 到 10.10.10.1 的路徑 : 數(shù)據(jù)包經(jīng)過兩跳到達(dá) 10.10.10.1 網(wǎng)關(guān)。數(shù)據(jù)包首先發(fā)送到 router_100_101 連接 vlan101 的 interface(172.16.101.1)。然后通過連接 ext_net 的 interface(10.10.10.2) 轉(zhuǎn)發(fā)出去,最后到達(dá) 10.10.10.1。 當(dāng)數(shù)據(jù)包從 router 連接外網(wǎng)的接口 qg-b8b32a88-03 發(fā)出的時(shí)候,會(huì)做一次 Source NAT,即將包的源地址修改為 router 的接口地址 10.10.10.2,這樣就能夠保證目的端能夠?qū)?yīng)答的包發(fā)回給 router,然后再轉(zhuǎn)發(fā)回源端 instance。 11)可以通過 iptables 命令查看 SNAT 的規(guī)則: 當(dāng) cirros-vm3(172.16.101.3) Ping 10.10.10.1 時(shí),可用通過 tcpdump 分別觀察 router 兩個(gè) interface 的icmp 數(shù)據(jù)包來驗(yàn)證 SNAT 的行為。 12)vlan101 interface qr-e17162c5-00 的 tcpdump 輸出: 13)ext_net interface qg-b8b32a88-03 的 tcpdump 輸出: SNAT 讓 instance 能夠直接訪問外網(wǎng),但外網(wǎng)還不能直接訪問 instance。因?yàn)?instance 沒有外網(wǎng) IP。這里 “直接訪問 instance” 是指通信連接由外網(wǎng)發(fā)起,例如從外網(wǎng) SSH cirros-vm3。 這個(gè)問題可以通過 floating IP 解決,下一節(jié)我們將討論浮動(dòng) IP。 創(chuàng)建 Floating IP: 1)先復(fù)習(xí)一下前面我們討論的知識(shí): 當(dāng)租戶網(wǎng)絡(luò)連接到 Neutron router,通常將 router 作為默認(rèn)網(wǎng)關(guān)。當(dāng) router 接收到 instance 的數(shù)據(jù)包,并將其轉(zhuǎn)發(fā)到外網(wǎng)時(shí):a)router 會(huì)修改包的源地址為自己的外網(wǎng)地址,這樣確保數(shù)據(jù)包轉(zhuǎn)發(fā)到外網(wǎng),并能夠從外網(wǎng)返回。b)router 修改返回的數(shù)據(jù)包,并轉(zhuǎn)發(fā)給真正的 instance。這個(gè)行為被稱作 Source NAT。 如果需要從外網(wǎng)直接訪問 instance,則可以利用 floating IP。下面是關(guān)于 floating IP 必須知道的事實(shí):a)floating IP 提供靜態(tài) NAT 功能,建立外網(wǎng) IP 與 instance 租戶網(wǎng)絡(luò) IP 的一對(duì)一映射。b)floating IP 是配置在 router 提供網(wǎng)關(guān)的外網(wǎng) interface 上的,而非 instance 中。c)router 會(huì)根據(jù)通信的方向修改數(shù)據(jù)包的源或者目的地址。 2)下面我們通過實(shí)驗(yàn)深入學(xué)習(xí) floating IP 。點(diǎn)擊 Project -> Compute -> Access & Security 菜單,打開 Floating IPs 標(biāo)簽頁點(diǎn)擊 “Allocate IP To Project” 按鈕: 3)floating IP Pool 為 ext_net,點(diǎn)擊 “Allocate IP” 按鈕: 從 Pool 中成功分配了一個(gè) IP 10.10.10.3。 4)下面我們將它分配給 cirror-vm3,點(diǎn)擊 “Associate” 按鈕: 5)在下拉列表中選擇 cirror-vm3,點(diǎn)擊 “Associate” 按鈕: 6)分配成功,floating IP 10.10.10.3 已經(jīng)對(duì)應(yīng)到 cirros-vm3 的租戶 IP 172.16.101.3: 7)執(zhí)行ip netns exec ip a首先查看 router 的 interface 配置: 可以看到,floating IP 已經(jīng)配置到 router 的外網(wǎng) interface qg-b8b32a88-03 上。 8)執(zhí)行ip netns exec iptables -t nat -S查看 router 的 NAT 規(guī)則: iptables 增加了兩條處理 floating IP 的規(guī)則: a)當(dāng) router 接收到從外網(wǎng)發(fā)來的包,如果目的地址是 floating IP 10.10.10.3,將目的地址修改為 cirros-vm3 的 IP 172.16.101.3。這樣外網(wǎng)的包就能送達(dá)到 cirros-vm3。b)當(dāng) cirros-vm3 發(fā)送數(shù)據(jù)到外網(wǎng),源地址 172.16.101.3 將被修改為 floating IP 10.10.10.3。 9)在我的實(shí)驗(yàn)環(huán)境中,10.10.10.1 是外網(wǎng)中的物理交換機(jī),現(xiàn)在讓它 PING cirros-vm3,能PING通: 10)ext_net interface qg-b8b32a88-03 的 tcpdump 輸出: 可見,在外網(wǎng)接口 qg-b8b32a88-03 上,始終是通過 floating IP 10.10.10.3 與外網(wǎng)通信。 11)vlan101 interface qr-e17162c5-00 的 tcpdump 輸出: 當(dāng)數(shù)據(jù)轉(zhuǎn)發(fā)到租戶網(wǎng)絡(luò),地址已經(jīng)變?yōu)?cirros-vm3 的租戶 IP 172.16.101.3 了。 12)小結(jié): a)floating IP 能夠讓外網(wǎng)直接訪問租戶網(wǎng)絡(luò)中的 instance。這是通過在 router 上應(yīng)用 iptalbes 的 NAT 規(guī)則實(shí)現(xiàn)的。 b)floating IP 是配置在 router 的外網(wǎng) interface 上的,而非 instance,這一點(diǎn)需要特別注意。 至此,我們已經(jīng)完成了 Neutron L3 服務(wù)連接不同 subnet,訪問外網(wǎng),以及 floating IP 的學(xué)習(xí)。

2.5.5.8 vxlan network

前言: 除了前面討論的 local, flat, vlan 這幾類網(wǎng)絡(luò),OpenStack 還支持 vxlan 和 gre 這兩種 overlay network。overlay network 是指建立在其他網(wǎng)絡(luò)上的網(wǎng)絡(luò)。 該網(wǎng)絡(luò)中的節(jié)點(diǎn)可以看作通過虛擬(或邏輯)鏈路連接起來的。 overlay network 在底層可能由若干物理鏈路組成,但對(duì)于節(jié)點(diǎn),不需要關(guān)心這些底層實(shí)現(xiàn)。例如 P2P 網(wǎng)絡(luò)就是 overlay network,隧道也是。 vxlan 和 gre 都是基于隧道技術(shù)實(shí)現(xiàn)的,它們也都是 overlay network。目前 linux bridge 只支持 vxlan,不支持 gre;open vswitch 兩者都支持。 vxlan 與 gre 實(shí)現(xiàn)非常類似,而且 vxlan 用得較多,所以本教程只介紹 vxlan。VXLAN 全稱 Virtual eXtensible Local Area Network(虛擬擴(kuò)展局域網(wǎng)),VXLAN 提供與 VLAN 相同的以太網(wǎng)二層服務(wù),但是擁有更強(qiáng)的擴(kuò)展性和靈活性。與 VLAN 相比,VXLAN 有下面幾個(gè)優(yōu)勢(shì): 1)支持更多的二層網(wǎng)段。 VLAN 使用 12-bit 標(biāo)記 VLAN ID,最多支持 4094 個(gè) VLAN,這對(duì)于大型云部署會(huì)成為瓶頸。VXLAN 的 ID (VNI 或者 VNID)則用 24-bit 標(biāo)記,支持 16777216 個(gè)二層網(wǎng)段; 2)VXLAN 的數(shù)據(jù)包是封裝到 UDP 通過三層傳輸和轉(zhuǎn)發(fā)的; 3)避免物理交換機(jī) MAC 表耗盡。 由于采用隧道機(jī)制, 交換機(jī)無需在 MAC 表中記錄虛擬機(jī)的信息。VXLAN 封裝和包格式: 1)VXLAN 是將二層建立在三層上的網(wǎng)絡(luò)。 通過將二層數(shù)據(jù)封裝到 UDP 的方式來擴(kuò)展數(shù)據(jù)中心的二層網(wǎng)段數(shù)量; 2)VXLAN 是一種在現(xiàn)有物理網(wǎng)絡(luò)設(shè)施中支持大規(guī)模多租戶網(wǎng)絡(luò)環(huán)境的解決方案。 VXLAN 的傳輸協(xié)議是 IP + UDP; 3)VXLAN 定義了一個(gè) MAC-in-UDP 的封裝格式。 在原始的 Layer 2 網(wǎng)絡(luò)包前加上 VXLAN header,然后放到 UDP 和 IP 包中。 通過 MAC-in-UDP 封裝,VXLAN 能夠在 Layer 3 網(wǎng)絡(luò)上建立起了一條 Layer 2 的隧道; 4)VXLAN 包的格式如下: 如上圖所示,VXLAN 引入了 8-byte VXLAN header,其中 VNI 占 24-bit。VXLAN 和原始的 L2 frame 被封裝到 UDP 包中。這 24-bit 的 VNI 用于標(biāo)示不同的二層網(wǎng)段,能夠支持 16777216 個(gè) LAN。VXLAN Tunnel Endpoint 1)VXLAN 使用 VXLAN tunnel endpoint (VTEP) 設(shè)備處理 VXLAN 的封裝和解封。每個(gè) VTEP 有一個(gè) IP interface,配置了一個(gè) IP 地址。VTEP 使用該 IP 封裝 Layer 2 frame,并通過該 IP interface 傳輸和接收封裝后的 VXLAN 數(shù)據(jù)包。 2)下面是 VTEP 的示意圖: 3)VXLAN 獨(dú)立于底層的網(wǎng)絡(luò)拓?fù)?;反過來,兩個(gè) VTEP 之間的底層 IP 網(wǎng)絡(luò)也獨(dú)立于 VXLAN。 VXLAN 數(shù)據(jù)包是根據(jù)外層的 IP header 路由的,該 header 將兩端的 VTEP IP 作為源和目標(biāo) IP。VXLAN包轉(zhuǎn)發(fā)流程: VXLAN 在 VTEP 間建立隧道,通過 Layer 3 網(wǎng)絡(luò)傳輸封裝后的 Layer 2 數(shù)據(jù)。數(shù)據(jù)傳輸過程如下: 1)Host-A 向 Host-B 發(fā)送數(shù)據(jù)時(shí),Host-B 的 MAC 和 IP 作為數(shù)據(jù)包的目標(biāo) MAC 和 IP,Host-A 的 MAC 作為數(shù)據(jù)包的源 MAC 和 IP,然后通過 VTEP-1 將數(shù)據(jù)發(fā)送出去。 2)VTEP-1 從自己維護(hù)的映射表中找到 MAC-B 對(duì)應(yīng)的 VTEP-2,然后執(zhí)行 VXLAN 封裝,加上 VXLAN頭,UDP 頭,以及外層 IP 和 MAC 頭。此時(shí)的外層 IP 頭,目標(biāo)地址為 VTEP-2 的 IP,源地址為 VTEP-1 的IP。同時(shí)由于下一跳是 Router-1,所以外層 MAC 頭中目標(biāo)地址為 Router-1 的 MAC。 3)數(shù)據(jù)包從 VTEP-1 發(fā)送出去后,外部網(wǎng)絡(luò)的路由器會(huì)依據(jù)外層 IP 頭進(jìn)行包路由,最后到達(dá)與 VTEP-2 連接的路由器 Router-2。 4)Router-2將數(shù)據(jù)包發(fā)送給 VTEP-2。VTEP-2 負(fù)責(zé)解封數(shù)據(jù)包,依次去掉外層 MAC 頭,外層 IP 頭,UDP 頭 和 VXLAN 頭。 5)VTEP-2 依據(jù)目標(biāo) MAC 地址將數(shù)據(jù)包發(fā)送給 Host-B。 上面的流程我們看到 VTEP 是 VXLAN 的最核心組件,負(fù)責(zé)數(shù)據(jù)的封裝和解封。隧道也是建立在 VTEP 之間的,VTEP 負(fù)責(zé)數(shù)據(jù)的傳送。在 ML2 中配置 VXLAN: 1)在 /etc/neutron/plugins/ml2/ml2_conf.ini 設(shè)置 vxlan network 相關(guān)參數(shù): 2)然后指定 vxlan 的范圍: 上面的配置定義了 vxlan vni 的范圍是 1001 – 2000。這個(gè)范圍是針對(duì)普通用戶在自己的租戶里創(chuàng)建 vxlan network 的范圍。因?yàn)槠胀ㄓ脩魟?chuàng)建 network 時(shí)并不能指定 vni,Neutron 會(huì)按順序自動(dòng)從這個(gè)范圍中取值。對(duì)于 admin 則沒有 vni 范圍的限制,admin 可以創(chuàng)建 vni 范圍為 1-16777216 的 vxlan network。 3)接著需要在 [VXLAN] 中配置 VTEP: 控制節(jié)點(diǎn) devstack_controller 的 ml2_conf.ini 配置如下: 計(jì)算節(jié)點(diǎn) devstack_compute01 的 ml2_conf.ini 配置如下: local_ip 指定節(jié)點(diǎn)上用作 VTEP 的 IP 地址。devstack_controller 的 VTEP IP 是 166.66.16.10,網(wǎng)卡為 eth1。devstack_compute01 的 VTEP IP 是 166.66.16.11,網(wǎng)卡為 eth1。注意:作為準(zhǔn)備工作,這兩個(gè) VTEP IP 需要提前配置到節(jié)點(diǎn)的 eht1 上,Neutron 并不會(huì)幫我們分配這個(gè) IP。創(chuàng)建 VXLAN: 1)打開菜單 Admin -> Networks,點(diǎn)擊 “Create Network” 按鈕 2)顯示創(chuàng)建頁面,Provider Network Type 選擇 “VXLAN” Segmentation ID 即 VNI,設(shè)置為 100。點(diǎn)擊 “Create Network”,vxlan100 創(chuàng)建成功: 3)點(diǎn)擊 vxlan100 鏈接,進(jìn)入 network 配置頁面: 4)目前還沒有 subnet,點(diǎn)擊 “Create Subnet” 按鈕: 5)創(chuàng)建 subnet_172_16_100_0,IP 地址為 172.16.100.0/24: 6)底層網(wǎng)絡(luò)發(fā)生了什么變化 。在控制節(jié)點(diǎn)上執(zhí)行 brctl show,查看當(dāng)前的網(wǎng)絡(luò)結(jié)構(gòu): Neutron 創(chuàng)建了: a. vxlan100 對(duì)應(yīng)的網(wǎng)橋 brq1762d312-d4 b. vxlan interface vxlan-100 c. dhcp 的 tap 設(shè)備 tap4df76d0e-59 d. vxlan-100 和 tap4df76d0e-59 已經(jīng)連接到 brq1762d312-d4,vxlan100 的二層網(wǎng)絡(luò)就緒。 7)執(zhí)行 ip -d link show dev vxlan-100 查看 vxlan interface 的詳細(xì)配置 可見,vxlan-100 的 VNI 是 100,對(duì)應(yīng)的 VTEP 網(wǎng)絡(luò)接口為 eth1。 8)此時(shí) vxlan100 結(jié)構(gòu)如圖所示: 部署 Instance 到 VXLAN: 1)launch 新的 instance “cirros-vm1”,網(wǎng)絡(luò)選擇vxlan100: 2)cirros-vm1 分配到的 IP 為 172.16.100.3: 3)cirros-vm1 被 schedule 到控制節(jié)點(diǎn),對(duì)應(yīng)的 tap 設(shè)備為 tap099caa87-cd,并且連接到 bridge brq1762d312-d4: 4)當(dāng)前 vxlan100 的結(jié)構(gòu)如下: 5)繼續(xù)用同樣的方式 launch instance cirros-vm2,分配到的 IP 為 172.16.100.4: 6)cirros-vm2 被 schedule 到計(jì)算節(jié)點(diǎn),對(duì)應(yīng)的 tap 設(shè)備為 tap457cc048-aa,并且連接到 bridge brq1762d312-d4: 7)因?yàn)橛?jì)算節(jié)點(diǎn)上沒有 dhcp 服務(wù),所以沒有相應(yīng)的 tap 設(shè)備。另外,bridge 的名稱與控制節(jié)點(diǎn)上一致,都是 brq1762d312-d4,表明是同一個(gè) network。 8)當(dāng)前vxlan100的結(jié)構(gòu)如下: 9)cirros-vm1(172.16.100.3) 與 cirros-vm2(172.16.100.4) 位于不同節(jié)點(diǎn),通過 vxlan100 相連,下面執(zhí)行 PING 驗(yàn)證連通性。 在 cirros-vm1 控制臺(tái)中執(zhí)行 ping 172.16.100.4: 如我們預(yù)料,ping 成功。對(duì)于多 vxlan 之間的 routing 以及 floating ip,實(shí)現(xiàn)方式與 vlan 非常類似。L2 Population 原理: 1)作用:L2 Population 是用來提高 VXLAN 網(wǎng)絡(luò) Scalability 的。通常我們說某個(gè)系統(tǒng)的 Scalability 好,其意思是:當(dāng)系統(tǒng)的規(guī)模變大時(shí),仍然能夠高效地工作。 2)L2 Population 到底解決了怎樣的 Scalability 問題,請(qǐng)看下圖: 3)這是一個(gè)包含 5 個(gè)節(jié)點(diǎn)的 VXLAN 網(wǎng)絡(luò),每個(gè)節(jié)點(diǎn)上運(yùn)行了若干 VM?,F(xiàn)在假設(shè) Host 1 上的 VM A 想與 Host 4 上的 VM G 通信。VM A 要做的第一步是獲知 VM G 的 MAC 地址。于是 VM A 需要在整個(gè) VXLAN 網(wǎng)絡(luò)中廣播 APR 報(bào)文:“VM G 的 MAC 地址是多少?” 4)如果 VXLAN 網(wǎng)絡(luò)的節(jié)點(diǎn)很多,廣播的成本會(huì)很大,這樣 Scalability 就成問題了,幸好 L2 Population 出現(xiàn)了:L2 Population 的作用是在 VTEP 上提供 Porxy ARP 功能,使得 VTEP 能夠預(yù)先獲知 VXLAN 網(wǎng)絡(luò)中如下信息:VM IP — MAC 對(duì)應(yīng)關(guān)系、VM — VTEP 的對(duì)應(yīng)關(guān)系: 5)當(dāng) VM A 需要與 VM G 通信時(shí):a)Host 1 上的 VTEP 直接響應(yīng) VM A 的 APR 請(qǐng)求,告之 VM G 的 MAC 地址。b)因?yàn)?Host 1 上的 VTEP 知道 VM G 位于 Host 4,會(huì)將封裝好的 VXLAN 數(shù)據(jù)包直接發(fā)送給 Host 4 的 VTEP。這樣就解決了 MAC 地址學(xué)習(xí)和 APR 廣播的問題,從而保證了 VXLAN 的 Scalability。 6)那么下一個(gè)關(guān)鍵問題是:VTEP 是如何提前獲知 IP — MAC — VTEP 相關(guān)信息的呢? 答案是:a)Neutron 知道每一個(gè) port 的狀態(tài)和信息; port 保存了 IP,MAC 相關(guān)數(shù)據(jù)。b)instance 啟動(dòng)時(shí),其 port 狀態(tài)變化過程為:down -> build -> active。c)每當(dāng) port 狀態(tài)發(fā)生變化時(shí),Neutron 都會(huì)通過 RPC 消息通知各節(jié)點(diǎn)上的 Neutron agent,使得 VTEP 能夠更新 VM 和 port 的相關(guān)信息。VTEP 可以根據(jù)這些信息判斷出其他 Host 上都有哪些 VM,以及它們的 MAC 地址,這樣就能直接與之通信,從而避免了不必要的隧道連接和廣播。配置 L2 Population: 1)目前 L2 Population 支持 VXLAN with Linux bridge 和 VXLAN/GRE with OVS; 2)在 /etc/neutron/plugins/ml2/ml2_conf.ini 設(shè)置 l2population mechanism driver: 3)同時(shí)在 [VXLAN] 中配置 enable L2 Population: 4)L2 Population 生效后,輸入ip -d link show dev vxlan-100命令,發(fā)現(xiàn)創(chuàng)建的 vxlan-100 會(huì)多一個(gè) Proxy ARP 功能: 5)輸入bridge fdb show dev vxlan-100命令查看控制節(jié)點(diǎn)上的 forwarding database,可以看到 VTEP 保存了 cirros-vm2 的 port 信息: 6)cirros-vm2 的 MAC 為 fa:16:3e:1d:23:a3。 VTEP IP 為 166.66.16.11。當(dāng)需要與 cirros-vm2 通信時(shí),控制節(jié)點(diǎn) VTEP 166.66.16.10 會(huì)將封裝好的 VXLAN 數(shù)據(jù)包直接發(fā)送給計(jì)算節(jié)點(diǎn)的 VTEP 166.66.16.11。 7)輸入bridge fdb show dev vxlan-100命令查看計(jì)算節(jié)點(diǎn)上的 forwarding database: 8)fdb 中保存了 cirros-vm1 和 dhcp 的 port 信息。當(dāng)需要與它們通信時(shí),計(jì)算節(jié)點(diǎn) VTEP 知道應(yīng)該將數(shù)據(jù)包直接發(fā)送給控制節(jié)點(diǎn)的 VTEP。

2.5.5.9 Security Group

Neutron 為 instance 提供了兩種管理網(wǎng)絡(luò)安全的方法:安全組(Security Group)和虛擬防火墻。安全組的原理是通過 iptables 對(duì) instance 所在計(jì)算節(jié)點(diǎn)的網(wǎng)絡(luò)流量進(jìn)行過濾。虛擬防火墻則由 Neutron Firewall as a Service(FWaaS)高級(jí)服務(wù)提供。其底層也是使用 iptables,在 Neutron Router 上對(duì)網(wǎng)絡(luò)包進(jìn)行過濾。默認(rèn)安全組:每個(gè) Project(租戶)都有一個(gè)命名為 “default” 的默認(rèn)安全組。 1)點(diǎn)擊菜單 Project -> Compute -> Access & Security,查看 Security Group 列表: 2)點(diǎn)擊Manage Rules按鈕,查看 “default” 安全組的規(guī)則: 3)“default” 安全組有四條規(guī)則,其作用是:允許所有外出(Egress)的流量,但禁止所有進(jìn)入(Ingress)的流量。 4)當(dāng)我們創(chuàng)建 instance 時(shí),可以在 “Access & Security” 標(biāo)簽頁中選擇安全組。如果當(dāng)前只有 “default” 這一個(gè)安全組,則會(huì)強(qiáng)制使用 “default” : 5)當(dāng)前在 devstack-controller 上有 instance “cirros-vm1”: 6)在 devstack-controller 上執(zhí)行 iptables-save 命令查看相關(guān)規(guī)則。iptables 的規(guī)則較多,這里我們節(jié)選了 cirros-vm1 相關(guān)的規(guī)則。這些規(guī)則是 Neutron 根據(jù)安全組自動(dòng)生成的。cirros-vm1 的 TAP interface 為 tap8bca5b86-23,可以看到: 7)iptables 的規(guī)則是應(yīng)用在 Neutron port 上的,port 在這里是 cirros-vm1 的虛擬網(wǎng)卡 tap8bca5b86-23。ingress 規(guī)則集中定義在命名為 “neutron-linuxbri-i8bca5b86-2” 的 chain 中。egress 規(guī)則集中定義在命名為 “neutron-linuxbri-o8bca5b86-2” 的 chain 中。 8)我們通過 dhcp namespace 對(duì) cirros-vm1 進(jìn)行 ping 和 ssh 測(cè)試: 9)無法 ping 和 ssh cirros-vm1,可見當(dāng)前的規(guī)則實(shí)現(xiàn)了 “default” 安全組,所有 ingress 流量都被禁止。應(yīng)用新的安全組:Neutron 默認(rèn)的安全組規(guī)則會(huì)禁止掉所有從外面訪問 instance 的流量。本節(jié)我們會(huì)修改安全組的配置,允許 ping 和 ssh instance。有兩種方法可以達(dá)到這個(gè)目的:a)修改 “default” 安全組。b)為 cirros-vm1 添加新的安全組。 1)添加新的安全組,在安全組列表頁面點(diǎn)擊按鈕: 2)為安全組命名并點(diǎn)擊 “Create Security Group”: 3)新的安全組 “allow ping & ssh” 創(chuàng)建成功: 4)點(diǎn)擊Manage Group按鈕,查看 “allow ping & ssh” 的規(guī)則: 5)系統(tǒng)默認(rèn)定義了兩條規(guī)則,運(yùn)行所有的外出流量。點(diǎn)擊Add Rule按鈕,添加允許 ping 的規(guī)則,“Rule” 選擇 “All ICMP”,“Direction” 選擇 “Ingress”,然后點(diǎn)擊 “Add” 按鈕:

6)同樣的方式添加 ssh 規(guī)則: 7)在列表中查看添加成功的規(guī)則: 8)接下來設(shè)置 cirros-vm1,使用新的安全組 。進(jìn)入 instance 列表頁面,點(diǎn)擊 cirros-vm1 下拉操作列表中的 “Edit Security Groups”: 9)可以看到 cirros-vm1 當(dāng)前使用的安全組為 “default”,可選安全組為 “allow ping & ssh”。點(diǎn)擊安全組 “allow ping & ssh” 后面的 “+” 按鈕: 10)點(diǎn)擊 “Save” 保存: 11)iptables 會(huì)立即更新,下面通過 vimdiff 查看 iptables 前后的變化: 12)“allow ping & ssh” 安全組引入了下面兩條 iptables 規(guī)則。作用是運(yùn)行 ingress 的 ssh 和 ping 流量: 13)測(cè)試一下,現(xiàn)在能夠 ping 和 ssh cirros-vm1 了:

小結(jié)-安全組有以下特性: 1)通過宿主機(jī)上 iptables 規(guī)則控制進(jìn)出 instance 的流量; 2)安全組作用在 instance 的 port 上; 3)安全組的規(guī)則都是 allow,不能定義 deny 的規(guī)則; 4)instance 可應(yīng)用多個(gè)安全組疊加使用這些安全組中的規(guī)則。

2.5.5.10 Firewall as a Service

理解概念:Firewall as a Service(FWaaS)是 Neutron 的一個(gè)高級(jí)服務(wù)。用戶可以用它來創(chuàng)建和管理防火墻,在 subnet 的邊界上對(duì) layer 3 和 layer 4 的流量進(jìn)行過濾。傳統(tǒng)網(wǎng)絡(luò)中的防火墻一般放在網(wǎng)關(guān)上,用來控制子網(wǎng)之間的訪問。FWaaS 的原理也一樣,是在 Neutron 虛擬 router 上應(yīng)用防火墻規(guī)則,控制進(jìn)出租戶網(wǎng)絡(luò)的數(shù)據(jù)。FWaaS 有三個(gè)重要概念: Firewall、Policy 和 Rule: 1)Firewall:租戶能夠創(chuàng)建和管理的邏輯防火墻資源。 Firewall 必須關(guān)聯(lián)某個(gè) Policy,因此必須先創(chuàng)建 Policy。 2)Firewall Policy:Policy 是 Rule 的集合,F(xiàn)irewall 會(huì)按順序應(yīng)用 Policy 中的每一條 Rule。 3)Firewall Rule:Rule 是訪問控制的規(guī)則,由源與目的子網(wǎng) IP、源與目的端口、協(xié)議、allow 或 deny 動(dòng)作組成。例如,我們可以創(chuàng)建一條 Rule,允許外部網(wǎng)絡(luò)通過 ssh 訪問租戶網(wǎng)絡(luò)中的 instance,端口為 22。與 FWaaS 容易混淆的概念是安全組(Security Group): 1)安全組的應(yīng)用對(duì)象是虛擬網(wǎng)卡,由 L2 Agent 實(shí)現(xiàn),比如 neutron_openvswitch_agent 和neutron_linuxbridge_agent; 2)安全組會(huì)在計(jì)算節(jié)點(diǎn)上通過 iptables 規(guī)則來控制進(jìn)出 instance 虛擬網(wǎng)卡的流量。也就是說:安全組保護(hù)的是 instance; 3)FWaaS 的應(yīng)用對(duì)象是 router,可以在安全組之前控制外部過來的流量,但是對(duì)于同一個(gè) subnet 內(nèi)的流量不作限制。也就是說:FWaaS 保護(hù)的是 subnet。所以,可以同時(shí)部署 FWaaS 和安全組實(shí)現(xiàn)雙重防護(hù)。啟用 FWaaS: 1)因?yàn)?FWaaS 是在 router 中實(shí)現(xiàn)的,所以 FWaaS 沒有單獨(dú)的 agent。已有的 L3 agent 負(fù)責(zé)提供所有 FWaaS 功能。要啟用 FWaaS,必須在 Neutron 的相關(guān)配置文件中做些設(shè)置。 2)配置 firewall driver。Neutron 在 /etc/neutron/fwaas_driver.ini 文件中設(shè)置 FWaaS 使用的 driver: 這里 driver 為 iptables。如果以后支持更多的 driver,可以在這里替換。 3)配置 Neutron。在 Neutron 配置文件 /etc/neutron/neutron.conf 中啟用 FWaaS plugin: 進(jìn)行實(shí)踐,默認(rèn)規(guī)則: 1)環(huán)境:在我們的實(shí)驗(yàn)環(huán)境中,有兩個(gè) instance: cirros-vm1(172.16.100.3) 和 cirros-vm2(172.16.101.3) 2)cirros-vm1 和 cirros-vm2 分別位于網(wǎng)絡(luò) vlan100 和 vlan101。vlan100 和 vlan101 之間由虛擬路由器 test_router 連接。 3)網(wǎng)絡(luò)拓?fù)淙缦滤荆? 4)在 test_router 沒有應(yīng)用任何 FWaaS 的情況下,cirros-vm1 可以通過 ping 和 ssh 跨網(wǎng)絡(luò)訪問 cirros-vm2: 5)下面我們將進(jìn)行如下實(shí)驗(yàn):a)創(chuàng)建一個(gè)不包含任何 rule 的 firewall “test_firewall” 并應(yīng)用到 test_router。此時(shí) FWaaS 生效,默認(rèn)情況下會(huì)阻止任何跨子網(wǎng)的流量。b)創(chuàng)建 rule 允許 ssh,并將其添加到 test_firewall。此時(shí) cirros-vm1 應(yīng)該能夠 ssh cirros-vm2。 6)應(yīng)用無 rule 的 firewall ,點(diǎn)擊菜單 Project -> Network -> Firewalls,打開 Firewall Policies 標(biāo)簽頁面,目前沒有定義任何 Policy: 7)點(diǎn)擊Add Policy顯示Policy創(chuàng)建頁面,將 Policy 命名為 “test_policy”,直接點(diǎn)擊 “Add” 按鈕: 8)這樣我們創(chuàng)建的 test_policy 不包含任何 Rule: 9)進(jìn)入 “Firewalls” 標(biāo)簽頁,點(diǎn)擊 “Create Firewall” 按鈕: 10)將新的 Firewall 命名為 “test_firewall”,并關(guān)聯(lián) “test_policy”: 11)在 “Routers” 標(biāo)簽頁中選擇 “test_router”,點(diǎn)擊 “Add” 創(chuàng)建 firewall: 12)等待 test_firewall 的 Status 變?yōu)?“Active”,此時(shí) test_router 已經(jīng)成功應(yīng)用 test_policy: 13)通過 iptables-save 查看 router namespace 的 iptables 規(guī)則: 14)為了讓大家了解底層到底發(fā)生了什么變化,下面用 vimdiff 顯示了應(yīng)用 test_firewall 前后 iptables 規(guī)則的變化: 15)分析一下規(guī)則: route 在轉(zhuǎn)發(fā)數(shù)據(jù)包時(shí)會(huì)使用 chain: neutron-vpn-agen-FORWARD 的規(guī)則如下: 我們以第一條為例,其含義是:從 router namespace 任何一個(gè) qr-* interface 發(fā)出的流量都會(huì)應(yīng)用 chain neutron-vpn-agen-iv4e85f4601,該 chain 定義如下: 其規(guī)則為:如果數(shù)據(jù)包的狀態(tài)為 INVALID,則 DROP;如果數(shù)據(jù)包的狀態(tài)為 RELATED 或 ESTABLISHED,則 ACCEPT。 其他正常傳輸?shù)臄?shù)據(jù)怎么處理呢? 回到 neutron-vpn-agen-FORWARD chain 的下一條關(guān)于 router 外出數(shù)據(jù)的規(guī)則: neutron-vpn-agen-fwaas-defau 內(nèi)容為: 可見,數(shù)據(jù)會(huì)被丟棄。同樣的道理,router 上所有進(jìn)入 qr-* interface 的數(shù)據(jù)也會(huì)被丟棄。其結(jié)論是:在沒有定義任何 firewall rule 的情況下,進(jìn)出 router 的數(shù)據(jù)包都會(huì)被丟棄。 16)ping 和 ssh 測(cè)試表明目前 cirros-vm1 確實(shí)已經(jīng)無法與 cirros-vm2 通信:進(jìn)行實(shí)踐,允許 SSH: 1)添加一條 firewall rule,允許 ssh,在 Firewall Rules 標(biāo)簽頁面點(diǎn)擊 “Add Rule” 按鈕: 2)將新 rule 命名為 “allow ssh”, Protocal 選擇 “TCP”, Action 為 “ALLOW”,Destination Port/Port Range 為 “22”: 3)點(diǎn)擊 “Add” ,rule 創(chuàng)建成功: 4)接下來將 rule 添加到 policy 中 。點(diǎn)擊 Firewall Policies 標(biāo)簽頁面,然后點(diǎn)擊 “test_policy” 后面的 “Insert Rule” 按鈕: 5)在下拉框中選擇 Rule “allow ssh”,點(diǎn)擊 “Save Changes”,可以看到,“allow ssh” 已經(jīng)成功添加到 “test_policy” 中: 6)通過 vimdiff 查看 router namespace 的 iptables-save 發(fā)生了什么變化: 7)iptables 添加了兩條規(guī)則: 其含義是進(jìn)出 router 的 tcp 數(shù)據(jù)包,如果目的端口為 22(ssh)ssh,則一律 ACCEPT。 8)測(cè)試一下,cirros-vm1 已經(jīng)可以 ssh cirros-vm2,但 ping 還是不通,這與預(yù)期一致: “allow ssh” 已經(jīng)起作用。同時(shí)我們也發(fā)現(xiàn),firewall rule 對(duì)進(jìn)出流量同時(shí)生效,不區(qū)分方向。FWaaS 用于加強(qiáng) Neutron 網(wǎng)絡(luò)的安全性,與安全組可以配合使用,F(xiàn)WaaS 和安全組做個(gè)比較: 1)相同點(diǎn):底層都是通過 iptables 實(shí)現(xiàn)。 2)不同點(diǎn):a)FWaaS 的 iptables 規(guī)則應(yīng)用在 router 上,保護(hù)整個(gè)租戶網(wǎng)絡(luò)。安全組則應(yīng)用在虛擬網(wǎng)卡上,保護(hù)單個(gè) instance; b)FWaaS 可以定義 allow 或者 deny 規(guī)則,安全組只能定義 allow 規(guī)則;c)目前 FWaaS 規(guī)則不能區(qū)分進(jìn)出流量,對(duì)雙向流量都起作用,安全組規(guī)則可以區(qū)分 ingress 和 egress。

2.5.5.11 Load Balancing as a Service

Load Balance as a Service(LBaaS)是 Neutron 提供的一項(xiàng)高級(jí)網(wǎng)絡(luò)服務(wù)。LBaaS 允許租戶在自己的網(wǎng)絡(luò)中創(chuàng)建和管理 load balancer。load balancer 可以說是分布式系統(tǒng)中比較基礎(chǔ)的組件。它接收前端發(fā)來的請(qǐng)求,然后將請(qǐng)求按照某種均衡策略轉(zhuǎn)發(fā)給后端資源池中的某個(gè)處理單元,以完成處理。load balancer 可以實(shí)現(xiàn)系統(tǒng)高可用和橫向擴(kuò)展。LBaaS 有三個(gè)主要的概念: Pool Member,Pool 和 Virtual IP: 1)Pool Member:Pool Member 是 layer 4 的實(shí)體,擁有 IP 地址并通過監(jiān)聽端口對(duì)外提供服務(wù)。例如 Pool Member 可以是一個(gè) web server,IP 為 172.16.100.9 并通過 80 端口提供 HTTP 服務(wù)。 2)Pool:Pool 由一組 Pool Member 組成。 這些 Pool Member 通常提供同一類服務(wù)。例如一個(gè) web server pool,包含:web1:172.16.100.9:80、web2:172.16.100.10:80; 3)Virtual IP:Virtual IP 也稱作 VIP,是定義在 load balancer 上的 IP 地址。每個(gè) pool member 都有自己的 IP,但對(duì)外服務(wù)則是通過 VIP。load balancer 負(fù)責(zé)監(jiān)聽外部的連接,并將連接分發(fā)到 pool member。外部 client 只知道 VIP,不知道也不需要關(guān)心是否有 pool 或者有多少個(gè) pool member。OpenStack Neutron 目前默認(rèn)通過 HAProxy 軟件來實(shí)現(xiàn) LBaaS。HAProxy 是一個(gè)流行的開源 load balancer。Neutron 也支持其他一些第三方 load balancer。下圖展示了 HAProxy 實(shí)現(xiàn) load balancer 的方式: 1)左圖是 client 發(fā)送請(qǐng)求到 web server 的數(shù)據(jù)流: a)Client 10.10.10.4 通過瀏覽器訪問服務(wù)器的外網(wǎng) IP 10.10.10.7。 b)請(qǐng)求首先到達(dá)路由器,將目的地址設(shè)置為服務(wù)器的內(nèi)網(wǎng) VIP 172.16.100.11 c)VIP 設(shè)置在 load balancer 上,load balancer 收到請(qǐng)求后選擇 pool member WEB1,將數(shù)據(jù)包的目的 IP 設(shè)為 WEB1 的地址 172.16.100.9。 d)在將數(shù)據(jù)包轉(zhuǎn)發(fā)給 WEB1 之前,load balancer 將數(shù)據(jù)包的源 IP 修改為自己的 VIP 地址 172.16.100.11,其目的是保證 WEB1 能夠?qū)?yīng)答數(shù)據(jù)發(fā)送回 load balancer。 e) WEB1 收到請(qǐng)求數(shù)據(jù)包。 2)右圖是 web server 應(yīng)答的數(shù)據(jù)流: a)WEB1 將數(shù)據(jù)包發(fā)送給 load balancer。 b)load balancer 收到 WEB1 發(fā)回的數(shù)據(jù)后,將目的 IP 修改為 Client 的地址 10.10.10.4。時(shí)也將數(shù)據(jù)包的源 IP 修改為 VIP 地址 172.16.100.11,保證 Client 能夠?qū)⒑罄m(xù)的數(shù)據(jù)發(fā)送給自己。 c)load balancer 將數(shù)據(jù)發(fā)送給路由器。 d) 路由器將數(shù)據(jù)包的源地址恢復(fù)成服務(wù)器的外網(wǎng) IP 10.10.10.7,然后發(fā)送給 Client。 e)Client 收到應(yīng)答數(shù)據(jù)。 3)以上就是 Load Balance as a Service 的工作原理。實(shí)踐LBaaS 1)Neutron 通過 lbaas plugin 和 lbaas agent 提供 LBaaS 服務(wù)。lbaas plugin 與 Neutron Server 一起運(yùn)行在控制節(jié)點(diǎn)上。lbaas agent 運(yùn)行在網(wǎng)絡(luò)節(jié)點(diǎn)上。對(duì)于我們的實(shí)驗(yàn)環(huán)境,控制節(jié)點(diǎn)和網(wǎng)絡(luò)節(jié)點(diǎn)是一個(gè),都是 devstack-controller。 2)首先在配置中啟用LBaaS服務(wù),配置LBaaS agent。Neutron 配置 LBaaS agent 的地方是 /etc/neutron/services/loadbalancer/haproxy/lbaas_agent.ini。定義 interface_driver: interface_driver 的作用是設(shè)置 load balancer 的網(wǎng)絡(luò)接口驅(qū)動(dòng),可以有兩個(gè)選項(xiàng): Linux Bridge: Open vSwitch: 3)配置 LBaaS plugin,在 /etc/neutron/neutron.conf 中設(shè)置啟用 LBaaS plugin: 在 /etc/neutron/neutron_lbaas.conf 中設(shè)置 service provider: 從注釋信息可以看到,除了默認(rèn)的 HAProxy,Neutron 也支持第三方 provider,比如 radware,VMWareEdge 等。 4)重啟 neutron 服務(wù),確保 LBaaS 正常運(yùn)行: 5)開始實(shí)現(xiàn)如下LBaaS環(huán)境: 環(huán)境描述如下:a)創(chuàng)建一個(gè) Pool “web servers”;b)兩個(gè) pool member “WEB1” 和 “WEB2”,均為運(yùn)行 Ubuntu cloud image 的 instance;3)load balancer VIP 與 floating IP 關(guān)聯(lián);4)位于外網(wǎng)的 client 通過 floating IP 外網(wǎng)訪問 web server。 6)第一步開始,創(chuàng)建 Pool 。點(diǎn)擊菜單 Project -> Network -> Load Balancers,點(diǎn)擊 Pools 標(biāo)簽頁中的 “Add Pool” 按鈕: 7)顯示 Pool 創(chuàng)建頁面: 將 Pool 命名為“web servers”。 Provider 選擇默認(rèn)的 “haproxy”。 Subnet 選擇 “172.16.100.0/24”。 Protocol 選擇 “HTTP”。 Load Balancing Method 選擇 “ROUND_ROBIN”。 8)點(diǎn)擊 “Add” 按鈕,“web servers” 創(chuàng)建成功: 9)幾個(gè)屬性說明: LBaaS 支持如下幾種 Protocol: 因?yàn)槲覀冇?web server 做實(shí)驗(yàn),所以這里需要選擇 “HTTP”。 LBaaS 支持多種 load balance method: a)ROUND_ROUBIN:如果采用 round robin 算法,load balancer 按固定的順序從 pool 中選擇 member 響應(yīng) client的連接請(qǐng)求。 這種方法的不足是缺乏機(jī)制檢查 member 是否負(fù)載過重。 有可能出現(xiàn)某些 member由于處理能力弱而不得不繼續(xù)處理新連接的情況。 如果所有 pool member 具有相同處理能力、內(nèi)存容量,并且每個(gè)連接持續(xù)的時(shí)間大致相同,這種情況非常適合 round robin,每個(gè) member 的負(fù)載會(huì)很均衡。 b)LEAST_CONNECTIONS:如果采用 least connections 算法,load balancer 會(huì)挑選當(dāng)前連接數(shù)最少的 pool member。這是一種動(dòng)態(tài)的算法,需要實(shí)時(shí)監(jiān)控每個(gè) member 的連接數(shù)量和狀態(tài)。 計(jì)算能力強(qiáng)的 member 能夠更快的處理連接進(jìn)而會(huì)分配到更多的新連接。 c)SOURCE_IP:如果采用 source IP 算法,具有相同 source IP 的連接會(huì)被分發(fā)到同一個(gè) pool member。 source IP算法對(duì)于像購物車這種需要保存狀態(tài)的應(yīng)用特別有用,因?yàn)槲覀兿M猛?server 來處理某個(gè) client 連續(xù)的在線購物操作。 在我們的實(shí)驗(yàn)中選擇的是 ROUND_ROUBIN 算法。 10)為 Pool 添加 VIP: 在 “web servers” 的操作列表中點(diǎn)擊 “Add VIP” VIP 命名為 “VIP for web servers”。 VIP Subnet 選擇 “172.16.100.0/24”,與 pool 一致。 指定 VIP 為 172.16.100.11,如果不指定,系統(tǒng)會(huì)自動(dòng)從 subnet 中分配。 指定 HTTP 端口 80。 Session Persistence 選擇 “SOURCE IP”。 可以通過 Connection Limit 限制連接的數(shù)量,如果不指定則為不加限制。 11)點(diǎn)擊 “Add”,VIP 創(chuàng)建成功: 通常我們希望讓同一個(gè) server 來處理某個(gè) client 的連續(xù)請(qǐng)求。 否則 client 可能會(huì)由于丟失 session 而不得不重新登錄。這個(gè)特性就是 Session Persistence。 VIP 支持如下幾種 Session Persistence 方式: a)SOURCE_IP:這種方式與前面 load balance 的 SOURCE_IP 效果一樣。 初始連接建立后,后續(xù)來自相同 source IP 的 client請(qǐng)求會(huì)發(fā)送給同一個(gè) member。 當(dāng)大量 client 通過同一個(gè)代理服務(wù)器訪問 VIP 時(shí)(比如在公司和學(xué)校上網(wǎng)),SOURCE_IP方式會(huì)造成 member 負(fù)載不均。 b)HTTP_COOKIE:工作方式如下: 當(dāng) client 第一次連接到 VIP 時(shí),HAProxy 從 pool 中挑選出一個(gè) member。 當(dāng)此 member響應(yīng)請(qǐng)求時(shí),HAProxy 會(huì)在應(yīng)答報(bào)文中注入命名為 “SRV” 的 cookie,這個(gè) cookie 包含了該 member 的唯一標(biāo)識(shí)。client 的后續(xù)請(qǐng)求都會(huì)包含這個(gè) “SRV” cookie。 HAProxy 會(huì)分析 cookie 的內(nèi)容,并將請(qǐng)求轉(zhuǎn)發(fā)給同一個(gè)member。HTTP_COOKIE 優(yōu)于 SOURCE_IP,因?yàn)樗灰蕾?client 的 IP。 c)APP_COOKIE:app cookie 依賴于服務(wù)器端應(yīng)用定義的 cookie。 比如 app 可以通過在 session 中創(chuàng)建 cookie 來區(qū)分不同的 client。HAProxy 會(huì)查看報(bào)文中的 app cookie,確保將包含 app cookie 的請(qǐng)求發(fā)送到同一個(gè) member。如果沒有 cookie(新連接或者服務(wù)器應(yīng)用不創(chuàng)建 cookie),HAProxy 會(huì)采用 ROUND_ROUBIN 算法分配 member。 12)比較 Load Balance Method 和 Session Persistence: 前面我們介紹了三種 Load Balance Method: 這里還有三種 Session Persistence: 因?yàn)閮烧叨忌婕暗饺绾芜x擇 pool member,所以很容易混淆。 它們之間的最大區(qū)別在于選擇 pool member 的階段不同:a)Load Balance Method 是為新連接選擇 member 的方法;b)Session Persistence 是為同一個(gè) client 的后續(xù)連接選擇 member 的方法。 例如這里我們的設(shè)置為:Load Balance Method — ROUND_ROUBIN;Session Persistence — SOURCE_IP;當(dāng) client A 向 VIP 發(fā)送第一個(gè)請(qǐng)求時(shí),HAProxy 通過 ROUND_ROUBIN 選擇 member1。對(duì)于 client A 后續(xù)的請(qǐng)求,HAProxy 則會(huì)應(yīng)用 SOURCE_IP 機(jī)制,仍然選擇 member1 來處理請(qǐng)求。 13)使用 Ubuntu Cloud Image,由于 cirros 鏡像不能運(yùn)行 HTTP 服務(wù),我們將使用 Ubuntu Cloud Image,下載地址為 http://uec-images.ubuntu.com/trusty/current/trusty-server-cloudimg-amd64-disk1.img: 與以前的 instance 不同,Web1 和 Web2 使用了命名為“cloud”的 Key Pair。這是因?yàn)?Ubuntu Cloud Image 默認(rèn)用戶 “ubuntu” 的密碼是隨機(jī)生成的,通過 Key Pair 訪問是一個(gè)比較方便的方法。 下面是 Key Pair 的配置方法: a)通過 ssh-keygen -t rsa -f cloud.key 生成 Key Pair: 其中 cloud.key.pub 是公鑰,需要添加到 instance 的 ~/.ssh/authorized_keys 文件中。 cloud.key 是私鑰,用于訪問 instance。 b)將 Pair Key 導(dǎo)入 OpenStack: 進(jìn)入 Project -> Compute -> Access & Security 菜單,點(diǎn)擊 Key Pairs 標(biāo)簽頁的 “Import Key Pair” 按鈕。 復(fù)制 cloud.key.pub 的內(nèi)容。 粘貼到 Public Key 輸入框中,給 Key Pair 命名為 “cloud”,并點(diǎn)擊 “Import Key Pair”。 Key Pair “cloud” 成功導(dǎo)入。 c)使用 Key Pair “cloud”。 launch instance 的時(shí)候,在 Access & Security 標(biāo)簽頁中選擇 Key Pair “cloud”。OpenStack 會(huì)自動(dòng)將公鑰添加進(jìn) instance 的 ~/.ssh/authorized_keys 文件。 d)ssh instance: 用 ssh -i cloud.key ubuntu@172.16.100.9 指定私鑰,并以 ubuntu 用戶 ssh “Web1” 和 “Web2”。 無需密碼直接登錄 instance。注:為了便于演示,這里我們是在 router 的 namespace 中執(zhí)行 ssh,主要目的是網(wǎng)絡(luò)可達(dá)。 “Web1” 和 “Web2” 準(zhǔn)備就緒了,可以添加到 Pool 中了。 14)在 Project -> Network -> Load Balancers 的 Members 標(biāo)簽頁中 點(diǎn)擊 “Add Member” 按鈕: Pool 選擇 “web servers”。Member(s) 中多選 “Web1” 和 “Web2”。Protocol Port 設(shè)置為 “80”。 點(diǎn)擊 “Add”,member 添加成功: 15)創(chuàng)建 Monitor,監(jiān)控 Pool Member 健康狀態(tài):如果某個(gè) member 不能正常工作,monitor 會(huì)將其狀態(tài)設(shè)置為 down,從而避免將后續(xù)請(qǐng)求轉(zhuǎn)發(fā)給它。 在 Monitors 標(biāo)簽頁中點(diǎn)擊 “Add Monitor” 按鈕: Type 選擇 “HTTP”,含義是通過 HTTP 檢查 member 的健康狀態(tài)。 Delay 設(shè)置為 “10”,含義是 10 秒檢查一次 member 的狀態(tài)。 Timeout 設(shè)置為 “5”,含義是如果 member 在 5 秒內(nèi)無法應(yīng)答,則超時(shí)。 Max Reties 設(shè)置為 “3”,含義是如果嘗試 3 次都超時(shí)或者失敗,則將 member 狀態(tài)設(shè)置為 down。 HTTP Method 設(shè)置為 “GET” URL 設(shè)置為 “/” Expected HTTP Status Codes 設(shè)置為 “200” 上面三項(xiàng)的含義是通過 HTTP GET 請(qǐng)求 member “/” URL,如果返回碼為 200,則認(rèn)為 member 狀態(tài)正常。 點(diǎn)擊 “Add”,monitor 創(chuàng)建成功: 將新建的 monitor 添加到 pool,在 “web servers” 的操作列表中點(diǎn)擊 “Associate Monitor” : 選擇我們剛剛創(chuàng)建的 monitor 點(diǎn)擊 “Associate”。 16)測(cè)試 LBaaS : a)經(jīng)過上面的設(shè)置,我們創(chuàng)建了包含 member “Web1” 和 “Web2” 的 Pool “web servers”,并添加了 monitor。 準(zhǔn)備就緒,可以測(cè)試 load balancer 是否正常工作了。首先在 Web1 和 Web2 中啟動(dòng) HTTP 服務(wù),在 80 端口監(jiān)聽: 這里我們使用 python 提供的 SimpleHTTPServer 模塊啟動(dòng)了 HTTP 服務(wù)(sudo python -m SimpleHTTPServer 80)。web server 的 index.html 顯示當(dāng)前訪問的是哪個(gè) member。 b)在 router 的 namespace 上多次執(zhí)行 curl 172.16.100.11(VIP): 測(cè)試結(jié)果顯示每次訪問的都是 Web2 這個(gè) member。 c)為什么沒有訪問到 Web1 呢? 還記得我們前面討論的內(nèi)容嗎: Load Balance Method — ROUND_ROUBIN Session Persistence — SOURCE_IP 在這種配置下,第一個(gè) curl 請(qǐng)求 HAProxy 通過 ROUND_ROUBIN 選擇了 Web2。而后續(xù)的請(qǐng)求,HAProxy 則會(huì)應(yīng)用 SOURCE_IP 機(jī)制,仍然選擇 Web2。 d)下面我們修改一下配置。在“web servers” 的操作列表中點(diǎn)擊 “Edit VIP”: 選擇 “No session persistence” 并保存: 再進(jìn)行 curl 測(cè)試 可以看到已經(jīng)在 “Web1” 和 “Web2” 之間 round robin 了。 17)重點(diǎn)分析 Neutron 是如何用 Haproxy 來實(shí)現(xiàn)負(fù)責(zé)均衡: a)在控制節(jié)點(diǎn)上運(yùn)行 ip netns,我們發(fā)現(xiàn) Neutron 創(chuàng)建了新的 namespace qlbaas-xxx: 該 namespace 對(duì)應(yīng)我們創(chuàng)建的 pool “web servers”。其命名格式為 qlbaas-< pool ID>。 b)可以通過 ip a 查看其設(shè)置: VIP 172.16.100.11 已經(jīng)配置在 namespace interface 上。 c)在 subnet 的 Port 列表中也可以找到該 interface 的相應(yīng)配置: 對(duì)于每一個(gè) pool,Neutron 都會(huì)啟動(dòng)一個(gè) haproxy 進(jìn)程提供 load balancering 功能。 d)通過 ps 命令查找 haproxy 進(jìn)程: haproxy 配置文件保存在 /opt/stack/data/neutron/lbaas/< pool ID>/conf 中。 e)查看 “web servers” 的配置內(nèi)容: 可以看到: frontend 使用的 HTTP 地址為 VIP:80; backend 使用的 HTTP 地址為 172.16.100.10:80 和 172.16.100.9:80; balance 方法為 roundrobin; 18)通過 Floating IP 訪問 VIP: a)訪問 Project -> Compute -> Access & Security,打開 Floating IPs 標(biāo)簽頁,點(diǎn)擊 “Allocate IP to Project” 按鈕: b)在下拉列表中選擇 “ext_net”,Neutron 將從該網(wǎng)絡(luò)中分配 floating IP: c)點(diǎn)擊 “Allocate IP”: 分配到的 IP 為 “10.10.10.7”。 d)點(diǎn)擊 “Associate” 按鈕: e)在 “Port to be associated” 列表中選擇 “VIP for web servers: 172.16.100.11” 并點(diǎn)擊 “Associate”: 成功將外網(wǎng) IP 10.10.10.7 關(guān)聯(lián)到 VIP。 f)下面是在 IP 為 10.10.10.4 的 instance 中進(jìn)行 curl 測(cè)試: floating IP 生效,load balaner 工作正常。LBaaS 小節(jié): 1)LBaaS 為租戶提供了橫向擴(kuò)展應(yīng)用的能力; 2)租戶可以將外部請(qǐng)求 balancing 到多個(gè) instance 上,并通過 monitor 實(shí)現(xiàn)應(yīng)用的高可用; 3)LBaaS 當(dāng)前的實(shí)現(xiàn)是基于 HAProxy,其功能已經(jīng)能夠滿足普通業(yè)務(wù)需求。

2.5.6 Open vSwitch實(shí)現(xiàn)Neutron網(wǎng)絡(luò)

基礎(chǔ)環(huán)境: 實(shí)驗(yàn)環(huán)境兩節(jié)點(diǎn)的網(wǎng)卡分配方式與 Linux Bridge 一致,如下所示: 1)控制節(jié)點(diǎn)三個(gè)網(wǎng)卡(eth0, eth1, eth2),計(jì)算節(jié)點(diǎn)兩網(wǎng)卡(eth0, eth1)。 2)合并 Management 和 API 網(wǎng)絡(luò),使用 eth0,IP 段為 192.168.104.0/24。 3)VM 網(wǎng)絡(luò)使用 eht1。 4)控制節(jié)點(diǎn)的 eth2 與 External 網(wǎng)絡(luò)連接,IP 段為 10.10.10.0/24。網(wǎng)絡(luò)拓?fù)洌? 這個(gè)圖在 Linux Bridge 實(shí)現(xiàn)中也看到過,唯一的區(qū)別是:對(duì)于節(jié)點(diǎn)中的 “Virtual Network Switch” 我們將用 Open vSwitch 替換掉 Linux Bridge。配置 openvswitch mechanism driver: 要將 Liunx Bridge 切換成 Open vSwitch,首先需要安裝 Open vSwitch 的 agent,修改 devstack 的 local.conf: 重新運(yùn)行 ./stack,devstack 會(huì)自動(dòng)下載并安裝 Open vSwitch。接下來就可以修改 ML2 的配置文件 /etc/neutron/plugins/ml2/ml2_conf.ini,設(shè)置使用 openvswitch mechanism driver: 控制節(jié)點(diǎn)和計(jì)算節(jié)點(diǎn)都需要按照上面的方法安裝并配置 Open vSwitch。Neutron 服務(wù)重啟后,可以通過 neutron agent-list 命令查看到 neutron-openvswitch-agent 已經(jīng)在兩個(gè)節(jié)點(diǎn)上運(yùn)行: 初始網(wǎng)絡(luò)狀態(tài): 1)控制節(jié)點(diǎn): ifconfig 顯示控制節(jié)點(diǎn)上有三個(gè)網(wǎng)橋 br-ex,br-int 和 br-tun。從命名上看我們大致能猜出他們的用途: a)br-ex:連接外部(external)網(wǎng)絡(luò)的網(wǎng)橋 b)br-int:集成(integration)網(wǎng)橋,所有 instance 的虛擬網(wǎng)卡和其他虛擬網(wǎng)絡(luò)設(shè)備都將連接到該網(wǎng)橋。 c)br-tun:隧道(tunnel)網(wǎng)橋,基于隧道技術(shù)的 VxLAN 和 GRE 網(wǎng)絡(luò)將使用該網(wǎng)橋進(jìn)行通信。 這些網(wǎng)橋都是 Neutron 自動(dòng)為我們創(chuàng)建的,但是通過 brctl show 命令卻看不到它們。 這是因?yàn)槲覀兪褂玫氖?Open vSwitch 而非 Linux Bridge,需要用 Open vSwitch 的命令 ovs-vsctl show 查看,如下圖所示: 2)計(jì)算節(jié)點(diǎn) 計(jì)算節(jié)點(diǎn)上也有 br-int 和 br-tun,但沒有 br-ext。這是合理的,因?yàn)榘l(fā)送到外網(wǎng)的流量是通過網(wǎng)絡(luò)節(jié)點(diǎn)上的虛擬路由器轉(zhuǎn)發(fā)出去的,所以 br-ext 只會(huì)放在網(wǎng)絡(luò)節(jié)點(diǎn)(devstack-controller)上。 了解 Open vSwitch 環(huán)境中的各種網(wǎng)絡(luò)設(shè)備。在 Open vSwitch 環(huán)境中,一個(gè)數(shù)據(jù)包從 instance 發(fā)送到物理網(wǎng)卡大致會(huì)經(jīng)過下面幾個(gè)類型的設(shè)備: 1)tap interface:命名為 tapXXXX; 2)linux bridge:命名為 qbrXXXX; 3)veth pair:命名為 qvbXXXX, qvoXXXX; 4)OVS integration bridge:命名為 br-int; 5)OVS patch ports:命名為 int-br-ethX 和 phy-br-ethX(X 為 interface 的序號(hào)); 6)OVS provider bridge:命名為 br-ethX(X 為 interface 的序號(hào)); 7)物理 interface:命名為 ethX(X 為 interface 的序號(hào)); 8)OVS tunnel bridge:命名為 br-tun,OVS provider bridge:會(huì)在 flat 和 vlan 網(wǎng)絡(luò)中使用;OVS tunnel bridge 則會(huì)在 vxlan 和 gre 網(wǎng)絡(luò)中使用。Open vSwitch 支持 local, flat, vlan, vxlan 和 gre 所有五種 network type。

2.5.6.1 local network

local network 的特點(diǎn)是不會(huì)與宿主機(jī)的任何物理網(wǎng)卡相連,也不關(guān)聯(lián)任何的 VLAN ID。對(duì)于每個(gè) local netwrok,ML2 linux-bridge 會(huì)創(chuàng)建一個(gè) bridge,instance 的 tap 設(shè)備會(huì)連接到 bridge。位于同一個(gè) local network 的 instance 會(huì)連接到相同的 bridge,這樣 instance 之間就可以通信了。因?yàn)?bridge 沒有與物理網(wǎng)卡連接,所以 instance 無法與宿主機(jī)之外的網(wǎng)絡(luò)通信。同時(shí)因?yàn)槊總€(gè) local network 有自己的 bridge,bridge 之間是沒有連通的,所以兩個(gè) local network 之間也不能通信。創(chuàng)建第一個(gè)local network: 1)進(jìn)入菜單 Admin -> Networks,點(diǎn)擊 “Create Network” 按鈕: 2)顯示創(chuàng)建頁面: “Provider Network Type” 選擇 “Local”,點(diǎn)擊 “Create Network”,first_local_net 創(chuàng)建成功; 3)點(diǎn)擊 first_local_net 鏈接,進(jìn)入 network 配置頁面,目前還沒有 subnet,點(diǎn)擊 “Create Subnet” 按鈕: 4)設(shè)置 IP 地址為 “172.16.1.0/24”: 5)點(diǎn)擊 “Next”,勾選 “Enable DHCP”,IP 池設(shè)置為 “172.16.1.2,172.16.1.99”: 6)點(diǎn)擊 “Create”,subnet 創(chuàng)建成功: 7)同時(shí) devstack-controler 針對(duì)此 subnet 的 DHCP 服務(wù)也已經(jīng) Active: 8)底層網(wǎng)絡(luò)發(fā)生了什么變化,打開控制節(jié)點(diǎn)的 shell 終端,用 ovs-vsctl show 查看當(dāng)前 Open vSwitch 的狀態(tài): 9)可以看到 Neutron 自動(dòng)在 br-int 網(wǎng)橋上創(chuàng)建了 port “tap7970bdcd-f2”。從命名可知,該 port 對(duì)應(yīng) local_net 的 dhcp 接口。與 linux bridge driver 一樣,dhcp 設(shè)備也是放在命名空間里的: 10)目前網(wǎng)絡(luò)結(jié)構(gòu)如下圖所示: 將 Instance 部署到 OVS Local Network: 1)launch 一個(gè) instance,選擇 first_local_net 網(wǎng)絡(luò): 2)instance 部署成功,分配的 IP 地址為 172.16.1.3: 3)如上圖所示,port 列表中增加了一個(gè) port “(fc1c6ebb-719d)”,IP 為 172.16.1.3,點(diǎn)擊 port 名稱查看 MAC 信息: 4)Open vSwitch driver 會(huì)如何將 cirros-vm1 連接到 first_local_net? 如果采用類似的實(shí)現(xiàn)方法,neutron-openvswitch-agent 會(huì)根據(jù) port 信息創(chuàng)建 tap 設(shè)備 tapfc1c6ebb-71,并將其連接到 br-int 網(wǎng)橋,tapfc1c6ebb-71 就是 cirros-vm1 的虛擬網(wǎng)卡。cirros-vm1 部署到了控制節(jié)點(diǎn),通過 ovs-vsctl show 查看 bridge 的配置: 非常遺憾,在 br-int 上并沒有看到 tapfc1c6ebb-71,而是多了一個(gè) qvofc1c6ebb-71。目前我們并不知道 qvofc1c6ebb-71 是什么,我們?cè)儆?brctl show 查看一下 linux bridge 的配置: 這里我們看到有一個(gè)新建的網(wǎng)橋 qbrfc1c6ebb-71,上面連接了兩個(gè)設(shè)備 qvbfc1c6ebb-71 和 tapfc1c6ebb-71。從命名上看,他們都應(yīng)該與 cirros-vm1 的虛擬網(wǎng)卡有關(guān)。 5)通過 virsh edit 查看 cirros-vm1 的配置: 確實(shí) tapfc1c6ebb-71 是 cirros-vm1 的虛擬網(wǎng)卡。那么 linux bridge qbrfc1c6ebb-71 上的 qvbfc1c6ebb-71 設(shè)備與 Open vSwitch br-int 上的 qvofc1c6ebb-71 是什么關(guān)系呢? 6)我們用 ethtool -S 分別查看 qvbfc1c6ebb-71 和 qvofc1c6ebb-71 的 statistics: 原來 qvbfc1c6ebb-71 和 qvofc1c6ebb-71 都是 veth 設(shè)備,它們對(duì)應(yīng)的另一端 veth 設(shè)備 的 index 分別是 12 和 13。 7)通過 ip a 命令找到 index 12 和 13 的設(shè)備: 其實(shí)qvbfc1c6ebb-71 和 qvofc1c6ebb-71 組成了一個(gè) veth pair。veth pair 是一種成對(duì)出現(xiàn)的特殊網(wǎng)絡(luò)設(shè)備,它們像一根虛擬的網(wǎng)線連接兩個(gè)網(wǎng)絡(luò)設(shè)備。這里 qvbfc1c6ebb-71 和 qvofc1c6ebb-71 的作用就是連接網(wǎng)橋 qbrfc1c6ebb-71 和 br-int。 8)拓?fù)浣Y(jié)構(gòu)如下所示: 由圖所示,tapfc1c6ebb-71 通過 qbrfc1c6ebb-71 間接連接到 br-int。 9)為什么 tapfc1c6ebb-71 不能像左邊的 DHCP 設(shè)備 tap7970bdcd-f2 那樣直接連接到 br-int 呢? 其原因是: Open vSwitch 目前還不支持將 iptables 規(guī)則放在與它直接相連的 tap 設(shè)備上。如果做不到這一點(diǎn),就無法實(shí)現(xiàn) Security Group 功能。為了支持 Security Group,不得不多引入一個(gè) Linux Bridge 支持 iptables。這樣的后果就是網(wǎng)絡(luò)結(jié)構(gòu)更復(fù)雜了,路徑上多了一個(gè) linux bridge 和 一對(duì) veth pair 設(shè)備。再部署一個(gè) Instance 和 Local Network: 1)再部署一個(gè) Instance 到first_local_network,以同樣的方式 launch instance “cirros-vm2”,分配的 IP 為 172.16.1.4: 2)cirros-vm2 也被 schedule 到控制節(jié)點(diǎn),ovs-vsctl show 的輸出如下: 3)cirros-vm2 對(duì)于的 tap 設(shè)備為 tapddbbb728-93: 4)從 cirros-vm2 能夠 Ping 通 cirros-vm1 的 IP 地址 172.16.1.3: 5)當(dāng)前宿主機(jī)的網(wǎng)絡(luò)結(jié)構(gòu)如下 : 兩個(gè) instance 都掛在 br-int 上,可以相互通信。 6)創(chuàng)建第二個(gè) local network: 為了分析 local network 的連通性,我們?cè)賱?chuàng)建一個(gè) “second_local_net”,second_local_net 的絕大部分屬性與 first_local_net 相同,除了 IP 池范圍為 172.16.1.101-172.16.1.200: second_local_net 的 DHCP 設(shè)備也已經(jīng)就緒: DHCP 對(duì)應(yīng)的 tap 設(shè)備為 tap2c1b3c58-4e,已經(jīng)連接到 br-int: 部署instance到second_local_network 1)launch 新的 instance “cirros-vm3”,網(wǎng)絡(luò)選擇 second_local_net: 2)cirros-vm3 分配到的 IP 為 172.16.1.102: 3)cirros-vm3 被 schedule 到控制節(jié)點(diǎn),其虛擬網(wǎng)卡也連接到 br-int: 4)當(dāng)前的控制節(jié)點(diǎn)上的網(wǎng)絡(luò)結(jié)構(gòu)如下 : 5)下面我們討論一個(gè)有趣的問題:cirros-vm3 能否 Ping 到 cirros-vm1 呢?根據(jù)我們?cè)?linux bridge 中學(xué)到的知識(shí),既然 cirros-vm3 和 cirros-vm1 都連接到同一個(gè)網(wǎng)橋 br-int,那么它們之間應(yīng)該是可以 Ping 通的。但另一方面,根據(jù) Neutron 的設(shè)計(jì),不同 local 網(wǎng)絡(luò)之間是無法通信的。那么事實(shí)到底是如何呢? 實(shí)驗(yàn)證明 cirros-vm3 無法 Ping 到 cirros-vm1。 6)下面我們需要解釋同一個(gè)網(wǎng)橋上的 port 為什么不能通信,讓我們重新審視一下 br-int 上各個(gè) port 的配置。 這次我們注意到,虛擬網(wǎng)卡和 DHCP 對(duì)應(yīng)的 port 都有一個(gè)特殊的 tag 屬性。first_local_net 相關(guān) port 其 tag 為 1;second_local_net 相關(guān) port 其 tag 為 2。玄機(jī)就在這里了: Open vSwitch 的每個(gè)網(wǎng)橋都可以看作一個(gè)真正的交換機(jī),可以支持 VLAN,這里的 tag 就是 VLAN ID。br-int 中標(biāo)記 tag 1 的 port 和 標(biāo)記 tag 2 的 port 分別屬于不同的 VLAN,它們之間是隔離的。需要特別說明的是: Open vSwitch 中的 tag 是內(nèi)部 VLAN,用于隔離網(wǎng)橋中的 port,與物理網(wǎng)絡(luò)中的 VLAN 沒有關(guān)系。 7)我們將 tag 信息添加到網(wǎng)絡(luò)結(jié)構(gòu)圖中,如下所示:

2.5.6.2 flat network

flat network 是不帶 tag 的網(wǎng)絡(luò),要求宿主機(jī)的物理網(wǎng)卡直接與 linux bridge 連接,這意味著:每個(gè) flat network 都會(huì)獨(dú)占一個(gè)物理網(wǎng)卡。在ML2中配置 enable flat network 1)在控制節(jié)點(diǎn) /etc/neutron/plugins/ml2/ml2_conf.ini 中設(shè)置 flat network 相關(guān)參數(shù): 指定普通用戶創(chuàng)建的網(wǎng)絡(luò)類型為 flat。需要注意的是:因?yàn)?flat 網(wǎng)絡(luò)與物理網(wǎng)卡一一對(duì)應(yīng),一般情況下租戶網(wǎng)絡(luò)不會(huì)采用 flat,這里只是示例。接著需要指明 flat 網(wǎng)絡(luò)與物理網(wǎng)絡(luò)的對(duì)應(yīng)關(guān)系: 如上所示:在 [ml2_type_flat] 中通過 flat_networks 定義了一個(gè) flat 網(wǎng)絡(luò),label 為 “default”。在 [ovs] 中通過 bridge_mappings 指明 default 對(duì)應(yīng)的 Open vSwitch 網(wǎng)橋?yàn)?br-eth1。 label 是 flat 網(wǎng)絡(luò)的標(biāo)識(shí),在創(chuàng)建 flat 時(shí)會(huì)用到,label 的名字可以是任意字符串,只要確保各個(gè)節(jié)點(diǎn) ml2_conf.ini 中的 label 命名一致就可以了。各個(gè)節(jié)點(diǎn)中 label 與物理網(wǎng)卡的對(duì)于關(guān)系可能不一樣。這是因?yàn)槊總€(gè)節(jié)點(diǎn)可以使用不同的物理網(wǎng)卡將 instance 連接到 flat network。與 linux bridge 實(shí)現(xiàn)的 flat 網(wǎng)絡(luò)不同,ml2 中并不會(huì)直接指定 label 與物理網(wǎng)卡的對(duì)應(yīng)關(guān)系,而是指定 label 與 ovs bridge 的對(duì)應(yīng)關(guān)系。 2)這里的 ovs bridge 是 br-eth1,我們需要提前通過 ovs-vsctl add-br br-eth1和ovs-vsctl add-port br-eth1 eth1 命令創(chuàng)建 br-eth1。將物理網(wǎng)卡 eth1 橋接在 br-eth1 上。 3)如果要?jiǎng)?chuàng)建多個(gè) flat 網(wǎng)絡(luò),需要定義多個(gè) label,用逗號(hào)隔開,當(dāng)然也需要用到多個(gè) ovs bridge,如下所示: 4)計(jì)算節(jié)點(diǎn)也需要做相同的配置,然后重啟所有節(jié)點(diǎn)的 Neutron 服務(wù),通過ovs-vsctl show檢視一下當(dāng)前的網(wǎng)絡(luò)結(jié)構(gòu): 對(duì)于 ovs bridge “br-eth1” 和其上橋接的 port “eth1” 我們應(yīng)該不會(huì)感到意外,這是前面配置的結(jié)果。然而除此之外,br-int 和 br-eth1 分別多了一個(gè) port “int-br-eth1” 和 “phy-br-eth1”,而且這兩個(gè) port 都是 “patch” 類型,同時(shí)通過 “peer” 指向?qū)Ψ健I厦娴呐渲妹枋隽诉@樣一個(gè)事實(shí):br-int 與 br-eht1 這兩個(gè)網(wǎng)橋通過 int-br-eth1 和 phy-br-eth1 連接在一起了。 5)目前控制節(jié)點(diǎn)網(wǎng)絡(luò)結(jié)構(gòu)如下: 6)veth pair VS patch port: 在前面 local network 我們看到,br-int 與 linux bridge 之間可以通過 veth pair 連接。 而這里兩個(gè) ovs bridge 之間是用 patch port 連接的??磥?veth pair 和 patch port 都可以連接網(wǎng)橋,使用的時(shí)候如何選擇呢?patch port 是 ovs bridge 自己特有的 port 類型,只能在 ovs 中使用。如果是連接兩個(gè) ovs bridge,優(yōu)先使用 patch port,因?yàn)樾阅芨?。所以:a)連接兩個(gè) ovs bridge,優(yōu)先使用 patch port。技術(shù)上veth pair 也能實(shí)現(xiàn),但性能不如 patch port。b)連接 ovs bridge 和 linux bridge,只能使用 veth pair。c)連接兩個(gè) linux bridge,只能使用 veth pair。創(chuàng)建 OVS Flat Network: 1)Admin -> Networks,點(diǎn)擊 “Create Network” 按鈕: 顯示創(chuàng)建頁面: Provider Network Type 選擇 “Flat”。 Physical Network 填寫 “default”,與 ml2_conf.ini 中 flat_networks 參數(shù)值保持一致。 2)點(diǎn)擊 “Create Network”,flat_net 創(chuàng)建成功: 3)點(diǎn)擊 flat_net 鏈接,進(jìn)入 network 配置頁面,目前還沒有 subnet。點(diǎn)擊 “Create Subnet” 按鈕: 4)設(shè)置 IP 地址為 “172.16.1.0/24”: 5)點(diǎn)擊 “Next”,勾選 “Enable DHCP”: 6)點(diǎn)擊 “Create”,subnet 創(chuàng)建成功: 7)查看控制節(jié)點(diǎn)的網(wǎng)絡(luò)結(jié)構(gòu),執(zhí)行 ovs-vsctl show: Neutron 自動(dòng)在 br-int 網(wǎng)橋上創(chuàng)建了 flat-net dhcp 的接口 “tap83421c44-93”。 8)此時(shí) flat_net 結(jié)構(gòu)如圖所示: 部署 Instance 到ovs flat network: 1)launch 新的 instance “cirros-vm1”,網(wǎng)絡(luò)選擇 falt_net: 2)cirros-vm1 分配到的 IP 為 172.16.1.3: 3)cirros-vm1 被 schedule 到控制節(jié)點(diǎn),其虛擬網(wǎng)卡也連接到 br-int: 虛擬網(wǎng)卡與 br-int 的連接方式與 local 網(wǎng)絡(luò)是一樣的,不再贅述。 4)當(dāng)前 flat_net 的結(jié)構(gòu)如下: 5)繼續(xù)用同樣的方式 launch instance cirros-vm2,分配到的 IP 為 172.16.1.4: 6)cirros-vm2 被 schedule 到計(jì)算節(jié)點(diǎn),虛擬網(wǎng)卡已經(jīng)連接到 br-int: 因?yàn)橛?jì)算節(jié)點(diǎn)上沒有 hdcp 服務(wù),所以沒有相應(yīng)的 tap 設(shè)備。 7)當(dāng)前 flat_net 的結(jié)構(gòu)如下: cirros-vm1(172.16.1.3) 與 cirros-vm2(172.16.1.4) 位于不同節(jié)點(diǎn),通過 flat_net 相連,下面驗(yàn)證連通性。 8)在 cirros-vm2 控制臺(tái)中 ping 172.16.1.3: 如我們預(yù)料兩臺(tái)虛擬機(jī)位于同一個(gè)flat network中,所以可以ping 成功。

2.5.6.3 vlan network

vlan network 是帶 tag 的網(wǎng)絡(luò)。在 Open vSwitch 實(shí)現(xiàn)方式下,不同 vlan instance 的虛擬網(wǎng)卡都接到 br-int 上。這一點(diǎn)與 linux bridge 非常不同,linux bridge 是不同 vlan 接到不同的網(wǎng)橋上。在我們的實(shí)驗(yàn)環(huán)境中,收發(fā) vlan 數(shù)據(jù)的物理網(wǎng)卡為 eth1,上面可以走多個(gè) vlan,所以物理交換機(jī)上與 eth1 相連的的 port 要設(shè)置成 trunk 模式,而不是 access 模式。在 ML2 配置中 enable vlan network: 1)在 /etc/neutron/plugins/ml2/ml2_conf.ini 設(shè)置 vlan network 相關(guān)參數(shù),指定普通用戶創(chuàng)建的網(wǎng)絡(luò)類型為 vlan: 2)指定 vlan 的范圍: 上面配置定義了 label 為 “default” 的 vlan network,vlan id 的范圍是 3001 – 4000。 這個(gè)范圍是針對(duì)普通用戶在自己的租戶里創(chuàng)建 network 的范圍。因?yàn)槠胀ㄓ脩魟?chuàng)建 network 時(shí)并不能指定 vlan id,Neutron 會(huì)按順序自動(dòng)從這個(gè)范圍中取值。對(duì)于 admin 則沒有 vlan id 的限制,admin 可以創(chuàng)建 id 范圍為 1-4094 的 vlan network。 3)接著需要指明 vlan 網(wǎng)絡(luò)與物理網(wǎng)絡(luò)的對(duì)應(yīng)關(guān)系: 如上所示:在 [ml2_type_vlan] 中定義了 lable “default”,[ovs] 中則通過 bridge_mappings 指明 default 對(duì)應(yīng)的 Open vSwitch 網(wǎng)橋?yàn)?br-eth1。這里 label 的作用與前面 flat network 中的 label 一樣,只是一個(gè)標(biāo)示,可以是任何字符串 4)我們需要提前通過 ovs-ovctl 命令創(chuàng)建 br-eth1,并將物理網(wǎng)卡 eth1 橋接在 br-eth1 上。 創(chuàng)建 OVS Vlan100 Netwrok: 1)打開菜單 Admin -> Networks,點(diǎn)擊 “Create Network” 按鈕: 顯示創(chuàng)建頁面: Provider Network Type 選擇 “VLAN”。 Physical Network 填寫 “default”,與 ml2_conf.ini 中 network_vlan_ranges 參數(shù)值保持一致。 Segmentation ID 即 VLAN ID,設(shè)置為 100。 2)點(diǎn)擊 “Create Network”,vlan100 創(chuàng)建成功: 3)點(diǎn)擊 vlan100 鏈接,進(jìn)入 network 配置頁面,目前還沒有 subnet,點(diǎn)擊 “Create Subnet” 按鈕: 4)創(chuàng)建 subnet_172_16_100_0,IP 地址為 172.16.100.0/24: 5)在控制節(jié)點(diǎn)上執(zhí)行 ovs-vsctl show,查看網(wǎng)絡(luò)結(jié)構(gòu): Neutron 自動(dòng)在 br-int 網(wǎng)橋上創(chuàng)建了 vlan100 dhcp 的接口 “tap43567363-50”。 6)此時(shí) vlan100 結(jié)構(gòu)如圖所示: 部署 Instance 到vlan100: 1)launch 新的 instance “cirros-vm1”,網(wǎng)絡(luò)選擇 vlan100: 2)cirros-vm1 分配到的 IP 為 172.16.100.3: 3)cirros-vm1 被 schedule 到控制節(jié)點(diǎn),其虛擬網(wǎng)卡也連接到 br-int: 虛擬網(wǎng)卡與 br-int 的連接方式與 local 和 flat 網(wǎng)絡(luò)一樣。 4)當(dāng)前 vlan100 的結(jié)構(gòu)如下: 5)繼續(xù)用同樣的方式 launch instance cirros-vm2,分配到的 IP 為 172.16.100.104: 6)cirros-vm2 被 schedule 到計(jì)算節(jié)點(diǎn),虛擬網(wǎng)卡已經(jīng)連接到 br-int: 因?yàn)橛?jì)算節(jié)點(diǎn)上沒有 hdcp 服務(wù),所以沒有相應(yīng)的 tap 設(shè)備。 7)當(dāng)前 vlan100 的結(jié)構(gòu)如下: 8)cirros-vm1(172.16.100.3) 與 cirros-vm2(172.16.100.4) 位于不同節(jié)點(diǎn),通過 vlan100 相連,下面執(zhí)行 PING 驗(yàn)證連通性。在 cirros-vm1 控制臺(tái)中執(zhí)行 ping 172.16.100.4: 創(chuàng)建vlan 101并部署instance: 1)創(chuàng)建vlan 101: 2)subnet IP 地址為 172.16.101.0/24: 3)Neutron 自動(dòng)在 br-int 網(wǎng)橋上創(chuàng)建了 vlan100 dhcp 的接口 “tap1820558c-0a”: 4)現(xiàn)在,網(wǎng)絡(luò)結(jié)構(gòu)如下: 5)將 instance 連接到 vlan101,unch 新的 instance “cirros-vm3”,網(wǎng)絡(luò)選擇 vlan101: 6)cirros-vm3 分配到的 IP 為 172.16.101.103 : 7)cirros-vm3 被 schedule 到計(jì)算節(jié)點(diǎn),虛擬網(wǎng)卡已經(jīng)連接到 br-int: 8)當(dāng)前網(wǎng)絡(luò)結(jié)構(gòu)如下: cirros-vm1 位于控制節(jié)點(diǎn),屬于 vlan100。 cirros-vm2 位于計(jì)算節(jié)點(diǎn),屬于 vlan100。cirros-vm3 位于計(jì)算節(jié)點(diǎn),屬于 vlan101。cirros-vm1 與 cirros-vm2 都在 vlan100,它們之間能通信。cirros-vm3 在 vlan101,不能與 cirros-vm1 和 cirros-vm2 通信。分析 OVS 如何實(shí)現(xiàn) vlan 隔離: 1)之前完成的OVS vlan 環(huán)境的搭建,當(dāng)前拓?fù)浣Y(jié)構(gòu)如下所示: a)cirros-vm1 位于控制節(jié)點(diǎn),屬于 vlan100; b)cirros-vm2 位于計(jì)算節(jié)點(diǎn),屬于 vlan100; c)cirros-vm3 位于計(jì)算節(jié)點(diǎn),屬于 vlan101。 2)詳細(xì)分析 OVS 如何實(shí)現(xiàn) vlan100 和 vlan101 的隔離: 與 Linux Bridge driver 不同,Open vSwitch driver 并不通過 eth1.100, eth1.101 等 VLAN interface 來隔離不同的 VLAN。 所有的 instance 都連接到同一個(gè)網(wǎng)橋 br-int,Open vSwitch 通過 flow rule(流規(guī)則)來指定如何對(duì)進(jìn)出 br-int 的數(shù)據(jù)進(jìn)行轉(zhuǎn)發(fā),進(jìn)而實(shí)現(xiàn) vlan 之間的隔離。具體來說:當(dāng)數(shù)據(jù)進(jìn)出 br-int 時(shí),flow rule 可以修改、添加或者剝掉數(shù)據(jù)包的 VLAN tag,Neutron 負(fù)責(zé)創(chuàng)建這些 flow rule 并將它們配置到 br-int,br-eth1 等 Open vSwitch 上。 3)下面我們就來研究一下當(dāng)前的 flow rule,查看 flow rule 的命令是 ovs-ofctl dump-flow : br-eth1 上配置了四條 rule,每條 rule 有不少屬性,其中比較重要的屬性有: a)priority:rule 的優(yōu)先級(jí),值越大優(yōu)先級(jí)越高。Open vSwitch 會(huì)按照優(yōu)先級(jí)從高到低應(yīng)用規(guī)則。 b)in_port:inbound 端口編號(hào),每個(gè) port 在 Open vSwitch 中會(huì)有一個(gè)內(nèi)部的編號(hào)??梢酝ㄟ^命令 ovs-ofctl show 查看 port 編號(hào)。 比如 br-eth1: eth1 編號(hào)為 1;phy-br-eth1 編號(hào)為 2。 c)dl_vlan:數(shù)據(jù)包原始的 VLAN ID。 d)actions:對(duì)數(shù)據(jù)包進(jìn)行的操作。 br-eth1 跟 VLAN 相關(guān)的 flow rule 是前面兩條,下面我們來詳細(xì)分析。清晰起見,我們只保留重要的信息,如下: 第一條的含義是:從 br-eth1 的端口 phy-br-eth1(in_port=2)接收進(jìn)來的包,如果 VLAN ID 是 1(dl_vlan=1),那么需要將 VLAN ID 改為 100(actions=mod_vlan_vid:100) 從上面的網(wǎng)絡(luò)結(jié)構(gòu)我們可知,phy-br-eth1 連接的是 br-int,phy-br-eth1 的 inbound 包實(shí)際上就是 instance 通過 br-int 發(fā)送給物理網(wǎng)卡的數(shù)據(jù)。 4)那么怎么理解將 VLAN ID 1 改為 VLAN ID 100 呢? 請(qǐng)看下面計(jì)算節(jié)點(diǎn) ovs-vsctl show 的輸出: br-int 通過 tag 隔離不同的 port,這個(gè) tag 可以看成內(nèi)部的 VLAN ID。從 qvo4139d09b-30(對(duì)應(yīng) cirros-vm2,vlan100)進(jìn)入的數(shù)據(jù)包會(huì)被打上 1 的 VLAN tag。從 qvo98582dc9-db(對(duì)應(yīng) cirros-vm3,vlan101)進(jìn)入的數(shù)據(jù)包會(huì)被打上 5 的 VLAN tag。因?yàn)?br-int 中的 VLAN ID 跟物理網(wǎng)絡(luò)中的 VLAN ID 并不相同,所以當(dāng) br-eth1 接收到 br-int 發(fā)來的數(shù)據(jù)包時(shí),需要對(duì) VLAN 進(jìn)行轉(zhuǎn)換。Neutron 負(fù)責(zé)維護(hù) VLAN ID 的對(duì)應(yīng)關(guān)系,并將轉(zhuǎn)換規(guī)則配置在 flow rule 中。 5)理解了 br-eth1 的 flow rule,我們?cè)賮矸治?br-int 的 flow rule: 最關(guān)鍵的是下面兩條: port 1 為 int-br-eth1,那么這兩條規(guī)則的含義就應(yīng)該是: a)從物理網(wǎng)卡接收進(jìn)來的數(shù)據(jù)包,如果 VLAN 為 100,則改為內(nèi)部 VLAN 1。 b)從物理網(wǎng)卡接收進(jìn)來的數(shù)據(jù)包,如果 VLAN 為 101,則將為內(nèi)部 VLAN 5。 簡單的說,數(shù)據(jù)包在物理網(wǎng)絡(luò)中通過 VLAN 100 和 VLAN 101 隔離,在計(jì)算節(jié)點(diǎn) OVS br-int 中則是通過內(nèi)部 VLAN 1 和 VLAN 5 隔離。

2.5.6.4 Routing

Neutron Routing 服務(wù)提供跨 subnet 互聯(lián)互通的能力。 例如前面我們搭建了實(shí)驗(yàn)環(huán)境: cirros-vm1 172.16.100.3 vlan100 cirros-vm3 172.16.101.3 vlan101 這兩個(gè) instance 要通信必須借助 router。可以是物理 router 或者虛擬 router。詳細(xì)討論 Neutron 的虛擬 router 實(shí)現(xiàn): 1)配置 l3 agent,Neutron 的路由服務(wù)是由 l3 agent 提供的。 l3 agent 需要正確配置才能工作,配置文件為 /etc/neutron/l3_agent.ini,位于控制節(jié)點(diǎn)或網(wǎng)絡(luò)節(jié)點(diǎn): external_network_bridge 指定連接外網(wǎng)的網(wǎng)橋,默認(rèn)是 br-ex。 interface_driver 是最重要的選項(xiàng),如果 mechanism driver 是 open vswitch,則: 如果選用 linux bridge,則: 2)l3 agent 運(yùn)行在控制或網(wǎng)絡(luò)節(jié)點(diǎn),采用neutron agent-list命令查詢: 3)創(chuàng)建虛擬 router “router_100_101”,打通 vlan100 和 vlan101: 進(jìn)入操作菜單 Project -> Network -> Routers: 4)點(diǎn)擊 “Create Router” 按鈕: 5)outer 命名為 “router_100_101”,點(diǎn)擊 “Create Router” 按鈕確認(rèn): 6)router_100_101 創(chuàng)建成功: 7)接下來需要將 vlan100 和 vlan101 連接到 router_100_101。點(diǎn)擊 “router_100_101” 鏈接進(jìn)入 router 的配置頁面,在 “Interfaces” 標(biāo)簽中點(diǎn)擊 “Add Interface” 按鈕: 8)選擇 vlan100 的 subnet_172_16_100_0,點(diǎn)擊 “Add Interface” 確認(rèn): 9)用同樣的方法添加 vlan101 的 subnet_172_16_101_0: 完成后,可以看到 router_100_101 有了兩個(gè) interface,其 IP 正好是 subnet 的 Gateway IP 172.16.100.1 和 172.16.101.1。 10)到這里,router_100_101 已經(jīng)連接了subnet_172_16_100_0 和subnet_172_16_101_0。router_100_101 上已經(jīng)設(shè)置好了兩個(gè) subnet 的 Gateway IP。cirros-vm1 和 cirros-vm3 應(yīng)該可以通信了。 不出所料,cirros-vm1 和 cirros-vm3 能通信了。Neutron Router 工作原理: 1)先查看控制節(jié)點(diǎn)的網(wǎng)絡(luò)結(jié)構(gòu)發(fā)生了什么變化: br-int 上多了兩個(gè) port: a)qr-d295b258-45,從命名上可以推斷該 interface 對(duì)應(yīng) router_100_101 的 interface (d295b258-4586),是subnet_172_16_100_0 的網(wǎng)關(guān)。 b)qr-2ffdb861-73,從命名上可以推斷該 interface 對(duì)應(yīng) router_100_101 的 interface (2ffdb861-731c),是subnet_172_16_101_0 的網(wǎng)關(guān)。 2)與 linux bridge 實(shí)現(xiàn)方式一樣, router_100_101 運(yùn)行在自己的 namespace 中: 如上所示,qrouter-a81cc110-16f4-4d6c-89d2-8af91cec9714 為 router 的 namespace,兩個(gè) Gateway IP 分別配置在 qr-2ffdb861-73 和 qr-d295b258-45 上。 3)當(dāng)前網(wǎng)絡(luò)結(jié)構(gòu)如圖所示:

route_101_101 上配置了 vlan100 和 vlan101 的網(wǎng)關(guān),兩個(gè)網(wǎng)絡(luò)在三層上就通了。

訪問外網(wǎng),這里的外部網(wǎng)絡(luò)是指的租戶網(wǎng)絡(luò)以外的網(wǎng)絡(luò)。租戶網(wǎng)絡(luò)是由 Neutron 創(chuàng)建和維護(hù)的網(wǎng)絡(luò)。 外部網(wǎng)絡(luò)不由 Neutron 創(chuàng)建。如果是私有云,外部網(wǎng)絡(luò)通常指的是公司 intranet;如果是公有云,外部網(wǎng)絡(luò)通常指的是 internet 1)具體到我們的實(shí)驗(yàn)網(wǎng)絡(luò)環(huán)境,計(jì)算節(jié)點(diǎn)和控制節(jié)點(diǎn) eth1 提供的是租戶網(wǎng)絡(luò),IP 段租戶可以自由設(shè)置??刂乒?jié)點(diǎn) eth2 連接的就是外部網(wǎng)絡(luò),IP 網(wǎng)段為 10.10.10.2/24。如下圖所示: 2)配置準(zhǔn)備: 為了連接外部網(wǎng)絡(luò),需要預(yù)先在配置文件中告訴 Neutron 外部網(wǎng)絡(luò)的類型以及對(duì)應(yīng)的 Open vSwitch 網(wǎng)橋。外部網(wǎng)絡(luò)是已經(jīng)存在的物理網(wǎng)絡(luò),一般都是 flat 或者 vlan 類型。這里我們將外部網(wǎng)絡(luò)的 label 命名為 “external”,網(wǎng)橋?yàn)?br-ex。 a)如果類型為 flat,控制節(jié)點(diǎn)/etc/neutron/plugins/ml2/ml2_conf.ini 配置如下: b)如果類型為 vlan,配置如下: 在我們的網(wǎng)絡(luò)環(huán)境中,外部網(wǎng)絡(luò)是 flat 類型。 修改配置后,需要重啟 neutron 的相關(guān)服務(wù)。另外,我們需要提前準(zhǔn)備好 br-ex,將 eth2 添加到 br-ex: br-ex 已經(jīng)存在,我們只需要添加 eth2。 3)創(chuàng)建ext_net: a)進(jìn)入 Admin -> Networks 菜單,點(diǎn)擊 “Create Network” 按鈕: 顯示創(chuàng)建頁面: Provider Network Type 選擇 “Flat”。 Network 填寫 “external”,與 ml2_conf.ini 中 flat_networks 的參數(shù)值保持一致。 勾選 External Network 選擇框。 b)點(diǎn)擊 “Create Network”,ext_net 創(chuàng)建成功: c)點(diǎn)擊 ext_net 鏈接,進(jìn)入 network 配置頁面,目前還沒有 subnet。點(diǎn)擊 “Create Subnet” 按鈕: d)創(chuàng)建 subnet_10_10_10_0,IP 地址為 10.10.10.0/24: 這里 Gateway 我們使用默認(rèn)地址 10.10.10.1。 通常我們需要詢問網(wǎng)絡(luò)管理員外網(wǎng) subnet 的 Gateway IP,然后填在這里。 e)點(diǎn)擊 “Next”: 因?yàn)槲覀儾粫?huì)直接為 instance 分配外網(wǎng) IP,所以不需要 enable DHCP。 f)點(diǎn)擊 “Create”: subnet 創(chuàng)建成功,網(wǎng)關(guān)為 10.10.10.1。 g)下面查看控制節(jié)點(diǎn)網(wǎng)絡(luò)結(jié)構(gòu)的變化,執(zhí)行 ovs-vsctl show命令: 上圖所示,br-ex 與 br-int 通過 patch port “phy-br-ex” 和 “int-br-ex” 連接。 3)接下來需要將ext_net連接到 Neutron 的router,這樣 instance 才能訪問外網(wǎng): a)點(diǎn)擊菜單 Project -> Network -> Routers 進(jìn)入 router 列表: b)點(diǎn)擊 router_100_101 的 “Set Gateway” 按鈕 : c)在 “External Network” 下拉列表中選擇 ext_net,點(diǎn)擊 “Set Gateway”: d)外網(wǎng)設(shè)置成功。點(diǎn)擊 “router_100_101” 鏈接,打開 “Interfaces” 標(biāo)簽頁: router 多了一個(gè)新 interface,IP 為 10.10.10.2。 該 interface 用于連接外網(wǎng) ext_net,對(duì)應(yīng)的 br-ex 的 port “qg-cf54d3ea-6a”。 e)在 router 的 namespace 中查看到 qg-cf54d3ea-6a 已經(jīng)配置了 IP 10.10.10.2: router interface 的命名規(guī)則如下: i)如果 interface 用于連接租戶網(wǎng)絡(luò),命名格式為 qr-xxx。 ii)如果 interface 用于連接外部網(wǎng)絡(luò),命名格式為 qg-xxx。 f)查看 router 的路由表信息: 可以看到默認(rèn)網(wǎng)關(guān)為 10.10.10.1。 意味著對(duì)于訪問 vlan100 和 vlan101 租戶網(wǎng)絡(luò)以外的所有流量,router_100_101 都將轉(zhuǎn)發(fā)給 ext_net 的網(wǎng)關(guān) 10.10.10.1。 g)現(xiàn)在 router_100_101 已經(jīng)同時(shí)連接了 vlan100, vlan101 和 ext_net 三個(gè)網(wǎng)絡(luò),如下圖所示: h)我們?cè)?cirros-vm3 上測(cè)試一下: cirros-vm3 位于計(jì)算節(jié)點(diǎn),現(xiàn)在已經(jīng)可以 Ping 到 ext_net 網(wǎng)關(guān) 10.10.10.1 了。 i)通過 traceroute 命令 查看一下 cirros-vm3 到 10.10.10.1 的路徑: 數(shù)據(jù)包經(jīng)過兩跳到達(dá) 10.10.10.1 網(wǎng)關(guān)。 i)數(shù)據(jù)包首先發(fā)送到 router_100_101 連接 vlan101 的 interface(172.16.101.1)。 ii)然后通過連接 ext_net 的 interface(10.10.10.2) 轉(zhuǎn)發(fā)出去,最后到達(dá) 10.10.10.1。 當(dāng)數(shù)據(jù)包從 router 連接外網(wǎng)的接口 qg-cf54d3ea-6a 發(fā)出的時(shí)候,會(huì)做一次 Source NAT,將包的源地址修改為 router的接口地址 10.10.10.2,這樣就能夠保證目的端能夠?qū)?yīng)答的包發(fā)回給 router,然后再轉(zhuǎn)發(fā)回源端 instance。floating IP 1)通過 SNAT 使得 instance 能夠直接訪問外網(wǎng),但外網(wǎng)還不能直接訪問 instance。 2)直接訪問 instance 指的是通信連接由外網(wǎng)發(fā)起,例如從外網(wǎng) SSH instance。 如果需要從外網(wǎng)直接訪問 instance,可以利用 floating IP。 3)Open vSwitch driver 環(huán)境中 floating IP 的實(shí)現(xiàn)與 Linux Bridge driver 完全一樣:都是通過在 router 提供網(wǎng)關(guān)的外網(wǎng) interface 上配置 iptables NAT 規(guī)則實(shí)現(xiàn)。 4)有關(guān) floating IP 的詳細(xì)分析可以參考 Linux Bridge 中 floating IP 的相關(guān)章節(jié)。

2.5.6.5 vxlan network

Open vSwitch 支持 VXLAN 和 GRE 這兩種 overlay network。因?yàn)?OpenStack 對(duì)于 VXLAN 與 GRE 配置和實(shí)現(xiàn)差別不大,這里只討論如何實(shí)施 VXLAN。ML2配置ovs vxlan: 1)在 ML2 配置中 enable vxlan network,在 /etc/neutron/plugins/ml2/ml2_conf.ini 設(shè)置 vxlan network 相關(guān)參數(shù): 2)指定普通用戶創(chuàng)建的網(wǎng)絡(luò)類型為 vxlan,同時(shí) enable l2 population mechanism driver,然后指定 vxlan 的范圍(L2 Population 是用來提高 VXLAN 網(wǎng)絡(luò) Scalability 的。通常我們說某個(gè)系統(tǒng)的 Scalability 好,其意思是:當(dāng)系統(tǒng)的規(guī)模變大時(shí),仍然能夠高效地工作。): 上面配置定義了 vxlan vni 的范圍是 1001 – 2000,這個(gè)范圍是針對(duì)普通用戶在自己的租戶里創(chuàng)建 vxlan network 的范圍。 因?yàn)槠胀ㄓ脩魟?chuàng)建 network 時(shí)不能指定 vni,Neutron 會(huì)按順序自動(dòng)從這個(gè)范圍中取值。對(duì)于 admin 則沒有 vni 范圍的限制,admin 可以創(chuàng)建 vni 范圍為 1-16777216 的 vxlan network。 3)在 [agent] 中配置啟用 vxlan 和 l2population: 4)最后在 [ovs] 中配置 VTEP: vxlan tunnel 對(duì)應(yīng)的網(wǎng)橋?yàn)?br-tun。 local_ip 指定 VTEP 的 IP 地址。 devstack-controller 使用 166.66.16.10,此 IP 配置在網(wǎng)卡 eth1 上。 devstack-compute01 則使用 166.66.16.11,此 IP 配置在網(wǎng)卡 eth1 上。 初始網(wǎng)絡(luò)結(jié)構(gòu): Neutron 服務(wù)重啟后,通過 ovs-vsctl show 查看網(wǎng)絡(luò)配置: br-int 與 br-tun 通過 patch port “patch-tun” 和 “br-tun” 連接。目前網(wǎng)絡(luò)結(jié)構(gòu)如下所示: 創(chuàng)建vxlan 100_net,并將instance連接到此網(wǎng)絡(luò)上: 1)創(chuàng)建 vxlan100_net: 打開菜單 Admin -> Networks,點(diǎn)擊 “Create Network” 按鈕: 2)顯示創(chuàng)建頁面: Provider Network Type 選擇 “VXLAN”。 Segmentation ID 即 VNI,設(shè)置為 100。 3)點(diǎn)擊 “Create Network”,vxlan100 創(chuàng)建成功: 4)點(diǎn)擊 vxlan100 鏈接,進(jìn)入 network 配置頁面,目前還沒有 subnet。點(diǎn)擊 “Create Subnet” 按鈕: 5)創(chuàng)建 subnet_172_16_100_0,IP 地址為 172.16.100.0/24: 6)將 instance 連接到 vxlan100_net。launch 新的 instance “cirros-vm1”,“cirros-vm2” 網(wǎng)絡(luò)選擇 vxlan100: 7)cirros-vm1,cirros-vm2 分別部署到控制節(jié)點(diǎn)和計(jì)算節(jié)點(diǎn),IP 如下: 8)測(cè)試 cirros-vm1 和 cirros-vm2 的連通性: 底層網(wǎng)絡(luò)結(jié)構(gòu)分析: 1)在控制節(jié)點(diǎn),執(zhí)行 ovs-vsctl show: a)br-int: br-int 連接了如下 port: i)tap0d4cb13a-7a 是 vxlan100_net 的 DHCP 服務(wù)對(duì)應(yīng)的 interface。 ii)qvoa2ac3b9a-24 將 cirros-vm1 虛擬網(wǎng)卡連接到 vxlan100_net。 b)br-tun: br-tun 上創(chuàng)建了一個(gè)特殊的 port “vxlan-a642100b”,它是 VXLAN 的隧道端點(diǎn),指定了本地(devstack-controller)節(jié)點(diǎn)和遠(yuǎn)端(devstack-compute1)節(jié)點(diǎn) VTEP 的 IP 2)在計(jì)算節(jié)點(diǎn),執(zhí)行 ovs-vsctl show: a)br-int: br-int 上 qvoab219616-01 將 cirros-vm2 虛擬網(wǎng)卡連接到 vxlan100_net。 b)br-tun: br-tun 上也創(chuàng)建了 port “vxlan-a642100b”,配置內(nèi)容與控制節(jié)點(diǎn)相對(duì),指定了本地(devstack-compute1)節(jié)點(diǎn)和遠(yuǎn)端(devstack-controller)節(jié)點(diǎn) VTEP 的 IP。 3)當(dāng)前網(wǎng)絡(luò)結(jié)構(gòu)如下: 需要特別注意的是:無論存在多少個(gè) VXLAN,devstack-controller 與 devstack-compute1 之間所有的數(shù)據(jù)都只通過 “vxlan-a642100b” 這對(duì) port 上建立的隧道傳輸。flow rule分析: 1)br-int 的 flow rule: br-int 的 rule 看上去雖然多,其實(shí)邏輯很簡單,br-int 被當(dāng)作一個(gè)二層交換機(jī),其重要的 rule 是下面這條: 此規(guī)則的含義是:根據(jù) vlan 和 mac 進(jìn)行轉(zhuǎn)發(fā)。br-tun 的 flow rule: 這些才是真正處理 VXLAN 數(shù)據(jù)包的 rule,流程如下: 上圖各方塊中的數(shù)字對(duì)應(yīng) rule 中 table 的序號(hào),比如編號(hào)為0的方塊對(duì)應(yīng)下面三條 rule。 1)table 0: 結(jié)合如下 port 編號(hào): table 0 flow rule 的含義為: a)從 port 1(patch-int)進(jìn)來的包,扔給 table 2 處理:actions=resubmit(,2) b)從 port 2(vxlan-a642100b)進(jìn)來的包,扔給 table 4 處理:actions=resubmit(,4) 即第一條 rule 處理來自內(nèi)部 br-int(這上面掛載著所有的網(wǎng)絡(luò)服務(wù),包括路由、DHCP 等)的數(shù)據(jù); 第二條 rule 處理來自外部 VXLAN 隧道的數(shù)據(jù)。 2)table 4: table 4 flow rule 的含義為: 如果數(shù)據(jù)包的 VXLAN tunnel ID 為 100(tun_id=0x64),action 是添加內(nèi)部 VLAN ID 1(tag=1),然后扔給 table 10 去學(xué)習(xí)。 3)table 10: table 10 flow rule 的含義為: 學(xué)習(xí)外部(從 tunnel)進(jìn)來的包,往 table 20 中添加對(duì)返程包的正常轉(zhuǎn)發(fā)規(guī)則,然后從 port 1(patch-int)扔給 br-int。 4)table2: table 2 flow rule 的含義為: a)br-int 發(fā)過來數(shù)據(jù)如果是單播包,扔給 table 20 處理:resubmit(,20) b)br-int 發(fā)過來數(shù)據(jù)如果是多播或廣播包,扔 table 22 處理:resubmit(,22) 5)table20: table 20 flow rule 的含義為: a)第一條規(guī)則就是 table 10 學(xué)習(xí)來的結(jié)果。內(nèi)部 VLAN 號(hào)為 1(tag=1),目標(biāo) MAC 是 fa:16:3e:fd:8a:ed(virros-vm2)的數(shù)據(jù)包,即發(fā)送給 virros-vm2 的包,action 是去掉 VLAN 號(hào),添加 VXLAN tunnel ID 100(十六進(jìn)制 0x64),并從 port 2 (tunnel 端口 vxlan-a642100b) 發(fā)出。 b)對(duì)于沒學(xué)習(xí)到規(guī)則的數(shù)據(jù)包,則扔給 table 22 處理。 6)table22: table 22 flow rule 的含義為: 如果數(shù)據(jù)包的內(nèi)部 VLAN 號(hào)為 1(tag=1),action 是去掉 VLAN 號(hào),添加 VXLAN tunnel ID 100(十六進(jìn)制 0x64),并從 port 2 (tunnel 端口 vxlan-a642100b) 發(fā)出。VXLAN 的路由和 floating IP 支持 對(duì)于多 VXLAN 之間的 routing 以及 floating IP,實(shí)現(xiàn)方式與 vlan 非常類似,這里不再贅述,請(qǐng)參看前面 vlan 相關(guān)章節(jié)。

柚子快報(bào)邀請(qǐng)碼778899分享:云計(jì)算之OpenStack核心

http://yzkb.51969.com/

好文推薦

評(píng)論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。

轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://m.gantiao.com.cn/post/18903494.html

發(fā)布評(píng)論

您暫未設(shè)置收款碼

請(qǐng)?jiān)谥黝}配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問

文章目錄