Skip to content

Terraform modules for deploying F5 BIG-IP on Google Cloud Platform. Community supported.

License

Notifications You must be signed in to change notification settings

memes/terraform-google-f5-bigip

Repository files navigation

Unofficial F5 BIG-IP Terraform modules for Google Cloud Platform

You are viewing a 2.x release of the modules, which supports Terraform 0.13 and 0.14 only. For modules compatible with Terraform 0.12, use a 1.x release. Functionality is identical, but separate releases are required due to the difference in variable validation between Terraform 0.12 and 0.13+.

This repo contains unofficial and unsupported1 Terraform modules to deploy F5 BIG-IP Virtual Edition on Google Cloud Platform, using a modular approach that can be composed into a solution that is consistent for each variant of a product.

TIP: If you require assistance please join our Slack GCP channel and ask!

These modules support deploying supported BIG-IP versions instances to Google Cloud in an opinionated manner. By themselves they do not implement a full stack or solution, and additional setup will be needed for firewall rules, service account creation and role assignments.

NOTE: The modules do not include setup and configuration of supporting resources, such as ingress firewall rules or service accounts. Where required, the examples will include the bare-minimum setup to demonstrate usage.

Examples are provided for standalone, HA and CFE deployments.

Rationale

The intent is allow for integration of BIG-IP with GCP infrastructure that is managed using Google's Cloud Foundation Toolkit Terraform modules or an equivalent. The modules here are not fully-baked solutions, but can be integrated with foundational elements to build a reusable deployment pipeline.

For example, the modules do not include ingress firewall rule resources as core module components. This is because some organizations may mandate use of service account based rules, where others prefer tag based, or a combination of both where interfaces are attached to peered VPCs. The exception to this is the firewall module to support ConfigSync for HA and CFE clusters; since the BIG-IPs will be deployed to the same VPC networks, it is reasonably safe to assume a service account based rule will be universally applicable.

BIG-IP module options

The BIG-IP module will create standalone BIG-IP VMs that include default AS3 and DO declarations (unless overridden). The sub-modules extend the standalone functionality while retaining an the same API (implemented as Terraform input variables) where possible. This promotes consistency and reuse when your project calls for a CFE or Autoscaling approach. For more information about these see the README files in each sub-module.

  • Standalone BIG-IP instances
    • Support 1-8 network interfaces
    • Opinionated startup scripts
    • Override default gateway when needed; e.g. for bootstrapping in a restricted VPC where data-plane does not have egress
    • Applications Services 3 extension support
    • Declarative Onboarding extension support
  • High-availability BIG-IP clusters
    • configsync-fw helper sub-module to create required firewall rules for ConfigSync on control and data-plane networks
    • Cloud Failover Extension support
    • cfe-role helper sub-module to create a custom role which satisfies the minimum privileges required for CFE to interact with GCP APIs

Dependencies

The BIG-IP modules all have a common set of requirements.

  1. Terraform 0.13.x or 0.14.x

    You are viewing a 2.x release of the modules, which supports Terraform 0.13 or 0.14 only. For modules compatible with Terraform 0.12, use a 1.x release. Functionality is identical, but separate releases are required due to the difference in variable validation between Terraform 0.12 and 0.13+.

  2. Google Cloud Secret Manager

    There are many good options for run-time secret injection but this module is supporting Google's Secret Manager only at this time.

  3. APIs to enable

    • Compute Engine compute.googleapis.com
    • Secret Manager secretmanager.googleapis.com
    • Storage (required for CFE) storage-api.googleapis.com

Run-time setup

The BIG-IP modules in this repo support cloud-init and metadata-startup-script boot options, defaulting to the metadata startup-script for compatibility with BIG-IP versions 13.x, 14.x, and 15.x. Set the use_cloud_init input variable to true to force the use of cloud-init on BIG-IP v15+.

Fundamentally both approaches launch the same shell scripts; the difference is that cloud-init script installs a systemd service unit with dependencies to prevent early execution, and automatically disables the service unit after success. The simple metadata startup-script will execute on every boot.

For more information on how run-time configuration is applied to each BIG-IP instance through the use of Terraform variables see CONFIGURATION. For guidelines and steps to diagnose deployment and run-time issues see TROUBLESHOOTING.

Requirements

Name Version
terraform > 0.12
google >= 3.48

Providers

Name Version
google >= 3.48

Modules

Name Source Version
do_payloads ./modules/do-builder/
metadata ./modules/metadata/

Resources

Name Type
google_compute_instance.bigip resource

Inputs

Name Description Type Default Required
admin_password_secret_manager_key The Secret Manager key for BIG-IP admin password; during initialisation, the
BIG-IP admin account's password will be changed to the value retrieved from GCP
Secret Manager (or other implementor - see secret_implementor) using this key.

NOTE: if the secret does not exist, is misidentified, or if the VM cannot read
the secret value associated with this key, then the BIG-IP onboarding will fail
to complete, and onboarding will require manual intervention.
string n/a yes
external_subnetwork The fully-qualified self-link of the subnet that will be used for external ingress
(2+ NIC deployment), or for all traffic in a 1NIC deployment.
string n/a yes
image The self-link URI for a BIG-IP image to use as a base for the VM cluster. This
can be an official F5 image from GCP Marketplace, or a customised image.
string n/a yes
project_id The GCP project identifier where the cluster will be created. string n/a yes
service_account The service account that will be used for the BIG-IP VMs. string n/a yes
zones The compute zones which will host the BIG-IP VMs. list(string) n/a yes
allow_phone_home Allow the BIG-IP VMs to send high-level device use information to help F5
optimize development resources. If set to false the information is not sent.
bool true no
as3_payloads An optional, but recommended, list of AS3 JSON files that can be used to setup
the BIG-IP instances. If left empty (default), the module will use a simple
no-op AS3 declaration.
list(string) [] no
automatic_restart Determines if the BIG-IP VMs should be automatically restarted if terminated by
GCE. Defaults to true to match expected GCE behaviour.
bool true no
custom_script An optional, custom shell script that will be executed during BIG-IP
initialisation, after BIG-IP networking is auto-configured, admin password is set from Secret
Manager (if possible), etc. Declarative Onboarding offers a better approach,
where suitable (see do_payload).

NOTE: this value should contain the script contents, not a file path.
string "" no
default_gateway Set this to the value to use as the default gateway for BIG-IP instances. This
must be a valid IP address or an empty string. If left blank (default), the
generated Declarative Onboarding JSON will use the gateway associated with nic0
at run-time.
string "" no
delete_disk_on_destroy Set this flag to false if you want the boot disk associated with the launched VMs
to survive when instances are destroyed. The default value of true will ensure the
boot disk is destroyed when the instance is destroyed.
bool true no
disk_size_gb Use this flag to set the boot volume size in GB. If left at the default value
the boot disk will have the same size as specified in 'bigip_image'.
number null no
disk_type The boot disk type to use with instances; can be 'pd-ssd' (default), or
'pd-standard'.
Note: Choosing 'pd-standard' will reduce operating cost, but at the expense of
network performance.
string "pd-ssd" no
dns_servers An optional list of DNS servers for BIG-IP instances to use if custom DO payloads
are not provided. The default is ["169.254.169.254"] to use GCE metadata server.
list(string)
[
"169.254.169.254"
]
no
do_payloads The Declarative Onboarding contents to apply to the instances. Required. This
module has migrated to use of Declarative Onboarding for module activation,
licensing, NTP, DNS, and other basic configurations. Sample payloads are in the
examples folder.

Note: if left empty, the module will use a simple JSON that sets NTP and DNS,
and enables LTM.
list(string) [] no
domain_name An optional domain name to append to generated instance names to fully-qualify
them. If an empty string (default), then the instances will be qualified as-per
Google Cloud internal naming conventions ".ZONE.c.PROJECT_ID.internal".
string "" no
enable_serial_console Set to true to enable serial port console on the VMs. Default value is false. bool false no
external_subnetwork_network_ips An optional list of private IP addresses to assign to BIG-IP instances on their
externa interface. The list may be empty, or contain empty strings, to selectively
applies addresses to instances.
list(string) [] no
external_subnetwork_public_ips An optional list of public IP addresses to assign to BIG-IP instances on their
external interface. The list may be empty, or contain empty strings, to selectively
applies addresses to instances.

Note: these values are only applied if provision_external_public_ip is 'true'
and will be ignored if that value is false.
list(string) [] no
external_subnetwork_tier The network tier to set for external subnetwork; must be one of 'PREMIUM'
(default) or 'STANDARD'. This setting only applies if the external interface is
permitted to have a public IP address (see provision_external_public_ip)
string "PREMIUM" no
external_subnetwork_vip_cidrs An optional list of VIP CIDR lists to assign to BIG-IP instances on their
external interface. E.g. to assign two CIDR blocks as VIPs on the first instance,
and a single IP address as a VIP on the second instance:-

external_subnetwork_vip_cidrs = [
[
"10.1.0.0/16",
"10.2.0.0/24",
],
[
"192.168.0.1/32",
]
]
list(list(string)) [] no
external_subnetwork_vip_cidrs_named_range An optional named range to use when assigning CIDRs to BIG-IP instances as VIPs
on their external interface. E.g. to assign CIDRs from
secondary range 'dmz-bigip':-

external_subnetwork_vip_cidrs_named_range = "dmz-bigip"
string "" no
extramb The amount of extra RAM (in Mb) to allocate to BIG-IP administrative processes;
must be an integer between 0 and 2560. The default of 2048 is recommended for
BIG-IP instances on GCP; setting too low can cause issues when applying large DO
or AS3 payloads.
number 2048 no
install_cloud_libs An optional list of cloud library URLs that will be downloaded and installed on
the BIG-IP VM during initial boot. The contents of each download will be compared
to the verifyHash file, and failure will cause the boot scripts to fail. Default
list will install F5 Cloud Libraries (w/GCE extension), AS3, Declarative
Onboarding, and Telemetry Streaming extensions.
list(string)
[
"https://github.com/F5Networks/f5-appsvcs-extension/releases/download/v3.25.0/f5-appsvcs-3.25.0-3.noarch.rpm",
"https://github.com/F5Networks/f5-declarative-onboarding/releases/download/v1.18.0/f5-declarative-onboarding-1.18.0-4.noarch.rpm",
"https://github.com/F5Networks/f5-telemetry-streaming/releases/download/v1.17.0/f5-telemetry-1.17.0-4.noarch.rpm"
]
no
instance_name_template A format string that will be used when naming instance, that should include a
format token for including integer ordinal numbers as defined in Go fmt package,
including support for zero-padding etc. Default value is 'bigip-%d' which will
generate names of 'bigip-0', 'bigip-1', through 'bigip-N', where N is the number
of instances - 1.

Examples:
instance_name_template = "bigip-%03d" will create instances named 'bigip-000',
'bigip-001', etc.
instance_name_template = "prod-ha-%x" will create instances using lower-case hex
, such as 'prod-ha-0' ... 'prod-ha-1f'.

See instance_ordinal_offset variable to change the lower bounds of the numbering
scheme.
string "bigip-%d" no
instance_ordinal_offset An offset to apply to each instance ordinal when naming; use to change zero-based
instance ordinal to a different number when setting instance names and hostnames.
Default value is '0'.

E.g. to change 0-based instance names ('bigip-0', 'bigip-1', etc.) to 1-based
instance names ('bigip-1', 'bigip-2', etc.) use
instance_ordinal_offset = 1

See instance_name_template for more examples.
number 0 no
internal_subnetwork_network_ips An optional list of lists of private IP addresses to assign to BIG-IP instances
on their internal interface. The list may be empty, or contain empty strings, to
selectively applies addresses to instances. E.g. to assign addresses to two
internal networks:

internal_subnetwork_network_ips = [
# Will be assigned to first instance
[
"10.0.0.4", # first internal nic
"10.0.1.4", # second internal nic
],
# Will be assigned to second instance
[
...
],
...
]
list(list(string)) [] no
internal_subnetwork_public_ips An optional list of lists of public IP addresses to assign to BIG-IP instances
on their internal interface. The list may be empty, or contain empty strings, to
selectively applies addresses to instances.

Note: these values are only applied if provision_internal_public_ip is 'true'
and will be ignored if that value is false.

E.g. to assign addresses to two internal networks:

internal_subnetwork_network_ips = [
# Will be assigned to first instance
[
"x.x.x.x", # first internal nic
"y.y.y.y", # second internal nic
],
# Will be assigned to second instance
[
...
],
...
]
list(list(string)) [] no
internal_subnetwork_tier The network tier to set for internal subnetwork; must be one of 'PREMIUM'
(default) or 'STANDARD'. This setting only applies if the internal interface is
permitted to have a public IP address (see provision_internal_public_ip)
string "PREMIUM" no
internal_subnetwork_vip_cidrs An optional list of CIDR lists to assign to BIG-IP instances as VIPs on their
internal interface. E.g. to assign two CIDR blocks as VIPs on the first
instance, and a single IP address as a VIP on the second instance:-

internal_subnetwork_vip_cidrs = [
# Will be assigned to first instance
[
["10.1.0.0/16"], # first internal nic
["10.2.0.0/24"], # second internal nic
],
# Will be assigned to second instance
[
["192.168.0.1/32"], # first internal nic
]
]
list(list(list(string))) [] no
internal_subnetwork_vip_cidrs_named_ranges An optional named range to use when assigning CIDRs to BIG-IP instances as VIPs
on their internal interfaces. E.g. to assign CIDRs from
secondary range 'internal-bigip' on first internal interface:-

internal_subnetwork_vip_cidrs_named_ranges = [
"internal-bigip",
]
list(string) [] no
internal_subnetworks An optional list of fully-qualified subnet self-links that will be assigned as
internal traffic on NICs eth[2-8].
list(string) [] no
labels An optional map of labels to add to the instance template. map(string) {} no
machine_type The machine type to use for BIG-IP VMs; this may be a standard GCE machine type,
or a customised VM ('custom-VCPUS-MEM_IN_MB'). Default value is 'n1-standard-4'.
Note: machine_type is highly-correlated with network bandwidth and performance;
an N2 or N2D machine type will give better performance but has limited availability.
string "n1-standard-4" no
management_subnetwork An optional fully-qualified self-link of the subnet that will be used for
management access (2+ NIC deployment).
string null no
management_subnetwork_network_ips An optional list of private IP addresses to assign to BIG-IP instances on their
management interface. The list may be empty, or contain empty strings, to
selectively applies addresses to instances.
list(string) [] no
management_subnetwork_public_ips An optional list of public IP addresses to assign to BIG-IP instances on their
management interface. The list may be empty, or contain empty strings, to
selectively applies addresses to instances.

Note: these values are only applied if provision_management_public_ip is 'true'
and will be ignored if that value is false.
list(string) [] no
management_subnetwork_tier The network tier to set for management subnetwork; must be one of 'PREMIUM'
(default) or 'STANDARD'. This setting only applies if the management interface is
permitted to have a public IP address (see provision_management_public_ip)
string "PREMIUM" no
management_subnetwork_vip_cidrs An optional list of CIDR lists to assign to BIG-IP instances as VIPs on their
management interface. E.g. to assign two CIDR blocks as VIPs on the first
instance, and a single IP address as an alias on the second instance:-

external_subnetwork_vip_cidrs = [
[
"10.1.0.0/16",
"10.2.0.0/24",
],
[
"192.168.0.1/32",
]
]
list(list(string)) [] no
management_subnetwork_vip_cidrs_named_range An optional named range to use when assigning CIDRs to BIG-IP instances as VIPs
on their management interface. E.g. to assign CIDRs from
secondary range 'management-bigip':-

management_subnetwork_vip_cidrs_named_range = "management-bigip"
string "" no
metadata An optional map of metadata values that will be applied to the instances. map(string) {} no
min_cpu_platform An optional constraint used when scheduling the BIG-IP VMs; this value prevents
the VMs from being scheduled on hardware that doesn't meet the minimum CPU
micro-architecture. Default value is 'Intel Skylake'.
string "Intel Skylake" no
modules A map of BIG-IP module = provisioning-level pairs to enable, where the module
name is key, and the provisioning-level is the value. This value is used with the
default Declaration Onboarding template; a better option for full control is to
explicitly declare the modules to be provisioned as part of a custom JSON file.
See do_payloads.

E.g. the default is
modules = {
ltm = "nominal"
}

To provision ASM and LTM, the value might be:-
modules = {
ltm = "nominal"
asm = "nominal"
}
map(string)
{
"ltm": "nominal"
}
no
ntp_servers An optional list of NTP servers for BIG-IP instances to use if custom DO files
are not provided. The default is ["169.254.169.254"] to use GCE metadata server.
list(string)
[
"169.254.169.254"
]
no
num_instances The number of standalone BIG-IP instances to provision. Default value is 1. number 1 no
preemptible If set to true, the BIG-IP instances will be deployed on preemptible VMs, which
could be terminated at any time, and have a maximum lifetime of 24 hours. Default
value is false.
string false no
provision_external_public_ip If this flag is set to true (default), a publicly routable IP address WILL be
assigned to the external interface of instances. If set to false, the BIG-IP
instances will NOT have a public IP address assigned to the external interface.
bool true no
provision_internal_public_ip If this flag is set to true, a publicly routable IP address WILL be assigned to
the internal interfaces of instances. If set to false (default), the BIG-IP
instances will NOT have a public IP address assigned to the internal interfaces.
bool false no
provision_management_public_ip If this flag is set to true, a publicly routable IP address WILL be assigned to
the management interface of instances. If set to false (default), the BIG-IP
instances will NOT have a public IP address assigned to the management interface.
bool false no
search_domains An optional list of DNS search domains for BIG-IP instances to use if custom DO
payloads are not provided. If left empty (default), search domains will be added
for "google.internal" and the zone/project specific domain assigned to instances.
list(string) [] no
secret_implementor The secret retrieval implementor to use; default value is an empty string.
Must be an empty string, 'google_secret_manager', or 'metadata'. Future
enhancements will add other implementors.
string "" no
ssh_keys An optional set of SSH public keys, concatenated into a single string. The keys
will be added to instance metadata. Default is an empty string.
string "" no
tags An optional list of network tags to add to the instance template. list(string) [] no
timezone The Olson timezone string from /usr/share/zoneinfo for BIG-IP instances if custom
DO files are not provided. The default is 'UTC'. See the TZ column here
(https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) for legal values.
For example, 'US/Eastern'.
string "UTC" no
use_cloud_init If this value is set to true, cloud-init will be used as the initial
configuration approach; false (default) will fall-back to a standard shell
script for boot-time configuration.

Note: the BIG-IP version must support Cloud Init on GCP for this to function
correctly. E.g. v15.1+.
bool false no

Outputs

Name Description
external_addresses A list of the IP addresses and alias CIDRs assigned to instances on the external
NIC.
external_public_ips A list of the public IP addresses assigned to instances on the external NIC.
external_vips A list of IP CIDRs assigned to instances on the external NIC, which usually
corresponds to the VIPs defined on each instance.
instance_addresses A map of instance name to assigned IP addresses and alias CIDRs.
internal_addresses A list of the IP addresses and alias CIDRs assigned to instances on the internal
NICs, if present.
internal_public_ips A list of the public IP addresses assigned to instances on the internal NICs,
if present.
management_addresses A list of the IP addresses and alias CIDRs assigned to instances on the
management NIC, if present.
management_public_ips A list of the public IP addresses assigned to instances on the management NIC,
if present.
self_links A list of self-links of the BIG-IP instances.
zone_instances A map of compute zones from var.zones input variable to instance self-links. If
no instances are deployed to a zone, the mapping will be to an empty list.

E.g. if var.zones = ["us-east1-a", "us-east1-b", "us-east1-c"] and
var.num_instances = 2 then the output will be:
{
us-east1-a = [self-link-instance0]
us-east1-b = [self-link-instance1]
us-east1-c = []
}

1This repo will be maintained on a best-effort basis, but is not a substitute for F5 support.