Layer 7 Cookbook

介绍

本文档提供了常见的 L7 负载均衡器使用示例。有关 L7 负载均衡的描述,请参阅: Layer 7 负载均衡

为了便于说明,我们假设将使用 OpenStack Client 命令行界面配置 Octavia 的所有功能,后端驱动程序为 Octavia 驱动程序。此外,为了使这些示例简短,我们假设许多非 L7 配置任务(例如部署负载均衡器、监听器、池、成员、健康检查器等)已经完成。每个示例下文都给出了起始条件的描述。

示例

http://www.example.com/ 重定向到 https://www.example.com/

场景描述:

  • 负载均衡器 lb1 已使用 TERMINATED_HTTPS 监听器 tls_listener 在 TCP 端口 443 上设置。

  • tls_listener 已填充默认池、成员等。

  • tls_listener 在 DNS 名称 https://www.example.com/ 下可用

  • 我们希望将发送到 lb1 TCP 端口 80 的任何常规 HTTP 请求重定向到 tls_listener 的 TCP 端口 443。

解决方案:

  1. lb1 端口 80 上创建 HTTP 监听器 http_listener

  2. http_listener 上设置 L7 策略 policy1,其操作为 REDIRECT_TO_URL,指向 URL https://www.example.com/

  3. policy1 添加一个 L7 规则,该规则匹配所有请求。

CLI 命令:

openstack loadbalancer listener create --name http_listener --protocol HTTP --protocol-port 80 lb1
openstack loadbalancer l7policy create --action REDIRECT_PREFIX --redirect-prefix https://www.example.com/ --name policy1 http_listener
openstack loadbalancer l7rule create --compare-type STARTS_WITH --type PATH --value / policy1

将以 /js 或 /images 开头的请求发送到 static_pool

场景描述:

  • 负载均衡器 lb1 上的监听器 listener1 设置为将其所有请求发送到其默认池 pool1

  • 我们正在引入静态内容服务器 10.0.0.10 和 10.0.0.11 在子网 private-subnet 上,并且希望任何 URL 以“/js”或“/images”开头的 HTTP 请求都发送到这两台服务器,而不是 pool1

解决方案:

  1. lb1 上创建池 static_pool

  2. 使用新的后端成员填充 static_pool

  3. 创建 L7 策略 policy1,其操作为 REDIRECT_TO_POOL,指向 static_pool

  4. policy1 上创建一个 L7 规则,该规则查找请求路径开头的“/js”。

  5. 创建 L7 策略 policy2,其操作为 REDIRECT_TO_POOL,指向 static_pool

  6. policy2 上创建一个 L7 规则,该规则查找请求路径开头的“/images”。

CLI 命令:

openstack loadbalancer pool create --lb-algorithm ROUND_ROBIN --loadbalancer lb1 --name static_pool --protocol HTTP
openstack loadbalancer member create --address 10.0.0.10 --protocol-port 80 --subnet-id private-subnet static_pool
openstack loadbalancer member create --address 10.0.0.11 --protocol-port 80 --subnet-id private-subnet static_pool
openstack loadbalancer l7policy create --action REDIRECT_TO_POOL --redirect-pool static_pool --name policy1 listener1
openstack loadbalancer l7rule create --compare-type STARTS_WITH --type PATH --value /js policy1
openstack loadbalancer l7policy create --action REDIRECT_TO_POOL --redirect-pool static_pool --name policy2 listener1
openstack loadbalancer l7rule create --compare-type STARTS_WITH --type PATH --value /images policy2

替代方案(使用正则表达式)

  1. lb1 上创建池 static_pool

  2. 使用新的后端成员填充 static_pool

  3. 创建 L7 策略 policy1,其操作为 REDIRECT_TO_POOL,指向 static_pool

  4. policy1 上创建一个 L7 规则,该规则使用正则表达式匹配请求路径开头的“/js”或“/images”。

CLI 命令:

openstack loadbalancer pool create --lb-algorithm ROUND_ROBIN --loadbalancer lb1 --name static_pool --protocol HTTP
openstack loadbalancer member create --address 10.0.0.10 --protocol-port 80 --subnet-id private-subnet static_pool
openstack loadbalancer member create --address 10.0.0.11 --protocol-port 80 --subnet-id private-subnet static_pool
openstack loadbalancer l7policy create --action REDIRECT_TO_POOL --redirect-pool static_pool --name policy1 listener1
openstack loadbalancer l7rule create --compare-type REGEX --type PATH --value '^/(js|images)' policy1

将对 http://www2.example.com/ 的请求发送到 pool2

场景描述:

  • 负载均衡器 lb1 上的监听器 listener1 设置为将其所有请求发送到其默认池 pool1

  • 我们已在 lb1 上设置了一个新的池 pool2,并且希望使用 HTTP/1.1 主机名 www2.example.com 的任何请求都发送到 pool2

解决方案:

  1. 创建 L7 策略 policy1,其操作为 REDIRECT_TO_POOL,指向 pool2

  2. policy1 上创建一个 L7 规则,该规则匹配主机名 www2.example.com

CLI 命令:

openstack loadbalancer l7policy create --action REDIRECT_TO_POOL --redirect-pool pool2 --name policy1 listener1
openstack loadbalancer l7rule create --compare-type EQUAL_TO --type HOST_NAME --value www2.example.com policy1

将对 *.example.com 的请求发送到 pool2

场景描述:

  • 负载均衡器 lb1 上的监听器 listener1 设置为将其所有请求发送到其默认池 pool1

  • 我们已在 lb1 上设置了一个新的池 pool2,并且希望使用任何 HTTP/1.1 主机名(如 *.example.com)的任何请求都发送到 pool2

解决方案:

  1. 创建 L7 策略 policy1,其操作为 REDIRECT_TO_POOL,指向 pool2

  2. policy1 上创建一个 L7 规则,该规则匹配以 example.com 结尾的任何主机名。

CLI 命令:

openstack loadbalancer l7policy create --action REDIRECT_TO_POOL --redirect-pool pool2 --name policy1 listener1
openstack loadbalancer l7rule create --compare-type ENDS_WITH --type HOST_NAME --value example.com policy1

将未经验证的用户发送到 login_pool(场景 1)

场景描述:

  • TERMINATED_HTTPS 监听器 listener1 在负载均衡器 lb1 上设置,将其所有请求发送到其默认池 pool1

  • 站点背后 listener1 需要所有 Web 用户进行身份验证,之后浏览器 cookie auth_token 将被设置。

  • 当 Web 用户注销时,或者如果 auth_token 无效时,pool1 中的应用程序服务器会清除 auth_token

  • 我们希望引入一个新的安全身份验证服务器 10.0.1.10 在 Neutron 子网 secure_subnet 上(与默认应用程序服务器不同的 Neutron 子网),该服务器负责验证 Web 用户并设置 auth_token

注意: 显然,为了拥有一个更安全的身份验证系统,该系统不易受到 XSS 等攻击,新的安全身份验证服务器需要设置会话变量,默认池服务器可以在 Web 客户端的数据路径之外访问这些变量。可能还有其他安全问题。此示例并非旨在解决如何完成这些操作,而是主要用于展示如何基于浏览器 cookie 进行 L7 应用程序路由。

解决方案:

  1. lb1 上创建池 login_pool

  2. secure_subnet 上的成员 10.0.1.10 添加到 login_pool

  3. 创建 L7 策略 policy1,其操作为 REDIRECT_TO_POOL,指向 login_pool

  4. policy1 上创建一个 L7 规则,该规则查找浏览器 cookie auth_token(具有任何值),如果它不存在,则匹配。

CLI 命令:

openstack loadbalancer pool create --lb-algorithm ROUND_ROBIN --loadbalancer lb1 --name login_pool --protocol HTTP
openstack loadbalancer member create --address 10.0.1.10 --protocol-port 80 --subnet-id secure_subnet login_pool
openstack loadbalancer l7policy create --action REDIRECT_TO_POOL --redirect-pool login_pool --name policy1 listener1
openstack loadbalancer l7rule create --compare-type REGEX --key auth_token --type COOKIE --value '.*' --invert policy1

将未经验证的用户发送到 login_pool(场景 2)

场景描述:

  • TERMINATED_HTTPS 监听器 listener1 在负载均衡器 lb1 上设置,将其所有请求发送到其默认池 pool1

  • 站点背后 listener1 需要所有 Web 用户进行身份验证,之后浏览器 cookie auth_token 将被设置。

  • 当 Web 用户注销时,或者如果 auth_token 无效时,pool1 中的应用程序服务器会将 auth_token 设置为文字字符串“INVALID”。

  • 我们希望引入一个新的安全身份验证服务器 10.0.1.10 在 Neutron 子网 secure_subnet 上(与默认应用程序服务器不同的 Neutron 子网),该服务器负责验证 Web 用户并设置 auth_token

注意: 显然,为了拥有一个更安全的身份验证系统,该系统不易受到 XSS 等攻击,新的安全身份验证服务器需要设置会话变量,默认池服务器可以在 Web 客户端的数据路径之外访问这些变量。可能还有其他安全问题。此示例并非旨在解决如何完成这些操作,而是主要用于展示如何基于浏览器 cookie 进行 L7 应用程序路由。

解决方案:

  1. lb1 上创建池 login_pool

  2. secure_subnet 上的成员 10.0.1.10 添加到 login_pool

  3. 创建 L7 策略 policy1,其操作为 REDIRECT_TO_POOL,指向 login_pool

  4. policy1 上创建一个 L7 规则,该规则查找浏览器 cookie auth_token(具有任何值),如果它不存在,则匹配。

  5. 创建 L7 策略 policy2,其操作为 REDIRECT_TO_POOL,指向 login_pool

  6. policy2 上创建一个 L7 规则,该规则查找浏览器 cookie auth_token,如果它等于文字字符串“INVALID”,则匹配。

CLI 命令:

openstack loadbalancer pool create --lb-algorithm ROUND_ROBIN --loadbalancer lb1 --name login_pool --protocol HTTP
openstack loadbalancer member create --address 10.0.1.10 --protocol-port 80 --subnet-id secure_subnet login_pool
openstack loadbalancer l7policy create --action REDIRECT_TO_POOL --redirect-pool login_pool --name policy1 listener1
openstack loadbalancer l7rule create --compare-type REGEX --key auth_token --type COOKIE --value '.*' --invert policy1
openstack loadbalancer l7policy create --action REDIRECT_TO_POOL --redirect-pool login_pool --name policy2 listener1
openstack loadbalancer l7rule create --compare-type EQUAL_TO --key auth_token --type COOKIE --value INVALID policy2

将对 http://api.example.com/api 的请求发送到 api_pool

场景描述:

  • 负载均衡器 lb1 上的监听器 listener1 设置为将其所有请求发送到其默认池 pool1

  • 我们已在 lb1 上创建了池 api_pool,但是,由于遗留业务逻辑原因,我们只想在主机名匹配 api.example.com 并且请求路径以 /api 开头时才将请求发送到此池。

解决方案:

  1. 创建 L7 策略 policy1,其操作为 REDIRECT_TO_POOL,指向 api_pool

  2. policy1 上创建一个 L7 规则,该规则匹配主机名 api.example.com

  3. policy1 上创建一个 L7 规则,该规则匹配请求路径开头的 /api。(此规则将与前一个规则逻辑 AND 运算。)

CLI 命令:

openstack loadbalancer l7policy create --action REDIRECT_TO_POOL --redirect-pool api_pool --name policy1 listener1
openstack loadbalancer l7rule create --compare-type EQUAL_TO --type HOST_NAME --value api.example.com policy1
openstack loadbalancer l7rule create --compare-type STARTS_WITH --type PATH --value /api policy1

重定向具有无效 TLS 客户端身份验证证书的请求

场景描述:

  • 负载均衡器 lb1 上的监听器 listener1 配置为 OPTIONAL client_authentication。

  • 不提供 TLS 客户端身份验证证书的 Web 客户端应被重定向到注册页面 http://www.example.com/signup

解决方案:

  1. 创建负载均衡器 lb1

  2. 创建类型为 TERMINATED_TLS 的监听器 listner1,具有 client_ca_tls_container_ref 和 client_authentication OPTIONAL

  3. listener1 上创建 L7 策略 policy1,其操作为 REDIRECT_TO_URL,指向 URL http://www.example.com/signup

  4. policy1 添加一个 L7 规则,该规则不匹配 SSL_CONN_HAS_CERT

CLI 命令:

openstack loadbalancer create --name lb1 --vip-subnet-id public-subnet
openstack loadbalancer listener create --name listener1 --protocol TERMINATED_HTTPS --client-authentication OPTIONAL --protocol-port 443 --default-tls-container-ref http://192.0.2.15:9311/v1/secrets/697c2a6d-ffbe-40b8-be5e-7629fd636bca --client-ca-tls-container-ref http://192.0.2.15:9311/v1/secrets/dba60b77-8dad-4171-8a96-f21e1ca5fb46 lb1
openstack loadbalancer l7policy create --action REDIRECT_TO_URL --redirect-url http://www.example.com/signup --name policy1 listener1
openstack loadbalancer l7rule create --type SSL_CONN_HAS_CERT --invert --compare-type EQUAL_TO --value True policy1

将来自财务部门的用户发送到 pool2

场景描述:

  • 财务部门的用户在其专有名称 (DN) 的 OU 字段中具有客户端证书,该字段设置为 finance

  • 只有具有有效的财务部门客户端证书的用户才能访问 pool2。其他用户将被拒绝。

解决方案:

  1. 创建负载均衡器 lb1

  2. 创建类型为 TERMINATED_TLS 的监听器 listner1,具有 client_ca_tls_container_ref 和 client_authentication MANDATORY

  3. 在负载均衡器 lb1 上创建池 pool2

  4. listener1 上创建 L7 策略 policy1,其操作为 REDIRECT_TO_POOL,指向 pool2

  5. policy1 添加一个 L7 规则,该规则匹配 SSL_CONN_HAS_CERT

  6. policy1 添加一个 L7 规则,该规则匹配 SSL_VERIFY_RESULT,其值为 0。

  7. policy1 添加一个类型为 SSL_DN_FIELD 的 L7 规则,该规则查找客户端身份验证专有名称 (DN) 的“OU”字段中的“finance”。

CLI 命令:

openstack loadbalancer create --name lb1 --vip-subnet-id public-subnet
openstack loadbalancer listener create --name listener1 --protocol TERMINATED_HTTPS --client-authentication MANDATORY --protocol-port 443 --default-tls-container-ref http://192.0.2.15:9311/v1/secrets/697c2a6d-ffbe-40b8-be5e-7629fd636bca --client-ca-tls-container-ref http://192.0.2.15:9311/v1/secrets/dba60b77-8dad-4171-8a96-f21e1ca5fb46 lb1
openstack loadbalancer pool create --lb-algorithm ROUND_ROBIN --loadbalancer lb1 --name pool2 --protocol HTTP
openstack loadbalancer l7policy create --action REDIRECT_TO_POOL --redirect-pool pool2 --name policy1 listener1
openstack loadbalancer l7rule create --type SSL_CONN_HAS_CERT --compare-type EQUAL_TO --value True policy1
openstack loadbalancer l7rule create --type SSL_VERIFY_RESULT --compare-type EQUAL_TO --value 0 policy1
openstack loadbalancer l7rule create --type SSL_DN_FIELD --compare-type EQUAL_TO --key OU --value finance policy1