---
component: ROOT
version: "2026.3"
slug: ROOT/installation/gke-kubernetes
canonical_url: "https://docs.develocity.ai/2026.3/installation/google-cloud/gke-kubernetes/"
title: "Google GKE Kubernetes Installation Guide"
description: "Install and run Develocity on Google Kubernetes Engine (GKE): provision the cluster, configure Helm values and storage, and deploy the services."
keywords:
  - "Kubernetes"
  - "cluster"
  - "Helm chart"
status: current
---

<!-- llms-index: https://docs.develocity.ai/llms.txt -->

# Google GKE Kubernetes Installation Guide

<a id="preamble"></a>

Install Develocity on a [Google Kubernetes Engine](https://cloud.google.com/kubernetes-engine) cluster with Helm, a static external IP, and a Google-managed SSL certificate. Appendices cover using Cloud SQL as the database and Google Cloud Storage for Build Scan data.

Cloud services are frequently updated. This documentation may not reflect the latest changes. Always verify steps and interfaces with the current provider documentation.

Develocity can be [installed into an existing Kubernetes cluster](https://docs.develocity.ai/2026.3/installation/kubernetes-installation/). It can also be installed on a standalone virtual machine, as shown in the [Google Compute Engine Standalone Installation Guide](https://docs.develocity.ai/2026.3/installation/google-cloud/gce-standalone/).

> [!NOTE]
> This guide is for the latest version of Develocity, and might not work with earlier versions.

Develocity can generally be installed on Kubernetes clusters running modern Kubernetes versions. The exact supported versions are in the [version overview matrix](https://docs.develocity.ai/2026.3/miscellaneous/compatibility/#kubernetes_and_helm). Later versions might be compatible but have not been verified to work.

Most of this guide covers creating and minimally configuring a cluster in GKE for a Develocity installation. If you already have GKE expertise and are able to provision a cluster, you can skip straight to the [Develocity installation instructions](#installing_gradle_enterprise).

> [!CAUTION]
> These steps have not been tested with Google Cloud’s Assured Workloads for Government, and are not guaranteed to work there. For help installing Develocity on Assured Workloads for Government, contact [Develocity support](https://support.gradle.com/) or your customer representative.

<a id="prerequisites"></a>

## Prerequisites

<a id="a-google-cloud-account"></a>

### A Google Cloud Account

You can [create an account](https://cloud.google.com/) if you do not already have one.

<a id="get_license"></a>

### A Develocity License

If you have purchased Develocity, you will already have a license file. Otherwise, you can [request a Develocity trial license](https://develocity.ai/trial/).

<a id="google_cloud_project"></a>

### A Google Cloud Project With Billing Enabled

You will need a Google Cloud project that has billing enabled for this guide. If you have a project you want to use, ensure it has billing and the GKE APIs enabled. You can create a project by following [this guide](https://docs.cloud.google.com/resource-manager/docs/creating-managing-projects). To enable billing, follow [these instructions](https://cloud.google.com/billing/docs/how-to/modify-project#enable_billing_for_a_project) for your project.

> [!NOTE]
> If you are using a new project, you might be asked to enable various APIs when running commands. Enable them: they are necessary for this guide.

<a id="required_permissions"></a>

### A Google Cloud IAM User With GKE Permissions

> [!NOTE]
> If you are the project owner, you likely have all permissions already.

Your Google Cloud IAM user needs permission to create and manage various resources (GKE clusters, static IPs, managed certificates, or buckets). You also need permission to create resources in GKE clusters, including RBAC roles (which requires the `container.roles.create` permission). GKE creates your nodes with the Compute Engine default service account, so you also need permission to use that account.

You can obtain these permissions using the following [predefined roles](https://cloud.google.com/iam/docs/understanding-roles):

*   Kubernetes Engine admin (`roles/container.admin`)
    
*   Certificate Manager Editor (`roles/certificatemanager.editor`)
    
*   Compute Public IP Admin (`roles/compute.publicIpAdmin`)
    
*   Storage Object Admin (`roles/storage.objectAdmin`) for bucket creation and administration
    
*   Service Account User (`roles/iam.serviceAccountUser`) for the Compute Engine default service account
    

> [!NOTE]
> Consult the Develocity installation guide for information about debugging required Kubernetes permissions. For more details on Google Kubernetes Engine’s access control model, consult the GKE IAM guide and the GKE access control guide.

> [!TIP]
> If you choose to follow the [Cloud SQL](#cloud_sql) appendix, you will need the permissions described in it, too.

<a id="hostname-prereq"></a>

### Hostname

Google Cloud Platform machines are provisioned with an external IP address but no hostname.

To access Develocity by a hostname of your choosing, for example `develocity.example.com`, you must be able to create a DNS record. That record routes the name to the instance IP address.

<a id="host_requirements"></a>

## Host Requirements

> [!NOTE]
> Develocity only supports the x86\_64 architecture.

<a id="database"></a>

### Database

Develocity installations have two database options:

1.  A **user-managed database** can be any PostgreSQL database compatible with versions 15 through 18, including [CloudSQL for PostgreSQL](https://cloud.google.com/sql?hl=en) and [AlloyDB](https://cloud.google.com/products/alloydb).
    
2.  An **embedded database** that’s highly dependent on disk performance.
    

The [compatibility matrix](https://docs.develocity.ai/2026.3/miscellaneous/compatibility/#user_managed_database) lists the supported versions for every Develocity release.

By default, Develocity stores its data in a PostgreSQL database run as part of the application, storing database files in a directory mounted on its host machine. Although this is the default, a user-managed database is recommended.

<a id="cloud-sql-database"></a>

#### Cloud SQL Database

There are instructions for using Google Cloud SQL as a user-managed database in [Using Cloud SQL as a Develocity User-Managed Database](#cloud_sql). This has several benefits, including easier resource scaling, backup management, and failover support. It allows you to store Build Scan data in the Object Storage.

<a id="storage"></a>

### Storage

Develocity uses [persistent volume claims](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims) for storing data and backups. Develocity uses your cluster’s default [StorageClass](https://kubernetes.io/docs/concepts/storage/storage-classes/#default-storageclass) if it has one.

If no default StorageClass is configured, or you want to use a different one, provide the name of the StorageClass to use for provisioning persistent volumes.

Different StorageClasses can be specified for the different types of storage used.

> [!NOTE]
> Use faster StorageClasses for data, and a separate slower, cost-efficient one for backups.

Some Pods use multiple persistent volumes. On Kubernetes platforms with multiple availability zones, those Pods and their persistent volumes must sit in the same zone. In this case, use a StorageClass with a `volumeBindingMode` of `WaitForFirstConsumer` to ensure that all persistent volumes are provisioned in the same zone that the pod was scheduled in.

Where available, use StorageClasses that allow [persistent volume claim expansion](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#expanding-persistent-volumes-claims). Expanding storage is then straightforward as your Develocity usage grows.

<a id="storage_requirements_capacity"></a>

#### Capacity

The recommended minimum capacities for the persistent volumes are:

 
| Description | Size in GiB |
| --- | --- |
| Build Scan data | 250 |
| Build Scan data backups | 250 |
| Edge Node | 50 |
| Test Distribution | 10 |
| Embedded Object Storage | 80 |

> [!NOTE]
> The embedded object storage provisions a single persistent volume sized to the sum of `objectStorage.embedded.storage.internalBuffer.capacity` (default `5Gi`), `objectStorage.embedded.storage.buildCache.capacity` (default `50Gi`, which holds the durable Build Cache content, including artifacts uploaded from co-located and externally provisioned Edge nodes), `objectStorage.embedded.storage.monitoring.capacity` (default `20Gi`, which holds the monitoring metrics), and `objectStorage.embedded.storage.monitoring.logging.capacity` (default `5Gi`, which holds the monitoring logs). Adjust the sub-settings to change the overall PV size.

> [!NOTE]
> The Edge node volume provides a low-latency cache for build agents. For optimal read speeds, this volume must be placed on local SSD block storage. Do not use network file systems (NFS) or remotely-mounted volumes. Remote storage introduces significant latency, negating the performance benefits of the cache. The volume is ephemeral, so it is not retained across Pod restarts, updates, or scale-down. After such an event, the cache starts empty and warms on demand. As builds request entries, the new Pod fetches them from peer Edge nodes. On a miss, it fetches them through Develocity from the durable Object Storage. Expect temporarily reduced performance while the cache warms this way. Reads are still served, but from Object Storage rather than the local volume until the working set is warm again. If the durable Object Storage sits in a different region than the cluster, this refill traffic also increases Develocity’s cross-region read volume. Entries served from Object Storage still register as ordinary remote-cache hits. As a result, the extra warm-up latency does not surface as a distinct signal in the Build Scan. When troubleshooting a slow build that follows an Edge node restart, correlate it with the restart event. No data is lost: the durable copy remains in the Object Storage connected to Develocity.

Adjust its size with `edgeNode.storage.data.capacity`, or see the [Edge Node](https://docs.develocity.ai/2026.3/reference/helm-charts/cluster/#edge_node) configuration to scale it.

Consider provisioning more storage if you produce more than 1 GiB of Build Scan data in a day. Do the same if you intend to retain Build Scan data for 30 days or more. If your StorageClass does not allow expanding volumes, you should also consider preparing for future data growth by adding additional disk capacity upfront.

<a id="performance"></a>

#### Performance

For production workloads, the data StorageClass should exhibit SSD-class disk performance of at least **3000 IOPS** (input/output operations per second). The StorageClass used for backup volumes might be slower.

> [!NOTE]
> Disk performance has a significant impact on Develocity performance. Network file systems (such as Amazon EFS) are not compatible with Develocity due to their performance characteristics.

<a id="object-storage"></a>

#### Object Storage

You can configure Develocity to store Build Scan data in an Object Storage service, such as [Google Cloud Storage](https://cloud.google.com/products/storage). This can improve performance in high-traffic installations by reducing the load on the database. See [Build Scan Object Storage](https://docs.develocity.ai/2026.3/administration/build-scan/build-scan-storage/#build_scan_object_storage) in the Develocity Administration Manual for a description of the benefits and limitations.

For instructions on configuring Develocity to use Google Cloud Storage, see the [Object Storage Configuration](https://docs.develocity.ai/2026.3/reference/helm-charts/cluster/#helm_config_object_storage) section of the Kubernetes Helm Chart Configuration Guide.

<a id="network"></a>

### Network Connectivity

Develocity requires network connectivity for periodic license validation.

> [!WARNING]
> registry.gradle.com serves the Develocity container images. A Develocity installation does not start if it cannot connect to harbor.gradle.com, which is responsible for license verification.

Use HTTPS with a trusted certificate for production installations of Develocity.

When installing Develocity, you will need to provide a hostname, such as `develocity.example.com`.

<a id="preinstallation"></a>

## Preinstallation

You need to use several tools to create Google Cloud resources and install Develocity. You can either install them locally, or use Google Cloud’s [Cloud Shell](https://docs.cloud.google.com/shell/docs), which comes with the tools you will need preinstalled and mostly preconfigured.

> [!NOTE]
> You can use Cloud Shell via SSH by following these instructions. This requires installing gcloud locally, and then using it to SSH into Cloud Shell, where you would run this guide’s commands. This guide assumes you are using bash as your shell, although any compatible shell, such as zsh, should also work. This guide assumes that the files it names are on the machine you run the command from. If you are using Cloud Shell, you will need to upload them to the shell machine by following the Cloud Shell documentation.

If you are using Cloud Shell, complete [Configure `gcloud`](#configure_gcloud) (unless the project and zone are already configured) and then skip to [Creating a Google Kubernetes Engine Cluster](#creating_gke_cluster).

<a id="install-gcloud"></a>

### Install `gcloud`

You will be using the `gcloud` command line tool to provision and configure the Google Kubernetes Engine cluster. To install `gcloud` on your local machine, follow the [instructions in the Google Cloud documentation](https://docs.cloud.google.com/sdk/docs/install-sdk).

<a id="configure_gcloud"></a>

### Configure `gcloud`

> [!TIP]
> Cloud Shell does not save `gcloud` configurations by default. To save your configuration, follow [these instructions](https://cloud.google.com/shell/docs/configuring-cloud-shell#preferences).

To configure `gcloud`, run `gcloud init` and follow the [initialization guide](https://docs.cloud.google.com/sdk/docs/install-sdk#initializing-the-cli). You want to use the project you created or decided on in [A Google Cloud Project With Billing Enabled](#google_cloud_project). If your project does not have a [default zone](https://docs.cloud.google.com/compute/docs/regions-zones/changing-default-zone-region), set the zone and region to where you want to install Develocity. Setting the zone often sets the region automatically. If you do not know which zone or region to select, consult [Google Cloud’s region and zone documentation](https://cloud.google.com/compute/docs/regions-zones#available).

> [!TIP]
> Pick the region geographically closest to you or to any pre-existing compute resources, such as CI agents, to ensure the best performance.

<a id="install-kubectl"></a>

### Install `kubectl`

To install a `gcloud`\-managed version of `kubectl`, you can run:

```shell
gcloud components install kubectl
```

You can also install `kubectl` through any other means. The [Kubernetes documentation](https://kubernetes.io/docs/tasks/tools/) lists some of the most popular options. You only need to install `kubectl`, not any of the other tools listed there.

<a id="install-the-gcloud-auth-plugin-for-kubectl"></a>

### Install the `gcloud` Auth Plugin for `kubectl`

To authenticate with your GKE cluster, `kubectl` needs a GKE-specific plugin. If you are using an older Kubernetes version, this might not be necessary, but it does no harm.

To install the plugin, run:

```shell
gcloud components install gke-gcloud-auth-plugin
```

> [!NOTE]
> For more details on installation, and why the plugin is necessary, see [Google’s blog post](https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke).

<a id="miscellaneous-command-line-tools"></a>

### Miscellaneous Command Line Tools

This guide assumes that various common command line tools such as `wget`, `curl` and `jq` are already available on your host. Refer to the official documentation of these tools for installation instructions.

<a id="creating_gke_cluster"></a>

## Creating a Google Kubernetes Engine Cluster

In this section you will create a Google Kubernetes Engine cluster to run a Develocity instance, and a static external IP for Develocity to use.

> [!NOTE]
> If you are using Cloud Shell, remember to run these commands there.

<a id="create-a-cluster"></a>

### Create a Cluster

This guide uses a [Standard cluster](https://docs.cloud.google.com/kubernetes-engine/docs/concepts/cluster-architecture) with 5 nodes, using the `e2-standard-4` machine type with 4 vCPUs and 16 GiB of memory. See [Resource requirements](https://docs.develocity.ai/2026.3/installation/kubernetes-installation/#resource_requirements) in the Self-Hosted Kubernetes Installation Guide for recommendations.

> [!NOTE]
> Develocity is fully compatible with [Autopilot clusters](https://cloud.google.com/kubernetes-engine/docs/concepts/autopilot-overview) which will automatically provision nodes based on your workload. There are also GKE solutions for autoscaling nodes horizontally and vertically in standard clusters.

Name this cluster `develocity`. To create it, run:

```shell
gcloud container clusters create develocity \
  --machine-type e2-standard-4 \
  --num-nodes 5 \
  --workload-pool=$(gcloud config get project).svc.id.goog
```

This command will take a while to complete. It will automatically add and activate a `kubectl` configuration.

Confirm the cluster exists by running:

```shell
kubectl config get-contexts
```

**Output:**

```
CURRENT   NAME                                   CLUSTER                                AUTHINFO                                      NAMESPACE
*         gke_project-name_us-west1_develocity   gke_project-name_us-west1_develocity   gke_project-name_us-west1_develocity
```

> [!NOTE]
> For more details, see [GKE’s Standard cluster creation documentation](https://docs.cloud.google.com/kubernetes-engine/docs/how-to/creating-a-zonal-cluster) or [GKE general documentation](https://docs.cloud.google.com/kubernetes-engine/docs/how-to/managing-clusters).

<a id="create_external_ip"></a>

### Create an External IP

Before installing Develocity, you need to create a static external IP for Develocity to use. You can configure the IP and hostname later by running `helm upgrade` with the updated Helm values file, but configuring them now is simpler.

To create the static IP, run:

```shell
gcloud compute addresses create develocity-static-ip --global
```

You can see the IP address used by the resource by running:

```shell
gcloud compute addresses describe develocity-static-ip --global --format='value(address)'
```

<a id="hostname"></a>

### Configure the Hostname

If you intend to use a custom hostname to access your Develocity instance, you now need to add the appropriate DNS records.

Add an `A` record for your hostname that points to the IP you created in the [previous step](#create_external_ip). For example:

```
develocity.example.com A 34.110.226.160
```

Verify that your DNS record works before installing Develocity, such as by using `dig develocity.example.com`.

<a id="create_managed_certificate"></a>

### Create a Managed SSL Certificate

You can provision and use a Google-managed trusted SSL certificate using Kubernetes manifests.

This guide uses a Google-managed certificate. To use a custom SSL certificate instead, skip this step. Follow the instructions in [HTTP or HTTPS](https://docs.develocity.ai/2026.3/reference/helm-charts/cluster/#https) when you create your Helm values file below.

To provision a Google-managed SSL certificate, create a managed certificate resource on the cluster.

**managed-cert.yaml:**

```
apiVersion: v1
kind: Namespace
metadata:
  name: develocity
---
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
  name: develocity-cert
  namespace: develocity
spec:
  domains:
    - develocity.example.com (1)
```

1. Use the hostname you decided on in Configure the Hostname.

To apply this manifest, run the following command:

```shell
kubectl apply -f managed-cert.yaml
```

The certificate does not start provisioning until Develocity is installed.

> [!NOTE]
> For more details, consult Google’s [guide to using managed certificates with GKE](https://docs.cloud.google.com/kubernetes-engine/docs/how-to/secure-traffic-management).

<a id="installing_gradle_enterprise"></a>

## Installing Develocity

In this section you will install Develocity on the cluster you created. For full details on installation options, see the [Develocity Helm Kubernetes Installation Manual](https://docs.develocity.ai/2026.3/installation/kubernetes-installation/).

<a id="install_helm"></a>

### Install `helm`

To install Helm, run:

```shell
curl -qs https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
```

> [!NOTE]
> See Helm’s [installation documentation](https://helm.sh/docs/intro/install/) for more details, and non-Linux instructions.

<a id="values_yaml"></a>

### Prepare a Helm Values File

Create a Helm values file named `values.yaml` as shown below:

**values.yaml:**

```
global:
  hostname: develocity.example.com (1)
  externalSSLTermination: true (2)
  storage:
    data:
      class: premium-rwo (3)
    backup:
      class: standard (4)

ingress:
  enabled: true
  annotations:
    kubernetes.io/ingress.global-static-ip-name: develocity-static-ip (5)
    networking.gke.io/managed-certificates: develocity-cert (6)
```

1. Use the hostname you decided on in Configure the Hostname or substitute it later as shown below.
2. Required to use the ManagedCertificate provided by Google Cloud in step Create a Managed SSL Certificate
3. Use a high-performance volume for data volumes. See Choosing Storage Classes.
4. Use a low performance volume for backups. See Choosing Storage Classes.
5. Configure the Ingress’s load balancer to use the static IP you created earlier.
6. Configure the Ingress’s load balancer to use the managed SSL certificate you created.

> [!NOTE]
> When adding things to your Helm values file, merge any duplicate blocks. Alternatively, you can use separate files and pass all of them with `--values «file»` when running Helm commands.

This file configures Develocity and its installation. For the full set of configuration options, see the [Kubernetes Helm Chart Configuration Guide](https://docs.develocity.ai/2026.3/reference/helm-charts/cluster/).

> [!TIP]
> To use [Cloud SQL PostgreSQL](#cloud_sql), [Google Cloud Storage](#google_cloud_storage), or both, follow the appendices and then return to this procedure.

<a id="storage_classes"></a>

#### Choosing Storage Classes

The example Helm values file configures Develocity to use a high-performance SSD (the `premium-rwo` StorageClass) for its data volumes. This is optional, but recommended for best performance. See the [installation manual’s section on storage requirements](https://docs.develocity.ai/2026.3/installation/kubernetes-installation/#storage) for more details.

The same file configures the backup storage and log storage to use non-SSD disks (the `standard` StorageClass). This is more cost-efficient and avoids Google Cloud’s default 500 GiB SSD quota.

You can see the performance characteristics of the different Google Cloud disk types in [Google Cloud’s disk performance docs](https://docs.cloud.google.com/compute/docs/disks/performance). Note that Develocity has a 250 GiB main data volume by default.

> [!NOTE]
> If you are using a user-managed database (such as a Cloud SQL database), then this data volume is not created.

StorageClasses do not necessarily map to disk types, but you can see which disk type each StorageClass uses by running:

```shell
kubectl describe storageclass
```

The type will be listed as `Parameters: type=pd-«disk-type»` for the StorageClasses that map to persistent disks.

> [!WARNING]
> Google Cloud’s default `standard-rwo` StorageClass maps to the `pd-balanced` disk type, which is a SSD, despite the StorageClass’s name. If you do not explicitly set a StorageClass for the backup storage, you will end up using SSDs for backup and log storage.

<a id="install_the_gradle_enterprise_helm_chart"></a>

### Install the `gradle-enterprise` Helm Chart

First, add the `https://helm.gradle.com/` helm repository and update it:

```shell
helm repo add gradle https://helm.gradle.com/ && \
  helm repo update gradle
```

> [!NOTE]
> Cloud Shell might provide an older Helm version. On an older version, you might need to run `helm repo update` instead of `helm repo update gradle`.

Second, download the [kustomization.zip](https://docs.develocity.ai/2026.3/installation/_attachments/kustomization.zip) file containing the post-renderer resources into your current working directory

Extract the downloaded ZIP file:

```shell
unzip -j kustomization.zip
```

Give the script execute permissions:

```shell
chmod a+x add-develocity-backend-config.sh
```

> [!NOTE]
> This kustomize script creates additional Google Cloud resources and configures service definitions, neither of which is possible with the Helm chart.

Make sure that [kustomize](https://kustomize.io) is available on your host. If you have opted for Cloud Shell, kustomize is already preinstalled. Otherwise, you can install it with the following command:

```shell
curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
```

Then run `helm install` with the following command:

```shell
helm install \
  --create-namespace --namespace develocity \
  develocity \
  gradle/gradle-enterprise \
  --values path/to/values.yaml \(1)
  --set-file global.license.file=path/to/develocity.license \(2)
  --post-renderer=./add-develocity-backend-config.sh (3)
```

1. The Helm values file you created in Prepare a Helm Values File.
2. The license you obtained in A Develocity License.
3. The post renderer script you downloaded

You should see output similar to this:

**Output:**

```
NAME: develocity
LAST DEPLOYED: Wed Jul 13 04:08:35 2022
NAMESPACE: develocity
STATUS: deployed
REVISION: 1
TEST SUITE: None
```

If you see this error instead:

**Output:**

```
Error: INSTALLATION FAILED: roles.rbac.authorization.k8s.io is forbidden: User "me@gmail.com" cannot create resource "roles" in API group "rbac.authorization.k8s.io" in the namespace "develocity": requires one of ["container.roles.create"] permission(s).
```

Consult [A Google Cloud IAM User With GKE Permissions](#required_permissions).

<a id="wait-for-develocity-to-start"></a>

### Wait for Develocity to Start

You can see the status of Develocity starting up by examining its Pods.

```shell
kubectl --namespace develocity get pods
```

**Output:**

```
NAME                                               READY   STATUS              RESTARTS     AGE
edge-node-7d9c8b6f4d-x2kfp                         0/1     ContainerCreating   0            4s
gradle-database-5f9ddc958b-pn8wm                   0/3     Init:0/3            0            4s
gradle-embedded-object-storage-86745c9cd7-2lpb9    0/1     ContainerCreating   0            4s
gradle-enterprise-app-58b7b75579-4c5hz             0/1     Init:0/4            0            4s
gradle-enterprise-operator-bdb9b67bc-5m9wb         0/1     ContainerCreating   0            4s
gradle-keycloak-64cd768b89-rk9g2                   0/1     Init:0/1            1            4s
gradle-monitoring-849994bb56-4wr9t                 0/5     ContainerCreating   0            3s
gradle-proxy-6d7b965c4f-b6jdb                      0/1     ContainerCreating   0            3s
gradle-test-distribution-broker-5494796d9b-gb289   0/1     Init:0/1            0            3s
```

> [!NOTE]
> If you use the GKE web UI, some deployments or stateful sets will show as `Does not have minimum availability` while their init containers are running.

Eventually the Pods should all report as `Running`:

```shell
kubectl --namespace develocity get pods
```

**Output:**

```
NAME                                               READY   STATUS    RESTARTS   AGE
edge-node-7d9c8b6f4d-x2kfp                         1/1     Running   0          4m41s
gradle-database-5f9ddc958b-pn8wm                   3/3     Running   0          4m41s
gradle-embedded-object-storage-86745c9cd7-2lpb9    1/1     Running   0          4m41s
gradle-enterprise-app-58b7b75579-4c5hz             1/1     Running   0          4m41s
gradle-enterprise-operator-bdb9b67bc-5m9wb         1/1     Running   0          4m41s
gradle-keycloak-64cd768b89-rk9g2                   1/1     Running   1          4m41s
gradle-monitoring-849994bb56-4wr9t                 5/5     Running   0          4m41s
gradle-proxy-6d7b965c4f-b6jdb                      1/1     Running   0          4m41s
gradle-test-distribution-broker-5494796d9b-gb289   1/1     Running   0          4m41s
```

Then check that all backends are healthy:

```shell
kubectl get ingress gradle-enterprise-ingress --namespace develocity --output jsonpath="{.metadata.annotations}" | jq -r '.["ingress.kubernetes.io/backends"]' | jq .
```

**Output:**

```
{
  "k8s1-6c91367d-develocit-gradle-test-distribution-b-808-e398ea74": "HEALTHY",
  "k8s1-6c91367d-develocity-edge-node-8080-a1b9f3c7": "HEALTHY",
  "k8s1-6c91367d-develocity-gradle-enterprise-app-6011-7ee160cb": "HEALTHY",
  "k8s1-6c91367d-develocity-gradle-proxy-80-d2766b81": "HEALTHY",
  "k8s1-6c91367d-kube-system-default-http-backend-80-72022d96": "HEALTHY"
}
```

Once all Pods have a status of `Running` and the backends are `HEALTHY`, the system is up. Visit its URL in a web browser to interact with it. You can also visit the URL as soon as the backends are healthy. You then see a starting screen, which redirects to a Build Scan list once the app has started.

If the Pods do not all start correctly, see the [support section in the administration manual](https://docs.develocity.ai/2026.3/operations/support-and-diagnostics/).

Once the Pods are ready, Google provisions the managed SSL certificate. This can take up to 60 minutes, though it is usually faster. Check the certificate status by running:

```shell
kubectl describe managedcertificate --namespace develocity develocity-cert
```

Look for the `Status`, `Certificate Status`, and `Domain Status` fields in the output.

<a id="using_gradle_enterprise"></a>

## Using Develocity

Once Develocity is running, you can configure many of its features in Develocity itself, including access control, database backups, and Build Scan retention. The [administration manual](https://docs.develocity.ai/2026.3/administration/) covers the features you can configure after installation.

See [Teardown and Cleanup](#teardown) for instructions on uninstalling Develocity and deleting related resources, such as persistent disk volumes.

<a id="next_steps"></a>

## Next Steps

*   [Sign in as the System User](https://docs.develocity.ai/2026.3/administration/access-control/system-user/): Set the system user password and create a personal administrator account.
    
*   [Publish Your First Build Scan](https://docs.develocity.ai/2026.3/using-develocity/build-scan/): Validate your installation end-to-end from Gradle, Maven, sbt, Bazel, or npm.
    
*   [Kubernetes Helm Chart Configuration Guide](https://docs.develocity.ai/2026.3/reference/helm-charts/cluster/): Develocity Helm chart options.
    
*   [Develocity Administration](https://docs.develocity.ai/2026.3/administration/): Learn how to configure and administer Develocity.
    
*   [DPE University](https://dpeuniversity.gradle.com/app/catalog?product=Develocity): A free, self-paced training portal to get the most out of Develocity.
    

* * *

<a id="cloud_sql"></a>

## Appendix A: Using Cloud SQL as a Develocity User-Managed Database

Develocity can use a user-managed database instead of using its own embedded database. The benefits include easier resource scaling (and autoscaling), easier backup and snapshot management, and failover support. For the pros and cons of a user-managed database, see the [Database options](https://docs.develocity.ai/2026.3/reference/helm-charts/cluster/#database_type) section of the Kubernetes Helm Chart Configuration Guide. This appendix will walk you through using Google Cloud SQL as a user-managed database.

<a id="obtain-the-required-permissions"></a>

### Obtain the Required Permissions

You will need permission to create and manage Cloud SQL instances and service accounts, and to add roles to service accounts.

You can obtain these permissions using the following built-in roles: `roles/iam.serviceAccountAdmin`, `roles/resourcemanager.projectIamAdmin`, and `roles/cloudsql.admin`.

If you cannot obtain `roles/iam.serviceAccountAdmin` and `roles/resourcemanager.projectIamAdmin`, ask someone who can create service accounts and add roles to them to complete [Bind Kubernetes Service Account to Cloud SQL Permissions](#create_google_service_account) for you.

<a id="set-up-a-cloud-sql-instance"></a>

### Set Up a Cloud SQL Instance

Before starting, review Develocity’s [supported PostgreSQL versions](https://docs.develocity.ai/2026.3/installation/kubernetes-installation/#database) and [storage requirements](https://docs.develocity.ai/2026.3/installation/kubernetes-installation/#storage).

<a id="decide-on-a-root-username-and-password"></a>

#### Decide on a Root Username and Password

Decide on a root password for the database instance. This guide refers to it as `«db-root-password»`. This is the password you will use for your database connection, so save it somewhere secure.

> [!NOTE]
> Develocity uses the superuser only to set up the database and create the migrator and application users. To stop Develocity from using the superuser, set up the database yourself. The [Database options](https://docs.develocity.ai/2026.3/reference/helm-charts/cluster/#database_type) section of the Kubernetes Helm Chart Configuration Guide describes how. For help with this, please contact [Develocity support](https://support.gradle.com/).

<a id="create-the-cloud-sql-instance"></a>

#### Create the Cloud SQL Instance

Create the Cloud SQL instance:

```shell
gcloud sql instances create develocity \
  --edition=enterprise \
  --database-version=POSTGRES_18 \
  --cpu=2 \
  --memory=8GB \
  --storage-size=250GB \
  --require-ssl \
  --database-flags=max_connections=200 \
  --zone=$(gcloud config get compute/zone) \(1)
  --root-password=«db-root-password» \
  && \
  gcloud sql databases create develocity --instance=develocity (2)
```

1. The zone where you created your GKE cluster.
2. Creates the develocity database inside the Cloud SQL instance.

This will create an instance with 2 vCPUs and 8 GiB of memory, with 250 GiB of storage, without any replication. The storage will automatically increase if necessary, but will not decrease.

> [!NOTE]
> Cloud SQL databases are not backed up by default, but you can enable backups. See the backup documentation. Consult the command reference to see all options available when creating the Cloud SQL instance. Creating an instance with a private (VPC-only) IP is possible. Consult this documentation for details. The connection method in this appendix still works with a private IP, with some modifications described in the Cloud SQL proxy docs.

<a id="make-the-database-accessible-from-your-gke-cluster"></a>

### Make the Database Accessible From Your GKE Cluster

To connect to the instance, you use the Cloud SQL Auth proxy running as a standalone service. Google’s documentation recommends running the proxy as a sidecar container, but that does not work for Develocity: some of its init containers need database access.

<a id="create_kubernetes_service_account"></a>

#### Create a Kubernetes Service Account for the Cloud SQL Proxy

The Cloud SQL Proxy needs a service account to authenticate with your Cloud SQL instance.

**db-service-account.yaml:**

```
apiVersion: v1
kind: Namespace
metadata:
  name: develocity
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: dv-database-service-account
  namespace: develocity
```

To apply this manifest, run the following command:

```shell
kubectl apply -f db-service-account.yaml
```

<a id="create_google_service_account"></a>

#### Bind Kubernetes Service Account to Cloud SQL Permissions

Bind the service account you created to the required role by running the following commands:

```shell
(
PROJECT_ID=$(gcloud config get project); \
PROJECT_NUMBER=$(gcloud projects list \
  --filter="$PROJECT_ID" \
  --format="value(PROJECT_NUMBER)"); \
NAMESPACE="develocity"; \
KUBERNETES_SERVICE_ACCOUNT="dv-database-service-account"; \
gcloud projects add-iam-policy-binding "$PROJECT_ID" \
  --role="roles/cloudsql.client" \
  --member="principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}.svc.id.goog/subject/ns/${NAMESPACE}/sa/${KUBERNETES_SERVICE_ACCOUNT}"
)
```

<a id="deploy_proxy"></a>

#### Deploy the Cloud SQL Proxy

Get the connection name of your Cloud SQL instance by running:

```shell
gcloud sql instances describe develocity --format='value(connectionName)'
```

This guide refers to it as `«connection-name»`.

Then deploy the proxy and create a service for it by applying the following manifest:

**database-proxy.yaml:**

```
apiVersion: v1
kind: Namespace
metadata:
  name: develocity
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: gradle-database-proxy
  namespace: develocity
spec:
  selector:
    matchLabels:
      app.kubernetes.io/part-of: gradle-enterprise
      app.kubernetes.io/component: database-proxy
  template:
    metadata:
      labels:
        app.kubernetes.io/part-of: gradle-enterprise
        app.kubernetes.io/component: database-proxy
    spec:
      serviceAccountName: dv-database-service-account
      containers:
        - name: cloud-sql-proxy
          image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:latest (1)
          ports:
            - containerPort: 6543
          args: (2)
            - "--port"
            - "6543"
            - "--address"
            - "0.0.0.0"
            - "«connection-name»" (3)
          resources:
            requests:
              cpu: "1" (4)
              memory: "2Gi" (5)
            limits:
              cpu: "2" (4)
              memory: "4Gi" (5)
          securityContext:
            runAsNonRoot: true
---
apiVersion: v1
kind: Service
metadata:
  name: gradle-database-proxy
  namespace: develocity
spec:
  selector:
    app.kubernetes.io/part-of: gradle-enterprise
    app.kubernetes.io/component: database-proxy
  ports:
    - port: 5432
      targetPort: 6543
```

1. This uses the latest version of the Cloud SQL proxy. For long-lived environments, use a specific version instead.
2. The arguments to the Cloud SQL proxy.
3. The connection name of your Cloud SQL instance, which you can substitute as shown below.
4. The proxy is lightweight, but its CPU use scales linearly with database I/O.
5. The proxy is lightweight, but its memory use scales linearly with the number of active connections.

> [!NOTE]
> The arguments used here are only valid for major version 2 of the Cloud SQL Proxy. If you are using version 1, you can reverse-migrate the arguments using the migration guide. Consult the GKE and Cloud SQL tutorial and Connect from GKE documentation for more details on setting up Cloud SQL access from GKE.

🔍 Apply the manifest with substitution

To apply this manifest with the correct `«connection-name»` substituted in, run (verbatim):

```shell
CONNECTION_NAME=$(gcloud sql instances describe develocity --format='value(connectionName)') && \
  sed "s/«connection-name»/${CONNECTION_NAME}/g" | kubectl apply -f -
```

And then paste the above manifest (verbatim) into `stdin`.

> [!NOTE]
> When writing or pasting to a shell’s `stdin`, use EOF (usually `ctrl+d`) to end the input.

<a id="configure-develocity-to-use-your-cloud-sql-instance"></a>

### Configure Develocity to Use Your Cloud SQL Instance

Add the following configuration snippet to your Helm values file:

**values.yaml:**

```
database:
  location: user-managed
  connection:
    host: gradle-database-proxy
    port: 5432
    databaseName: develocity
    params: "?ssl=false"
  credentials:
    superuser:
      username: postgres
      password: «db-root-password»
```

If you skipped to this appendix from [Prepare a Helm Values File](#values_yaml) while installing Develocity, continue at [Install the `gradle-enterprise` Helm Chart](#install_the_gradle_enterprise_helm_chart).

> [!NOTE]
> When adding things to your Helm values file, merge any duplicate blocks. Alternatively, you can use separate files and pass all of them with --values «file» when running Helm commands. For additional information about database configuration, you can consult the Database options for Kubernetes or user-managed database migration guide if required. This embeds your database superuser credentials in your Helm values file, meaning it must be kept secure. If you prefer to provide the credentials as a Kubernetes secret, consult Develocity’s Database options.

<a id="google_cloud_storage"></a>

## Appendix B: Using Google Cloud Storage as User-Managed Object Storage

Develocity can use user-managed Object Storage instead of its own embedded version. This gives you scalable storage, lower operational burden, and better backup and failover management. You can store Build Scan data in Object Storage. This appendix will walk you through using Google Cloud Storage as user-managed Object Storage.

<a id="gcs_bucket_creation"></a>

### Create the Google Cloud Storage Bucket

Create two buckets using the `gcloud` CLI:

```shell
gcloud storage buckets create \
  gs://develocity-application-data \(1)
  --location=$(gcloud config get compute/zone | sed 's@\(.*\)-[a-z]@\1@') \(3)
  --uniform-bucket-level-access \
&& \
gcloud storage buckets create \
  gs://develocity-monitoring-data \(2)
  --location=$(gcloud config get compute/zone | sed 's@\(.*\)-[a-z]@\1@') \(3)
  --uniform-bucket-level-access
```

1. The name of the bucket meant to store application data, such as Build Scan data or Build Cache entries
2. The name of the bucket meant to store monitoring data, such as logs and metrics collected during application lifetime
3. The region to store data in. For performance, use the same region as your cluster.

> [!NOTE]
> Storing data in different buckets allows you to apply various strategies, such as access control, replication, soft-delete, backup, and more. You can also use one bucket for both application and monitoring data. That is an operational decision based on your own practices.

<a id="gcs_bind_workload_identity"></a>

### Bind Kubernetes Service Accounts to IAM Roles Required

To use Object Storage, some Develocity components need read and write access to the buckets you created, through the `roles/storage.objectUser` role. Each component uses one of the two buckets:

*   `gradle-enterprise-app` and `gradle-enterprise-app-background-processor` need to access the **application bucket**, named `gs://develocity-application-data`
    
*   `gradle-enterprise-operator` and `gradle-monitoring` need to access the **monitoring bucket**, named `gs://develocity-monitoring-data`
    

Create those bindings with the following commands:

```shell
(
PROJECT_ID=$(gcloud config get project)
PROJECT_NUMBER=$(gcloud projects list \
  --filter="$PROJECT_ID" \
  --format="value(PROJECT_NUMBER)")
NAMESPACE="develocity"
for KUBERNETES_SERVICE_ACCOUNT in 'gradle-enterprise-app' 'gradle-enterprise-app-background-processor' (1)
do
gcloud storage buckets add-iam-policy-binding gs://develocity-application-data \
  --role="roles/storage.objectUser" \
  --member="principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}.svc.id.goog/subject/ns/${NAMESPACE}/sa/${KUBERNETES_SERVICE_ACCOUNT}" \
  --condition=None (3)
done
for KUBERNETES_SERVICE_ACCOUNT in 'gradle-enterprise-operator' 'gradle-monitoring' (2)
do
gcloud storage buckets add-iam-policy-binding gs://develocity-monitoring-data \
  --role="roles/storage.objectUser" \
  --member="principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}.svc.id.goog/subject/ns/${NAMESPACE}/sa/${KUBERNETES_SERVICE_ACCOUNT}" \
  --condition=None (3)
done
)
```

1. Develocity components requiring access to the application bucket: gradle-enterprise-app and gradle-enterprise-app-background-processor
2. Develocity components requiring access to the monitoring bucket: gradle-enterprise-operator and gradle-monitoring
3. Binds the roles/storage.objectUser role on each bucket to the service accounts listed for that bucket.

<a id="gcs_deploy_with_gcs"></a>

### Configure Develocity to Use Your Google Cloud Storage Bucket

To configure Develocity to use Google Cloud Storage, you must use the [unattended configuration mechanism](https://docs.develocity.ai/2026.3/administration/unattended-configuration/). The steps below extend your Helm values file with the unattended configuration block for Google Cloud Storage.

First you need to create a minimal unattended configuration file. This requires you to choose a password for the system user and hash it. To do this, install [develocityctl](https://docs.develocity.ai/develocityctl/1.24/).

Then run the following command to hash your password, from standard-input (`stdin`), and write it to `secret.txt`:

```shell
develocityctl config-file hash -o secret.txt -s -
```

This guide refers to the hashed password in `secret.txt` as `«hashed-system-password»`.

To use your buckets, add the following to your Helm values file:

**values.yaml:**

```
global:
  unattended:
    configuration:
      version: 17 (1)
      systemPassword: "«hashed-system-password»" (2)
      buildScans:
        incomingStorageType: objectStorage

objectStorage:
  type: googleCloudStorage (3)
  googleCloudStorage:
    bucket: develocity-application-data (4)
    credentials:
      type: workloadIdentity (5)
    monitoring: (6)
      bucket: develocity-monitoring-data (7)
      credentials:
        type: workloadIdentity (5)
```

1. The version of the unattended configuration
2. Your hashed system password
3. Object Storage type used in this installation, here set to googleCloudStorage
4. Bucket created in Create the Google Cloud Storage Bucket, used for application data storage (Build Cache, Build Scan)
5. The authentication mechanism for this installation. This guide uses workloadIdentity, which needs no long-lived key. Use serviceAccount with a service account key only if Workload Identity Federation can’t be enabled on the cluster.
6. Configuration block dedicated to monitoring data storage (metrics, logs). Its structure is identical to the one in objectStorage.googleCloudStorage
7. Bucket created in Create the Google Cloud Storage Bucket, used for monitoring data (metrics and logs)

When adding things to your Helm values file, merge any duplicate blocks. Alternatively, you can use separate files and pass all of them with `--values «file»` when running Helm commands.

> [!IMPORTANT]
> Switching between embedded Object Storage and user-managed Object Storage is not supported.

<a id="teardown"></a>

## Appendix C: Teardown and Cleanup

This appendix will walk you through tearing down Develocity and deleting any resources created by following this guide. Before deleting your cluster, you should uninstall the Develocity helm chart. Otherwise, the persistent storage disks will not be deleted.

To uninstall Develocity, run:

```shell
helm uninstall --namespace develocity develocity
```

After running this command, wait a minute or so for the disks to be deleted. The disks backing the three log volumes and the nodes' boot disks will remain. You can delete the log disks manually. The node boot disks are deleted when you delete the cluster. You can list the disks by running:

```shell
gcloud compute disks list
```

To delete the managed certificate and static IP address, run:

```shell
kubectl delete managedcertificate --namespace develocity develocity-cert && \
gcloud compute addresses delete develocity-static-ip --global
```

To delete the cluster, run:

```shell
gcloud container clusters delete develocity
```

This will ask if you want to continue. Enter `y` to delete the cluster.

If you are using other resources, such as a [Cloud SQL database](#cloud_sql), remember to delete them too. [Cloud SQL](#teardown_cloud_sql) teardown instructions are in the section below.

<a id="teardown_cloud_sql"></a>

### Cloud SQL

If you followed [Using Cloud SQL as a Develocity User-Managed Database](#cloud_sql), you have some additional cleanup to do.

> [!CAUTION]
> Deleting a Cloud SQL instance also deletes any automated backups of its database.

To delete your Cloud SQL instance, run:

```shell
gcloud sql instances delete develocity
```

To also delete the service account binding you created, run:

```shell
(
PROJECT_ID=$(gcloud config get project)
PROJECT_NUMBER=$(gcloud projects list \
  --filter="$PROJECT_ID" \
  --format="value(PROJECT_NUMBER)")
NAMESPACE="develocity"
KUBERNETES_SERVICE_ACCOUNT="dv-database-service-account"
gcloud projects remove-iam-policy-binding "$PROJECT_ID" \
  --role="roles/cloudsql.client" \
  --member="principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}.svc.id.goog/subject/ns/${NAMESPACE}/sa/${KUBERNETES_SERVICE_ACCOUNT}" \
  --condition=None
)
```

> [!NOTE]
> If you did not get full permissions for service account management, you might not be able to do this yourself.

<a id="teardown_cloud_storage"></a>

### Cloud Storage

If you followed [Using Google Cloud Storage as User-Managed Object Storage](#google_cloud_storage), you have some additional cleanup to do.

To delete your Cloud Storage buckets, run:

```shell
gcloud storage rm --recursive \
  gs://develocity-application-data \
  gs://develocity-monitoring-data
```

To also delete the service account bindings you created, run:

```shell
(PROJECT_ID=$(gcloud config get project)
PROJECT_NUMBER=$(gcloud projects list \
  --filter="$PROJECT_ID" \
  --format="value(PROJECT_NUMBER)")
NAMESPACE="develocity"
for KUBERNETES_SERVICE_ACCOUNT in 'gradle-enterprise-app' 'gradle-enterprise-app-background-processor' (1)
do
  gcloud storage buckets remove-iam-policy-binding gs://develocity-application-data \
    --role="roles/storage.objectUser" \
    --member="principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}.svc.id.goog/subject/ns/${NAMESPACE}/sa/${KUBERNETES_SERVICE_ACCOUNT}" \
    --condition=None (3)
done
for KUBERNETES_SERVICE_ACCOUNT in 'gradle-enterprise-operator' 'gradle-monitoring' (2)
do
  gcloud storage buckets remove-iam-policy-binding gs://develocity-monitoring-data \
    --role="roles/storage.objectUser" \
    --member="principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}.svc.id.goog/subject/ns/${NAMESPACE}/sa/${KUBERNETES_SERVICE_ACCOUNT}" \
    --condition=None (3)
done)
```