Managing F5 BIG-IP Systems with Pulumi

Posted on

The Pulumi ecosystem is continuously growing and today we’re excited to announce the F5 BIG-IP provider for Pulumi.

F5’s BIG-IP Local Traffic Managment (LTM) services provides advanced traffic management, acceleration, security, and analytics features to your applications. With the addition of our F5 BIG-IP Pulumi provider we are bringing Cloud Native Infrastructure as Code to F5 BIG-IP devices with familiar programming languages and a consistent programming model. This addresses a frequent use-case we’ve heard from our customers for both on-premises and Cloud workloads.

Let’s look at some examples to demonstrate what’s capable with this provider and the power and flexibility that Pulumi brings to working with your F5 BIG-IP systems.

Simple Load Balancing

In the code below we create a handful of resources that allow us to use our BIG-IP to load balance to two backend HTTP servers. It’s omitted for the sake of brevity, but we could easily create these HTTP servers inline in the same code as our BIG-IP resources - managing them side by side in the same Pulumi application.

import * as pulumi from "@pulumi/pulumi";
import * as f5bigip from "@pulumi/f5bigip";

// The backend IP:Port we want to load balance to.
const backendInstance = "172.31.47.29:80";

// Create our health check monitor
const httpMonitor = new f5bigip.ltm.Monitor("www", {
    name: "/Common/www",
    parent: "/Common/http",
    send: "GET /",
    timeout: 5,
    interval: 10,
});

// Create our pool that we'll attach our HTTP servers to
const wwwPool = new f5bigip.ltm.Pool("www", {
    name: "/Common/www",
    monitors: [httpMonitor.name],
    allowNat: "yes",
    allowSnat: "yes",
});

// Create a pool attachment for our HTTP server
const wwwPoolAttachment = new f5bigip.ltm.PoolAttachment(`www`, {
    pool: wwwPool.name,
    node: pulumi.interpolate`/Common/${backendInstance}`,
});

// Create our LTM Virtual Server
const wwwVirtualServer = new f5bigip.ltm.VirtualServer("www", {
    pool: wwwPool.name,
    name: "/Common/www",
    destination: new pulumi.Config().require("f5PrivateIp"),
    port: 80,
    ipProtocol: "tcp",
    profiles: ["/Common/http"],
    sourceAddressTranslation: "automap",
});

Managing iRules

iRules are one of the more powerful features within the BIG-IP Local Traffic Management (LTM) system. iRules allow you to validate and manipulate request and response data passing through your BIG-IP as well as make decisions on such traffic such as directing traffic to different backend server pools.

These rules are highly dependent on your application configuration and requirements so we’ll show a simple example here that logs connection information within the BIG-IP system based on the presence of a query parameter on the HTTP request - e.g. ?_debug=true. Again we’re omitting some of the resources to keep the example short.

import * as pulumi from "@pulumi/pulumi";
import * as f5bigip from "@pulumi/f5bigip";

// ...

const iRuleTcl = `
when HTTP_REQUEST {
    # initialize our connection-scoped variable
    set client_debug 0

    # if request query string contains _debug=true
    if {[URI::query [HTTP::uri] _debug] eq "true"} {
        set client_debug 1
    }
}
when SERVER_CONNECTED {
    # if our connection-scoped variable is true, log connection info
    if {$client_debug} {
        log local0. "Client debug info requested... [IP::client_addr]:[TCP::client_port] -> [clientside {IP::local_addr}]:[clientside {TCP::local_port}] -> [IP::remote_addr]:[TCP::remote_port]"
    }
}
when HTTP_RESPONSE {
    # add a response header so clients know their connection info was logged
    if {$client_debug} {
        HTTP::header insert "X-Client-Debug" "true"
    }
}
`;

// Create our iRule
const iRule = new f5bigip.ltm.IRule("www", {
    name: "/Common/www",
    irule: iRuleTcl,
});

// Create our LTM Virtual Server
const wwwVirtualServer = new f5bigip.ltm.VirtualServer("www", {
    pool: wwwPool.name,
    name: "/Common/www",
    destination: new pulumi.Config().require("f5PrivateIp"),
    port: 80,
    ipProtocol: "tcp",
    profiles: ["/Common/http"],
    sourceAddressTranslation: "automap",
    irules: [iRule.name],
});

Dynamically Creating iRules

So far the BIG-IP resources we’ve created have been relatively static. Let’s leverage the full power of Pulumi by dynamically creating resources based on an array of values. A common scenario when creating a website is to provide versions of the website in various languages for your audience. In this example we’ll create a number of iRules to redirect users to localized websites based on a user’s language preference.

We define the languages we currently support in an array called supportedLanguages and then use this array to create an iRule for each language.

import * as pulumi from "@pulumi/pulumi";
import * as f5bigip from "@pulumi/f5bigip";

// ...

// The languages we currently support.
const supportedLanguages = [
    "es",
    "fr",
]

const iRules = supportedLanguages.map(languageCode => {
    const iRuleTcl = `
    when HTTP_REQUEST {
        # if request path equals '/'
        if {[HTTP::uri] eq "/"} {
            if { [HTTP::header "Accept-Language"] starts_with "${languageCode}" } {
                HTTP::respond 301 Location "/${languageCode}/"
            }
        }
    }
    `;

    // Create our iRule
    const iRule = new f5bigip.ltm.IRule(`www-${languageCode}`, {
        name: `/Common/www-${languageCode}`,
        irule: iRuleTcl,
    });
    return iRule;
});

// Create our LTM Virtual Server
const wwwVirtualServer = new f5bigip.ltm.VirtualServer("www", {
    pool: wwwPool.name,
    name: "/Common/www",
    destination: new pulumi.Config().require("f5PrivateIp"),
    port: 80,
    ipProtocol: "tcp",
    profiles: ["/Common/http"],
    sourceAddressTranslation: "automap",
    irules: iRules.map(irule => irule.name),
});

Wrap Up

With the F5 BIG-IP Pulumi provider you can manage BIG-IP systems whether they’re in the cloud, as available on Amazon Web Services, Microsoft Azure, and Google Cloud Platform, or in your on-premises data centers. In a matter of minutes you can bring modern code and development practices to your BIG-IP-powered applications.

To start managing your F5 BIG-IP systems with familiar programming languages, please check out the following links: