Add L7 user guides
This includes both an overall description of L7 load balancing as implemented in Octavia, as well as a cookbook for common L7 usage. Both of these documents are aimed at end-users. Change-Id: I01c4484e2276257c97cfb6ba02d6224a25cdbc80 Closes-Bug: 1558377
This commit is contained in:
353
doc/source/guides/l7-cookbook.rst
Normal file
353
doc/source/guides/l7-cookbook.rst
Normal file
@@ -0,0 +1,353 @@
|
|||||||
|
..
|
||||||
|
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 puposes 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://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
|
||||||
185
doc/source/guides/l7.rst
Normal file
185
doc/source/guides/l7.rst
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
..
|
||||||
|
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 Load Balancing
|
||||||
|
======================
|
||||||
|
|
||||||
|
What is L7 load balancing?
|
||||||
|
==========================
|
||||||
|
Layer 7 load balancing takes its name from the OSI model, indicating that the
|
||||||
|
load balancer distributes requests to back-end pools based on layer 7
|
||||||
|
(application) data. Layer 7 load balancing is also known as "request
|
||||||
|
switching," "application load balancing," "content based routing," "content
|
||||||
|
based switching," and "content based balancing."
|
||||||
|
|
||||||
|
A layer 7 load balancer consists of a listener that accepts requests on behalf
|
||||||
|
of a number of back-end pools and distributes those requests based on policies
|
||||||
|
that use application data to determine which pools should service any given
|
||||||
|
request. This allows for the application infrastructure to be specifically
|
||||||
|
tuned/optimized to serve specific types of content. For example, one group of
|
||||||
|
back-end servers (pool) can be tuned to serve only images, another for
|
||||||
|
execution of server-side scripting languages like PHP and ASP, and another for
|
||||||
|
static content such as HTML, CSS, and JavaScript.
|
||||||
|
|
||||||
|
Unlike lower-level load balancing, layer 7 load balancing does not require that
|
||||||
|
all pools behind the load balancing service have the same content. In fact, it
|
||||||
|
is generally expected that a layer 7 load balancer expects the back-end servers
|
||||||
|
from different pools will have different content. Layer 7 load balancers are
|
||||||
|
capable of directing requests based on URI, host, HTTP headers, and other data
|
||||||
|
in the application message.
|
||||||
|
|
||||||
|
|
||||||
|
L7 load balancing in Octavia
|
||||||
|
----------------------------
|
||||||
|
The layer 7 load balancing capabilities described in this document were added
|
||||||
|
to Neutron LBaaS and Octavia in the Mitaka release cycle (Octavia 0.8).
|
||||||
|
|
||||||
|
While layer 7 load balancing in general can theoretically be done for any
|
||||||
|
well-defined layer 7 application interface, for the purposes of Octavia, L7
|
||||||
|
functionality refers only to the HTTP protocol and its semantics.
|
||||||
|
|
||||||
|
|
||||||
|
How does it work?
|
||||||
|
=================
|
||||||
|
Neutron LBaaS and Octavia accomplish the logic of layer 7 load balancing
|
||||||
|
through the use of L7 Rules and L7 Policies. An L7 Rule is a single, simple
|
||||||
|
logical test which evaluates to true or false. An L7 Policy is a collection of
|
||||||
|
L7 rules, as well as a defined action that should be taken if all the rules
|
||||||
|
associated with the policy match.
|
||||||
|
|
||||||
|
These concepts and their specific details are expanded upon below.
|
||||||
|
|
||||||
|
|
||||||
|
L7 Rules
|
||||||
|
--------
|
||||||
|
An L7 Rule is a single, simple logical test which returns either true or false.
|
||||||
|
It consists of a rule type, a comparison type, a value, and an optional key
|
||||||
|
that gets used depending on the rule type. An L7 rule must always be associated
|
||||||
|
with an L7 policy.
|
||||||
|
|
||||||
|
See also: :doc:`../api/octaviaapi`
|
||||||
|
|
||||||
|
Rule types
|
||||||
|
__________
|
||||||
|
L7 rules have the following types:
|
||||||
|
|
||||||
|
* ``HOST_NAME``: The rule does a comparison between the HTTP/1.1 hostname in
|
||||||
|
the request against the value parameter in the rule.
|
||||||
|
* ``PATH``: The rule compares the path portion of the HTTP URI against the
|
||||||
|
value parameter in the rule.
|
||||||
|
* ``FILE_TYPE``: The rule compares the last portion of the URI against the
|
||||||
|
value parameter in the rule. (eg. "txt", "jpg", etc.)
|
||||||
|
* ``HEADER``: The rule looks for a header defined in the key parameter and
|
||||||
|
compares it against the value parameter in the rule.
|
||||||
|
* ``COOKIE``: The rule looks for a cookie named by the key parameter and
|
||||||
|
compares it against the value parameter in the rule.
|
||||||
|
|
||||||
|
Comparison types
|
||||||
|
________________
|
||||||
|
L7 rules of a given type always do comparisons. The types of comparisons we
|
||||||
|
support are listed below. Note that not all rule types support all comparison
|
||||||
|
types:
|
||||||
|
|
||||||
|
* ``REGEX``: Perl type regular expression matching
|
||||||
|
* ``STARTS_WITH``: String starts with
|
||||||
|
* ``ENDS_WITH``: String ends with
|
||||||
|
* ``CONTAINS``: String contains
|
||||||
|
* ``EQUAL_TO``: String is equal to
|
||||||
|
|
||||||
|
Invert
|
||||||
|
______
|
||||||
|
In order to more fully express the logic required by some policies, rules may
|
||||||
|
have their result inverted. That is to say, if the invert parameter of a given
|
||||||
|
rule is true, the result of its comparison will be inverted. (For example, an
|
||||||
|
inverted "equal to" rule effectively becomes a "not equal to", and an inverted
|
||||||
|
"regex" rule returns true only if the given regex does not match.)
|
||||||
|
|
||||||
|
|
||||||
|
L7 Policies
|
||||||
|
-----------
|
||||||
|
An L7 Policy is a collection of L7 rules associated with a Listener, and which
|
||||||
|
may also have an association to a back-end pool. Policies describe actions that
|
||||||
|
should be taken by the load balancing software if all of the rules in the
|
||||||
|
policy return true.
|
||||||
|
|
||||||
|
See also: :doc:`../api/octaviaapi`
|
||||||
|
|
||||||
|
Policy Logic
|
||||||
|
____________
|
||||||
|
Policy logic is very simple: All the rules associated with a given policy are
|
||||||
|
logically ANDed together. A request must match all the policy's rules to match
|
||||||
|
the policy.
|
||||||
|
|
||||||
|
If you need to express a logical OR operation between rules, then do this by
|
||||||
|
creating multiple policies with the same action (or, possibly, by making a more
|
||||||
|
elaborate regular expression).
|
||||||
|
|
||||||
|
Policy Actions
|
||||||
|
______________
|
||||||
|
If an L7 policy matches a given request, then that policy's action is executed.
|
||||||
|
The following are the actions an L7 Policy may take:
|
||||||
|
|
||||||
|
* ``REJECT``: The request is denied with an appropriate response code, and not
|
||||||
|
forwarded on to any back-end pool.
|
||||||
|
* ``REDIRECT_TO_URL``: The request is sent an HTTP redirect to the URL defined
|
||||||
|
in the ``redirect_url`` parameter.
|
||||||
|
* ``REDIRECT_TO_POOL``: The request is forwarded to the back-end pool
|
||||||
|
associated with the L7 policy.
|
||||||
|
|
||||||
|
Policy Position
|
||||||
|
_______________
|
||||||
|
When multiple L7 Policies are associated with a listener, then the policies'
|
||||||
|
``position`` parameter becomes important. The ``position`` parameter is used
|
||||||
|
when determining the order in which L7 policies are evaluated. Here are a few
|
||||||
|
notes about how policy position affects listener behavior:
|
||||||
|
|
||||||
|
* In the reference implementation (haproxy amphorae) of Octavia, haproxy
|
||||||
|
enforces the following ordering regarding policy actions:
|
||||||
|
|
||||||
|
* ``REJECT`` policies take precedence over all other policies.
|
||||||
|
* ``REDIRECT_TO_URL`` policies take precedence over ``REDIRECT_TO_POOL``
|
||||||
|
policies.
|
||||||
|
* ``REDIRECT_TO_POOL`` policies are only evaluated after all of the above,
|
||||||
|
and in the order specified by the ``position`` of the policy.
|
||||||
|
|
||||||
|
* L7 Policies are evaluated in a specific order (as defined by the ``position``
|
||||||
|
attribute), and the first policy that matches a given request will be the one
|
||||||
|
whose action is followed.
|
||||||
|
* If no policy matches a given request, then the request is routed to the
|
||||||
|
listener's default pool ,if it exists. If the listener has no default pool,
|
||||||
|
then an error 503 is returned.
|
||||||
|
* Policy position numbering starts with 1.
|
||||||
|
* If a new policy is created with a position that matches that of an existing
|
||||||
|
policy, then the new policy is inserted at the given position.
|
||||||
|
* If a new policy is created without specifying a position, or specifying a
|
||||||
|
position that is greater than the number of policies already in the list, the
|
||||||
|
new policy will just be appended to the list.
|
||||||
|
* When policies are inserted, deleted, or appended to the list, the policy
|
||||||
|
position values are re-ordered from 1 without skipping numbers. For example,
|
||||||
|
if policy A, B, and C have position values of 1, 2 and 3 respectively, if you
|
||||||
|
delete policy B from the list, policy C's position becomes 2.
|
||||||
|
|
||||||
|
|
||||||
|
L7 usage examples
|
||||||
|
=================
|
||||||
|
For a cookbook of common L7 usage examples, please see the :doc:`l7-cookbook`
|
||||||
|
|
||||||
|
|
||||||
|
Useful links
|
||||||
|
============
|
||||||
|
* :doc:`../api/octaviaapi`
|
||||||
|
* https://github.com/openstack/neutron-specs/blob/master/specs/mitaka/lbaas-l7-rules.rst
|
||||||
|
* http://cbonte.github.io/haproxy-dconv/1.6/configuration.html#7
|
||||||
@@ -12,6 +12,15 @@ Getting started
|
|||||||
|
|
||||||
main/glossary.rst
|
main/glossary.rst
|
||||||
|
|
||||||
|
For users
|
||||||
|
---------
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
|
||||||
|
guides/l7.rst
|
||||||
|
guides/l7-cookbook.rst
|
||||||
|
|
||||||
For developers
|
For developers
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user