配置

要部署此自动故障转移解决方案,您需要配置负载平衡器、设置预警和通知、创建函数以及配置 OCI API Gateway

下面详细介绍了以下步骤:

  1. 该过程从准备负载平衡器开始,该过程需要设置辅助监听程序和用于控制重定向行为的特定规则集。
  2. 接下来,配置警报和通知以在应用服务器都处于不健康状态时以及健康服务器可用时触发操作。
  3. 然后,您可以使用 OCI Functions 部署招标来启用核心自动化,该功能基于当前预警状态以编程方式控制负载平衡器规则集的附加或分离。
  4. 最后,配置 OCI API Gateway 以托管您的定制静态维护页面。

这些配置中的每个配置在实现无缝、自动故障转移到友好的维护页面方面都发挥着特定的集成作用。

配置负载均衡器

此解决方案的基础在于负载平衡器,该负载平衡器已面向应用并在其后端服务器之间分配流量。这些步骤假定大多数部署先决条件已到位,包括应用程序监听程序(HTTP 或 HTTPS)、配置了运行状况检查的后端集以及通过 Internet 网关进行路由,以便用户可以访问服务。

从负载平衡器上的主监听程序入手,该监听程序配置为处理应用的常规流量。当所有内容都正常运行时,此监听程序会将传入请求路由到 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 Alarms 中配置的预警条件(例如,所有受监视的 VM 不健康超过一分钟)时,它会立即触发通知。此通知不仅适用于人类管理员。您可以通过 OCI Notifications 进行路由,以调用使用 OCI Functions 部署的定制函数。该功能用于更改负载平衡器配置以显示定制错误页。

发送到函数的通知消息包含维 - 键 - 值对,这些维描述度量事件所属的资源和后端 VM 集。

在报警配置的正文中,您将包含以下代码:

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

此表介绍了此报警正文的组件:

元素 说明 用途
{{dimensions.resourceId}} 生成度量事件的负载平衡器资源的 OCID 此函数使用此 OCID 标识哪些负载平衡器需要更新规则集
{{dimensions.backendSetName}} 不健康的后端集的名称 该函数可以验证或记录失败的后端集;对于具有多个后端集的动态环境很有用
<name of the ruleset> 静态值(字符串)- 当所有后端都不健康时要附加的规则集的名称 让函数知道在触发时要应用哪个规则集

此设计允许您重用相同的功能来处理任务,例如配置负载平衡器以显示服务器维护页面,以及在恢复服务后将流量路由回实际应用。此方法还可以应用于跨 OCI 部署管理负载平衡器上的所有负载平衡器或应用。

OCI Load Balancer 服务会在名称空间 oci_lbaas 中自动发布名为 Unhealthybackendserver 的度量。它跟踪每个后端集中的不健康后端数。

对于此解决方案,此度量中的重要项包括:

  • 说明
  • 尺寸
  • 触发器规则
  • 消息分组

在此解决方案中,当所有后端服务器 (VM) 变得不健康时,应触发预警。这意味着不健康的服务器计数应大于或等于集中的后端服务器总数。

以下是预警触发规则查询示例:

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

查询将转换为以下内容:

  • 如果不健康后端的最大数量大于或等于特定值(在本例中为 1)
  • 在定义的 1 分钟期间内。
  • 然后,警报将转换为 FIRING 状态。

但是,仅当在消息分组下启用了拆分通知时,此动态填充值才起作用。拆分通知将强制 OCI 为每个维值发送一个通知,而不是将所有内容分组在一起。因此,到达定制功能的预警通知包含确切的负载平衡器 OCID 和发生故障的确切后端集名称。因此,同一功能将在多个负载平衡器、后端集或环境中完全可重用,而无需对负载平衡器详细信息进行硬编码。

此配置允许整个自动化链工作 - 报警发布动态上下文,函数读取动态上下文,并在向最终用户提供应用程序的确切监听程序上执行正确的规则集附件。

配置预警和通知

执行以下步骤可配置此解决方案的预警和通知。

  1. 在 OCI 控制台中,导航到: Observability & Management ,选择监视,然后选择预警状态
  2. 选择 Create Alarm 。在预警名称字段中,为预警创建名称。
  3. 度量输入值:
    • 区间:< 选择负载平衡器所在的区间 >
    • 度量名称空间oci_lbaas
    • 度量名称:< 选择 UnhealthyBackendServers>
    • 间隔:< 轮询间隔的频率 >
    • 统计信息Max
    • Metric Dimensions(度量维)
      • 维名称:< 选择负载平衡器名称 >
      • 维值:<select the name of the backend set>
  4. 创建包含以下值的触发规则
    • 运算符:≥(大于或等于符号)
    • :< 后端集中的后端服务器总数 >
    • 触发延迟分钟数:< 触发预警之前的时间延迟(分钟)>
  5. 设置严重性设置为警报的所需严重性。
  6. 设置 Alarm Body{{dimensions.resourceId}},{{dimensions.backendSetName}},<ruleset name>
  7. 使用以下值定义预警通知:
    • 目标服务notification
    • 区间:选择包含服务的区间
    • 主题:通知 > 的主题名称
    • 消息分组Split notifications per metric stream
    • 消息格式Send formatted messages
创建新警报后,在控制台中启用它。

创建函数

自动化核心在于一个功能,每当警报检测到所有应用程序后端都不健康时就会触发该功能。

该函数的作用很简单但功能强大:它通过附加或分离处理流量重定向的规则集来动态更新负载平衡器配置。

函数中的 Python 代码遵循三个逻辑步骤:

  • 使用 OCI 进行身份验证:该功能首先使用资源主用户与 OCI 建立安全会话(这是允许 OCI 中的函数在不手动管理密钥的情况下调用其他 OCI 服务的方式)。这可确保代码可以安全地与负载平衡器服务交互。有关验证的更多信息,请参阅“浏览更多”中的链接。
  • 用于修改负载平衡器监听程序的 API 调用:通过验证后,代码将调用负载平衡器 API。
    • 如果后端失败,该函数将重定向规则集附加到应用程序监听程序,将用户重定向到定制错误页。
    • 如果后端恢复,该函数将分离规则集,将正常流量恢复到应用服务器。
  • 日志记录和验证:代码还包括简单的日志记录,以便管理员可以跟踪执行了什么操作:例如 "Attached Maintenance-Page rule set to 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 网关

在此解决方案中,将 OCI API Gateway 配置为直接提供静态 Web 页。

注意:

使用 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. Configure Authentication
    您可以使用默认配置。
  5. 配置路由
    • 路径/{req*}(通配符匹配项)
    • 方法GET
    • 单击 Edit(编辑)以添加单个后端。
    • 后端类型Stock response
    • 状态代码200
    • 正文:< 维护页面的 HTML 内容 >
    • 标头名称content-type
    • 标题值text/html