Quickstart for Cloud Load Balancers#

The Rackspace Cloud Load Balancers service provides a means to protect your infrastructure by distributing traffic efficiently.

Concepts#

To use this service effectively, you should understand how these key ideas are used in this context:

monitor

A configurable feature of each load balancer. It is used to determine whether or not a back-end node is usable for processing a request. It is not related to the Cloud Monitoring service.

node

A back-end device providing a service on a specified IP and port.

Authentication#

To use this service you have to authenticate first. To do this, you will need your Rackspace username and API key. Your username is the one you use to login to the Cloud Control Panel at http://mycloud.rackspace.com/.

To find your API key, use the instructions in View and reset your API key.

You can specify a default region. Here is a list of available regions:

  • DFW (Dallas-Fort Worth, TX, US)

  • HKG (Hong Kong, China)

  • IAD (Blacksburg, VA, US)

  • LON (London, England)

  • SYD (Sydney, Australia)

Some users have access to another region in ORD (Chicago, IL). New users will not have this region.

Once you have these pieces of information, you can pass them into the SDK by replacing {username}, {apiKey}, and {region} with your info:

CloudIdentity cloudIdentity = new CloudIdentity()
{
    APIKey = "{apikey}",
    Username = "{username}"
};
CloudLoadBalancerProvider cloudLoadBalancerProvider =
      new CloudLoadBalancerProvider(
        cloudIdentity,
        "{region}",
        null);
import (
  "github.com/rackspace/gophercloud"
  "github.com/rackspace/gophercloud/rackspace"
  "github.com/rackspace/gophercloud/rackspace/compute/v1/servers"
  "github.com/rackspace/gophercloud/rackspace/lb/v1/acl"
  "github.com/rackspace/gophercloud/rackspace/lb/v1/lbs"
  "github.com/rackspace/gophercloud/rackspace/lb/v1/monitors"
  "github.com/rackspace/gophercloud/rackspace/lb/v1/nodes"
  "github.com/rackspace/gophercloud/rackspace/lb/v1/throttle"
  "github.com/rackspace/gophercloud/rackspace/lb/v1/vips"
)

provider, err := rackspace.AuthenticatedClient(gophercloud.AuthOptions{
  Username: "{username}",
  APIKey: "{apiKey}",
})

client, err := rackspace.NewLBV1(provider, gophercloud.EndpointOpts{
  Region: "{region}",
})
// Authentication in jclouds is lazy and happens on the first call to the cloud.
CloudLoadBalancersApi clbApi = ContextBuilder.newBuilder("rackspace-cloudloadbalancers-us")
    .credentials("{username}", "{apiKey}")
    .buildApi(CloudLoadBalancersApi.class);
var pkgcloud = require('pkgcloud');

var rackspace = pkgcloud.loadbalancer.createClient({
  provider: 'rackspace',
  username: '{username}',
  apiKey: '{apiKey}',
  region: '{region}'
});
require 'vendor/autoload.php';

use OpenCloud\Rackspace;

$client = new Rackspace(Rackspace::US_IDENTITY_ENDPOINT, array(
    'username' => '{username}',
    'apiKey'   => '{apiKey}'
));
import pyrax
pyrax.set_setting("identity_type", "rackspace")
pyrax.set_default_region('{region}')
pyrax.set_credentials('{username}', '{apiKey}')
require 'fog'

@client = Fog::Rackspace::LoadBalancers.new(
  :rackspace_username => '{username}',
  :rackspace_api_key => '{apiKey}',
  :rackspace_region => '{region}'
)
# {username}, {apiKey} below are placeholders, do not enclose '{}' when you replace them with actual credentials.

curl -s https://identity.api.rackspacecloud.com/v2.0/tokens -X POST \
   -d '{"auth":{"RAX-KSKEY:apiKeyCredentials":{"username":"{username}", "apiKey":"{apiKey}"}}}' \
   -H "Content-Type: application/json" | python -m json.tool

# From the resulting json, set environment variables with values you'll need later.

export TENANT="{tenantId}"
export TOKEN="{tokenId}"
export ENDPOINT="{publicUrl}" # For the cloud load balancers service
export COMPUTE_ENDPOINT="{publicComputeUrl}" # For the compute service, used to find servers.

Use the API#

Some of the basic operations you can perform with this API are described below.

Set up your load balancer#

Create a load balancer#

When creating a load balancer, there are a few mandatory parameters that you need to provide. You need to specify a name, a protocol (such as HTTP, FTP, SMTP) and the types of IP you want to use (v4 or v6). Here is an example:

IEnumerable<LoadBalancingProtocol> protocols =
      await cloudLoadBalancerProvider.ListProtocolsAsync(CancellationToken.None);
LoadBalancingProtocol httpProtocol =
      protocols.First(i => i.Name.Equals("HTTP", StringComparison.OrdinalIgnoreCase));
LoadBalancerConfiguration configuration = new LoadBalancerConfiguration(
    name: "{load_balancer_name}",
    nodes: null,
    protocol: httpProtocol,
    virtualAddresses: new[] { new LoadBalancerVirtualAddress(
              LoadBalancerVirtualAddressType.ServiceNet) },
    algorithm: LoadBalancingAlgorithm.RoundRobin);
LoadBalancer tempLoadBalancer =
      await cloudLoadBalancerProvider.CreateLoadBalancerAsync(
              configuration,
              AsyncCompletionOption.RequestCompleted,
              CancellationToken.None, null);
opts := lbs.CreateOpts{
  Name:     "My Load Balancer",
  Port:     80,
  Protocol: "HTTP",
  VIPs: []vips.VIP{
    vips.VIP{Type: vips.PUBLIC},
  },
  Nodes: []nodes.Node{
    nodes.Node{Address: "10.1.1.1", Port: 80, Condition: nodes.ENABLED},
  },
}

lb, err := lbs.Create(client, opts).Extract()
LoadBalancerApi lbApi = clbApi.getLoadBalancerApi("{region}");

CreateLoadBalancer createLB = CreateLoadBalancer.builder()
    .name("My Load Balancer")
    .protocol("HTTP")
    .port(80)
    .algorithm(BaseLoadBalancer.Algorithm.RANDOM)
    .virtualIPType(VirtualIP.Type.PUBLIC)
    .build();

LoadBalancer loadBalancer = lbApi.create(createLB);
client.createLoadBalancer({
  name: 'My Load Balancer',
  protocol: pkgcloud.providers.rackspace.loadbalancer.Protocols.HTTP,
  virtualIps: [
    {
      type: pkgcloud.providers.rackspace.loadbalancer.VirtualIpTypes.PUBLIC
    }]
}, function(err, lb) {
  if (err) {
    // TODO handle as appropriate
    return;
  }

  // TODO use your load balancer
});
// Get an empty Load Balancer object
$loadBalancer = $service->loadBalancer();

// Add the IP types that your Load Balancer will support
$loadBalancer->addVirtualIp('PUBLIC', 4);

// Add a node, specifying IP address and port
$loadBalancer->addNode('192.168.0.2', 80);

// Send to the API
$loadBalancer->create(array(
    'name'     => 'My Load Balancer',
    'port'     => 80,
    'protocol' => 'HTTP'
));
clb = pyrax.cloud_loadbalancers
virtual_ipv4 = clb.VirtualIP(type="PUBLIC", ipVersion='IPV4')

load_balancer = clb.create("balanced", port=80, protocol="HTTP",
                           virtual_ips=[virtual_ipv4])
@balancer = @client.load_balancers.create(
  :name => 'balanced',
  :protocol => 'HTTP',
  :port => 8080,
  :virtual_ips => [{ :type => 'PUBLIC' }],
  :nodes => []
)
curl -s -X POST $ENDPOINT/loadbalancers \
  -H "X-Auth-Token: $TOKEN" \
  -H "Content-Type: application/json" \
  -d \
    '{
        "loadBalancer": {
            "name": "balanced",
            "port": 8080,
            "protocol": "HTTP",
            "virtualIps": [
              { "type": "PUBLIC" }
            ]
        }
    }' | python -m json.tool

Once this operation is executed, the API will asynchronously provision a load balancer based on your configuration. Some SDKs allow you to query its progress:

int limit = 1;
ReadOnlyCollection<LoadBalancer> loadBalancers =
      await (await cloudLoadBalancerProvider.ListLoadBalancersAsync(
              null,
              limit,
              CancellationToken.None)).GetAllPagesAsync(CancellationToken.None, null);
LoadBalancerStatus loadBalancerStatus = loadBalancers[0].Status;
// Values include:
// LoadBalancerStatus.Active;
// LoadBalancerStatus.Build;
// LoadBalancerStatus.Deleted;
// LoadBalancerStatus.Error;
// LoadBalancerStatus.PendingDelete;
// LoadBalancerStatus.PendingUpdate;
// LoadBalancerStatus.Suspended;
gophercloud.WaitFor(60, func() (bool, error) {
  lb, err := lbs.Get(client, id).Extract()
  if err != nil {
    return false, err
  }

  if lb.Status != lbs.ACTIVE {
    // It has not yet reached ACTIVE
    return false, nil
  }

  // It has reached ACTIVE
  return true, nil
})
LoadBalancerApi lbApi = clbApi.getLoadBalancerApi("{region}");

if (!LoadBalancerPredicates.awaitAvailable(lbApi).apply(loadBalancer)) {
    throw new TimeoutException("Timeout on creating load balancer: " + loadBalancer);
}
// Poll the resource until it reaches an ACTIVE state, with a 2500ms frequency
lb.setWait({
  status: 'ACTIVE'
}, 2500, function(err) {
  if (err) {
    // TODO handle as appropriate
  }
});
// Write a callback which outputs the name, status and progress of a LB
$callback = function($lb) {
    if (!empty($lb->error)) {
        var_dump($lb->error);
        exit;
    } else {
        printf(
            "Waiting on %s/%-12s %4s%%",
            $lb->name(),
            $lb->status(),
            isset($lb->progress) ? $lb->progress : 0
        );
    }
};

// Poll the resource until it reaches an ACTIVE state, with a 600s (5 min) timeout
// Please be aware this is a blocking operation
$server->waitFor('ACTIVE', 300, $callback);
pyrax.utils.wait_until(load_balancer, "status", "ACTIVE", interval=1,
                       attempts=30)
@balancer.wait_for { ready? }
curl -s -X GET $ENDPOINT/loadbalancers/{loadBalancerId} \
  -H "X-Auth-Token: $TOKEN" \
  -H "Accept: application/json" | python -m json.tool

# Watch for loadBalancer.status to become "ACTIVE"

Select the servers you want as nodes#

For a load balancer to distribute traffic, it needs to be aware of the servers or databases you want guarded. These are known as nodes.

Server server1 = cloudServersProvider.GetDetails("{serverId1}");
Server server2 = cloudServersProvider.GetDetails("{serverId2}");
computeClient := rackspace.NewComputeV2(provider, gophercloud.EndpointOpts{
  Region: "{region}",
})

pager := servers.List(computeClient, nil)
err := pager.EachPage(func(page pagination.Page) (bool, error) {
  serverList, err := servers.ExtractServers(page)

  for _, s := range serverList {
     // To retrieve a server's IP address, call s.AccessIPv4
  }

  return true, nil
})
NovaApi novaApi = ContextBuilder.newBuilder("rackspace-cloudservers-us")
        .credentials("{username}, "{apiKey}")
        .buildApi(NovaApi.class);
ServerApi serverApi = novaApi.getServerApi("{region}");

Server server1 = serverApi.get("{serverId}");
Server server2 = serverApi.get("{serverId}");
// We're using async, a flow control library to make parallel calls easy
var async = require('async');

// We also need a compute client to retrieve details of two servers
var compute = pkgcloud.compute.createClient({
  provider: 'rackspace',
  username: '{username}',
  apiKey: '{apiKey}',
  region: '{region}'
});

var serverIds = ['{serverId1}','{serverId2}'],
  servers = [];

async.forEach(serverIds, function(serverId, next) {
  compute.getServer(serverId, function(err, server) {
    // If you had an error, callback with err
    if (err) {
      next(err);
      return;
    }

    // save our server into our array
    servers.push(server);
    next();
  });
}, function(err) {
  if (err) {
    // TODO handle as appropriate
  }

  // TODO next we'll add the nodes
});
$computeService = $client->computeService('cloudServersOpenStack', 'DFW');

// Retrieve servers using their UUIDs
$serverOne = $computeService->server('{serverId1}');
$serverTwo = $computeService->server('{serverId2}');
pyrax.connect_to_cloudservers("{region}")
server_one = cs.servers.get('{serverId1}')
server_two = cs.servers.get('{serverId2}')
compute = Fog::Compute.new(
  :provider => 'rackspace',
  :rackspace_username => '{username}',
  :rackspace_api_key => '{apiKey}',
  :rackspace_region => '{region}'
)

@server_one = compute.servers.get('{serverId1}')
@server_two = compute.servers.get('{serverId2}')
# Retrieve servers using their UUIDs.
curl -s -X GET $COMPUTE_ENDPOINT/servers/{serverId1} \
  -H "X-Auth-Token: $TOKEN" \
  -H "Accept: application/json" | python -m json.tool

curl -s -X GET $COMPUTE_ENDPOINT/servers/{serverId1} \
  -H "X-Auth-Token: $TOKEN" \
  -H "Accept: application/json" | python -m json.tool

# Make a note of server.addresses.private.addr for each server.

The above sample retrieves two cloud servers using their unique IDs. You can obtain a server’s ID by following the steps outlined in the Quickstart for Cloud Servers for retrieving servers based on arbitrary properties.

Now that you have your servers, you can create your nodes and add them to the load balancer:

LoadBalancerId loadBalancerId = new LoadBalancerId("{load_balancer_id}");
NodeConfiguration nodeConfiguration =
      new NodeConfiguration(
              "{host_domain}",
              80,
              NodeCondition.Enabled,
              NodeType.Primary,
              null);
Node node =
      await cloudLoadBalancerProvider.AddNodeAsync(
              loadBalancerId,
              nodeConfiguration,
              AsyncCompletionOption.RequestCompleted,
              CancellationToken.None,
              null);
opts := nodes.CreateOpts{
  nodes.CreateOpt{
    Address:   "10.2.2.3",
    Port:      80,
    Condition: nodes.ENABLED,
    Type:      nodes.PRIMARY,
  },
  nodes.CreateOpt{
    Address:   "10.2.2.4",
    Port:      81,
    Condition: nodes.ENABLED,
    Type:      nodes.SECONDARY,
  },
}

nodeList := nodes.Create(client, "{loadBalancerId}", opts)
NodeApi nodeApi = clbApi.getNodeApi("{region}", "{loadBalancerId}");

AddNode node1 = AddNode.builder()
    .address(server1.getAccessIPv4())
    .condition(BaseNode.Condition.DISABLED)
    .port(80)
    .weight(20)
    .build();

AddNode node2 = AddNode.builder()
    .address(server2.getAccessIPv4())
    .condition(BaseNode.Condition.ENABLED)
    .port(80)
    .weight(20)
    .build();

Set<AddNode> addNodes = Sets.newHashSet();
addNodes.add(node1);
addNodes.add(node2);

nodeApi.add(addNodes);
var nodes = [];

// using our servers array from above
servers.forEach(function(server) {
  nodes.push({
    address: server.addresses.['private'][0].addr,
    port: 80,
    weight: 20,
    condition: 'ENABLED',
    type: 'PRIMARY'
  });
});

client.addNodes(lb, nodes, function(err) {
  if (err) {
    // TODO handle as appropriate
  }
});
use OpenCloud\LoadBalancer\Enum\NodeCondition;

$serverOneNode = $loadBalancer->node(array(
    'address'   => $serverOne->addresses->private[0]->addr,
    'port'      => 8080,
    'condition' => NodeCondition::ENABLED
));
$serverOneNode->create();

$serverTwoNode = $loadBalancer->node(array(
    'address'   => $serverTwo->addresses->private[0]->addr,
    'port'      => 8080,
    'condition' => NodeCondition::ENABLED
));
$serverTwoNode->create();
server_one_node = clb.Node(address=server_one.accessIPv4, port=8080, condition="ENABLED")
server_two_node = clb.Node(address=server_two.accessIPv4, port=8080, condition="ENABLED")
load_balancer.add_nodes([server_one_node, server_two_node])
pyrax.utils.wait_until(load_balancer, "status", "ACTIVE", interval=1, attempts=30, verbose=True)
@server_one_node = @balancer.nodes.create(
  :address => @server_one.private_ip_address
  :port => 8080,
  :condition => 'ENABLED'
)
@balancer.wait_for { ready? }

@server_two_node = @balancer.nodes.create(
  :address => @server_two.private_ip_address
  :port => 8080,
  :condition => 'ENABLED'
)
@balancer.wait_for { ready? }
curl -s -X POST $ENDPOINT/loadbalancers/{loadBalancerId}/nodes \
  -H "X-Auth-Token: $TOKEN" \
  -H "Content-Type: application/json" \
  -d \
    '{
        "nodes": [
            {
                "address": "{serverOnePrivateAddress}",
                "port": 8080,
                "condition": "ENABLED",
                "type": "PRIMARY"
            },
            {
                "address": "{serverOnePrivateAddress}",
                "port": 8080,
                "condition": "ENABLED",
                "type": "PRIMARY"
            }
        ]
    }' | python -m json.tool

Monitor the health of your nodes#

The load balancing service includes a health monitor that periodically checks your nodes to ensure they are responding correctly. If a node is not responding, it is removed from rotation until the health monitor determines that it is functional. In addition to periodic checking, a check is performed against every node when added to your Load Balancer, ensuring that the node can safely service traffic.

To enable health monitoring on your load balancer, you’ll need to set:

  • Type - CONNECT is used to monitor connections

  • Delay - Minimum number of seconds to wait before executing the monitor

  • Timeout - Maximum duration in seconds to wait for a connection establishment before timing out

  • Attempts before deactivation - Number of monitor failures to tolerate before removing a node from rotation

LoadBalancerId loadBalancerId = new LoadBalancerId("{load_balancer_id}");
int attemptsBeforeDeactivation = 3;
TimeSpan timeout = TimeSpan.FromSeconds(30);
TimeSpan delay = TimeSpan.FromSeconds(30);
HealthMonitor healthMonitor =
      new ConnectionHealthMonitor(
              attemptsBeforeDeactivation,
              timeout,
              delay);
await cloudLoadBalancerProvider.SetHealthMonitorAsync(
      loadBalancerId,
      healthMonitor,
      AsyncCompletionOption.RequestCompleted,
      CancellationToken.None,
      null);
opts := monitors.UpdateConnectMonitorOpts{
  AttemptLimit: 3,
  Delay:        10,
  Timeout:      10,
}

err := monitors.Update(client, "{loadBalancerId}", opts).ExtractErr()
HealthMonitorApi healthMonitorApi =
    clbApi.getHealthMonitorApi("{region}", "{loadBalancerId}");

HealthMonitor healthMonitor = HealthMonitor.builder()
    .type(HealthMonitor.Type.CONNECT)
    .delay(3599)
    .timeout(30)
    .attemptsBeforeDeactivation(2)
    .build();

healthMonitorApi.createOrUpdate(healthMonitor);
// using our previously created lb

lb.updateHealthMonitor({
  type: 'CONNECT',
  attemptsBeforeDeactivation: 2,
  delay: 3599,
  timeout: 30
}, function (err) {
  if (err) {
    // TODO handle as appropriate
  }
});
$healthMonitor = $loadBalancer->healthMonitor();
$healthMonitor->update(array(
    'delay'   => 120,
    'timeout' => 60,
    'type'    => 'CONNECT',
    'attemptsBeforeDeactivation' => 3
));
load_balancer.add_health_monitor(type="CONNECT", delay=10, timeout=10,
                                 attemptsBeforeDeactivation=3)
@balancer.enable_health_monitor('CONNECT', 10, 10, 3)
@balancer.wait_for { ready? }
curl -X PUT $ENDPOINT/loadbalancers/{loadBalancerId}/healthmonitor \
  -H "X-Auth-Token: $TOKEN" \
  -H "Content-Type: application/json" \
  -d \
    '{
        "healthMonitor": {
            "type": "CONNECT",
            "delay": 10,
            "timeout": 10,
            "attemptsBeforeDeactivation": 3
        }
    }'

To view the status of a health monitor:

LoadBalancerId loadBalancerId = new LoadBalancerId("{load_balancer_id}");
HealthMonitor healthMonitor =
      await cloudLoadBalancerProvider.GetHealthMonitorAsync(
              loadBalancerId,
              CancellationToken.None);
hm, err := monitors.Get(client, "{loadBalancerId}").Extract()
HealthMonitorApi healthMonitorApi =
    clbApi.getHealthMonitorApi("{region}", "{loadBalancerId}");

HealthMonitor healthMonitor = healthMonitorApi.get();
lb.getHealthMonitor(function (err, monitor) {
  if (err) {
    // TODO handle as appropriate
  }

  // TODO use your health monitor here
});
$healthMonitor = $loadBalancer->healthMonitor();

// Output the monitoring type, its delay and timeout, and the amount of
// times it will poll the Load Balancer before deactivating
printf(
    "Monitoring type: %s, delay: %s, timeout: %s, attempts before deactivation: %s",
    $healthMonitor->type, $healthMonitor->delay, $healthMonitor->timeout
);
load_balancer.get_health_monitor()
@balancer.health_monitor
curl -s -X GET $ENDPOINT/loadbalancers/{loadBalancerId}/healthmonitor \
  -H "X-Auth-Token: $TOKEN" \
  -H "Accept: application/json" | python -m json.tool

Only one health monitor can be enabled on a load balancer at a time.

Set limits#

The connection throttling feature imposes limits on the number of connections per IP address to help mitigate malicious or abusive traffic to your applications. You can set the:

  • Max connection rate - Maximum connections from a single IP within the supplied rate interval (frequency in seconds)

  • Max connections - Maximum simultaneous connections to allow from a single IP within the rate interval

  • Min connections - Minimum amount of connections per IP before doing any throttling

  • Rate interval - the frequency in seconds at which the max connections are assessed

LoadBalancerId loadBalancerId = new LoadBalancerId("{load_balancer_id}");
int maxConnectionRate = 10000;
int maxConnections = 5000;
int minConnections = 2;
TimeSpan rateInterval = TimeSpan.FromSeconds(5);
ConnectionThrottles throttles = new ConnectionThrottles(
      maxConnectionRate,
      maxConnections,
      minConnections,
      rateInterval);
await cloudLoadBalancerProvider.UpdateThrottlesAsync(
      loadBalancerId,
      throttles,
      AsyncCompletionOption.RequestCompleted,
      CancellationToken.None,
      null);
opts := throttle.CreateOpts{
  MaxConnections:    200,
  MaxConnectionRate: 100,
  MinConnections:    0,
  RateInterval:      10,
}

err := throttle.Create(client, "{loadBalancerId}", opts).ExtractErr()
ConnectionApi connectionApi =
    clbApi.getConnectionApi("{region}", "{loadBalancerId}");

ConnectionThrottle throttle = ConnectionThrottle.builder()
    .maxConnectionRate(10000)
    .maxConnections(5000)
    .minConnections(2)
    .rateInterval(5)
    .build();

connectionApi.createOrUpdateConnectionThrottle(throttle);
lb.updateConnectionThrottle({
  minConnections: 2,
  maxConnections: 5000,
  maxConnectionRate: 10000,
  rateInterval: 5
}, function (err) {
  if (err) {
    // TODO handle as appropriate
  }
});
$throttle = $loadBalancer->connectionThrottle();

// Allow a maximum of 5,000 simultaneous connections (maxConnections) per minute (rateInterval).
// Limit each IP to a maximum of 50 connections (maxConnectionRate).
$throttle->create(array(
    'maxConnections'    => 5000,
    'minConnections'    => 10,
    'rateInterval'      => 60,
    'maxConnectionRate' => 50
));
load_balancer.add_connection_throttle(maxConnectionRate=10000,
                                      maxConnections=5000,
                                      minConnections=2,
                                      rateInterval=5)
@balancer.enable_connection_throttling(5000,  # max_connections
  2,  # min_connections
  10000,  # max_connection_rate
  5)  # rate_interval

@balancer.wait_for { ready? }
curl -X PUT $ENDPOINT/loadbalancers/{loadBalancerId}/connectionthrottle \
  -H "X-Auth-Token: $TOKEN" \
  -H "Content-Type: application/json" \
  -d \
    '{
        "connectionThrottle": {
            "maxConnections": 5000,
            "minConnections": 2,
            "maxConnectionRate": 10000,
            "rateInterval": 5
        }
    }'

Blacklist IP addresses#

Your access list allows fine-grained network access controls to be applied to a load balancer. A single IP address, multiple IP addresses, or entire network subnets can be added.

Items that are configured with the ALLOW type will take precedence over all other traffic, and items with the DENY type will have their traffic rejected.

LoadBalancerId loadBalancerId = new LoadBalancerId("{load_balancer_id}");
NetworkItem networkItem = new NetworkItem("206.160.165.0/24", AccessType.Deny);
await cloudLoadBalancerProvider.CreateAccessListAsync(
      loadBalancerId,
      networkItem,
      AsyncCompletionOption.RequestCompleted,
      CancellationToken.None,
      null);
list := acl.CreateOpts{
  acl.CreateOpt{Address: "206.160.165.0/24", Type: acl.DENY},
  acl.CreateOpt{Address: "206.160.166.0/24", Type: acl.ALLOW},
  acl.CreateOpt{Address: "0.0.0.0/0", Type: acl.DENY},
}

err := acl.Create(client, "{loadBalancerId}", list).ExtractErr()
AccessRuleApi accessRuleApi =
    clbApi.getAccessRuleApi("{region}", "{loadBalancerId}");

AccessRule rule1 = AccessRule.deny("206.160.165.0/24");
AccessRule rule2 = AccessRule.allow("206.160.165.0/2");
AccessRule blacklisted = AccessRule.deny("0.0.0.0/0");

List<AccessRule> accessList = ImmutableList.<AccessRule> of(rule1, rule2, blacklisted);

accessRuleApi.create(accessList);
lb.addAccessList([
  { type: 'DENY', address: '206.160.165.0/24'},
  { type: 'ALLOW', address: '206.160.166.0/24'},
  { type: 'DENY', address: '0.0.0.0/0'},
], function (err) {
  if (err) {
    // TODO handle as appropriate
  }
});
// Example 1: Blacklist a specific IP
$loadBalancer->createAccessList(array(
    (object) array(
        'type'    => 'DENY',
        'address' => '206.160.165.0/24'
    )
));

// Example 2: Only allow access to 1 IP, and blacklist everything else
$loadBalancer->createAccessList(array(
    (object) array(
        'type'    => 'ALLOW',
        'address' => '206.160.165.1/24'
    ),
    (object) array(
        'type'    => 'DENY',
        'address' => '0.0.0.0/0'
    )
));
load_balancer.add_access_list([
    {"type": 'DENY', "address": "206.160.165.0/24"},
    {"type": 'ALLOW', "address": "206.160.166.0/24"},
    {"type": 'DENY', "address": "0.0.0.0/0"}
])
# Example 1: Blacklist a specific IP

@balancer.access_rules.create(
  :type => 'DENY',
  :address => '206.160.165.0/24'
)
@balancer.wait_for { ready? }

# Example 2: Allow access to 1 IP, and blacklist everything else
@balancer.access_rules.create(
  :type => 'ALLOW',
  :address => '206.160.166.0/24'
)
@balancer.wait_for { ready? }

@balancer.access_rules.create(
  :type => 'DENY',
  :address => '0.0.0.0/0'
)
@balancer.wait_for { ready? }
# Example 1: Blacklist a specific IP

curl -X POST $ENDPOINT/{loadBalancerId}/accesslist \
  -H "X-Auth-Token: $TOKEN" \
  -H 'Content-Type: application/json' \
  -d \
    '{
        "accessList": [
            {
                "address" : "206.160.165.0/24",
                "type": "DENY"
            }
        ]
    }'

# Example 2: Allow access to 1 IP, and blacklist everything else
curl -X POST $ENDPOINT/loadbalancers/{loadBalancerId}/accesslist \
  -H "X-Auth-Token: $TOKEN" \
  -H 'Content-Type: application/json' \
  -d \
    '{
        "accessList": [
            {
                "address" : "206.160.166.0/24",
                "type": "ALLOW"
            },
            {
                "address" : "0.0.0.0/0",
                "type": "DENY"
            }
        ]
    }'

Cache content for performance#

When content caching is enabled, recently-accessed files are stored on the load balancer for easy retrieval by web clients. Content caching improves the performance of high traffic web sites by temporarily storing data that was recently accessed. While it’s cached, requests for that data will be served by the load balancer, which in turn reduces load off the back end nodes. The result is improved response times for those requests and less load on the web server.

LoadBalancerId loadBalancerId = new LoadBalancerId("{load_balancer_id}");
await cloudLoadBalancerProvider.SetContentCachingAsync(
      loadBalancerId,
      true,
      AsyncCompletionOption.RequestCompleted,
      CancellationToken.None,
      null);
// Check whether caching is set
isCached, err := lbs.IsContentCached(client, "{loadBalancerId}")

// Enable it
err := lbs.EnableCaching(client, "{loadBalancerId}").ExtractErr()

// Disable it
err := lbs.DisableCaching(client, "{loadBalancerId}").ExtractErr()
ContentCachingApi contentCachingApi =
    clbApi.getContentCachingApi("{region}", "{loadBalancerId}");

contentCachingApi.enable();
// Send false for the second argument to disable content caching
client.updateContentCaching(lb, true, function (err) {
  if (err) {
    // TODO handle as appropriate
  }
});
// To check whether caching is enabled
$loadBalancer->hasContentCaching();

// To enable caching
$loadBalancer->enableContentCaching(true);

// To disable caching
$loadBalancer->enableContentCaching(false);
# Check if content caching is enabled
load_balancer.content_caching

# Enable content_caching
load_balancer.content_caching = True
# To check whether or not content caching is enabled
@balancer.content_caching

# To enable content caching
@balancer.enable_content_caching
@balancer.wait_for { ready? }

# To disable caching
@balancer.disable_content_caching
@balancer.wait_for { ready? }
curl -X PUT $ENDPOINT/loadbalancers/{loadBalancerId}/contentcaching \
  -H "X-Auth-Token: $TOKEN" \
  -H "Content-Type: application/json" \
  -d \
    '{
        "contentCaching": {
            "enabled": true
        }
    }'

Use error pages#

An error page is the HTML file that is shown to your users when accessing a load balancer node that is offline or otherwise unavailable. By default, every provisioned load balancer is configured with a default error page. However, you can create a custom error page for load balancers that use the HTTP protocol:

LoadBalancerId loadBalancerId = new LoadBalancerId("{load_balancer_id}");
await cloudLoadBalancerProvider.SetErrorPageAsync(
      loadBalancerId,
      "{custom_error_page}",
      AsyncCompletionOption.RequestCompleted,
      CancellationToken.None,
      null);
html := "<html>New error page</html>"
content, err := lbs.SetErrorPage(client, "{loadBalancerId}", html).Extract()
ErrorPageApi errorPageApi = clbApi.getErrorPageApi("{region}", "{loadBalancerId}");

String content = "<html><body>Something went wrong...</body></html>";
errorPageApi.create(content);
lb.setErrorPage('<html><body>Something went wrong...</body></html>', function (err, page) {
  if (err) {
    // TODO handle as appropriate
  }
});
// To use a custom error page, specify the markup:
$errorPage = $loadBalancer->errorPage();
$errorPage->update(array(
    'content' => '<html><body>Something went wrong...</body></html>'
));

// To delete your custom error page:
$errorPage->delete();
# Set a custom error page, specify the markup, up to a maximum of 65536 bytes:
error_html = "<html><body>Something went wrong...</body></html>"
load_balancer.set_error_page(error_html)

# Delete the custom error page
load_balancer.clear_error_page()
# To use a custom error page, specify the markup, up to a maximum of 65536 bytes:
@balancer.error_page = '<html><body>Something went wrong...</body></html>'

# To delete your custom error page:
@balancer.reset_error_page
# To use a custom error page, specify the markup, up to a maximum of 65536 bytes:
curl -X PUT $ENDPOINT/loadbalancers/{loadBalancerId}/errorpage \
  -H "X-Auth-Token: $TOKEN" \
  -H "Content-Type: application/json" \
  -d \
    '{
        "errorpage": {
            "content": "&lt;html&gt;&lt;body&gt;Something went wrong...&lt;/body&gt;&lt;/html&gt;"
        }
    }'

# To delete your custom error page:
curl -X DELETE $ENDPOINT/loadbalancers/{loadBalancerId}/errorpage

More information#

This quickstart is intentionally brief, demonstrating only a few basic operations. To learn more about interacting with Rackspace cloud services, explore the following sites: