Load balancing with F5 and legacy Google-provided controllers
Stay organized with collections
Save and categorize content based on your preferences.
In version 1.29 and lower, user clusters created with the
loadBalancer.f5BigIP
configuration deployed F5 controllers provided by Google. Because these controllers
have
limitations,
in version 1.30 and higher, Google Distributed Cloud blocks creating clusters with the
loadBalancer.f5BigIP configuration. Instead, new clusters must be configured for
manual load balancing, and you need to
deploy F5 controllers yourself.
This page shows how to deploy the legacy Google-provided F5 controllers for a user
cluster created with Google Distributed Cloud. Although deploying these controllers is
supported, we recommend that you install the latest CIS controller from F5.
Prerequisites:
You have a user cluster with the manualLB configuration.
You have a F5 server for the user cluster and you know its login information.
You want to automate the process to configure virtual servers in F5 for
Kubernetes Services of type LoadBalancer in your user cluster.
Step1. Prepare templates for the controllers
Get the F5 information and generate the templates.
Get F5 information
Set the following placeholder variables with the login information from
the F5 server:
F5 UserName: USERNAME
F5 Password: PASSWORD
F5 Address: ADDRESS
F5 Partition: PARTITION
Set the SnatPoolName. If you aren't using SNAT, leave the placeholder
variable empty:
SnatPoolName: SNAT_POOL_NAME
Get the registry and version information
Get the onpremusercluster custom resource:
kubectl --kubeconfig USER_CLUSTER_KUBECONFIG get onpremusercluster -oyaml -n kube-system
Copy the following fields from the onpremusercluster custom resource:
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Hard to understand","hardToUnderstand","thumb-down"],["Incorrect information or sample code","incorrectInformationOrSampleCode","thumb-down"],["Missing the information/samples I need","missingTheInformationSamplesINeed","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-08-25 UTC."],[],[],null,["# Load balancing with F5 and legacy Google-provided controllers\n\nIn version 1.29 and lower, user clusters created with the\n[loadBalancer.f5BigIP](/kubernetes-engine/distributed-cloud/vmware/docs/how-to/user-cluster-configuration-file-latest#loadbalancer-f5bigip-section)\nconfiguration deployed F5 controllers provided by Google. Because these controllers\nhave\n[limitations](/kubernetes-engine/distributed-cloud/vmware/docs/concepts/migrate-recommended-features#migrate_configuration_settings_for_your_f5_big-ip_load_balancer),\nin version 1.30 and higher, Google Distributed Cloud blocks creating clusters with the\n`loadBalancer.f5BigIP` configuration. Instead, new clusters must be configured for\n[manual load balancing](/kubernetes-engine/distributed-cloud/vmware/docs/how-to/manual-load-balance), and you need to\ndeploy F5 controllers yourself.\n\nThis page shows how to deploy the legacy Google-provided F5 controllers for a user\ncluster created with Google Distributed Cloud. Although deploying these controllers is\nsupported, we recommend that you install the latest CIS controller from F5.\n\nPrerequisites:\n--------------\n\n- You have a user cluster with the [manualLB](/kubernetes-engine/distributed-cloud/vmware/docs/how-to/user-cluster-configuration-file-latest#loadbalancer-manuallb-section) configuration.\n\n- You have a F5 server for the user cluster and you know its login information.\n\n- You want to automate the process to configure virtual servers in F5 for\n Kubernetes Services of type LoadBalancer in your user cluster.\n\nStep1. Prepare templates for the controllers\n--------------------------------------------\n\nGet the F5 information and generate the templates.\n\n### Get F5 information\n\n1. Set the following placeholder variables with the login information from\n the F5 server:\n\n - F5 UserName: \u003cvar class=\"edit\" scope=\"USERNAME\" translate=\"no\"\u003eUSERNAME\u003c/var\u003e\n\n - F5 Password: \u003cvar class=\"edit\" scope=\"PASSWORD\" translate=\"no\"\u003ePASSWORD\u003c/var\u003e\n\n - F5 Address: \u003cvar class=\"edit\" scope=\"ADDRESS\" translate=\"no\"\u003eADDRESS\u003c/var\u003e\n\n - F5 Partition: \u003cvar class=\"edit\" scope=\"PARTITION\" translate=\"no\"\u003ePARTITION\u003c/var\u003e\n\n2. Set the `SnatPoolName`. If you aren't using SNAT, leave the placeholder\n variable empty:\n\n ```\n SnatPoolName: SNAT_POOL_NAME\n ```\n\n### Get the registry and version information\n\n1. Get the `onpremusercluster` custom resource:\n\n ```\n kubectl --kubeconfig USER_CLUSTER_KUBECONFIG get onpremusercluster -oyaml -n kube-system\n ```\n2. Copy the following fields from the `onpremusercluster` custom resource:\n\n ```\n Registry: REGISTRY (onpremusercluster.spec.registry.address)\n ImageTag: IMAGE_TAG (onpremusercluster.spec.gkeOnPremVersion)\n ```\n\nGenerate the templates\n----------------------\n\n```\ncat \u003e templates.yaml \u003c\u003c EOF\napiVersion: v1\nkind: Secret\nmetadata:\n name: bigip-login\n namespace: kube-system\nstringData:\n password: \"PASSWORD\"\n username: \"USERNAME\"\n url: \"ADDRESS\"\n partition: \"PARTITION\"\n---\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n name: bigip-ctlr\n namespace: kube-system\n---\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n name: load-balancer-f5\n namespace: kube-system\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: k8s-bigip-ctlr-deployment\n namespace: kube-system\nspec:\n replicas: 1\n selector:\n matchLabels:\n app: k8s-bigip-ctlr\n template:\n metadata:\n name: k8s-bigip-ctlr\n labels:\n app: k8s-bigip-ctlr\n spec:\n serviceAccountName: bigip-ctlr\n volumes:\n - name: bigip-login\n secret:\n secretName: bigip-login\n containers:\n - name: k8s-bigip-ctlr\n image: \"REGISTRY/k8s-bigip-ctlr:v1.14.0-gke.28\"\n resources:\n requests:\n cpu: 60m\n memory: 90Mi\n volumeMounts:\n - name: bigip-login\n readOnly: true\n mountPath: \"/etc/bigip-login\"\n env:\n - name: BIGIP_PARTITION\n valueFrom:\n secretKeyRef:\n name: bigip-login\n key: partition\n command: [\"/app/bin/k8s-bigip-ctlr\"]\n args: [\n # See the k8s-bigip-ctlr documentation for information about\n # all config options\n # http://clouddocs.f5.com/products/connectors/k8s-bigip-ctlr/latest\n \"--http-listen-address=:9097\",\n \"--credentials-directory=/etc/bigip-login\",\n \"--bigip-partition=\\$(BIGIP_PARTITION)\",\n \"--log-level=ERROR\",\n \"--pool-member-type=nodeport\",\n \"--manage-ingress=false\",\n \"--vs-snat-pool-name=SNAT_POOL_NAME\"\n ]\n dnsPolicy: Default\n imagePullSecrets:\n - name: private-registry-creds\n nodeSelector:\n kubernetes.io/os: linux\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: load-balancer-f5\n namespace: kube-system\n labels:\n app: load-balancer-f5\nspec:\n replicas: 1\n selector:\n matchLabels:\n app: load-balancer-f5\n template:\n metadata:\n name: load-balancer-f5\n labels:\n app: load-balancer-f5\n spec:\n serviceAccountName: load-balancer-f5\n containers:\n - name: load-balancer-f5\n image: \"REGISTRY/load-balancer-f5:IMAGE_TAG\"\n env:\n - name: BIGIP_PARTITION\n valueFrom:\n secretKeyRef:\n name: bigip-login\n key: partition\n command:\n - ./load-balancer-f5\n args:\n - \"--bigip-partition=\\$(BIGIP_PARTITION)\"\n resources:\n requests:\n cpu: 2m\n memory: 13Mi\n imagePullSecrets:\n - name: private-registry-creds\n nodeSelector:\n kubernetes.io/os: linux\n---\nkind: ClusterRoleBinding\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n name: bigip-ctlr-clusterrole-binding\nroleRef:\n apiGroup: rbac.authorization.k8s.io\n kind: ClusterRole\n name: bigip-ctlr-clusterrole\nsubjects:\n - kind: ServiceAccount\n name: bigip-ctlr\n namespace: kube-system\n---\nkind: ClusterRoleBinding\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n name: load-balancer-f5-clusterrole-binding\nroleRef:\n apiGroup: rbac.authorization.k8s.io\n kind: ClusterRole\n name: load-balancer-f5-clusterrole\nsubjects:\n - kind: ServiceAccount\n name: load-balancer-f5\n namespace: kube-system\n---\nkind: ClusterRole\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n name:\n bigip-ctlr-clusterrole\nrules:\n - apiGroups: [\"\", \"extensions\"]\n resources: [\"nodes\", \"services\", \"endpoints\", \"namespaces\", \"ingresses\", \"pods\"]\n verbs: [\"get\", \"list\", \"watch\"]\n - apiGroups: [\"\", \"extensions\"]\n resources: [\"configmaps\", \"events\", \"ingresses/status\"]\n verbs: [\"get\", \"list\", \"watch\"]\n - apiGroups: [\"\", \"extensions\"]\n resources: [\"secrets\"]\n resourceNames: [\"bigip-login\"]\n verbs: [\"get\", \"list\", \"watch\"]\n---\nkind: ClusterRole\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n name:\n load-balancer-f5-clusterrole\nrules:\n - apiGroups: [\"\"]\n resources: [\"events\", \"nodes\"]\n verbs: [\"get\", \"list\", \"watch\"]\n - apiGroups: [\"\"]\n resources: [\"services\", \"services/status\"]\n verbs: [\"get\", \"list\", \"watch\", \"patch\", \"update\"]\n - apiGroups: [\"\"]\n resources: [\"configmaps\"]\n verbs: [\"get\", \"list\", \"watch\", \"create\", \"patch\", \"delete\"]\nEOF\n```\n\nStep2. Apply the templates to user cluster\n------------------------------------------\n\n```\nkubectl --kubeconfig USER_CLUSTER_KUBECONFIG apply -f templates.yaml\n```\n| **Note:** After every upgrade of the cluster's control plane, you have to make these changes."]]