Jump to: navigation, search

Difference between revisions of "Neutron/LBaaS/l7"

< Neutron‎ | LBaaS
(L7 Switching)
(Massive overhaul of this content reflecting in-review patches)
Line 1: Line 1:
 
== L7 Switching ==
 
== L7 Switching ==
 
=== Background ===
 
=== Background ===
Layer 7 switching takes its name from the OSI model, indicating that the device switches requests based on layer 7 (application) data. Layer 7 switching is also known as "request switching", "application switching", and "content based routing".
+
Layer 7 switching takes its name from the OSI model, indicating that the device
A layer 7 switch presents to the outside world a "virtual server" that accepts requests on behalf of a number of servers and distributes those requests based on policies that use application data to determine which server should service which request. This allows for the application infrastructure to be specifically tuned/optimized to serve specific types of content. For example, one server 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.
+
switches requests based on layer 7 (application) data. Layer 7 switching is
Unlike load balancing, layer 7 switching does not require that all servers in the pool (farm/cluster) have the same content. In fact, layer 7 switching expects that servers will have different content, thus the need to more deeply inspect requests before determining where they should be directed. Layer 7 switches are capable of directing requests based on URI, host, HTTP headers, and anything in the application message.
+
also known as "request switching," "application switching," and "content based
 +
routing."
  
=== API Changes ===
+
A layer 7 switch presents to the outside world a "virtual server" that accepts
 +
requests on behalf of a number of servers and distributes those requests based
 +
on policies that use application data to determine which server or set of
 +
servers 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 server 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 switching does not require that all
 +
servers in the pool (farm/cluster) have the same content. In fact, it is
 +
generally expected that a load balancer configuration using layer 7 switching
 +
expects the back-end servers will have different content. Layer 7 switches are
 +
capable of directing requests based on URI, host, HTTP headers, and anything in
 +
the application message.
 +
 
 +
=== L7 switching in Neutron LBaaS ===
 +
The layer 7 switching capabilities described in this document are slated to be
 +
added to Neutron LBaaS in time for the Liberty release cycle. Note also that
 +
layer 7 switching applies only to the LBaaS v2 API only. Since LBaaS v1 is
 +
being phased out, there are no plans to make L7 switching capability work with
 +
Neutron LBaaS v1.
 +
 
 +
It's also worth nothing that while layer 7 switching can in theory be done for
 +
any well-defined layer 7 application interface, for the purposes of Neutron
 +
LBaaS, L7 functionality refers only to the HTTP protocol and its semantics.
 +
 
 +
It is also anticipated that initially not all load balancer vendors with
 +
Neutron LBaaS drivers will support L7 switching at first. However, we imagine
 +
the L7 switching functionality described in this document should be universal
 +
enough that all load balancer vendors capable of doing L7 functionality at all
 +
should be able to write drivers which work with Neutron LBaaS L7 switching.
 +
 
 +
=== API and logic changes ===
 +
* Pools can be created without necessarily being associated with a Listener
 +
* Pools have a "loose coupling" with Loadbalancers (ie. a pool can be effectively associated with zero or one loadbalancers through L7policies, or Listener default_pool assignments.) Notably, at the present time a given pool may exist within zero or one Loadbalancer trees.
 
* CRUD operations for L7Policy
 
* CRUD operations for L7Policy
 
* CRUD operations for L7Rule
 
* CRUD operations for L7Rule
* CRUD operations for L7VipPolicyAssociation
 
  
 
=== CLI Example ===
 
=== CLI Example ===
* '''neutron --policy policy1 lb-create-l7policy ''' (''Create  l7 policy named 'policy1' '')
+
* '''neutron lbaas-create-pool listener1 .....''' ('' Create listener'')
 
+
* '''neutron lbaas-create-pool pool1 .....''' ('' Create pool'')
* '''neutron lb-create-l7rule rule1 --attribute-type header --attribute-name "myheader" --attribute-value "transaction[1-9]{1,4}" --policy policy1''' (''Create l7 rule named 'rule1' and associate it with the policy 'policy1' '')
+
* '''neutron --policy policy1 lbaas-create-l7policy --name "policy1" --description "My Description" --listener "listener1" --action redirect_to_pool --pool "pool1" --position -1''' (''Create  l7 policy named 'policy1' appended to listener 'listener1' after any already existing l7 policies, with the action of this policy to redirect to pool 'pool1' '')
 
+
* '''neutron lbaas-create-l7rule rule1 --rule-type path --compare-type startswith --value "/api" --policy policy1''' (''Create l7 rule named 'rule1' and associate it with the policy 'policy1' '')
* '''neutron lb-create-l7rule rule2 --attribute-type path  --attribute-value "/shopping/.*" --policy p1''' (''Create l7 rule named 'rule2' and associate it with the policy 'policy1' '')
+
* '''neutron lbaas-create-l7rule rule2 --rule-type header --compare-type equals --key "mycookie" --value "myvalue" --invert --policy policy1''' (''Create l7 rule named 'rule2' and associate it with the policy 'policy1' '')
 
+
 
* '''neutron lb-create-pool pool1 .....''' ('' Create pool'')
+
 
 
+
The above L7 policy and rule creation should now enable the following logic:
* '''neutron lb-create-vip .vip1 ......''' ('' Create vip '')
+
 
 
+
In listener1's configuration, redirect any given request to pool1 IF: The request URI path starts with "/api" AND cookie "mycookie" is NOT equal to "myvalue"
* '''neutron lb-associate-vip-pool  --vip vip1 --pool pool1 --action SELECT-POOL  --l7policy policy1''' ('' Associate the vip and the pool to 'policy1.If policy1 will return True, the traffic of vip1 will be directed to pool1 ' '')
+
 
 +
=== L7 Rules ===
 +
An L7 Rule is a single, simple logical test which returns either true or false.
 +
 
 +
==== Rule types ====
 +
L7 rules have the following types:
 +
 
 +
* '''hostname''': 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 list of comparisons we
 +
support is below. Note that not all rule types support all comparison types:
 +
 
 +
* '''regex''': Perl type regular expression matching
 +
* '''startswith''': String start with
 +
* '''endswith''': String ends with
 +
* '''contains''': String contains
 +
* '''equalto''': String equals
 +
* '''greaterthan''': Integer is greater than
 +
* '''lessthan''': Integer is less than
 +
 
 +
==== 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 Listner, and which
 +
may also have an association to a back-end pool.
 +
 
 +
==== Policy Logic ====
 +
Policy logic is very simple: All the rules associated with a given policy are
 +
logically ANDed together. A request much 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.
  
=== Model ===
+
==== Policy Actions ====
 +
If an L7 policy matches a given request, then that policy's action is executed.
 +
The following are the actions a L7 Policy may take:
  
    class L7Rule {
+
* '''block''': The request is denied with an appropriate response code, and not forwarded on to any back-end pool.
      String l7policyID
+
* '''redirect_to_url''': The request is sent an HTTP redirect to the URL defined in the ''redirect_url'' parameter.
      enum Type [Hostname, Path, File Type, Header, Cookie], // need to decide: enum or string
+
* '''redirect_to_pool''': The request is forwarded to the back-end pool associated with the L7 policy (which is usually not the default pool associated with the listener).
      enum Compare Type [regext],
 
      String Value,
 
      int  position // L7Rules are held by L7Policy as a list, one can set the position of the rule in the list
 
    }
 
    class L7Policy {
 
      String name
 
      collection of L7Rule
 
    }
 
    class L7VipPolicyAssociation { // holds the association between a vip and l7policy
 
      String vipID
 
      String l7policyID
 
      String action // Nedd to decide if we want to have enaum here {REDIRECT_TO_URL,REDIRECT_TO_POOL,REJECT}
 
      String pooID // optional. mandatory if action is REDIRECT_TO_POOL
 
      String url // optional. mandatory if action is REDIRECT_TO_URL
 
    }
 
=== Backend travesing of rules and policies ===
 
The rules and policies are ordered. <br/>
 
Rules are ordered inside under a given Policy. <br/>
 
Policies are ordered under a given Vip. <br/>
 
Policy should return true by doing AND operations between rules <br/>
 
Policies should return true by doing OR operations between policies under the same Vip <br/>
 
===DB Migration===
 
  
=== Implementation Plan ===
+
==== Policy Position ====
* neutron-server change
+
L7 Policies are evaluated in a specific order (as defined by the 'position'
* db models and logic change
+
attribute), and the first policy that matches a given request will be the one
* lbaas plugin change
+
whose action is followed. If no policy matches a given request, then the
* lbaas driver change
+
request is routed to the listener's default pool.
* python-neutronclient
 
* horizon
 
  
=== HAProxy L7 Switching===
+
If a new policy is created with a position that matches that of an existing
HAProxy L7 Switching is based on HAProxy ACL engine.
+
policy, then the new policy is inserted at the given position.
Example 1 (blocking):
 
<br/>
 
# ... some HTTP content smugling and other various things
 
        acl forbidden_hdrs hdr_cnt(host) gt 1
 
        acl forbidden_hdrs hdr_cnt(content-length) gt 1
 
        acl forbidden_hdrs hdr_val(content-length) lt 0
 
        acl forbidden_hdrs hdr_cnt(proxy-authorization) gt 0
 
        block if forbidden_hdrs
 
Example 2 (switching - switch to the pool(backend) named 'www2' if 'host_www2' is true ):
 
      acl host_www2  hdr_beg(host) -i www2.
 
      use_backend  www2  if host_www2
 
  
[http://cbonte.github.io/haproxy-dconv/configuration-1.4.html#7 Using ACL]
+
=== Useful links ===
<br/>
+
* https://github.com/openstack/neutron-specs/blob/master/specs/liberty/lbaas-l7-rules.rst
[http://cbonte.github.io/haproxy-dconv/configuration-1.4.html#7.5.3 Matching at Layer 7]
+
* http://cbonte.github.io/haproxy-dconv/configuration-1.5.html#7
<br/>
 
[https://github.com/joewilliams/haproxy/blob/master/examples/acl-content-sw.cfg Examples]
 

Revision as of 00:38, 1 August 2015

L7 Switching

Background

Layer 7 switching takes its name from the OSI model, indicating that the device switches requests based on layer 7 (application) data. Layer 7 switching is also known as "request switching," "application switching," and "content based routing."

A layer 7 switch presents to the outside world a "virtual server" that accepts requests on behalf of a number of servers and distributes those requests based on policies that use application data to determine which server or set of servers 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 server 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 switching does not require that all servers in the pool (farm/cluster) have the same content. In fact, it is generally expected that a load balancer configuration using layer 7 switching expects the back-end servers will have different content. Layer 7 switches are capable of directing requests based on URI, host, HTTP headers, and anything in the application message.

L7 switching in Neutron LBaaS

The layer 7 switching capabilities described in this document are slated to be added to Neutron LBaaS in time for the Liberty release cycle. Note also that layer 7 switching applies only to the LBaaS v2 API only. Since LBaaS v1 is being phased out, there are no plans to make L7 switching capability work with Neutron LBaaS v1.

It's also worth nothing that while layer 7 switching can in theory be done for any well-defined layer 7 application interface, for the purposes of Neutron LBaaS, L7 functionality refers only to the HTTP protocol and its semantics.

It is also anticipated that initially not all load balancer vendors with Neutron LBaaS drivers will support L7 switching at first. However, we imagine the L7 switching functionality described in this document should be universal enough that all load balancer vendors capable of doing L7 functionality at all should be able to write drivers which work with Neutron LBaaS L7 switching.

API and logic changes

  • Pools can be created without necessarily being associated with a Listener
  • Pools have a "loose coupling" with Loadbalancers (ie. a pool can be effectively associated with zero or one loadbalancers through L7policies, or Listener default_pool assignments.) Notably, at the present time a given pool may exist within zero or one Loadbalancer trees.
  • CRUD operations for L7Policy
  • CRUD operations for L7Rule

CLI Example

  • neutron lbaas-create-pool listener1 ..... ( Create listener)
  • neutron lbaas-create-pool pool1 ..... ( Create pool)
  • neutron --policy policy1 lbaas-create-l7policy --name "policy1" --description "My Description" --listener "listener1" --action redirect_to_pool --pool "pool1" --position -1 (Create l7 policy named 'policy1' appended to listener 'listener1' after any already existing l7 policies, with the action of this policy to redirect to pool 'pool1' )
  • neutron lbaas-create-l7rule rule1 --rule-type path --compare-type startswith --value "/api" --policy policy1 (Create l7 rule named 'rule1' and associate it with the policy 'policy1' )
  • neutron lbaas-create-l7rule rule2 --rule-type header --compare-type equals --key "mycookie" --value "myvalue" --invert --policy policy1 (Create l7 rule named 'rule2' and associate it with the policy 'policy1' )


The above L7 policy and rule creation should now enable the following logic:

In listener1's configuration, redirect any given request to pool1 IF: The request URI path starts with "/api" AND cookie "mycookie" is NOT equal to "myvalue"

L7 Rules

An L7 Rule is a single, simple logical test which returns either true or false.

Rule types

L7 rules have the following types:

  • hostname: 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 list of comparisons we support is below. Note that not all rule types support all comparison types:

  • regex: Perl type regular expression matching
  • startswith: String start with
  • endswith: String ends with
  • contains: String contains
  • equalto: String equals
  • greaterthan: Integer is greater than
  • lessthan: Integer is less than

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 Listner, and which may also have an association to a back-end pool.

Policy Logic

Policy logic is very simple: All the rules associated with a given policy are logically ANDed together. A request much 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.

Policy Actions

If an L7 policy matches a given request, then that policy's action is executed. The following are the actions a L7 Policy may take:

  • block: 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 (which is usually not the default pool associated with the listener).

Policy Position

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 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.

Useful links