231d1bce40
Change-Id: I6541d0b396bfc47ac8d13bcd24f5b8e3c20708c7
357 lines
16 KiB
ReStructuredText
357 lines
16 KiB
ReStructuredText
..
|
|
Copyright (c) 2016 IBM
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
not use this file except in compliance with the License. You may obtain
|
|
a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
License for the specific language governing permissions and limitations
|
|
under the License.
|
|
|
|
================
|
|
Layer 7 Cookbook
|
|
================
|
|
|
|
Introduction
|
|
============
|
|
This document gives several examples of common L7 load balancer usage. For a
|
|
description of L7 load balancing see: :doc:`l7`
|
|
|
|
For the purposes of this guide we assume that the neutron command-line
|
|
interface is going to be used to configure all features of Neutron LBaaS with
|
|
an Octavia back-end. Also, in order to keep these examples short, we assume
|
|
that many non-L7 configuration tasks (such as deploying loadbalancers,
|
|
listeners, pools, members, healthmonitors, etc.) have already been
|
|
accomplished. A description of the starting conditions is given in each example
|
|
below.
|
|
|
|
|
|
Examples
|
|
========
|
|
|
|
.. _redirect-http-to-https:
|
|
|
|
Redirect http://www.example.com/ to https://www.example.com/
|
|
------------------------------------------------------------
|
|
**Scenario description**:
|
|
|
|
* Load balancer *lb1* has been set up with ``TERMINATED_HTTPS`` listener
|
|
*tls_listener* on TCP port 443.
|
|
* *tls_listener* has been populated with a default pool, members, etc.
|
|
* *tls_listener* is available under the DNS name *https://www.example.com/*
|
|
* We want any regular HTTP requests to TCP port 80 on *lb1* to be redirected
|
|
to *tls_listener* on TCP port 443.
|
|
|
|
**Solution**:
|
|
|
|
1. Create listener *http_listener* as an HTTP listener on *lb1* port 80.
|
|
2. Set up an L7 Policy *policy1* on *http_listener* with action
|
|
``REDIRECT_TO_URL`` pointed at the URL *https://www.example.com/*
|
|
3. Add an L7 Rule to *policy1* which matches all requests.
|
|
|
|
|
|
**CLI commands**:
|
|
|
|
::
|
|
|
|
neutron lbaas-listener-create --name http_listener --loadbalancer lb1 --protocol HTTP --protocol-port 80
|
|
neutron lbaas-l7policy-create --action REDIRECT_TO_URL --redirect-url https://www.example.com/ --listener http_listener --name policy1
|
|
neutron lbaas-l7rule-create --type PATH --compare-type STARTS_WITH --value / policy1
|
|
|
|
|
|
.. _send-requests-to-static-pool:
|
|
|
|
Send requests starting with /js or /images to *static_pool*
|
|
-----------------------------------------------------------
|
|
**Scenario description**:
|
|
|
|
* Listener *listener1* on load balancer *lb1* is set up to send all requests to
|
|
its default_pool *pool1*.
|
|
* We are introducing static content servers 10.0.0.10 and 10.0.0.11 on subnet
|
|
*private-subnet*, and want any HTTP requests with a URL that starts with
|
|
either "/js" or "/images" to be sent to those two servers instead of *pool1*.
|
|
|
|
**Solution**:
|
|
|
|
1. Create pool *static_pool* on *lb1*.
|
|
2. Populate *static_pool* with the new back-end members.
|
|
3. Create L7 Policy *policy1* with action ``REDIRECT_TO_POOL`` pointed at
|
|
*static_pool*.
|
|
4. Create an L7 Rule on *policy1* which looks for "/js" at the start of
|
|
the request path.
|
|
5. Create L7 Policy *policy2* with action ``REDIRECT_TO_POOL`` pointed at
|
|
*static_pool*.
|
|
6. Create an L7 Rule on *policy2* which looks for "/images" at the start
|
|
of the request path.
|
|
|
|
**CLI commands**:
|
|
|
|
::
|
|
|
|
neutron lbaas-pool-create --name static_pool --lb-algorithm ROUND_ROBIN --loadbalancer lb1 --protocol HTTP
|
|
neutron lbaas-member-create --subnet private-subnet --address 10.0.0.10 --protocol-port 80 static_pool
|
|
neutron lbaas-member-create --subnet private-subnet --address 10.0.0.11 --protocol-port 80 static_pool
|
|
neutron lbaas-l7policy-create --action REDIRECT_TO_POOL --redirect-pool static_pool --listener listener1 --name policy1
|
|
neutron lbaas-l7rule-create --type PATH --compare-type STARTS_WITH --value /js policy1
|
|
neutron lbaas-l7policy-create --action REDIRECT_TO_POOL --redirect-pool static_pool --listener listener1 --name policy2
|
|
neutron lbaas-l7rule-create --type PATH --compare-type STARTS_WITH --value /images policy2
|
|
|
|
**Alternate solution** (using regular expressions):
|
|
|
|
1. Create pool *static_pool* on *lb1*.
|
|
2. Populate *static_pool* with the new back-end members.
|
|
3. Create L7 Policy *policy1* with action ``REDIRECT_TO_POOL`` pointed at
|
|
*static_pool*.
|
|
4. Create an L7 Rule on *policy1* which uses a regular expression to match
|
|
either "/js" or "/images" at the start of the request path.
|
|
|
|
**CLI commands**:
|
|
|
|
::
|
|
|
|
neutron lbaas-pool-create --name static_pool --lb-algorithm ROUND_ROBIN --loadbalancer lb1 --protocol HTTP
|
|
neutron lbaas-member-create --subnet private-subnet --address 10.0.0.10 --protocol-port 80 static_pool
|
|
neutron lbaas-member-create --subnet private-subnet --address 10.0.0.11 --protocol-port 80 static_pool
|
|
neutron lbaas-l7policy-create --action REDIRECT_TO_POOL --redirect-pool static_pool --listener listener1 --name policy1
|
|
neutron lbaas-l7rule-create --type PATH --compare-type REGEX --value '^/(js|images)' policy1
|
|
|
|
|
|
Send requests for http://www2.example.com/ to *pool2*
|
|
-----------------------------------------------------
|
|
**Scenario description**:
|
|
|
|
* Listener *listener1* on load balancer *lb1* is set up to send all requests to
|
|
its default_pool *pool1*.
|
|
* We have set up a new pool *pool2* on *lb1* and want any requests using the
|
|
HTTP/1.1 hostname *www2.example.com* to be sent to *pool2* instead.
|
|
|
|
**Solution**:
|
|
|
|
1. Create L7 Policy *policy1* with action ``REDIRECT_TO_POOL`` pointed at
|
|
*pool2*.
|
|
2. Create an L7 Rule on *policy1* which matches the hostname
|
|
*www2.example.com*.
|
|
|
|
**CLI commands**:
|
|
|
|
::
|
|
|
|
neutron lbaas-l7policy-create --action REDIRECT_TO_POOL --redirect-pool pool2 --listener listener1 --name policy1
|
|
neutron lbaas-l7rule-create --type HOST_NAME --compare-type EQUAL_TO --value www2.example.com policy1
|
|
|
|
|
|
Send requests for *\*.example.com* to *pool2*
|
|
---------------------------------------------
|
|
**Scenario description**:
|
|
|
|
* Listener *listener1* on load balancer *lb1* is set up to send all requests to
|
|
its default_pool *pool1*.
|
|
* We have set up a new pool *pool2* on *lb1* and want any requests using any
|
|
HTTP/1.1 hostname like *\*.example.com* to be sent to *pool2* instead.
|
|
|
|
**Solution**:
|
|
|
|
1. Create L7 Policy *policy1* with action ``REDIRECT_TO_POOL`` pointed at
|
|
*pool2*.
|
|
2. Create an L7 Rule on *policy1* which matches any hostname that ends with
|
|
*example.com*.
|
|
|
|
**CLI commands**:
|
|
|
|
::
|
|
|
|
neutron lbaas-l7policy-create --action REDIRECT_TO_POOL --redirect-pool pool2 --listener listener1 --name policy1
|
|
neutron lbaas-l7rule-create --type HOST_NAME --compare-type ENDS_WITH --value example.com policy1
|
|
|
|
|
|
Send unauthenticated users to *login_pool* (scenario 1)
|
|
-------------------------------------------------------
|
|
**Scenario description**:
|
|
|
|
* ``TERMINATED_HTTPS`` listener *listener1* on load balancer *lb1* is set up
|
|
to send all requests to its default_pool *pool1*.
|
|
* The site behind *listener1* requires all web users to authenticate, after
|
|
which a browser cookie *auth_token* will be set.
|
|
* When web users log out, or if the *auth_token* is invalid, the application
|
|
servers in *pool1* clear the *auth_token*.
|
|
* We want to introduce new secure authentication server 10.0.1.10 on Neutron
|
|
subnet *secure_subnet* (a different Neutron subnet from the default
|
|
application servers) which handles authenticating web users and sets the
|
|
*auth_token*.
|
|
|
|
*Note:* Obviously, to have a more secure authentication system that is less
|
|
vulnerable to attacks like XSS, the new secure authentication server will need
|
|
to set session variables to which the default_pool servers will have access
|
|
outside the data path with the web client. There may be other security concerns
|
|
as well. This example is not meant to address how these are to be
|
|
accomplished--it's mainly meant to show how L7 application routing can be done
|
|
based on a browser cookie.
|
|
|
|
**Solution**:
|
|
|
|
1. Create pool *login_pool* on *lb1*.
|
|
2. Add member 10.0.1.10 on *secure_subnet* to *login_pool*.
|
|
3. Create L7 Policy *policy1* with action ``REDIRECT_TO_POOL`` pointed at
|
|
*login_pool*.
|
|
4. Create an L7 Rule on *policy1* which looks for browser cookie *auth_token*
|
|
(with any value) and matches if it is *NOT* present.
|
|
|
|
**CLI commands**:
|
|
|
|
::
|
|
|
|
neutron lbaas-pool-create --name login_pool --lb-algorithm ROUND_ROBIN --loadbalancer lb1 --protocol HTTP
|
|
neutron lbaas-member-create --subnet secure_subnet --address 10.0.1.10 --protocol-port 80 login_pool
|
|
neutron lbaas-l7policy-create --action REDIRECT_TO_POOL --redirect-pool login_pool --listener listener1 --name policy1
|
|
neutron lbaas-l7rule-create --type COOKIE --key auth_token --compare-type REGEX --value '.*' --invert policy1
|
|
|
|
|
|
Send unauthenticated users to *login_pool* (scenario 2)
|
|
--------------------------------------------------------
|
|
**Scenario description**:
|
|
|
|
* ``TERMINATED_HTTPS`` listener *listener1* on load balancer *lb1* is set up
|
|
to send all requests to its default_pool *pool1*.
|
|
* The site behind *listener1* requires all web users to authenticate, after
|
|
which a browser cookie *auth_token* will be set.
|
|
* When web users log out, or if the *auth_token* is invalid, the application
|
|
servers in *pool1* set *auth_token* to the literal string "INVALID".
|
|
* We want to introduce new secure authentication server 10.0.1.10 on Neutron
|
|
subnet *secure_subnet* (a different Neutron subnet from the default
|
|
application servers) which handles authenticating web users and sets the
|
|
*auth_token*.
|
|
|
|
*Note:* Obviously, to have a more secure authentication system that is less
|
|
vulnerable to attacks like XSS, the new secure authentication server will need
|
|
to set session variables to which the default_pool servers will have access
|
|
outside the data path with the web client. There may be other security concerns
|
|
as well. This example is not meant to address how these are to be
|
|
accomplished-- it's mainly meant to show how L7 application routing can be done
|
|
based on a browser cookie.
|
|
|
|
**Solution**:
|
|
|
|
1. Create pool *login_pool* on *lb1*.
|
|
2. Add member 10.0.1.10 on *secure_subnet* to *login_pool*.
|
|
3. Create L7 Policy *policy1* with action ``REDIRECT_TO_POOL`` pointed at
|
|
*login_pool*.
|
|
4. Create an L7 Rule on *policy1* which looks for browser cookie *auth_token*
|
|
(with any value) and matches if it is *NOT* present.
|
|
5. Create L7 Policy *policy2* with action ``REDIRECT_TO_POOL`` pointed at
|
|
*login_pool*.
|
|
6. Create an L7 Rule on *policy2* which looks for browser cookie *auth_token*
|
|
and matches if it is equal to the literal string "INVALID".
|
|
|
|
**CLI commands**:
|
|
|
|
::
|
|
|
|
neutron lbaas-pool-create --name login_pool --lb-algorithm ROUND_ROBIN --loadbalancer lb1 --protocol HTTP
|
|
neutron lbaas-member-create --subnet secure_subnet --address 10.0.1.10 --protocol-port 80 login_pool
|
|
neutron lbaas-l7policy-create --action REDIRECT_TO_POOL --redirect-pool login_pool --listener listener1 --name policy1
|
|
neutron lbaas-l7rule-create --type COOKIE --key auth_token --compare-type REGEX --value '.*' --invert policy1
|
|
neutron lbaas-l7policy-create --action REDIRECT_TO_POOL --redirect-pool login_pool --listener listener1 --name policy2
|
|
neutron lbaas-l7rule-create --type COOKIE --key auth_token --compare-type EQUAL_TO --value INVALID policy2
|
|
|
|
|
|
Send requests for *http://api.example.com/api* to *api_pool*
|
|
------------------------------------------------------------
|
|
**Scenario description**:
|
|
|
|
* Listener *listener1* on load balancer *lb1* is set up to send all requests
|
|
to its default_pool *pool1*.
|
|
* We have created pool *api_pool* on *lb1*, however, for legacy business logic
|
|
reasons, we only want requests sent to this pool if they match the hostname
|
|
*api.example.com* AND the request path starts with */api*.
|
|
|
|
**Solution**:
|
|
|
|
1. Create L7 Policy *policy1* with action ``REDIRECT_TO_POOL`` pointed at
|
|
*api_pool*.
|
|
2. Create an L7 Rule on *policy1* which matches the hostname *api.example.com*.
|
|
3. Create an L7 Rule on *policy1* which matches */api* at the start of the
|
|
request path. (This rule will be logically ANDed with the previous rule.)
|
|
|
|
**CLI commands**:
|
|
|
|
::
|
|
|
|
neutron lbaas-l7policy-create --action REDIRECT_TO_POOL --redirect-pool api_pool --listener listener1 --name policy1
|
|
neutron lbaas-l7rule-create --type HOST_NAME --compare-type EQUAL_TO --value api.example.com policy1
|
|
neutron lbaas-l7rule-create --type PATH --compare-type STARTS_WITH --value /api policy1
|
|
|
|
|
|
Set up A/B testing on an existing production site using a cookie
|
|
----------------------------------------------------------------
|
|
**Scenario description**:
|
|
|
|
* Listener *listener1* on load balancer *lb1* is a production site set up as
|
|
described under :ref:`send-requests-to-static-pool` (alternate solution)
|
|
above. Specifically:
|
|
|
|
* HTTP requests with a URL that starts with either "/js" or "/images" are
|
|
sent to pool *static_pool*.
|
|
* All other requests are sent to *listener1's* default_pool *pool1*.
|
|
|
|
* We are introducing a "B" version of the production site, complete with its
|
|
own default_pool and static_pool. We will call these *pool_B* and
|
|
*static_pool_B* respectively.
|
|
* The *pool_B* members should be 10.0.0.50 and 10.0.0.51, and the
|
|
*static_pool_B* members should be 10.0.0.100 and 10.0.0.101 on subnet
|
|
*private-subnet*.
|
|
* Web clients which should be routed to the "B" version of the site get a
|
|
cookie set by the member servers in *pool1*. This cookie is called
|
|
"site_version" and should have the value "B".
|
|
|
|
**Solution**:
|
|
|
|
1. Create pool *pool_B* on *lb1*.
|
|
2. Populate *pool_B* with its new back-end members.
|
|
3. Create pool *static_pool_B* on *lb1*.
|
|
4. Populate *static_pool_B* with its new back-end members.
|
|
5. Create L7 Policy *policy2* with action ``REDIRECT_TO_POOL`` pointed at
|
|
*static_pool_B*. This should be inserted at position 1.
|
|
6. Create an L7 Rule on *policy2* which uses a regular expression to match
|
|
either "/js" or "/images" at the start of the request path.
|
|
7. Create an L7 Rule on *policy2* which matches the cookie "site_version" to
|
|
the exact string "B".
|
|
8. Create L7 Policy *policy3* with action ``REDIRECT_TO_POOL`` pointed at
|
|
*pool_B*. This should be inserted at position 2.
|
|
9. Create an L7 Rule on *policy3* which matches the cookie "site_version" to
|
|
the exact string "B".
|
|
|
|
*A word about L7 Policy position*: Since L7 Policies are evaluated in order
|
|
according to their position parameter, and since the first L7 Policy whose L7
|
|
Rules all evaluate to True is the one whose action is followed, it is important
|
|
that L7 Policies with the most specific rules get evaluated first.
|
|
|
|
For example, in this solution, if *policy3* were to appear in the listener's L7
|
|
Policy list before *policy2* (that is, if *policy3* were to have a lower
|
|
position number than *policy2*), then if a web client were to request the URL
|
|
http://www.example.com/images/a.jpg with the cookie "site_version:B", then
|
|
*policy3* would match, and the load balancer would send the request to
|
|
*pool_B*. From the scenario description, this request clearly was meant to be
|
|
sent to *static_pool_B*, which is why *policy2* needs to be evaluated before
|
|
*policy3*.
|
|
|
|
**CLI commands**:
|
|
|
|
::
|
|
|
|
neutron lbaas-pool-create --name pool_B --lb-algorithm ROUND_ROBIN --loadbalancer lb1 --protocol HTTP
|
|
neutron lbaas-member-create --subnet private-subnet --address 10.0.0.50 --protocol-port 80 pool_B
|
|
neutron lbaas-member-create --subnet private-subnet --address 10.0.0.51 --protocol-port 80 pool_B
|
|
neutron lbaas-pool-create --name static_pool_B --lb-algorithm ROUND_ROBIN --loadbalancer lb1 --protocol HTTP
|
|
neutron lbaas-member-create --subnet private-subnet --address 10.0.0.100 --protocol-port 80 static_pool_B
|
|
neutron lbaas-member-create --subnet private-subnet --address 10.0.0.101 --protocol-port 80 static_pool_B
|
|
neutron lbaas-l7policy-create --action REDIRECT_TO_POOL --redirect-pool static_pool_B --listener listener1 --name policy2 --position 1
|
|
neutron lbaas-l7rule-create --type PATH --compare-type REGEX --value '^/(js|images)' policy2
|
|
neutron lbaas-l7rule-create --type COOKIE --key site_version --compare-type EQUAL_TO --value B policy2
|
|
neutron lbaas-l7policy-create --action REDIRECT_TO_POOL --redirect-pool pool_B --listener listener1 --name policy3 --position 2
|
|
neutron lbaas-l7rule-create --type COOKIE --key site_version --compare-type EQUAL_TO --value B policy3
|