Configure a load balancer for AlloyDB Omni on Kubernetes

Select a documentation version:

To expose your AlloyDB Omni database cluster to clients outside your Kubernetes cluster, you can configure a LoadBalancer Service in the DBCluster manifest. This document is for database administrators and Kubernetes operators who manage AlloyDB Omni deployments on Kubernetes and need to customize load balancer behavior.

When you enable external incoming traffic in your DBCluster manifest, the AlloyDB Omni Kubernetes operator creates a Kubernetes Service object of type LoadBalancer. Different Kubernetes platforms use custom annotations to control load balancer properties, such as internal or external IP address assignment. AlloyDB Omni lets you specify these annotations in the spec.primarySpec.dbLoadBalancerOptions.annotations field of your DBCluster manifest. When you create or update the database cluster with spec.allowExternalIncomingTraffic set to true, the AlloyDB Omni operator applies those annotations to the metadata.annotations field of the LoadBalancer Service object.

Configure a load balancer using the database spec

You can configure custom load balancer annotations by setting the dbLoadBalancerOptions field in the spec.primarySpec section of your DBCluster manifest.

Kubernetes

Annotations define the type and properties of the load balancer Service object in your Kubernetes environment. Check the documentation for your Kubernetes platform or load balancer implementation to identify the supported annotation keys and values.

To create a database cluster with custom load balancer annotations and allow incoming traffic from outside the Kubernetes cluster, apply the following manifest:

kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
  name: db-pw-DB_CLUSTER_NAME
  namespace: NAMESPACE
type: Opaque
data:
  DB_CLUSTER_NAME: "ENCODED_PASSWORD"
---
apiVersion: alloydbomni.dbadmin.goog/v1
kind: DBCluster
metadata:
  name: DB_CLUSTER_NAME
  namespace: NAMESPACE
spec:
  databaseVersion: "17.5.0"
  primarySpec:
    adminUser:
      passwordRef:
        name: db-pw-DB_CLUSTER_NAME
    resources:
      memory: 5Gi
      cpu: 1
      disks:
      - name: DataDisk
        size: 10Gi
    dbLoadBalancerOptions:
      annotations:
        ANNOTATION_KEY: "ANNOTATION_VALUE"
  allowExternalIncomingTraffic: true
EOF

Replace the following:

  • DB_CLUSTER_NAME: a name for your database cluster—for example, my-db-cluster.
  • NAMESPACE: the Kubernetes namespace for your database cluster.
  • ENCODED_PASSWORD: the password for the postgres administrator user, encoded as a base64 string.
  • ANNOTATION_KEY and ANNOTATION_VALUE: a load balancer annotation key and string value supported by your Kubernetes environment. Enclose the value in double quotes, even for boolean or numeric values such as "true". You can specify one or more key-value pairs under annotations.

In this manifest:

  • ANNOTATION_KEY: "ANNOTATION_VALUE": specifies a custom annotation that the AlloyDB Omni operator adds to the load balancer Service object for your database cluster.
  • allowExternalIncomingTraffic: true: sets the allowExternalIncomingTraffic field to true to allow incoming traffic from outside the Kubernetes cluster.

Get the database cluster and connectivity details

Kubernetes

To verify that the database cluster resource is in the Ready status, run the following command:

kubectl get dbclusters.alloydbomni.dbadmin.goog -n NAMESPACE -w

Replace NAMESPACE with the Kubernetes namespace for your database cluster.

The output is similar to the following:

NAME               PRIMARYENDPOINT   PRIMARYPHASE   DBCLUSTERPHASE
DB_CLUSTER_NAME    10.95.0.84        Ready          DBClusterReady

To verify that your custom annotation and the assigned external endpoint exist on the load balancer Service object, run the following command:

kubectl get svc LOAD_BALANCER_SERVICE_NAME -n NAMESPACE -o yaml

Replace the following:

  • LOAD_BALANCER_SERVICE_NAME: the name of the operator-managed LoadBalancer Service object. For the primary read-write endpoint, the AlloyDB Omni operator names this Service al-DB_CLUSTER_NAME-rw-elb (you can also list Service objects by running kubectl get svc -n NAMESPACE).
  • NAMESPACE: the name of the Kubernetes namespace for your load balancer Service object.

The output is similar to the following:

apiVersion: v1
kind: Service
metadata:
  annotations:
    ANNOTATION_KEY: "ANNOTATION_VALUE"
  creationTimestamp: "2024-02-22T15:26:18Z"
  finalizers:
  - service.kubernetes.io/load-balancer-cleanup
  labels:
    alloydbomni.internal.dbadmin.goog/dbcluster: DB_CLUSTER_NAME
    alloydbomni.internal.dbadmin.goog/dbcluster-ns: NAMESPACE
  name: LOAD_BALANCER_SERVICE_NAME
  namespace: NAMESPACE
  ownerReferences:
  - apiVersion: alloydbomni.dbadmin.goog/v1
    blockOwnerDeletion: true
    controller: true
    kind: DBCluster
    name: DB_CLUSTER_NAME
    uid: 2dd76c9f-7698-4210-be41-6d2259840a85
  resourceVersion: "33628320"
  uid: 1f45362b-6d6f-484d-ad35-11c14e91933e
spec:
  allocateLoadBalancerNodePorts: true
  clusterIP: 10.60.4.76
  clusterIPs:
  - 10.60.4.76
  externalTrafficPolicy: Cluster
  internalTrafficPolicy: Cluster
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - name: db
    nodePort: 31453
    port: 5432
    protocol: TCP
    targetPort: 5432
  selector:
    alloydbomni.internal.dbadmin.goog/dbcluster: DB_CLUSTER_NAME
    alloydbomni.internal.dbadmin.goog/dbcluster-ns: NAMESPACE
    alloydbomni.internal.dbadmin.goog/task-type: database
    dbs.internal.dbadmin.goog/ha-role: Primary
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip: 10.95.0.84

The output includes the following fields:

  • metadata.annotations: contains the ANNOTATION_KEY: "ANNOTATION_VALUE" annotation that you configured in your DBCluster manifest.
  • status.loadBalancer.ingress: displays the external endpoint assigned to the load balancer Service object. Depending on your Kubernetes environment, the load balancer controller populates either ip (which matches the PRIMARYENDPOINT value of your database cluster) or hostname (for DNS-based load balancers such as on AWS EKS, where status.primary.endpoints on the DBCluster records the hostname and port).

What's next