GCP (GKE)
GCP (GKE)
Prerequisites
You will need:
- A GCP account with billing enabled
- GCP CLI installed and configured
- Required APIs enabled:
container.googleapis.com,compute.googleapis.com - Terraform >= 1.5
- kubectl installed
- helm installed
Provision the GKE Cluster
The Terraform templates for provisioning a GKE cluster are available here.
- Clone the Terraform repository to your local machine.
- Navigate to
gcp/provision-gke-cluster. - Authenticate:
gcloud auth login && gcloud auth application-default login - Copy
terraform.tfvars.exampletoterraform.tfvarsand edit it with your desired settings. - Run
terraform init && terraform plan && terraform applyto provision the cluster. - Configure kubectl:
gcloud container clusters get-credentials <cluster-name> --region <region> --project <project-id>
If GOOGLE_APPLICATION_CREDENTIALS is set in your environment it silently overrides gcloud auth application-default login, and Terraform will authenticate as that service account instead of you. A permission error on a project you own is almost always this. Check with echo $GOOGLE_APPLICATION_CREDENTIALS and unset it if it is not what you intend.
The cluster takes roughly 10-12 minutes to create; the node pools follow.
This is a regional cluster, so system_node_count, sip_node_count and rtp_node_count are counts per zone. The SIP and RTP pools are pinned to a single zone by default so that each node gets exactly one static IP; set voip_node_locations to spread them across zones, and the static IP pools scale with it automatically. A default deployment is 8 nodes: 6 system (2 per zone) plus one SIP and one RTP.
Verify the node pools, their labels and their taints:
The Helm chart’s SBC DaemonSets select on voip-environment=sip and voip-environment=rtp, so a missing label produces pods that stay Pending rather than an error.
Deploy jambonz
Create the namespace and install the Traefik ingress controller:
Then install the chart from a clone of the Helm chart repository, replacing the domain with your own:
baseUrl drives every hostname: the portal is jambonz.example.com, the API is api.jambonz.example.com, and Grafana is grafana.jambonz.example.com.
sbc.eipAllocator.enabled=true assigns the static IP addresses the Terraform created, matched by the label role=sip-node / role=rtp-node. Run terraform output eip_allocator_helm_values to see the exact values the chart expects. The nodes need the compute-rw scope for this, which the Terraform configures.
Databases are initialized by two Jobs, which must complete before the application pods can start:
Confirm the SBC nodes claimed their static IPs — media depends on it:
Both should end with Static IP assigned successfully.
Set up DNS
Get the load balancer’s address:
On GCP this is an IP address, so create A records pointing at it for your portal hostname plus the api. and grafana. subdomains.
Enable HTTPS
Install cert-manager, then set global.traefik.tls.enabled=true, global.traefik.clusterIssuer=letsencrypt-prod and global.traefik.email in your values and run helm upgrade. Certificates take one to three minutes:
Log In
Browse to your portal hostname and log in as admin / admin. You will be prompted to change the password immediately.
Then complete the Post-Install Steps and generate a license key as described in Software Licensing.
Cleanup
Order matters. Kubernetes creates the load balancer, and Terraform does not know about it — the network will not delete while it exists.
Wait until no LoadBalancer services remain, then:
Finally check for persistent disks orphaned by the PVCs — deleting the namespace can race the PVC deletion, leaving disks that bill indefinitely: