設定

若要部署此自動化容錯移轉解決方案,您需要設定負載平衡器、設定警示和通知、建立功能,以及設定 OCI API 閘道

以下步驟詳述:

  1. 處理作業會從準備負載平衡器開始,此負載平衡器需要設定次要監聽器,以及控制重新導向行為的特定規則集。
  2. 接著,設定警示和通知,以在應用程式伺服器處於狀況不良狀態,以及當狀況良好的伺服器可用時觸發動作。
  3. 接著,您可以使用 OCI Functions 部署拍賣來啟用核心自動化,該函數會根據目前的警示狀態,以程式設計方式控制負載平衡器規則集的附件或切離。
  4. 最後,請設定 OCI API Gateway 以代管您的自訂靜態維護頁面。

這些組態在實現順暢、自動容錯移轉至友善的維護頁面時,都扮演了特定且整合的角色。

設定負載平衡程式

此解決方案的基礎位於負載平衡器中,此負載平衡器已融入應用程式,並將流量分散到其後端伺服器。這些步驟假設大多數的部署先決條件都已就緒,包括應用程式監聽器 (HTTP 或 HTTPS)、已設定狀況檢查的後端集,以及透過網際網路閘道路由,讓使用者能夠連線服務。

從負載平衡器上的主要監聽器開始,設定為處理通往應用程式的一般流量。當所有項目正常運作時,此監聽器會將內送要求遞送至 VM 執行處理的後端集。它會監聽標準連接埠 (HTTP/80 或 HTTPS/443),而且狀況檢查可確保只有狀況良好的 VM 才會接收流量。

若要提供維護頁面,請在負載平衡器上新增第二個監聽器。與應用程式監聽器不同,這不會將要求轉送至應用程式伺服器。而是它的後端集會指向 OCI API Gateway 執行處理,該執行處理負責代管靜態錯誤頁面。此區隔可確保即使所有應用程式伺服器都停止運作,負載平衡器仍可透過高可用性 API 閘道,呈現品牌且資訊豐富的維護頁面。您可以選擇是否建立次要監聽器和 API 閘道步驟:維護頁面可以在網際網路上的任何位置代管。

這兩個監聽器之間的交接是透過規則集來管理。規則集會附加至應用程式監聽器,並定義應重新導向流量的條件。在一般情況下,監聽器會直接將流量傳送至應用程式伺服器。不過,當應用程式伺服器的狀況檢查失敗時,規則集就會開始運作。它會告知負載平衡器將流量重新導向至維護監聽器,進而提供 API 閘道中代管的自訂頁面。

下列步驟描述如何建立用於將使用者重新導向至維護頁面的規則集。

  1. 在 OCI 主控台中,依序選取網路負載平衡器,然後選取您的負載平衡器。
  2. 選取規則集,然後選取建立規則集。使用下列值:
    • 名稱:(提供規則集名稱)
    • URL 重新導向規則
      • 條件:選取路徑 PREFIX_MATCH,然後將值設為 /。這將會比對到達負載平衡器的所有要求。
      • 動作:在 URL 重新導向規則下,選取重新導向
    • 通訊協定:選取 https (或 http)
    • 主機:輸入重新導向目標的 URL
    • 路徑:設為 /
    • 回應代碼307- temporary redirect

關於警示

「警報」可作為偵測與行動之間的橋樑。

OCI Monitoring 偵聽部署元件的運行狀況指標,包括負載平衡器,包括後端 VM 集的狀態。當您在 OCI 警示中設定的警示條件符合時 (例如,所有監控的 VM 都狀況不良超過 1 分鐘),它會立即觸發通知。此通知不僅適用於人力管理員。您可以透過 OCI Notifications 進行路由,以呼叫使用 OCI Functions 部署的自訂函數。該功能可用來變更負載平衡器組態,以顯示自訂錯誤頁面。

傳送給函數的通知訊息包含維度 - 索引鍵 - 值組,描述度量事件所屬的資源和一組 VM。

在警示組態的主體中,您會包含下列程式碼:

{{dimensions.resourceId}},{{dimensions.backendSetName}},<name of the ruleset>

此表格描述此警示主體的元件:

Element 描述 目的
{{dimensions.resourceId}} 產生此度量事件之負載平衡器資源的 OCID 此函數會使用此 OCID 來識別需要更新規則集的負載平衡器
{{dimensions.backendSetName}} 狀況不良的後端集名稱 此函數可以驗證或記錄哪些後端集失敗;對於具有多個後端集的動態環境非常有用
<name of the ruleset> 靜態值 (字串) — 所有後端狀況不良時要附加的規則集名稱 讓函數知道觸發時要套用的規則集

此設計可讓您重複使用相同的功能來處理工作,例如設定負載平衡器以顯示伺服器維護頁面,以及在還原服務後將流量遞送回真實應用程式。您也可以使用此方法來管理 OCI 部署中負載平衡器上的所有負載平衡器或應用程式。

OCI 負載平衡器服務會在命名空間 oci_lbaas 中自動發布稱為 Unhealthybackendserver 的測量結果。它會追蹤每個後端集中狀況不良的後端數目。

就此解決方案而言,此指標中的重要項目如下:

  • 描述
  • 尺寸
  • Triger 規則
  • 訊息群組

在本解決方案中,當所有後端伺服器 (VM) 狀況不良時,應觸發警示。這表示不正常的伺服器數目應大於或等於組中的後端伺服器總數。

以下是「警示觸發程式規則」查詢範例:

UnHealthyBackendServers[1m]{lbName = <name of lb>, backendSetName = <name of the backend set>}.max() >= 1

查詢轉譯為下列項目:

  • 如果狀況不良後端的數目上限大於或等於特定的值 (在此範例中為 1)
  • 定義的期間為 1 分鐘。
  • 然後警示會轉變為 FIRING 狀態。

不過,只有在訊息分組下啟用分割通知時,此動態植入值才有效。分割通知會強制 OCI 為每個維度值傳送一個通知,而不是將所有項目分組在一起。因此,到達您自訂函數的警示通知會包含完全相同的負載平衡器 OCID,以及發生失敗的確切後端集名稱。因此,在多個負載平衡器、後端集或環境之間,相同的函數會完全重複使用,而無須進行硬式編碼負載平衡器詳細資訊。

此組態可讓整個自動化鏈運作 - 警示會發布動態相關資訊環境,函數會讀取它,並在提供應用程式給一般使用者的確切監聽器上執行正確的規則集附件。

設定警示與通知

執行下列步驟以設定此解決方案的警示與通知。

  1. 在 OCI 主控台中,瀏覽至:可觀測性與管理,選取監控,然後選取警訊狀態
  2. 選取建立警示。在警示名稱欄位中,建立警示的名稱。
  3. 輸入「測量結果」的值:
    • 區間:< 選取負載平衡器所在的區間 >
    • 測量結果命名空間oci_lbaas
    • 測量結果名稱:< 選取 UnhealthyBackendServers>
    • 間隔:< 輪詢間隔的頻率 >
    • 統計Max
    • 公制維度
      • 維度名稱:< 選取負載平衡器名稱 >
      • 維度值:< 選取後端集的名稱 >
  4. 建立具有下列值的觸發程式規則
    • 運算子:≥ (大號或等號)
    • :< 後端集中的後端伺服器總數 >
    • 觸發延遲分鐘數:在最短時間內觸發警示前 < 時間延遲 >
  5. 設定嚴重度設為想要的警示嚴重度。
  6. 設定警示主體{{dimensions.resourceId}},{{dimensions.backendSetName}},<ruleset name>
  7. 以下列值定義警示通知:
    • 目的地服務notification
    • 區間:選取包含服務的區間
    • 主題:< 通知主題名稱 >
    • 訊息分組Split notifications per metric stream
    • 訊息格式Send formatted messages
建立新的鬧鐘後,請在主控台中開啟 。@ info:whatsthis

建立函數

自動化的核心是函數,每當警示偵測到所有應用程式後端都狀況不良時,就會觸發此函數。

此函數的角色簡單但功能強大:它會連附或取消連附處理流量重新導向的規則集,以動態更新負載平衡器組態。

函數內部的 Python 程式碼遵循三個邏輯步驟:

  • 使用 OCI 認證:此函數會從使用資源主體與 OCI 建立安全階段作業開始 (這是 OCI 中的函數如何能夠呼叫其他 OCI 服務,而不需要手動管理金鑰)。這樣可確保程式碼能安全地與負載平衡器服務互動。如需有關驗證的詳細資訊,請參閱「瀏覽更多」中的連結。
  • 用於修改負載平衡器監聽器的 API 呼叫:驗證後,程式碼便會呼叫負載平衡器 API。
    • 如果後端失敗,此函數會將重新導向規則集附加至應用程式監聽器,並將使用者重新導向至自訂錯誤頁面。
    • 如果後端復原,此函數會切離規則集,並將一般流量回復至應用程式伺服器。
  • 記錄日誌與驗證:程式碼也包含簡單的記錄日誌,讓管理員能夠追蹤採取的動作:例如,將附加的維護頁面規則設為 listener-1 。這在疑難排解或審核期間會變得非常有用。

使用下列範例 Python 程式碼在 Oracle Functions 中建立函數,視需要進行修改。

Function.py

import io
import json
import os
import oci
from fdk import response
import logging

def handler(ctx, data: io.BytesIO=None):
    message = "start of function"
    logging.getLogger().info("HTTP function start")
    try:
        payload_bytes = data.getvalue()
        if payload_bytes == b'':
            raise KeyError('No keys in payload')
        body1 = json.loads(payload_bytes)
        type1 = body1["type"]
        query = body1["body"]
        load_balancer_ocid = query.split(",")[0]
        maintenance = query.split(",")[2]
        signer = oci.auth.signers.get_resource_principals_signer()
        load_balancer_client = oci.load_balancer.LoadBalancerClient(config={}, signer=signer)
        load_balancer_client_composite_ops = oci.load_balancer.LoadBalancerClientCompositeOperations(load_balancer_client)
        load_balancer_data = json.loads(str(load_balancer_client.get_load_balancer(load_balancer_ocid).data))
        lb_config = load_balancer_data['listeners']
        list1 = json.dumps(lb_config)
        for key,value in json.loads(list1).items():
            if value['default_backend_set_name'] == query.split(",")[1]:
                f_list = key
                rulesets = value['rule_set_names']
                if type1=="OK_TO_FIRING":
                    message = "FIRE"
                    if maintenance in rulesets:
                        message = "Already in Maintenance Mode"
                        logging.getLogger().info("Already in Manintenance mode")
                    else:
                        rulesets.insert(0, maintenance)
                        message = "Entering Maintenance Mode"
                        logging.getLogger().info("Entering Main mode")
                        load_balancer_client_composite_ops.update_listener_and_wait_for_state(
                            oci.load_balancer.models.UpdateListenerDetails(
                                default_backend_set_name=value["default_backend_set_name"],
                                rule_set_names=rulesets,
                                port=value["port"],
                                protocol=value["protocol"],
                                ssl_configuration=value["ssl_configuration"]
                            ),
                            load_balancer_ocid,
                            key,
                            wait_for_states=[oci.load_balancer.models.WorkRequest.LIFECYCLE_STATE_SUCCEEDED]
                        )
                elif type1=="FIRING_TO_OK":
                    message = "OK"
                    if maintenance in rulesets:
                        message = "Entering Operation Mode"
                        logging.getLogger().info("Entering Operation Mode")
                        rulesets.remove(maintenance)
                        load_balancer_client_composite_ops.update_listener_and_wait_for_state(
                            oci.load_balancer.models.UpdateListenerDetails(
                                default_backend_set_name=value["default_backend_set_name"],
                                rule_set_names=rulesets,
                                port=value["port"],
                                protocol=value["protocol"],
                                ssl_configuration=value["ssl_configuration"]
                            ),
                            load_balancer_ocid,
                            key,
                            wait_for_states=[oci.load_balancer.models.WorkRequest.LIFECYCLE_STATE_SUCCEEDED]
                        )   

                    else:
                        message = "Already in operation Mode"
                        logging.getLogger().info("Already in Operation mode")


    except (Exception) as ex:
       message = "Error:" + str(ex)

    return message

設定 OCI API Gateway

在本解決方案中, OCI API Gateway 設定為直接服務靜態網頁。

附註:

您可以選擇是否使用 OCI API Gateway :也可以在 OCI 外部代管維護 / 錯誤頁面。

不同於將要求遞送至動態後端 (例如函數或運算實例) 的 OCI API Gateway 一般用途,此方法利用 OCI API Gateway 代管靜態回應的能力。此靜態頁面可作為易記的維護訊息,告知使用者服務因排定的維護或其他問題而暫時無法使用。靜態頁面完全由 OCI API Gateway 管理,無需使用其他基礎架構,例如 Web 伺服器或物件儲存。

當系統偵測到所有後端伺服器狀況不良時,警示觸發的函數會透過設定負載平衡器,將流量重新導向至 OCI API Gateway 執行處理的次要監聽器,確保體驗順暢且容易操作,不會顯示預設的錯誤頁面。

在此範例中,您只著重於使用 OCI API Gateway 設定靜態回應所需的步驟。如需詳細資訊,請參閱 Explore More 中的資源。

  1. 在 OCI 主控台中,導覽至閘道並開啟它、選取部署,然後選取建立部署
  2. 選擇建立新 API
  3. 設定基本資訊
    • 名稱webpage
    • 路徑首碼/
    • 區間:使用與閘道相同的區間

    保留其餘的選項作為預設值。

  4. 設定認證
    您可以使用預設組態。
  5. 設定路由
    • 路徑/{req*} (萬用字元相符)
    • 方法GET
    • 按一下編輯以新增單一後端。
    • 後端類型Stock response
    • 狀態代碼200
    • 主體:< 維護頁面的 HTML 內容 >
    • 標頭名稱content-type
    • 標頭值text/html