Managing F5 BIG-IP Network Devices with Puppet
Management of network devices is one of the exciting new features in Puppet Enterprise 2.0 and Puppet 2.7. In the initial release, support is limited to Cisco devices, but because Puppet is extensible via modules, we are able to build upon the existing framework and add support for F5 BIG-IP. Like most network appliances, installation of third party software is prohibited, which eliminates the ability to run an agent. Instead, Puppet takes advantage of F5 iControl API to interact and manage the device. F5 BIG-IP network appliances are capable of load balancing, SSL offloading, application monitoring, as well as many other advanced features, and now Puppet can manage these functionalities. Compared to traditional management methodologies and other third party tools that interact with F5, Puppet not only bridges the gap from deploying applications to bringing the service online to your customers, it also brings the unique benefit of the Puppet resource model to network devices. More specifically, the integration offers the ability to compare if a running configuration matches the desired configuration, and then enforce the changes once they’ve been reviewed.
In this blog post, we will step through the process of installing the F5 module, configuring connectivity, and writing a simple manifest to manage an F5 device with Puppet. If you are unfamiliar with BIG-IP devices, you may want to consult devcentral.f5.com for more information on F5 features such as iRules and iControl API.
In the following output, Puppet detects that the F5 device has the wrong iRule. We are running in simulation mode (--noop option) so Puppet only shows the changes that would be applied if we were enforcing the configuration.
$ puppet device --noop ... notice: /Stage[main]//F5_rule[redirect_404]/definition: current_value: when HTTP_RESPONSE { if { [HTTP::status] eq "404" } { redirect to "http://www.puppetlabs.com/404/" } }, should be when HTTP_RESPONSE { if { [HTTP::status] eq "404" } { redirect to "http://www.puppetlabs.com/redirect/404/" } } (noop) notice: Finished catalog run in 5.69 seconds |
Now running Puppet with out the --noop option set, the iRules are changed to match our resource declaration.
$ puppet device … notice: /Stage[main]//F5_rule[redirect_404]/definition: definition changed when HTTP_RESPONSE { if { [HTTP::status] eq "404" } { redirect to "http://www.puppetlabs.com/404/" } }, to when HTTP_RESPONSE { if { [HTTP::status] eq "404" } { redirect to "http://www.puppetlabs.com/redirect/404/" } } notice: Finished catalog run in 5.74 seconds |
In addition to iRules, the initial release supports key features to configure the device certificate, manage applications pool/poolmember/virtualserver, and monitor application health. The module is published on the Puppet Forge, along with comprehensive documentation of supported F5 resources. The latest development release is available on GitHub. The ability to extend Puppet is not limited to network devices, and the commands shown later in this post to install the module is applicable for other Puppet modules available on the Puppet Forge and GitHub.
The puppet device command is a new application mode in Puppet intended to manage devices that can’t install Ruby/Puppet and run puppet agent. If you haven’t checked it out yet, I would review Brice’s introduction to network devices first. The high level overview of the entire communication process:
Devices are managed through an intermediate proxy system where Puppet agent is installed. The proxy system stores a certificate on behalf of the device. In the case of F5, it should have iControl gem installed, as well as the account information in device.conf to communicate with the device. The proxy connects to the Puppet master to retrieve the catalog on behalf of the F5 and applies changes as necessary.
F5 module installation
Before we get started with the installation process, there are two ways to install F5 module. First, via puppet-module tool which retrieves it from forge.puppetlabs.com (for stable releases of the module). The latest development release from GitHub is accessible via git. The instructions below are specific for Puppet Enterprise, but open source users can also install the module with some changes to the puppet module path. Puppet Enterprise currently ships with the puppet-module gem, and it’s freely available on rubygems.org. Eventually this will become a Puppet Face and turn into the command ‘puppet module’(expected in later release of 2.7). Onwards to the install process:
# Puppet Enterprise: cd /etc/puppetlabs/puppet/modules puppet-module install puppetlabs-f5 |
This should create a directory called f5. Older versions of puppet-module tool might create a puppetlabs-f5 directory in the modules directory—in that case, change it to f5.
Installing from GitHub:
# Puppet Enterprise: cd /etc/puppetlabs/puppet/modules git clone git@github.com:puppetlabs/puppetlabs-f5.git ln -s puppetlabs-f5 f5 |
In Puppet 2.7, the transport between proxy agent and device supports telnet/ssh, however neither is suitable for F5 devices. Instead, we rely on F5’s iControl API. The iControl gem should be installed on both the master and the proxy system. This gem is available in the F5 module files directory.
# Puppet Enterprise: /opt/puppet/bin/gem install /etc/puppetlabs/puppet/modules/f5/files/f5-icontrol-10.2.0.2.gem |
Configuration and management
At this point we have the module installed, so we should configure connectivity for the device. The configuration for network devices by default are stored in /etc/puppet/device.conf:
[f5.puppetlabs.lan] type f5 url https://username:password@f5.puppetlabs.lan/partition |
[f5.dev.puppetlabs.lan] type f5 url https://username:password@f5.dev.puppetlabs.lan/partition |
You can also break down each device into it’s own configuration file such as /etc/puppet/f5_device1.conf, /etc/puppet/f5_device2.conf …, which is especially helpful if you wish to run against each device separately. In the square brackets is the device certificate name, and certificate management process is the same as puppet agent certs. The device type is f5, and the url is https instead of telnet/ssh. Because F5 supports different partitions we can optionally specify them at the end, and it will default to the ‘Common’ partition if it’s not provided. In the module, f5::config define resource type simplifies management of this configuration file on the proxy system:
f5::config { 'f5.puppetlabs.lan': username => 'admin', password => 'password', url => 'f5.puppetlabs.lan', target => '/etc/puppetlabs/puppet/device/f5.puppetlabs.lan.conf', } |
Once this configuration file is in place, we can initiate a puppet device run on the proxy server.
# execute on proxy server $ puppet device --deviceconf /etc/puppetlabs/puppet/device/f5.puppetlabs.lan.conf |
This should generate a certificate request on the master which should be signed:
# execute on puppet master $ puppet cert -l f5.puppetlabs.lan (2A:0C:A0:F8:C6:EE:EF:9B:B3:49:74:D1:27:31:1B:60) $ puppet cert -s f5.puppetlabs.lan |
At this point the master should have a node name f5.puppetlabs.lan in site.pp with the appropriate f5 resources:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | node f5.puppetlabs.lan { f5_rule { 'redirect_404': ensure => 'present', definition => 'when HTTP_RESPONSE { if { [HTTP::status] eq "404" } { redirect to "http://www.puppetlabs.com/redirect/404" } }', } f5_pool { 'webapp': ensure => 'present', action_on_service_down => 'SERVICE_DOWN_ACTION_NONE', allow_nat_state => 'STATE_ENABLED', allow_snat_state => 'STATE_ENABLED', lb_method => 'LB_METHOD_ROUND_ROBIN', member => { '10.10.0.1:80' => {'connection_limit' => '0', 'dynamic_ratio' => '1', 'priority' => '0', 'ratio' => '1'}, '10.10.0.2:80' => {'connection_limit' => '0', 'dynamic_ratio' => '1', 'priority' => '0', 'ratio' => '1'}, '10.10.0.3:80' => {'connection_limit' => '0', 'dynamic_ratio' => '1', 'priority' => '0', 'ratio' => '1'} }, minimum_active_member => '1', minimum_up_member => '0', } } |
When the puppet device command is executed again this will update the iRule and ensure the appropriate members are in the webapp pool:
$ puppet device --deviceconf /etc/puppetlabs/puppet/device/f5.puppetlabs.lan.conf |
A limitation to watch out for in the current Puppet release is that ‘puppet apply’ and ‘puppet resource’ cannot modify network resources. However, we implemented a feature to allow puppet resource to query a F5 device. (For authors of types/providers, making changes to resources aren’t supported until apply_to_device in resources type are handled differently by puppet apply/resource commands). For now we use url facts to establish connectivity to specific F5 devices:
export RUBYLIB=/etc/puppetlabs/puppet/modules/f5/lib/ export FACTER_url=https://admin:password@f5.puppetlabs.lan/Common puppet resource f5_rule |
f5_rule { '_sys_https_redirect': ensure => 'present', definition => ' when HTTP_REQUEST { set host [HTTP::host] HTTP::respond 302 Location "https://$host/" }', } f5_rule { '_sys_auth_ssl_cc_ldap': ensure => 'present', definition => ' when CLIENT_ACCEPTED { set tmm_auth_ssl_cc_ldap_sid 0 set tmm_auth_ssl_cc_ldap_done 0 } when CLIENTSSL_CLIENTCERT { … |
If you don’t have Puppet Enterprise 2.0 in your environment yet, you can either download the Learning Puppet VM, or Puppet Enterprise installation packages. F5 also provides F5 LTM Virtual Edition (VE) for trial on VMWare. Please report any issues or bugs to http://projects.puppetlabs.com/projects/modules/issues under the modules section.
Additional Resources
- Download the F5 module from the Puppet Forge
- Read the intro to managing network devices with Puppet: Puppet Network Device Management
- Learn how to use Puppet with the Learning Puppet VM or with a free ten node download of Puppet Enterprise


13 Comments
I forgot to mention in the blog post, but I want to thank the following contributors and testers who collaborated on this module:
Bernard Nauwelaerts
Brenton Leanhardt
Bret McMillan
Matthew Carpenter
Moshe Hyzon
Puppet Network Device Management | Puppet Labs
[...] Looking for more device management? Read about it here: Managing F5 BIG-IP Network Devices with Puppet [...]
Interesting, but how do you handle deregistration of nodes?
Matt, the node f5.puppetlabs.lan correspond with a f5 device. Are you commenting on the f5_pool? In the example above if you don’t want 10.10.0.3:80, simply change the resource to:
f5_pool { 'webapp': ensure => 'present', action_on_service_down => 'SERVICE_DOWN_ACTION_NONE', allow_nat_state => 'STATE_ENABLED', allow_snat_state => 'STATE_ENABLED', lb_method => 'LB_METHOD_ROUND_ROBIN', member => { '10.10.0.1:80' => {'connection_limit' => '0', 'dynamic_ratio' => '1', 'priority' => '0', 'ratio' => '1'}, '10.10.0.2:80' => {'connection_limit' => '0', 'dynamic_ratio' => '1', 'priority' => '0', 'ratio' => '1'}, }, minimum_active_member => '1', minimum_up_member => '0', }If you need a resource such as f5_virtualserver to be removed simply use:
f5_virtualserver { 'server1.puppetlabs.lan': ensure => 'absent', }Let me know if this answers your question.
This article has been very helpful.
In response to the suggestion above regarding attempting to remove member from a pool, the following error message is received … note the same message is received when the resource is ran again.
err: /Stage[main]//Node[ne-6900.cps.intel.com]/F5_pool[puppet-test-pool]/ensure: change from absent to present failed: Could not set ‘present on ensure: Exception caught in LocalLB::urn:iControl:LocalLB/Pool::create()
Exception: Common::OperationFailed
primary_error_code : 16908390 (0×01020066)
secondary_error_code : 0
error_string : 01020066:3: The requested pool (/Common/puppet-test-pool) already exists in partition Common. at /etc/puppet/manifests/nodes.pp:162
The error should only occur if you are managing the pool from a separate partition. So for example if you access from partition testing, and the pool exists in partition Common, you can’t manage this resource because F5 does not allow for duplicate resource:
In this case resource in the each partition should be managed as seperate nodes i.e.
Since on the same f5 device, you can’t have the same resource name, so it’s probably ideal to prefix other partitions with the partition name, and not touch resources in Common. If you are managing the Common partition and this error was triggered, please file an issue in projects.puppetlabs.com and notify me.
Thanks,
Nan
In the example above, what attribute do we need to specify in order to disable the member? i.e. i want to add ’10.10.0.1:80′ to the pool, but want to leave it in a disabled state?
The closest api call for LocalLB.PoolMember appears to be get/set_session_enabled_state. This simply controls whether new session are allowed to connect to the member. This isn’t an option that’s supported in the current official release, but seems like a one line change in f5_pool.rb provider file:
methods = [ 'connection_limit', 'dynamic_ratio', 'priority', 'ratio', ]to:
methods = [ 'connection_limit', 'dynamic_ratio', 'priority', 'ratio', 'session_enabled_state', ]Feel free to test this and see if this meets your need. A feature request in redmine would be appreciated (a patch would be even better).
In re: Luis’s problems with ensuring an f5 resource ‘present’ after having made it ‘absent’ before, I was seeing the same behavior right after the appliances I’m building were upgraded from 10.2.3 to 11.1.0.
Problems only seemed to come up when I tried to modify an existing resource.. The f5 would return with “The requested [resource] already exists in partition Common.”
I first tried appending the partition name (Common, in this case) to the device URL, but that didn’t have any effect. The puppet debug output was pretty clear that it was connecting to the Common partition regardless.
What worked was prepending the partition to my resource names, so instead of @f5::rule {‘myrule’}@ I write it as @f5::rule {‘/Common/myrule’}@
I’m still finding my legs with Puppet so it’s possible this was caused by a misconfiguration elsewhere, but this is what I’m seeing.
Thanks Steve for the detail info. The module was written against F5 v10. I don’t have v11 ready. Please try the custom branch and run it with the -d debug flag:
https://github.com/nanliu/puppetlabs-f5/tree/tb/debug
Specifically I’m interested in:
Puppet::Device::F5: connecting to F5 partition #{@partition} after parsing #{@url.path}.
Also for these type of issues, please file a ticket in projects.puppetlabs.com and feel free to ping me.
I went a while without access to the LTMs running v11, but I can confirm the custom branch worked as expected. I was able to connect to and manipulate rules in Common without prefixing them with ‘/Common/’.
OpenStack | think about…
[...] PuppetはF5 BIGIPも制御可能 Managing F5 BIG-IP Network Devices with Puppet [...]
Puppet @DC運用管理の自動化を助けるソフトウェア | think about…
[...] F5 BIGIPも制御可能 Managing F5 BIG-IP Network Devices with Puppet [...]