== Load balancer service as a sample OpenDaylight application This is a sample load balancer application that balances traffic to back-end servers based on the source address and source port on each incoming packet. The service reactively installs OpenFlow rules to direct all packets with a specific source address and source port to one of the appropriate back-end servers. The servers may be selected using a round robin policy or a random policy. This service can be configured using a REST API which is similar to the OpenStack Quantum LBaaS (Load-balancer-as-a-Service) v1.0 API proposal at http://wiki.openstack.org/Quantum/LBaaS. To use the load balancer service, a virtual IP (or VIP) must be introduced to the clients of the service and used as the destination address. NOTE: A VIP is an entity that comprises of a virtual IP, port, and protocol (TCP or UDP). === Assumptions for the VIP The assumptions for the VIP are as follows: * One or more VIPs may be mapped to the same server pool. * All VIPs that share the same pool must also share the same load balancing policy. The policy may be random or round robin. * Only one server pool can be be assigned to a VIP. * All flow rules are installed with an idle time-out of 5 seconds. * The flow rules must automatically time out after the idle time-out of 5 seconds. * Packets to a VIP must leave the OpenFlow cluster from the same switch from where they entered. * When you delete a VIP or a server pool or a server from a pool, the service does not delete the already installed flow rules. === Load balancer REST APIs summary .Load balancer REST APIs summary [cols="5*", options="header"] |=== |Description |URI |Type |Request Body/Arguments |Response Codes |List details of all existing pools |/one/nb/v2/lb/{container-name*}/ |GET | |200 ("Operation successful") + 404 ("The containerName is not found") + 503 "Load balancer service is unavailable") |List details of all existing VIPs |/one/nb/v2/lb/{container-name}/vips |GET | |200 ("Operation successful") + 404 ("The containerName is not found") + 503 ("Load balancer service is unavailable") |Create pool |/one/nb/v2/lb/{container-name}/create/pool |POST |{ "name":"", "lbmethod":"" } |201 ("Pool created successfully") + 404 ("The containerName not found") + 503 ("Load balancer service is unavailable") + 409 ("Pool already exist") + 415 ("Invalid input data") + |Delete pool |/one/nb/v2/lb/{container-name}/delete/pool/{pool-name} |Delete | |200 ("Pool deleted successfully") + 404 ("The containerName not found") + 503 ("Load balancer service is unavailable") + 404 ("Pool not found") + 500 ("Failed to delete pool") |Create VIP |/one/nb/v2/lb/{container-name}/create/vip |POST |{ "name":"", "ip":"ip in (xxx.xxx.xxx.xxx) format", "protocol":"TCP/UDP", "port":"any valid port number", "poolname":"" (optional) } |201 ("VIP created successfully")+ 404 ("The containerName not found") + 503 ("Load balancer service is unavailable")+ 409 ("VIP already exists") + 415 ("Invalid input data") |Update VIP |/one/nb/v2/lb/{container-name}/update/vip |PUT |{ "name":"", "poolname":"" } |201 ("VIP updated successfully") + 404 ("The containerName not found") + 503 ("VIP not found") + 404 ("Pool not found") + 405 ("Pool already attached to the VIP") + 415 ("Invalid input name") |Delete VIP |/one/nb/v2/lb/{container-name}/delete/vip/{vip-name} |DELETE | |200 ("VIP deleted successfully") + 404 ("The containerName not found") + 503 ("Load balancer service is unavailable") + 404 ("VIP not found") + 500 ("Failed to delete VIP") |Create pool member |/one/nb/v2/lb/{container-name}/create/poolmember |POST |{ "name":"", "ip":"ip in (xxx.xxx.xxx.xxx) format", "poolname":"existing pool name" } |201 ("Pool member created successfully") + 404 ("The containerName not found") + 503 ("Load balancer service is unavailable") + 404 ("Pool not found") + 409 ("Pool member already exists") + 415 ("Invalid input data") + |Delete pool member |/one/nb/v2/lb/{container-name}/delete/poolmember/{pool-member-name}/{pool-name} |DELETE | |200 ("Pool member deleted successfully") + 404 ("The containerName not found") + 503 ("Load balancer service is unavailable") + 404 ("Pool member not found") + 404 ("Pool not found") |=== NOTE: Current implementation of OpenDaylight uses `default` as a container name. Property `name` of each individual entity must be unique. === Starting the load balancer . Start the OpenDaylight controller. Ensure that the *samples.loadbalancer* and *samples.loadbalancer.northbound* modules are loaded by the controller. . Create any mininet topology and connect it to the controller. For this example, assume a tree topology with *depth=2* and *fanout=4*. This topology creates 16 hosts, 4 edge switches each connected to 4 hosts, and 1 core switch connected to all the 4 edge switches. You can use the following command to start mininet with this tree topology. [literal] mn --topo=tree,2,4 --controller=remote,ip=,port=6633 This default tree topology assigns ip addresses from 10.0.0.1 to 10.0.0.16/8 IP to its 16 hosts. [start=3] . Add a default gateway in OpenDaylight for the mininet network as mentioned in the following URL: https://wiki.opendaylight.org/view/OpenDaylight_Controller:Installation . Run the command *pingall* in mininet and make sure that all the hosts are reachable from each other. . Create the load balancer pool with round robin load balancing policy as follows: [literal] curl --user "admin":"admin" -H "Accept: application/json" -H "Content-type: application/json" -X POST http://:8080/one/nb/v2/lb/default/create/pool -d '{"name":"PoolRR","lbmethod":"roundrobin"}' [start=6] . Create the load balancer VIP as follows: [literal] curl --user "admin":"admin" -H "Accept: application/json" -H "Content-type: application/json" -X POST http://:8080/one/nb/v2/lb/default/create/vip -d '{"name":"VIP-RR","ip":"10.0.0.20","protocol":"TCP","port":"5550","poolname":"PoolRR"}' Pool-name data in the REST call above is optional. In case no pool exists while creating the VIP, you can attach the pool at a later point of time by using the following REST call: [literal] curl --user "admin":"admin" -H "Accept: application/json" -H "Content-type: application/json" -X PUT http://:8080/one/nb/v2/lb/default/update/vip -d '{"name":"VIP-RR","poolname":"PoolRR"}' [start=7] . Add pool members to the load balancer pool. Host H1 (10.0.0.1) will be used as a source or client that sends traffic to the VIP. [literal] curl --user "admin":"admin" -H "Accept: application/json" -H "Content-type: application/json" -X POST http://:8080/one/nb/v2/lb/default/create/poolmember -d '{"name":"PM2","ip":"10.0.0.2","poolname":"PoolRR"}' curl --user "admin":"admin" -H "Accept: application/json" -H "Content-type: application/json" -X POST http://:8080/one/nb/v2/lb/default/create/poolmember -d '{"name":"PM3","ip":"10.0.0.3","poolname":"PoolRR"}' Similarly you can add all the remaining 13 hosts to the pool. [start=8] . Since the VIP created in step 6 does not exist in the network, the controller does not resolve the ARP for the IP of the VIP. The load balancer application assumes that if the VIP is configured and exposed by the user to an internal or external network. Packets that are destined to the VIP's IP address gets routed to it through external mechanisms. For this example, we can locally resolve the ARP for the VIP's IP, by adding static entry to the ARP table of the client or source host. The steps below takes you through details of how to accomplish the step. ==== Locally resolving ARP for the VIP's IP . Spawn xterm for hosts h1 to h4 from the mininet prompt. . Add static ARP entry for VIP's IP address in the host h1 ARP cache. Run the following command in the h1 xterm window to add the ARP entry. [literal] arp -s 10.0.0.20 00:00:10:00:00:20 [start=3] . On h1, start iperf client that sends traffic to the virtual ip address. [literal] iperf -c 10.0.0.20 -p 5550 The iperf client connects to the iperf server running on host h2. [start=4] . After the previous test of iperf finishes, trigger the iperf client again. The iperf client connects to the iperf server running on host h3. Similarly, in the next iteration, it connects to the h4 node in round robin fashion. Similarly, you can try the random load balancing policy by creating the load balancer pool with `random` policy. === Cleaning the load balancer entity You can run the following curl commands to clean up the load balancer entities you created in the previous section. ==== Deleting pool members Delete pool members by running the command below: [literal] curl --user "admin":"admin" -H "Accept: application/json" -H "Content-type: application/json" -X DELETE http://:8080/one/nb/v2/lb/default/delete/poolmember/PM2/PoolRR' You can delete the remaining pool members similarly. ==== Deleting VIP Delete VIP by running the command below: [literal] curl --user "admin":"admin" -H "Accept: application/json" -H "Content-type: application/json" -X DELETE http://:8080/one/nb/v2/lb/default/delete/vip/VIP-RR ==== Deleting pool Delete pool by running the command below: [literal] curl --user "admin":"admin" -H "Accept: application/json" -H "Content-type: application/json" -X DELETE http://:8080/one/nb/v2/lb/default/delete/pool/PoolRR