【了解】
其實說白了,Octavia就是將用戶的API請求經過邏輯處理,轉換成Haproxy或者Nginx的配置參數,下發到amphora虛機中。
Octavia的內部實現中,邏輯流程的處理主要使用TaskFlow庫。
【基本概念】
LBaas
Load Balancing as a Service,在openstack平台上,LB被作為一種服務提供給用戶,用戶可以按需獲取可配置的業務負載分擔方案。
LBaaS(Load Balancer as a Service)是 OpenStack 的網絡負載均衡服務,為用戶提供應用集群負載均衡解決方案。LBaaS 支持將來自公網或內部網絡的應用服務訪問流量按照指定的均衡策略分發到資源池內的雲主機,允許用戶隨時增加、減少提供應用服務的雲主機而不影響業務可用性,有效保障了應用服務的響應速度和高可用。
以往,LBaaS 基於 Neutron 實現,LBaaS V1 API 在 Grizzly 版本被集成到 Neutron,功能模塊的代碼實現在 openstack/neutron-lbaas repo,支持 Plug-In 模式,提供了 HAProxy、F5 等多種 Driver 對接底層負載均衡器。LBaaS V2 API 在 Kilo 版本發布,Liberty 版本正式支持,同期發布的還有 Octavia Plugin。歷經幾個版本的迭代,Octavia 在 Pike 版本成為了需要在 Keystone 上注冊 endpoint 的獨立項目而不再是 Neutron 的一個服務插件。現在社區也正逐漸將 openstack/neutron-lbaas repo 實現的 Driver 遷移到 openstack/octavia repo,在 Queens 版本中 neutron-lbaas 正式被標記為廢棄「Neutron-lbaas is now deprecated」。
為什么廢棄 neutron-lbaas 擴展項目?社區給出了詳盡的說明,簡單總結一下有兩點原因:
-
neutron-lbaas 與 Neutron 項目的耦合度太高,前者會直接使用 Neutron 的代碼和 DB 從而導致 LBaaS API 的性能和擴展性不佳,而且 HAProxy Plugin 的實現也不具有高可用特性。總的來說,neutron-lbaas 不適用於大規模部署場景。
-
Ocatvia 項目已經成熟,可以向外提供穩定的 REST API,允許用戶跨版本集成和遷移。同時,完全獨立的狀態會使 Ocatvia 發展得更加迅速。
OpenStack neutron-lbaas Deprecation FAQ 請瀏覽:
https://wiki.openstack.org/wiki/Neutron/LBaaS/Deprecation
項目組織的變化:
items | Old | New |
---|---|---|
Repo | openstack/neutron-lbaas | openstack/octavia |
CLI | neutronclient | octaviaclient (openstackclient 的擴展) |
Horizon panels | neutron-lbaas-dashboard | octavia-dashboard (Queens 開始支持) |
Octavia
Octavia 定位於電信運營商級別的可靠、可擴展負載均衡項目,加速 OpenStack LBaaS 在大規模應用場景中的落地。默認采用 HAProxy + Keepalived 組合的高可用負載均衡方案提供底層支撐。
簡單總結一下 Octavia 的工作原理就是:Octavia 通過調用 Nova API 管理負載均衡器的 Lifecycle,調用 Neutron API 構建 LB Network 並接入業務網讓負載均衡器納管業務雲主機,最后根據用戶請求參數生成 HAProxy 和 Keepalived 的配置文件。前端為用戶提供統一的業務訪問入口(VIP),后端依靠負載均衡服務自動分發訪問請求。
軟件架構
網絡架構
操作對象基本概念
Load Balancer:負載均衡服務的根操作對象,同時也是與 VIP 關聯的邏輯對象。一個 Load Balancer 可以擁有一個或多個 VIPs。Load Balancer 需要占用 Neutron Subnet 的一個 Port,並從 Subnet 獲取 IP 地址作為 VIP。
Subnet:下屬 Neutron Network 的子網,用戶業務雲主機(Member)所處的網絡,Subnet 與 Load Balancer 關聯后,Load Balancer 擁有的 Amphora 才能與 Member 通信。
Listener:監聽器,用戶可通過其配置外部對VIP訪問的端口,算法,類型等等。本質是 Subnet 的一個 Port,用於監聽客戶端對 Load Balancer(VIP)的訪問請求,監聽項為 HTTP/HTTPS、TCP 協議的元素(e.g. Port,URI),但不監聽 IP 地址。符合監聽規則(e.g. HTTP Port:80)的訪問請求才會被轉發到與 Listener 關聯的 Pool 中。可以為一個 Load Balancer 設定若干個用於訪問請求監聽的 Listeners,一個 Listener 又可以關聯多個 Pool。
Pool:類似於傳統負載均衡系統中的 Backend Real Server Group 邏輯對象,作為 Member 的容器,接收 Listener 路由過來的客戶端訪問請求。通常的,會把業務類型相近的雲主機划分到同一個 Pool,例如:Web 的動靜分離場景。負責后端的虛擬機池。在Haproxy為driver的情況下,一個Pool對應着一個獨立的network namespace中運行的HaProxy進程中管理的backend。一個VIP只會有一個Pool。
Member:傳統負載均衡系統中的 Real Server,實際運行用戶業務的雲主機,被包含在一個 Pool 內,具有權重屬性。Member 和 Pool one to one 關聯。
Member 對應的是 pool 里面處理網絡請求的一個 OpenStack Nova 虛機。
Health Monitor:Member 的 Health Check,與 Pool 關聯,是一個單純的 DB 對象,描述了運行在 Amphora 中的負載均衡器應該如何對 Pool 下屬的 Member 進行健康狀態檢查的方法(e.g. HTTP Method、TCP、PING)。這是一個可選功能,但如果沒有 Health Monitor,Pool 會認為所有 Member 都是 ACTIVE 的,哪怕 Member 其實不能響應。所以 Disabled Health Monitor 可能會造成負載均衡響應異常。它用來檢測pool里面的member的狀態,支持很多種檢測方法,在neutron里面是可選的。
Amphora:為 Members 提供負載均衡服務的實體,類似於傳統負載均衡系統中的 Frontend,默認為雲主機,也可以是容器或裸機。Amphora 在用戶新建 Load Balancer 的同時自動創建,一個 Load Balancer 可以擁有若干個 Amphora,這取決於用戶選擇的 loadbalancer_topology。
LB Network:全稱 Load balancing management network,Octavia Controller 和 Amphora 通信的網絡,每一個 Amphora 至少有一個 Port 接入 LB Network。LB Network 不會與任意一個租戶關聯,也不會暴露給其他的 OpenStack Project 使用。
HAProxy:運行在 Amphora 中的負載均衡器軟件。
VIP:Virtual Load Balancer IP Address,與 Load Balancer 關聯的虛擬 IP 地址,由運行在 Amphora 中的 Keepalived 應用 VRRP 協議原理來維護 VIP 的漂移和高可用性。
Layer 7 Switching:是針對七層 HTTP/HTTPS 協議的負載均衡功能,能夠根據用戶設定的 L7 Policy 將不同的客戶端請求路由到不同的 Pool 中。
Layer 7 Policy:用於設定 Listener 將客戶端請求轉發到指定 Pool 的路由策略。當 Listener 關聯了多個 Pool 時,可以通過設定 L7 Policy 來控制流量轉發到指定的 Pool。Layer 7 Policy 只會與一個 Listener 關聯,但可以關聯多個 L7 Rule。例如:用戶可以設定 URI 以 “/api” 開頭的客戶端請求都轉發到 Listener 下的 Pool: “api_pool” 中。
Layer 7 Rule:本質是 HAProxy frontend section 下的 ACL 規則,可以根據是否滿足規則的條件來確定最終處理客戶請求的 Member。例如:用戶可以設定 L7 Rule: “/api” 來匹配 URI 以 “/api” 開頭的客戶端請求,交由 Member: api_service 處理。Layer 7 Rule 與 Layer 7 Policy 結合使用實現 Layer 7 Switching 的功能。
Transport Layer Security (TLS) Termination:TLS Termination 是負載均衡器處理 HTTPS 協議的一種方式。通常的,HTTPS 協議要求客戶端和服務端進行 3 次連接握手加上 9 次 SSL 安全驗證握手,共 12 次握手才得以建立連接。可見如果在服務端(Member)上處理 SSL 握手,會對服務端造成比較大的壓力。所以在負載均衡場景中,可以把這些壓力轉移到負載均衡服務器上,這就是負載均衡器的 TLS Termination 功能,將 HTTPS 連接中最耗時的部分從服務端剝離出來,讓服務端專心於自身的業務負載。如果 Listener 設定了 HTTPS 的 Layer 7 Switching,那么 TLS Termination 將會非常有用。
基本概念之間的交互流程如下圖:
【基本架構】
Amphora
負載均衡的載體,一般為雲主機。(當然也可以使用物理機,將多個負載均衡配置到同一/兩台Amphora節點上,提高數據包轉發效率,但是有單點故障隱患)
manage-network
管理網絡,通常管理數據走這條線路,東側連接Amphora,西側連接Octavia服務進程。
tenant-network
租戶網絡,內部通信使用,SLB轉發報文通過租戶網絡到各個后端服務器上。
vip-network
服務地址,主要用於對外提供服務。
PS:vip-net和tenant-net可以是同一個網絡,但是在生產環境中建議分開,以便於更好得划分網絡安全隔離。
VM
后端服務器,用戶的真實服務器
health-manager
Health Manager:用於監控 Member 的健康狀態,如果出現故障,則自動進行故障轉移。通過於 Agent 通信來更新 Amphora 中的負載均衡器的健康檢查方式。
octavia里面進行健康檢查的進程,主要有以下兩個作用
1. 監聽來自amphora虛擬機發來的運行狀態數據,以此更新lb,listener,pool,member的狀態,同時更新listener_statistics表(可作為計費依據),最重要的是更新amphora_health表。
2. 根據amphora_health數據表中的數據,找到異常狀態的amphora虛擬機,對該虛擬機進行更換操作。(即刪除舊的虛擬機,創建新的虛擬機並下發配置)
house-keeping
名副其實的 Housekeeping(家政)服務,保障 Octavia 的健康運行。
主要實現三個功能:
SpareAmphora: 清理虛擬機的池子, 確保空閑的amphorae池大小。
DatabaseCleanup: 定期清理數據庫中已刪除的amphorae記錄。
CertRotation: 定期更新amphorae中的證書。
Agent:Amphora Agent,運行在 Amphorae 內,接收外部請求並組織 HAProxy 和 Keepalived,同時也負責上報 Member 的健康狀態信息給 Health Manager。
Amphora Load Balancer Driver:負責 Controller 與 Amphora 在 LB Network 中的通信。
Octavia Worker
負責完成 API 請求,是 Octavia 主干功能的執行者。
主要作用是和nova,neutron等組件通信,用於虛擬機調度以及把對於虛擬機操作的指令下發給octavia agent。
實際的負載均衡業務邏輯,與 Nova 配合,完成 Amphora 的生命周期管理;與 Neutron 配合,完成 LB Network 接入 Subnet。還會通過與 Agent 通信將執行指令下發到 Amphora,支持插件框架。
基本流程如下:
Ocatvia Daemon 列表
octavia-api.service
octavia-worker.service octavia-health-manager.service octavia-housekeeping.service
【API 】
如下表:
Balancers |
GET |
/v2/lbaas/loadbalancers |
List Load Balancers |
|
POST |
/v2/lbaas/loadbalancers/{loadbalancer_id} |
Create a Load Balancer |
|
GET |
/v2/lbaas/loadbalancers/{loadbalancer_id} |
Show Load Balancer details |
|
PUT |
/v2/lbaas/loadbalancers/{loadbalancer_id} |
Update a Load Balancer |
|
DELETE |
/v2/lbaas/loadbalancers/{loadbalancer_id} |
Remove a Load Balancer |
|
GET |
/v2/lbaas/loadbalancers/{loadbalancer_id}/stats |
Get Load Balancer statistics |
|
GET |
/v2/lbaas/loadbalancers/{loadbalancer_id}/status |
Get the Load Balancer status tree |
|
PUT |
/v2/lbaas/loadbalancers/{loadbalancer_id}/failover |
Failover a load balancer |
Listeners |
GET |
/v2/lbaas/listeners |
List Listeners |
|
POST |
/v2/lbaas/listeners |
Create Listener |
|
GET |
/v2/lbaas/listeners/{listener_id} |
Show Listener details |
|
PUT |
/v2/lbaas/listeners/{listener_id} |
Update a Listener |
|
DELETE |
/v2/lbaas/listeners/{listener_id} |
Remove a Listener |
|
GET |
/v2/lbaas/listeners/{listener_id}/stats |
Get Listener statistics |
Pools |
|
|
|
|
GET |
/v2/lbaas/pools |
List Pools |
|
POST |
/v2/lbaas/pools |
Create Pool |
|
GET |
/v2/lbaas/pools/{pool_id} |
Show Pool details |
|
PUT |
/v2/lbaas/pools/{pool_id} |
Update a Pool |
|
DELETE |
/v2/lbaas/pools/{pool_id} |
Remove a Pool |
Members |
|
|
|
|
GET |
/v2/lbaas/pools/{pool_id}/members |
List Members |
|
POST |
/v2/lbaas/pools/{pool_id}/members |
Create Member |
|
GET |
/v2/lbaas/pools/{pool_id}/members/{member-id} |
Show Member details |
|
PUT |
/v2/lbaas/pools/{pool_id}/members/{member_id} |
Update a Member |
|
PUT |
/v2/lbaas/pools/{pool_id}/members |
Batch Update Members |
|
DELETE |
/v2/lbaas/pools/{pool_id}/members/{member_id} |
Remove a Member |
Health Monitor |
|
|
|
|
GET |
/v2/lbaas/healthmonitors |
List Health Monitors |
|
POST |
/v2/lbaas/healthmonitors |
Create Health Monitor |
|
GET |
/v2/lbaas/healthmonitors/{healthmonitor_id} |
Show Health Monitor details |
|
PUT |
/v2/lbaas/healthmonitors/{healthmonitor_id} |
Update a Health Monitor |
|
DELETE |
/v2/lbaas/healthmonitors/{healthmonitor_id} |
Remove a Health Monitor |
L7 Policies |
|
|
|
|
GET |
/v2/lbaas/l7policies |
List L7 Policies |
|
POST |
/v2/lbaas/l7policies |
Create an L7 Policy |
|
GET |
/v2/lbaas/l7policies/{l7policy_id} |
Show L7 Policy details |
|
PUT |
/v2/lbaas/l7policies/{l7policy_id} |
Update a L7 Policy |
|
DELETE |
/v2/lbaas/l7policies/{l7policy_id} |
Remove a L7 Policy |
L7 Rules |
|
|
|
|
GET |
/v2/lbaas/l7policies/{l7policy_id}/rules |
List L7 Rules |
|
POST |
/v2/lbaas/l7policies/{l7policy_id}/rules |
Create an L7 Rule |
|
GET |
/v2/lbaas/l7policies/{l7policy_id}/rules/{l7rule_id} |
Show L7 Rule details |
|
PUT |
/v2/lbaas/l7policies/{l7policy_id}/rules/{l7rule_id} |
Update a L7 Rule |
|
DELETE |
/v2/lbaas/l7policies/{l7policy_id}/rules/{l7rule_id} |
Remove a L7 Rule |
Quotas |
|
|
|
|
GET |
/v2/lbaas/quotas |
List Quota |
|
GET |
/v2/lbaas/quotas/defaults |
Show Quota Defaults |
|
GET |
/v2/lbaas/quotas/{project_id} |
Show Project Quota |
|
PUT |
/v2/lbaas/quotas/{project_id} |
Update a Quota |
|
DELETE |
/v2/lbaas/quotas/{project_id} |
Reset a Quota |
Providers |
|
|
|
|
GET |
/v2/lbaas/providers |
List Providers |
|
GET |
/v2/lbaas/providers/{provider}/flavor_capabilities |
Show Provider Flavor Capabilities |
Flavors |
|
|
|
|
GET |
/v2.0/lbaas/flavors |
List Flavors |
|
POST |
/v2.0/lbaas/flavors |
Create Flavor |
|
GET |
/v2.0/lbaas/flavors/{flavor_id} |
Show Flavor Details |
|
PUT |
/v2.0/lbaas/flavors/{flavor_id} |
Update a Flavor |
|
DELETE |
/v2.0/lbaas/flavors/{flavor_id} |
Remove a Flavor |
Flavor Profiles |
|
|
|
|
GET |
/v2.0/lbaas/flavorprofiles |
List Flavor Profiles |
|
POST |
/v2.0/lbaas/flavorprofiles |
Create Flavor Profile |
|
GET |
/v2.0/lbaas/flavorprofiles/{flavorprofile_id} |
Show Flavor Profile Details |
|
PUT |
/v2.0/lbaas/flavorprofiles/{flavorprofile_id} |
Update a Flavor Profile |
|
DELETE |
/v2.0/lbaas/flavorprofiles/{flavorprofile_id} |
Remove a Flavor Profile |
Amphorae |
|
|
|
|
GET |
/v2/octavia/amphorae |
List Amphora |
|
GET |
/v2/octavia/amphorae/{amphora_id} |
Show Amphora details |
|
GET |
/v2/octavia/amphorae/{amphora_id}/stats |
Show Amphora Statistics |
|
PUT |
/v2/octavia/amphorae/{amphora_id}/config |
Configure Amphora |
|
PUT |
/v2/octavia/amphorae/{amphora_id}/failover |
【數據結構】
以上是octavia主要數據表的拓撲圖。
我們可以發現,load_balancer表幾乎被關聯到了所有的關鍵表,health_monitor是通過pool表去關聯到listener和member的。
opertatingstatus和provisioning_status關聯到了所有的關鍵表,主要作用是體現當前組件狀態。
amphora_health主要體現amphora-agent的狀態。
listener_statistics表,根據來自amphorae虛擬機發送的運行狀態數據,實時維護對應 amphora_id與listener_id(主鍵) 的bytes_in,bytes_out,active_connections,total_connections字段,可以作為計費依據。
【主要流程】
創建loadbalancer
現支持single和active standby(主備雙活)兩種模式的loadbalancer。
P版本只支持single。
創建loadbalancer的參數中可以指定 vip 綁定的 port,如果沒有指定,octavia 會自動(在 API 層)創建:
普通創建 lb 時,在 API 層會創建 lb 和 vip 的數據庫記錄,然后把請求交由 worker 處理。
創建loadbalancer,Octavia會創建兩個虛擬機(active standby)。
如果配置enable_anti_affinity,則會針對這個 lb 先在Nova創建ServerGroup(這個ServerGroup的ID會記錄在DB中),兩個虛擬機就會創建在不同的host上。
虛擬機的flavor、image、network、security group、keypair信息都是從配置文件中獲取。
有了虛擬機后,同時在入參的subnet下給兩個虛擬機分別掛載網卡,並將VIP作為address pair配置到網卡。
然后,向虛擬機發送REST API, 參數中有VIP所在 subnet 的 CIDR,網關 IP,vrrp port 的 mac 地址,vrrp port 的 IP 地址等信息。
向amphora發送消息配置 keepalived 服務( active standby模式)。
至此,一個 loadbalancer 就創建結束了。基本上,后面創建listener、pool、member、health monitor,都是圍繞這兩個虛擬機,對haproxy(nginx)和keepalived進程進行配置。
在 octavia 中,資源之間的映射關系如下:
lb: 就是兩個管理員/租戶的虛擬機
listener: 虛擬機里面的一個 haproxy (nginx)進程,frontend 配置
pool: haproxy (nginx)配置中的一個 backend
member: backend 配置中的一個 member
上文中,frontend指的是前端,定義一系列監聽套字節,接收客戶端請求;backend指的是后端,定義一系列后端服務器,請求轉發。
創建完 lb,登錄 amphora 驗證創建 lb 后的網絡配置,可以看到默認只能看到管理 IP,只有在 namespace 中才能看到 vrrp 網卡信息。
amphora-agent 啟動腳本是 octavia repo 中 cmd 目錄下的 agent.py。
amphora-agent 還做一件事,定時向 health-monitor 發送haproxy的運行時信息,該信息是通過向haproxy進程發送socket查詢命令獲取到。
創建 listener 流程
在Octavia中,一個listener就對應amphorae 中一個haproxy進程。
首先生成haproxy配置文件,向amp發送消息,生成對應該 listener 的 haproxy 服務腳本。
再次向 amphorae 發送消息啟動 haproxy 服務:
先確定listener的配置目錄(/var/lib/octavia/{listener-id}/)在不在 如果是active standby,更新keepalived對各個haproxy的check腳本, /var/lib/octavia/vrrp/check_scripts/haproxy_check_script.sh 啟動haproxy服務,service haproxy-{listener_id} start
創建pool
創建 pool 的實現基本跟創建 listener 一致,在 amphorae 中僅僅是在 haproxy 的配置文件增加backend配置。
添加 member
在添加 member 之前,amphorae 虛擬機上已經有管理 port 和 vrrp port,其中 vrrp port 在命名空間中。
參考:https://www.cnblogs.com/liuxia912/p/11209968.html
https://blog.csdn.net/jmilk/article/details/81279795