Send feedback
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.
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 onpremusercluster
custom resource:
kubectl --kubeconfig USER_CLUSTER_KUBECONFIG get onpremusercluster -oyaml -n kube-system
Copy the following fields from the onpremusercluster
custom resource:
Registry: REGISTRY (onpremusercluster.spec.registry.address)
ImageTag: IMAGE_TAG (onpremusercluster.spec.gkeOnPremVersion)
Generate the templates
cat > templates.yaml << EOF
apiVersion: v1
kind: Secret
metadata:
name: bigip-login
namespace: kube-system
stringData:
password: "PASSWORD "
username: "USERNAME "
url: "ADDRESS "
partition: "PARTITION "
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: bigip-ctlr
namespace: kube-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: load-balancer-f5
namespace: kube-system
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: k8s-bigip-ctlr-deployment
namespace: kube-system
spec:
replicas: 1
selector:
matchLabels:
app: k8s-bigip-ctlr
template:
metadata:
name: k8s-bigip-ctlr
labels:
app: k8s-bigip-ctlr
spec:
serviceAccountName: bigip-ctlr
volumes:
- name: bigip-login
secret:
secretName: bigip-login
containers:
- name: k8s-bigip-ctlr
image: "REGISTRY /k8s-bigip-ctlr:v1.14.0-gke.28"
resources:
requests:
cpu: 60m
memory: 90Mi
volumeMounts:
- name: bigip-login
readOnly: true
mountPath: "/etc/bigip-login"
env:
- name: BIGIP_PARTITION
valueFrom:
secretKeyRef:
name: bigip-login
key: partition
command: ["/app/bin/k8s-bigip-ctlr"]
args: [
# See the k8s-bigip-ctlr documentation for information about
# all config options
# http://clouddocs.f5.com/products/connectors/k8s-bigip-ctlr/latest
"--http-listen-address=:9097",
"--credentials-directory=/etc/bigip-login",
"--bigip-partition=\$(BIGIP_PARTITION)",
"--log-level=ERROR",
"--pool-member-type=nodeport",
"--manage-ingress=false",
"--vs-snat-pool-name=SNAT_POOL_NAME "
]
dnsPolicy: Default
imagePullSecrets:
- name: private-registry-creds
nodeSelector:
kubernetes.io/os: linux
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: load-balancer-f5
namespace: kube-system
labels:
app: load-balancer-f5
spec:
replicas: 1
selector:
matchLabels:
app: load-balancer-f5
template:
metadata:
name: load-balancer-f5
labels:
app: load-balancer-f5
spec:
serviceAccountName: load-balancer-f5
containers:
- name: load-balancer-f5
image: "REGISTRY /load-balancer-f5:IMAGE_TAG "
env:
- name: BIGIP_PARTITION
valueFrom:
secretKeyRef:
name: bigip-login
key: partition
command:
- ./load-balancer-f5
args:
- "--bigip-partition=\$(BIGIP_PARTITION)"
resources:
requests:
cpu: 2m
memory: 13Mi
imagePullSecrets:
- name: private-registry-creds
nodeSelector:
kubernetes.io/os: linux
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: bigip-ctlr-clusterrole-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: bigip-ctlr-clusterrole
subjects:
- kind: ServiceAccount
name: bigip-ctlr
namespace: kube-system
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: load-balancer-f5-clusterrole-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: load-balancer-f5-clusterrole
subjects:
- kind: ServiceAccount
name: load-balancer-f5
namespace: kube-system
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name:
bigip-ctlr-clusterrole
rules:
- apiGroups: ["", "extensions"]
resources: ["nodes", "services", "endpoints", "namespaces", "ingresses", "pods"]
verbs: ["get", "list", "watch"]
- apiGroups: ["", "extensions"]
resources: ["configmaps", "events", "ingresses/status"]
verbs: ["get", "list", "watch"]
- apiGroups: ["", "extensions"]
resources: ["secrets"]
resourceNames: ["bigip-login"]
verbs: ["get", "list", "watch"]
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name:
load-balancer-f5-clusterrole
rules:
- apiGroups: [""]
resources: ["events", "nodes"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["services", "services/status"]
verbs: ["get", "list", "watch", "patch", "update"]
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list", "watch", "create", "patch", "delete"]
EOF
Step2. Apply the templates to user cluster
kubectl --kubeconfig USER_CLUSTER_KUBECONFIG apply -f templates.yaml
Note: After every upgrade of the cluster's control plane, you have to make
these changes.
Send feedback
Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License , and code samples are licensed under the Apache 2.0 License . For details, see the Google Developers Site Policies . Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2025-09-04 UTC.
Need to tell us more?
[[["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-09-04 UTC."],[],[],null,["In 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- 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\nGet the F5 information and generate the templates.\n\nGet 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\nGet 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```\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```\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."]]