Octavia 建立 loadbalancer 的實現與分析

目錄

從 Octavia API 看起

經過 CLI 建立一個 loadbalancerpython

(octavia_env) [root@control01 ~]# openstack loadbalancer create --vip-subnet-id 122056f4-0fad-4ab2-bdf9-9b0942d0b213 --name lb1 --debug

在這裏插入圖片描述

Create LB 的 Octavia API UML 圖web

在這裏插入圖片描述

其中 2. _validate_vip_request_object 的細節以下 UML 圖數據庫

在這裏插入圖片描述

經過 上述 UML 圖能夠看出當 octavia-api service 接收到 create loadbalancer 請求後主要處理了下列幾件事情:api

  1. 驗證請求用戶的身份。
  2. 驗證請求 VIP 及其相關對象(e.g. port, subnet, network, )是否可用,能夠經過 config secition [networking] 來配置 Allow/disallow 的網絡對象。
  3. 檢查請求 Project 的 LB 相關 Quota,能夠經過 config section [quotas] 來配置默認 Quota。
  4. 準備建立 loadbalancer 數據庫記錄的數據結構。
  5. 建立 loadbalancer 和 vip 的數據庫記錄。
  6. 調用 Amphora driver(default lb provider)建立 VIP 對應的 port,並將 Port、VIP、LB 三者的數據庫記錄關聯起來。
  7. 以圖的方式建立 loadbalancer 下屬的 Listeners 和 Pools。
  8. 準備傳遞給 Amphora driver 實際用於 create_loadbalancer_flow 的數據結構。
  9. 異步調用 octavia-cw service 執行 create_loadbalancer_flow。

其中有幾點值得咱們額外的注意:安全

  • 經過 networking 和 quota 用戶能夠限制 LBaaS 的資源範圍,e.g. loadbalancer 的個數、listener 的個數 etc… 甚至能夠規定使用的 VIP 列表和 VIP 只能在規定的 network/subnet 中建立。網絡

  • 雖然 CLI 並無給出相似 --listeners or --pools 的選項讓用戶傳遞 loadbalancer 下屬 Listeners 和 Pools 的 body 屬性,但實際上 POST /v2.0/lbaas/loadbalancers 的視圖函數時能夠處理這兩個參數的。因此在 UI 設定的時候能夠完成 CLI 不支持的一次性建立 loadbalancer、listener 及 pool 的操做。數據結構

  • 建立 loadbalancer 時,若是 VIP 的 port 不存在,那麼 octavia-api 會調用 neutronclient 建立,命名規則爲 lb-<load_balancer.id>,因此你會在 VIP 的 network/subnet 中看見相似的 Port。app

Octavia Controller Worker

在這裏插入圖片描述

這是一個典型的 taskflow 外層封裝,從 get flow、prepare flow store、get flow engine 到最後的 run flow。其中最核心的步驟是 3. self._lb_flows.get_create_load_balancer_flow,想要知道建立 loadbalancer 都作了些什麼事情,就要看看這個 Flow 裏面都有哪些 Task。異步

在這裏插入圖片描述

這裏咱們主要關注爲 loadbalancer 準備 Amphora 和 Amphora 的 Networking Setup。ide

爲 loadbalancer 準備 Amphora 的 UML 以下:

在這裏插入圖片描述

爲 loadbalancer 準備 Amphora 的過程當中有幾點值得咱們注意:

  • 若是配置 [controller_worker] loadbalancer_topology = ACTIVE_STANDBY 時,能夠結合 [nova] enable_anti_affinity = True 反親和性進一步提升 loadbalancer 的高可用性。
  • 爲 loadbalancer 準備 Amphora 並不是每次都是經過 create amphora 來實現的,flow 會先檢查是否存在能夠映射到 loadbalancer 的 Amphora instance,若是存在就直接映射給 loadbalancer 使用。若是不存在纔會啓動建立 Amphora instance 的任務流,這裏須要配合 housekeeping 機制來完成。housekeeping 會根據配置 [house_keeping] spare_amphora_pool_size=2 來準備 spare Amphora instance pool,加速 loadbalancer 的建立流程。
  • 建立 Amphora 使用的是 graph flow(圖流),圖流的特性就是開發者能夠自定義條件來控制任務的流向,amp_for_lb_flow.link 就是設定判斷條件的語句,這裏的判斷條件設定爲了:若是爲 loadbalancer mapping Amphora instance 成功就直接修改數據庫中相關對象的隱射關係,若是 mapping 失敗則先建立 Amphora instance 以後再修改數據庫中相關對象的隱射關係。

爲 loadbalancer 的 Amphora 準備 networking 的 UML 以下:

在這裏插入圖片描述

從 UML 能夠見 Amphora 的 Networking 主要的工做是爲 Amphora 的 Keepalived 設定 VIP,過程當中會涉及到大量的 octavia-cw service 與 amphora agent 的通訊。後面咱們再繼續深刻看看關鍵的 Task 中都作什麼什麼事情。

再繼續看看當 listeners 參數被傳入時的 flow 是怎麼樣的:

在這裏插入圖片描述

建立 Listener 實際上就是更新了 Amphora 內 HAProxy 的配置信息,因此可見上述最重要的 Task 就是 amphora_driver_task.ListenersUpdate

自此整個 create loadbalancer 的 flow 就都看完了,接下來咱們繼續深刻到一些關鍵的 Task 裏,看看都作了什麼事情。

database_tasks.MapLoadbalancerToAmphora

爲 loadbalancer 建立 amphora 時首先會嘗試 Maps and assigns a load balancer to an amphora in the database,若是 mapping SUCCESS 則會 return amphora uuid 不然爲 None。graph flow 類型的 amp_for_lb_flow 就是經過這個 return 來做爲任務流向控制判斷條件的。

if None:
    create_amp
else:
    map_lb_to_amp

compute_tasks.CertComputeCreate & ComputeCreate

Task CertComputeCreate & ComputeCreate 都是建立一個 amphora instance,經過配置項 [controller_worker] amphora_driver 進行選擇。當 amphora_driver = amphora_haproxy_rest_driver 時使用 CertComputeCreate,octavia-cw service 與 amphora-agent 之間經過 HTTPS 進行安全通訊;當 amphora_driver = amphora_noop_driver 時使用後者,但 amphora_noop_driver 通常被用做測試,能夠忽略不計。

compute_id = self.compute.build(
                name="amphora-" + amphora_id,
                amphora_flavor=CONF.controller_worker.amp_flavor_id,
                image_id=CONF.controller_worker.amp_image_id,
                image_tag=CONF.controller_worker.amp_image_tag,
                image_owner=CONF.controller_worker.amp_image_owner_id,
                key_name=key_name,
                sec_groups=CONF.controller_worker.amp_secgroup_list,
                network_ids=network_ids,
                port_ids=[port.id for port in ports],
                config_drive_files=config_drive_files,
                user_data=user_data,
                server_group_id=server_group_id)

這裏調用了 novaclient 的封裝來建立 amphora instance,其中 image、flavor、sec_groups、keypair 均在配置 [controller_worker] 中定義了。須要注意的是 config_drive_files 和 user_data 兩個形參就是爲了 amphora instance 啓動時爲 amphora-agent 注入證書的參數項,應用了 Nova Store metadata on a configuration drive 機制。

config_drive_files = {
            '/etc/octavia/certs/server.pem': server_pem,
            '/etc/octavia/certs/client_ca.pem': ca}

network_tasks.AllocateVIP

Task AllocateVIP 實際調用了 octavia.network.drivers.neutron.allowed_address_pairs:AllowedAddressPairsDriver.allocate_vip method,return 的是一個創建了 Port、VIP 和 LB 三者關係的 data_models.Vip 對象。該 method 在 octavia-api 已經被調用過一次了,因此到此時 VIP 的 Port 通常都已經存在了,只須要返回一個 data object 便可。而後在經過 Task UpdateAmphoraVIPData 落庫持久化。

network_tasks.PlugVIP

Task PlugVIP 是實際爲 Amphora instance(s) 設定 VIP 的。

在這裏插入圖片描述

在 PlugVIP 的過程當中須要注意幾點:

  • 在建立 Listener 時都會 update VIP port 的 security_group_rules,由於 Listener 是依附於 VIP 的,因此 Listener 監聽的協議端口都應該在 VIP 的安全組上打開,而且關閉沒必要要的端口。
  • PlugVIP 會輪詢檢查全部 loadbalancer.amphora 是否具備 VIP 對應的 Port,若是沒有則會建立出來,設定 VIP 再掛載到 Amphora instance 上。

NOTE:VIP 是 Act/Stby topo Amphora 的虛擬 IP。

最後

至此 Octavia 建立 loadbalancer 的流程就分析分完了,總的來講一圖頂千言,仍是但願經過 UML 圖來描述主要流程再輔以文字說明關鍵點的方式來進行介紹。

相關文章
相關標籤/搜索