Introduction

Prior to version 2022.1, Gradle Enterprise has been distributed as a Replicated Appliance or Replicated Ship / Kubernetes application.

From 2022.1 onwards, Gradle Enterprise is also distributed and installed using the Helm Kubernetes package manager. This is the preferred method to install Gradle Enterprise, and the previous distribution methods are now considered deprecated and will not be supported past 2022.

Migration options

There are two deployment options:

  • A standalone distribution for installation into a single host, similar to the existing appliance installation.

  • A distribution for installation into a Kubernetes cluster, similar to the existing Kubernetes installation.

This guide covers the following migration paths:

Migration of data

In all cases, data is preserved, including Gradle Enterprise configuration (i.e. from the Administration page). That is, there is no explicit data migration required in order to migrate a Replicated-based installation to a Helm-based one.

Appliance to standalone migration

Prior to starting, please review the Gradle Enterprise Helm Standalone Installation Manual which explains Helm and the Gradle Enterprise standalone distribution.

Prerequisites

  • To minimise downtime, this procedure recommends starting the K3s software while the existing appliance installation is still running. Please ensure that the host has at least 1GB of memory available in addition to its current usage to cover for the overhead.

  • The new Gradle Enterprise distribution mechanism has a new license file format. Please contact Gradle support to get an updated license file.

  • Airgap installations require a specific license entitlement. If this is a requirement, please contact your customer success representative.

Migration steps

Update to the latest Gradle Enterprise version

Upgrade to the latest version by clicking on the Check Now button and installing any updates found. This will ensure that the migration is from and to the same Gradle Enterprise version.

replicated dashboard

Upload required files to the host

Upload the following files to the Gradle Enterprise host:

  • Your new Gradle Enterprise license file.

  • Any SSL certificates being used.

Install K3s and helm

Please follow the instructions on installing K3s and Helm in the installation manual.

Create a values.yaml configuration file

Helm is configured using a combination of settings stored in a YAML file and standalone files such as the Gradle Enterprise license and SSL certificates.

Please review the Helm configuration section from the installation manual for details. We recommend to start with the values.yaml template file included in the helm distribution. See here for instructions how to retrieve it.

This section walks through translating the existing Replicated appliance configuration into a Helm values.yaml.

Create the values.yaml file, and populate it based on the following settings in the Replicated Settings page.

Network section

Translate the existing settings to the values.yaml file:

Replicated setting Helm configuration key

Hostname

Set global.hostname. Required.

Use HTTP / Use HTTPS

Set ingress.ssl.enabled to false to disable HTTPS.

Use HTTP with external HTTPS termination

Set ingress.ssl.enabled to false and global.externalSSLTermination to true.

HTTP port / HTTPS port

Set ingress.port.http or ingress.port.https to use non-standard ports.

SSL Private Key / SSL Certificate

Set ingress.ssl.key and ingress.ssl.cert.

Examples:

  • Using HTTP with the default port

    network http default port
    global:
      hostname: ge.example.com
    
    ingress:
      ssl:
        enabled: false
  • Using HTTP with a custom port

    network http custom port
    global:
      hostname: ge.example.com
    
    ingress:
      port:
        http: 8180
      ssl:
        enabled: false
  • Using HTTPS with a generated certificate and default ports

    network https default ports
    global:
      hostname: ge.example.com
  • Using HTTPS with a generated certificate and custom ports

    network https generated certificate
    global:
      hostname: ge.example.com
    
    ingress:
      port:
        http: 8180
        https: 8543
  • Using HTTPS with custom certificate and ports

    network https custom certificate
    global:
      hostname: ge.example.com
    
    ingress:
      ssl:
        port:
          http: 8180
          https: 8543
        key: |
          -----BEGIN RSA PRIVATE KEY-----
          MIIEpQIBAAKCAQEA4qV8JlqDMi7y85Ykq8dn7uIsi609D6KuFtlc+UvNYjatz0+u
          QzIr3iw//qf7sM8nx8fhGwuWvUWeCE6zbgKjuxDH82J9NQ0ctf70n0qVTeyW1CKR
          w/koEXyecIZIOA9Jh7KNkShfp/x5T3GZ4QK//A/4oJyhD3IeK/nEXr5mSe2AzGxq
          ...
          XlOfXr/xvkXA66PROgvVxfwpN/GNrLXFi1HvMg7MVZJUZQpNzpAzw5JTk2MbawOl
          G7tI0qQ6F20e5R4tPpEDKCFZykyvgGMhfLzsvVlrgaVW8QbVK4YWNtQ=
          -----END RSA PRIVATE KEY-----
        cert: |
          -----BEGIN CERTIFICATE-----
          MIIDKjCCAhKgAwIBAgIRAPNTIHf6/oUuzMKm3ffGNOgwDQYJKoZIhvcNAQELBQAw
          HDEaMBgGA1UEAxMRYXV0by1nZW5lcmF0ZWQtY2EwHhcNMjExMTMwMTU1NDU5WhcN
          MjExMjAxMTU1NDU5WjAjMSEwHwYDVQQDExhvbmx5LWZvci51bml0LXRlc3QubG9j
          ...
          Cn/3yUirFVTslrSYKAemLw8btLO6FDF9dc/lq1o7tKsYVuhEcjqnTah7puJjEN9h
          z+P5RmRxU/kaaFB+Vuw1pRezbaAtZNorVgXnBwrdseY4zLGyhAcGcR9v+VtCiQ==
          -----END CERTIFICATE-----

    Alternatively, the key and certificate can be provided to the helm command via --set-file parameters. See the installation manual for details.

  • Using HTTP with external HTTPS termination and custom ports

    network http external https termination
    global:
      hostname: ge.example.com
      externalSSLTermination: true
    
    ingress:
      ssl:
        enabled: false
      port:
        http: 8180
        https: 8543
Storage section
Replicated setting Helm configuration key

Installation directory

Set global.storage.directory. Default is /opt/gradle.

Logs directory

Set global.storage.logs.directory. Default is (global.storage.directory)/logs.

Backup directory

Set global.storage.backup.directory. Default is (global.storage.directory)/backups.

Examples:

  • Defaults

    storage defaults
    # Default configuration. No values required.
  • Custom locations

    storage custom locations
    global:
      storage:
        directory: /mnt/big-volume/ge
        logs:
          directory: /var/log/gradle-enterprise
        backup:
          directory: /mnt/vol2/ge-backups
Database section

By default, Gradle Enterprise will use an embedded database. Configuration settings only need to be set when connecting to a user-managed database.

Please review the Database configuration section of the installation manual for details. Different values are required based on which type of credentials are provided.

Replicated setting Helm configuration key

Store data in user-managed database

Set database.location to user-managed. Default is embedded.

Host

Set database.connection.host. Required for a user-managed database.

Port

Set database.connection.port. Default is 5432.

Database name

Set database.connection.databaseName. Required for a user-managed database.

Extra JDBC parameters

Set database.connection.params. Default is no extra paramters.

Database superuser username

Set database.credentials.superuser.username.

Database superuser password

Set database.credentials.superuser.password.

Database application user password

Set database.credentials.app.password.

Database migration user password

Set database.credentials.migration.password.

Examples:

  • Store data in embedded database

    database embedded
    # Default configuration. No values required.
  • Store data in user-managed database and provide database superuser credentials

    database user managed superuser
    database:
      location: user-managed
      connection:
        host: database.example.com
        port: 5432
        databaseName: gradle_enterprise
        params: "?connectTimeout=60"
      credentials:
        superuser:
          username: postgres
          password: superuserPassword
  • Store data in user-managed database and do not provide database superuser credentials

    database user managed no superuser
    database:
      location: user-managed
      connection:
        host: database.example.com
        port: 5432
        databaseName: gradle_enterprise
        params: "?connectTimeout=60"
      credentials:
        app:
          password: appUserPassword
        migrator:
          password: migratorUserPassword
Airgap installations

Airgap installation requires downloading a Gradle Enterprise airgap bundle on an internet-connected host and then transferring it to the installation host.

Airgap installations should add the below image pull policy to prevent the app from trying to pull Gradle Enterprise container images from the internet at runtime:

global:
  image:
    imagePullPolicy: Never

Chart and image download

Installation steps are slightly different, depending on whether an online or airgap installation is being performed.

Online installation chart download

Add the Gradle Helm repository:

helm repo add gradle https://helm.gradle.com
helm repo update gradle

Verify that Helm has the latest Gradle Enterprise standalone chart:

helm search repo gradle-enterprise-standalone

You should see the latest available:

NAME                               	CHART VERSION	APP VERSION	DESCRIPTION
gradle/gradle-enterprise-standalone	2022.3.0     	2022.3   	Official Gradle Enterprise Chart

Verify that this is the same version as is installed in the existing installation. If it is not, then either the existing installation needs to be upgraded or the local Helm repository cache should be updated again by running helm repo update gradle.

Airgap installation chart and image download

Verify that your license is airgap-enabled. If you examine the license file content, you should see airgap listed as an entitlement. If you need to perform an airgap installation but do not have the airgap entitlement on your license, please contact your customer success representative.

On an internet connected host, with your Gradle Enterprise license file available:

  1. Download the airgap bundle for the version that you are installing:

    curl -LOJd @/path/to/gradle-enterprise.license https://registry.gradle.com/airgap/gradle-enterprise-standalone-2022.3-bundle.tar.gz

    You can optionally verify the downloaded bundle file.

  2. Transfer the downloaded bundle file to your installation host.

On the installation host:

  1. Expand the bundle:

    tar zxvf gradle-enterprise-standalone-2022.3-bundle.tar.gz
  2. Run the following command to import images into K3s:

    k3s ctr images import gradle-enterprise-standalone-2022.3-images.tar

Stop the existing instance

At this point, expect Gradle Enterprise to be unavailable for up to 30 minutes.

  • Click the Stop now button in the Replicated console

    replicated dashboard
  • Wait for the application to be completely stopped

    replicated dashboard stopped

Install the Gradle Enterprise standalone Helm chart

Online installation

Install Gradle Enterprise by issuing the following command:

helm install \
  --create-namespace --namespace gradle-enterprise \
  ge gradle/gradle-enterprise-standalone \
  --values /path/to/values.yaml \
  --set-file global.license.file=/path/to/gradle-enterprise.license \
  # [other options] (1)
1 Further options:
  • If SSL certificate files are being used, and are not embedded in the values.yaml, these should also be passed here using --set-file. See the installation guide for an example.

  • See the appendix for extra parameters if you are using unattended installation.

Airgap installation
helm install \
  --create-namespace --namespace gradle-enterprise \
  ge gradle-enterprise-standalone-2022.3.0.tgz \(1)
  --values /path/to/values.yaml \
  --set-file global.license.file=/path/to/gradle-enterprise.license \
  # [other options] (2)
1 This is the path to the .tgz Helm chart file included in the downloaded airgap bundle.
2 Further options:
  • If SSL certificate files are being used, and are not embedded in the values.yaml, these should also be passed here using --set-file. See the installation guide for an example.

  • See the appendix for extra parameters if you are using unattended installation.

Verify system status

Gradle Enterprise service availability

You can inspect the status of the Gradle Enterprise pods by running kubectl get pods:

kubectl --namespace gradle-enterprise get pods
NAME                                               READY   STATUS    RESTARTS   AGE
gradle-enterprise-operator-76694c949d-md5dh        1/1     Running   0          84m
gradle-proxy-0                                     1/1     Running   0          83m
gradle-database-65d975cf8-dk7kw                    2/2     Running   0          83m
gradle-enterprise-app-0                            1/1     Running   0          83m
gradle-metrics-cfcd8f7f7-zqds9                     1/1     Running   0          83m
gradle-test-distribution-broker-6fd84c6988-x6jvw   1/1     Running   0          83m
gradle-build-cache-node-57b9bdd46d-2txf5           1/1     Running   0          84m
gradle-keycloak-0                                  1/1     Running   0          83m

The app will be ready once all pods report as Running.

Service connectivity verification

Please verify that your system is being connected-to correctly. Which services to check will depend on which you use:

  • If authentication is required, can users log in?

  • Are build scans being collected correctly? See /scans.

  • Are build cache nodes connected? See /cache-admin.

  • Are test distribution agents connected? /admin/test-distribution.

Data verification

Please inspect your system to validate that historical data has been migrated. Viewing /scans and ordering by oldest build scan will show the oldest scans in your system.

Support

If any steps do not result in the expected state, please contact Gradle support.

Cleanup

Once you have verified that your system is functional and has migrated configuration and data correctly, you may uninstall previously installed components at your convenience.

  • Uninstall Replicated. It is important to do this prior to a system restart as otherwise Replicated may attempt to start the old installation of Gradle Enterprise.

  • Docker is no longer needed, and may also be uninstalled.

Ship-based Kubernetes to Helm-based Kubernetes cluster migration

Prior to starting, please review the Gradle Enterprise Helm Kubernetes Installation Manual which explains Helm and the Gradle Enterprise distribution.

Prerequisites

  • The new Gradle Enterprise distribution mechanism has a new license file format. Please contact Gradle support to get an updated license file.

  • Typically the previous Ship-based Gradle Enterprise installation steps will have been executed on a host with access to your Kubernetes cluster. This migration guide assumes that this host is available for execution of commands, and that the previously created gradle-enterprise directory containing installation and support scripts is present. References to "the host" in this guide refer to this host.

  • You will need your current Ship customer ID and installation ID. Please contact Gradle Support if you do not have these recorded.

  • These instructions assume that only one Gradle Enterprise instance is installed in your Kubernetes cluster. For assistance in migrating an instance which shares a Kubernetes cluster with other instances, please contact Gradle Support.

  • In particular, review the installation options in the installation manual and know the installation method and required steps prior to starting steps in this guide. You should know the shape of the helm install command prior to starting.

Migration steps

Update to the latest Gradle Enterprise version

Upgrade to the latest version by following the guidelines in Gradle Enterprise Kubernetes Administration Manual. This will ensure that the migration is from and to the same Gradle Enterprise version.

Upload required files to the host

Upload the following files to the host:

  • Your new Gradle Enterprise license file.

  • Any SSL certificates being used.

Install Helm

Please follow the instructions on installing Helm in the installation manual.

Run the Ship app to review current settings

To view the current system configuration, first run the Ship app. It should be run in the gradle-enterprise directory created during the previous installation.

cd path/to/gradle-enterprise
docker run -p 8800:8800 --rm -it -v `pwd`:/out \
  -v /var/run/docker.sock:/var/run/docker.sock \
  replicated/ship:0.54.1 app \
  --customer-id=<cust-id> \
  --installation-id=<install-id>

This should show the app starting followed by some lines like this:

Please visit the following URL in your browser to continue the installation

        http://localhost:8800

Visit that port on the hostname of your installation host in your web browser:

k8s ship app

The current configuration should be visible. This can be used as a reference when creating a Helm configuration file below.

Create a values.yaml configuration file

Helm is configured using a combination of settings stored in a YAML file and standalone files such as the Gradle Enterprise license and SSL certificates.

Please review the Helm configuration section from the installation manual for details.

This section walks through translating the existing Replicated ship configuration into a Helm values.yaml.

Create the values.yaml file, and populate it based on the following settings from the Ship application settings screen.

Cluster info section

Translate the existing settings to the values.yaml file:

Replicated setting Helm configuration key

Kubernetes namespace

Specified as a part of helm install command. Check the installation manual for details.

Installation on Openshift platform

Set global.openshiftInstallation. Default is false.

Airgap cluster

See global.image.registry and global.image.imagePullSecret below.

Examples:

  • Defaults

    k8s cluster info non airgap
    # Default configuration. No values required.
  • Openshift

    k8s cluster info openshift
    global:
      openshiftInstallation: true
  • Airgap

    k8s cluster info airgap

    See the docker registry settings below.

Docker registry settings section
Replicated setting Helm configuration key

Docker registry address

Set global.image.registry. Setting this value will enable airgap mode.

Registry is a mirror

Nothing to set in Helm config. You will need to set up your mirror with appropriate credentials to pull images from registry.gradle.com though. Contact Gradle support for guidance prior to starting the migration.

Registry requires authentication

Set global.image.imagePullSecret. Check the installation manual for details.

Examples:

  • Airgap registry setup without credentials

    k8s docker registry settings no auth
    global:
      image:
        registry: registry.example.com/gradle-enterprise
  • Airgap registry setup with credentials

    k8s docker registry settings auth
    global:
      image:
        registry: registry.example.com/gradle-enterprise
        imagePullSecret: example-image-pull-secret-name
Network section

Please review the section on exposing Gradle Enterprise outside your cluster in the installation manual. Existing Ship Kubernetes installations will already be routing traffic to the application’s gradle-proxy service in some way. This guide assumes that this will continue and attempts to configure the proxy to accept traffic in the same way.

Replicated setting Helm configuration key

Hostname

Set global.hostname. Required.

Use HTTP / Use HTTPS

Set proxy.ssl.enabled to true to enable HTTPS terminated by the proxy service.

Use HTTP with external HTTPS termination

Set global.externalSSLTermination to true.

SSL Private Key / SSL Certificate

Set proxy.ssl.key and proxy.ssl.cert. Required when proxy.ssl.enabled=true.

Examples:

  • Using HTTP with the default port

    k8s network http
    global:
      hostname: ge.example.com
  • Using HTTPS with a custom certificate

    k8s network https
    global:
      hostname: ge.example.com
    
    
    proxy:
      ssl:
        enabled: true
        key: |
          -----BEGIN RSA PRIVATE KEY-----
          MIIEpQIBAAKCAQEA4qV8JlqDMi7y85Ykq8dn7uIsi609D6KuFtlc+UvNYjatz0+u
          QzIr3iw//qf7sM8nx8fhGwuWvUWeCE6zbgKjuxDH82J9NQ0ctf70n0qVTeyW1CKR
          w/koEXyecIZIOA9Jh7KNkShfp/x5T3GZ4QK//A/4oJyhD3IeK/nEXr5mSe2AzGxq
          ...
          XlOfXr/xvkXA66PROgvVxfwpN/GNrLXFi1HvMg7MVZJUZQpNzpAzw5JTk2MbawOl
          G7tI0qQ6F20e5R4tPpEDKCFZykyvgGMhfLzsvVlrgaVW8QbVK4YWNtQ=
          -----END RSA PRIVATE KEY-----
        cert: |
          -----BEGIN CERTIFICATE-----
          MIIDKjCCAhKgAwIBAgIRAPNTIHf6/oUuzMKm3ffGNOgwDQYJKoZIhvcNAQELBQAw
          HDEaMBgGA1UEAxMRYXV0by1nZW5lcmF0ZWQtY2EwHhcNMjExMTMwMTU1NDU5WhcN
          MjExMjAxMTU1NDU5WjAjMSEwHwYDVQQDExhvbmx5LWZvci51bml0LXRlc3QubG9j
          ...
          Cn/3yUirFVTslrSYKAemLw8btLO6FDF9dc/lq1o7tKsYVuhEcjqnTah7puJjEN9h
          z+P5RmRxU/kaaFB+Vuw1pRezbaAtZNorVgXnBwrdseY4zLGyhAcGcR9v+VtCiQ==
          -----END CERTIFICATE-----

    Alternatively, the key and certificate can be provided to the helm command via --set-file parameters. See the installation manual for details.

  • Using HTTP with external HTTPS termination

    k8s network https termination
    global:
      hostname: ge.example.com
      externalSSLTermination: true
Storage section

To ensure that your data is preserved when performing migration steps below, it is important that exactly the same storage class and capacities are used.

Replicated setting Helm configuration key

Storage class

Set all of global.storage.data.class, global.storage.backup.class, and global.storage.logs.class to this storage class name.

Build scans storage capacity

Set database.storage.data.capacity. Append Gi to the previous numeric value.

Build scans backups storage capacity

Set database.storage.backup.capacity. Append Gi to the previous numeric value.

Build cache storage capacity

Set buildCacheNode.storage.data.capacity. Append Gi to the previous numeric value.

Test Distribution file cache storage capacity

Set testDistribution.storage.data.capacity. Append Gi to the previous numeric value.

Example:

k8s storage custom
global:
  storage:
    data:
      class: some-provisioned-io-storage-class
    backup:
      class: some-provisioned-io-storage-class
    logs:
      class: some-provisioned-io-storage-class

database:
  storage:
    data:
      capacity: 500Gi
    backup:
      capacity: 500Gi
buildCacheNode:
  storage:
    data:
      capacity: 50Gi
testDistribution:
  storage:
    data:
      capacity: 30Gi
Horizontal scaling section
Replicated setting Helm configuration key

Number of replicas

Set global.scaling.replicas.

Examples:

  • Horizontal scaling disabled

    k8s horizontal scaling disabled
    # Default configuration. No values required.
  • Horizontal scaling enabled

    k8s horizontal scaling enabled
    global:
      scaling:
        replicas: 2
Database section

By default, Gradle Enterprise will use an embedded database. Configuration settings only need to be set when connecting to a user-managed database.

Please review the Database configuration section of the installation manual for details. Different values are required based on which type of credentials are provided.

Replicated setting Helm configuration key

Store data in user-managed database

Set database.location to user-managed. Default is embedded.

Host

Set database.connection.host. Required for a user-managed database.

Port

Set database.connection.port. Default is 5432.

Database name

Set database.connection.databaseName. Required for a user-managed database.

Extra JDBC parameters

Set database.connection.params. Default is no extra paramters.

Database superuser username

Set database.credentials.superuser.username.

Database superuser password

Set database.credentials.superuser.password.

Database application user password

Set database.credentials.app.password.

Database migration user password

Set database.credentials.migration.password.

Examples:

  • Store data in embedded database

    k8s database embedded
    # Default configuration. No values required.
  • Store data in user-managed database and provide database superuser credentials directly

    k8s database superuser direct values
    database:
      location: user-managed
      connection:
        host: database.example.com
        port: 5432
        databaseName: gradle_enterprise
        params: "?connectTimeout=60"
      credentials:
        superuser:
          username: postgres
          password: superuserPassword
  • Store data in user-managed database and provide database superuser credentials as ConfigMap/Secret

    k8s database superuser configmaps
    database:
      location: user-managed
      connection:
        configMapName: my-example-db-connection-details
      credentials:
        superuser:
          secretName: my-example-db-superuser-credentials
  • Store data in user-managed database and do not provide database superuser credentials (direct values)

    k8s database no superuser direct creds
    database:
      location: user-managed
      connection: ...
      credentials:
        app:
          password: app_password
        migrator:
          password: migrator_password
  • Store data in user-managed database and do not provide database superuser credentials (secrets)

    k8s database no superuser configmaps
    database:
      location: user-managed
      connection: ...
      credentials:
        app:
          secretName: my-example-db-application-credentials
        migrator:
          secretName: my-example-db-migrator-credentials
Terminate the Ship app

Once your values.yaml has been populated from the current settings, you may close the browser window and terminate the Ship app process by issuing a CTRL-C in the terminal in which it is running.

Verify that all persistent volumes used by existing app have Retain reclaim policy.

kubectl get pv | grep " gradle-enterprise/"

The output should look something like this:

NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                                                 STORAGECLASS   REASON   AGE
pvc-4367dd37-233c-43f5-998a-0b6f979626cb   200Mi      RWO            Delete           Bound    gradle-enterprise/gradle-test-distribution-logs-volume                local-path              76m
pvc-49421860-1100-4b8e-8ac6-8711343e1628   200Mi      RWO            Delete           Bound    gradle-enterprise/gradle-database-logs-volume                         local-path              76m
pvc-ed0a52c5-a7a4-4c93-b2a8-3a190f866db7   200Mi      RWO            Delete           Bound    gradle-enterprise/logs-gradle-keycloak-0                              local-path              76m
pvc-c0d91c7b-4f3e-41e1-a379-1673b07f4408   10Gi       RWO            Delete           Bound    gradle-enterprise/gradle-database-backups-volume                      local-path              76m
pvc-f92182bc-8d44-4c41-82e5-3719c1226444   200Mi      RWO            Delete           Bound    gradle-enterprise/gradle-metrics-volume                               local-path              76m
pvc-71fc04d0-b395-43b3-89be-9fbcb55c9301   10Gi       RWO            Delete           Bound    gradle-enterprise/gradle-database-volume                              local-path              76m
pvc-c1f84161-8cc6-4c41-ac5a-c78b3c2dfd41   10Gi       RWO            Delete           Bound    gradle-enterprise/gradle-build-cache-volume                           local-path              76m
pvc-537be141-4be6-4e34-8c1a-d6b161e06ede   200Mi      RWO            Delete           Bound    gradle-enterprise/gradle-build-cache-node-logs-volume                 local-path              76m
pvc-b6eadedf-eddd-460f-9b67-f852559a9627   200Mi      RWO            Delete           Bound    gradle-enterprise/logs-gradle-enterprise-app-0                        local-path              75m
pvc-f46ad5b2-1f2e-429d-88da-88cd33689c16   500Mi      RWO            Delete           Bound    gradle-enterprise/logs-gradle-proxy-0                                 local-path              75m
pvc-2ca92343-2bc9-4946-94f2-de7ca7243284   200Mi      RWO            Delete           Bound    gradle-enterprise/gradle-enterprise-operator-logs-volume              local-path              75m
pvc-d712f0de-324f-43c0-8508-96d5de148f68   10Gi       RWO            Delete           Bound    gradle-enterprise/gradle-test-distribution-broker-file-cache-volume   local-path              75m

If any have a Delete reclaim policy, it is very likely that data will be lost during the upgrade process.

Please review the Kubernetes documentation to understand the difference between Delete and Retain policies, and to see commands to update the policy.

The following steps can be used to update the reclaim policy:

  • All Gradle Enterprise persistent volume claim names start with gradle-enterprise/. If there are volume claim names that do not match the names shown in the output above, please contact Gradle Support so ensure that you do not accidentally change the policy for an incorrect persistent volume.

  • Run the following command to update the reclaim policy of matching volumes:

    kubectl get pv \
      | grep " gradle-enterprise/" \
      | awk '{print $1}' \
      | while read v ; do kubectl patch pv $v -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}' ; done

    You should see output like this:

persistentvolume/pvc-ed0a52c5-a7a4-4c93-b2a8-3a190f866db7 patched
persistentvolume/pvc-b6eadedf-eddd-460f-9b67-f852559a9627 patched
persistentvolume/pvc-f46ad5b2-1f2e-429d-88da-88cd33689c16 patched
persistentvolume/pvc-49421860-1100-4b8e-8ac6-8711343e1628 patched
persistentvolume/pvc-c0d91c7b-4f3e-41e1-a379-1673b07f4408 patched
persistentvolume/pvc-f92182bc-8d44-4c41-82e5-3719c1226444 patched
persistentvolume/pvc-71fc04d0-b395-43b3-89be-9fbcb55c9301 patched
persistentvolume/pvc-c1f84161-8cc6-4c41-ac5a-c78b3c2dfd41 patched
persistentvolume/pvc-537be141-4be6-4e34-8c1a-d6b161e06ede patched
persistentvolume/pvc-2ca92343-2bc9-4946-94f2-de7ca7243284 patched
persistentvolume/pvc-d712f0de-324f-43c0-8508-96d5de148f68 patched
persistentvolume/pvc-4367dd37-233c-43f5-998a-0b6f979626cb patched

Rechecking the volume states should show that they all have a Retain policy:

kubectl get pv | grep " gradle-enterprise/"
pvc-1da2bfc4-41f8-469a-a8e5-bd4544f42a2a   10Gi       RWO            Retain           Bound    gradle-enterprise/gradle-database-volume                              local-path              13m
pvc-8e13739c-f445-4537-acfb-27cb6f0cea54   200Mi      RWO            Retain           Bound    gradle-enterprise/logs-gradle-keycloak-0                              local-path              13m
pvc-36ce81f7-1e74-407a-84cc-41678bd802d9   200Mi      RWO            Retain           Bound    gradle-enterprise/gradle-database-logs-volume                         local-path              13m
pvc-a004b6d8-94e8-4f9d-9c4c-77f0a67a6015   10Gi       RWO            Retain           Bound    gradle-enterprise/gradle-test-distribution-broker-file-cache-volume   local-path              13m
pvc-0a0e05f1-d8aa-4407-b66a-3d7f275c7000   200Mi      RWO            Retain           Bound    gradle-enterprise/logs-gradle-enterprise-app-0                        local-path              13m
pvc-8df76bb3-7132-4ff9-88d8-27ebce374508   200Mi      RWO            Retain           Bound    gradle-enterprise/gradle-test-distribution-logs-volume                local-path              13m
pvc-83750521-8b28-45c9-9860-ade8add0e08b   500Mi      RWO            Retain           Bound    gradle-enterprise/logs-gradle-proxy-0                                 local-path              13m
pvc-c6d74ff6-f8c9-4366-b07a-ca86c8c48a3f   200Mi      RWO            Retain           Bound    gradle-enterprise/gradle-metrics-volume                               local-path              13m
pvc-342ba3e8-5646-4b71-8c90-cfa92c50e41f   10Gi       RWO            Retain           Bound    gradle-enterprise/gradle-database-backups-volume                      local-path              13m
pvc-6eb4b99e-32db-4ef5-bc5c-e653e63d1098   200Mi      RWO            Retain           Bound    gradle-enterprise/gradle-build-cache-node-logs-volume                 local-path              13m
pvc-6f2df0c5-4e8e-48b3-8896-3983b665b9e3   200Mi      RWO            Retain           Bound    gradle-enterprise/gradle-enterprise-operator-logs-volume              local-path              13m
pvc-aeb436f9-c084-4b41-83a2-050e3a062661   10Gi       RWO            Retain           Bound    gradle-enterprise/gradle-build-cache-volume                           local-path              13m

Chart and image download

Installation steps are slightly different, depending on whether an online or airgap installation is being performed.

Online installation chart download

On your installation host, add the Gradle Helm repository:

helm repo add gradle https://helm.gradle.com
helm repo update gradle

Verify that Helm has the latest Gradle Enterprise chart:

helm search repo gradle-enterprise

You should see the latest available:

NAME                    	CHART VERSION   APP VERSION   DESCRIPTION
gradle/gradle-enterprise	2022.3.0	2022.3        Official Gradle Enterprise Chart

Verify that this is the same version as is installed in the existing installation. If it is not, then either the existing installation needs to be upgraded or the local Helm repository cache should be updated again by running helm repo update gradle.

Airgap installation chart and image download

Verify that your license is airgap-enabled. If you examine the license file content, you should see airgap listed as an entitlement. If you need to perform an airgap installation but do not have the airgap entitlement on your license, please contact your customer success representative.

On an internet connected host, with your Gradle Enterprise license file available:

  1. Download the airgap bundle for the version that you are installing:

    curl -LOJd @/path/to/gradle-enterprise.license https://registry.gradle.com/airgap/gradle-enterprise-2022.3-bundle.tar.gz

    You can optionally verify the downloaded bundle file.

  2. Transfer the downloaded bundle file to your installation host, if the above was run on a different host.

On the installation host:

  1. Expand the bundle:

    tar zxvf gradle-enterprise-2022.3-bundle.tar.gz
  2. Run the following command to upload images to your internal container registry. You must be logged in to the registry prior to running the command. The upload-images.sh script is included in the airgap bundle and extracted in the step above.

    ./upload-images.sh --registry=registry.example.com/gradle-enterprise

Uninstall the existing installation

At this point, expect Gradle Enterprise to be unavailable for up to 30 minutes.

The uninstall script does not remove persistent volumes, and those set to a Retain policy above will remain available until the new installation picks them up.

Run the uninstall script for the current installation:

# from the previously-created grade-enterprise directory
./installer/scripts/uninstall.sh

In addition, some extra persistent volume claims may need to be deleted. Check if any are left (subsequent commands assume the application is installed in the gradle-enterprise namespace - please adjust to your setup):

kubectl -n gradle-enterprise get pvc
NAME                           STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
logs-gradle-keycloak-0         Bound    pvc-8e13739c-f445-4537-acfb-27cb6f0cea54   200Mi      RWO            local-path     23m
logs-gradle-enterprise-app-0   Bound    pvc-0a0e05f1-d8aa-4407-b66a-3d7f275c7000   200Mi      RWO            local-path     23m
logs-gradle-proxy-0            Bound    pvc-83750521-8b28-45c9-9860-ade8add0e08b   500Mi      RWO            local-path     23m

If any are left, remove them by executing the following command:

kubectl -n gradle-enterprise delete pvc \
  $(kubectl -n gradle-enterprise get pvc -o jsonpath='{.items[*].metadata.name}')
persistentvolumeclaim "logs-gradle-keycloak-0" deleted
persistentvolumeclaim "logs-gradle-enterprise-app-0" deleted
persistentvolumeclaim "logs-gradle-proxy-0" deleted

Make all persistent volumes available

At this point, all persistent volumes should be marked as Released. To confirm:

kubectl get pv | grep " gradle-enterprise/"
pvc-1da2bfc4-41f8-469a-a8e5-bd4544f42a2a   10Gi       RWO            Retain           Released   gradle-enterprise/gradle-database-volume                              local-path              27m
pvc-342ba3e8-5646-4b71-8c90-cfa92c50e41f   10Gi       RWO            Retain           Released   gradle-enterprise/gradle-database-backups-volume                      local-path              27m
pvc-36ce81f7-1e74-407a-84cc-41678bd802d9   200Mi      RWO            Retain           Released   gradle-enterprise/gradle-database-logs-volume                         local-path              27m
pvc-aeb436f9-c084-4b41-83a2-050e3a062661   10Gi       RWO            Retain           Released   gradle-enterprise/gradle-build-cache-volume                           local-path              27m
pvc-6eb4b99e-32db-4ef5-bc5c-e653e63d1098   200Mi      RWO            Retain           Released   gradle-enterprise/gradle-build-cache-node-logs-volume                 local-path              27m
pvc-a004b6d8-94e8-4f9d-9c4c-77f0a67a6015   10Gi       RWO            Retain           Released   gradle-enterprise/gradle-test-distribution-broker-file-cache-volume   local-path              27m
pvc-8df76bb3-7132-4ff9-88d8-27ebce374508   200Mi      RWO            Retain           Released   gradle-enterprise/gradle-test-distribution-logs-volume                local-path              27m
pvc-6f2df0c5-4e8e-48b3-8896-3983b665b9e3   200Mi      RWO            Retain           Released   gradle-enterprise/gradle-enterprise-operator-logs-volume              local-path              27m
pvc-c6d74ff6-f8c9-4366-b07a-ca86c8c48a3f   200Mi      RWO            Retain           Released   gradle-enterprise/gradle-metrics-volume                               local-path              27m
pvc-8e13739c-f445-4537-acfb-27cb6f0cea54   200Mi      RWO            Retain           Released   gradle-enterprise/logs-gradle-keycloak-0                              local-path              27m
pvc-0a0e05f1-d8aa-4407-b66a-3d7f275c7000   200Mi      RWO            Retain           Released   gradle-enterprise/logs-gradle-enterprise-app-0                        local-path              27m
pvc-83750521-8b28-45c9-9860-ade8add0e08b   500Mi      RWO            Retain           Released   gradle-enterprise/logs-gradle-proxy-0                                 local-path              27m

To make these available for the new installation to pick up, run the following command

kubectl get pv \
  | grep " gradle-enterprise/" \
  | awk '{print $1}' \
  | while read v ; do kubectl patch pv $v --type json -p '[{"op": "remove", "path": "/spec/claimRef/uid"}]' ; done
persistentvolume/pvc-1da2bfc4-41f8-469a-a8e5-bd4544f42a2a patched
persistentvolume/pvc-342ba3e8-5646-4b71-8c90-cfa92c50e41f patched
persistentvolume/pvc-36ce81f7-1e74-407a-84cc-41678bd802d9 patched
persistentvolume/pvc-aeb436f9-c084-4b41-83a2-050e3a062661 patched
persistentvolume/pvc-6eb4b99e-32db-4ef5-bc5c-e653e63d1098 patched
persistentvolume/pvc-a004b6d8-94e8-4f9d-9c4c-77f0a67a6015 patched
persistentvolume/pvc-8df76bb3-7132-4ff9-88d8-27ebce374508 patched
persistentvolume/pvc-6f2df0c5-4e8e-48b3-8896-3983b665b9e3 patched
persistentvolume/pvc-c6d74ff6-f8c9-4366-b07a-ca86c8c48a3f patched
persistentvolume/pvc-8e13739c-f445-4537-acfb-27cb6f0cea54 patched
persistentvolume/pvc-0a0e05f1-d8aa-4407-b66a-3d7f275c7000 patched
persistentvolume/pvc-83750521-8b28-45c9-9860-ade8add0e08b patched

Now all persistent volumes should report as being Available:

kubectl get pv | grep " gradle-enterprise/"
pvc-1da2bfc4-41f8-469a-a8e5-bd4544f42a2a   10Gi       RWO            Retain           Available   gradle-enterprise/gradle-database-volume                              local-path              32m
pvc-342ba3e8-5646-4b71-8c90-cfa92c50e41f   10Gi       RWO            Retain           Available   gradle-enterprise/gradle-database-backups-volume                      local-path              32m
pvc-36ce81f7-1e74-407a-84cc-41678bd802d9   200Mi      RWO            Retain           Available   gradle-enterprise/gradle-database-logs-volume                         local-path              32m
pvc-aeb436f9-c084-4b41-83a2-050e3a062661   10Gi       RWO            Retain           Available   gradle-enterprise/gradle-build-cache-volume                           local-path              32m
pvc-6eb4b99e-32db-4ef5-bc5c-e653e63d1098   200Mi      RWO            Retain           Available   gradle-enterprise/gradle-build-cache-node-logs-volume                 local-path              32m
pvc-a004b6d8-94e8-4f9d-9c4c-77f0a67a6015   10Gi       RWO            Retain           Available   gradle-enterprise/gradle-test-distribution-broker-file-cache-volume   local-path              32m
pvc-8df76bb3-7132-4ff9-88d8-27ebce374508   200Mi      RWO            Retain           Available   gradle-enterprise/gradle-test-distribution-logs-volume                local-path              32m
pvc-6f2df0c5-4e8e-48b3-8896-3983b665b9e3   200Mi      RWO            Retain           Available   gradle-enterprise/gradle-enterprise-operator-logs-volume              local-path              32m
pvc-c6d74ff6-f8c9-4366-b07a-ca86c8c48a3f   200Mi      RWO            Retain           Available   gradle-enterprise/gradle-metrics-volume                               local-path              32m
pvc-8e13739c-f445-4537-acfb-27cb6f0cea54   200Mi      RWO            Retain           Available   gradle-enterprise/logs-gradle-keycloak-0                              local-path              32m
pvc-0a0e05f1-d8aa-4407-b66a-3d7f275c7000   200Mi      RWO            Retain           Available   gradle-enterprise/logs-gradle-enterprise-app-0                        local-path              32m
pvc-83750521-8b28-45c9-9860-ade8add0e08b   500Mi      RWO            Retain           Available   gradle-enterprise/logs-gradle-proxy-0                                 local-path              32m

Install Helm-based Gradle Enterprise version

Follow the guidelines in installation manual and install Gradle Enterprise using Helm.

An example set of steps are shown below, assuming a direct install without extracting the Helm chart.

Online installation

Install Gradle Enterprise by issuing the following command:

helm install \
  --create-namespace --namespace gradle-enterprise \
  ge gradle/gradle-enterprise \
  --values /path/to/values.yaml \
  --set-file global.license.file=/path/to/gradle-enterprise.license \
  # [other options] (1)
1 Further options:
  • If SSL certificate files are being used, and are not embedded in the values.yaml, these should also be passed here using --set-file. See the installation guide for an example.

  • See the appendix for extra parameters if you are using unattended installation.

Airgap installation
helm install \
  --create-namespace --namespace gradle-enterprise \
  ge gradle-enterprise-2022.3.0.tgz \(1)
  --values /path/to/values.yaml \
  --set-file global.license.file=/path/to/gradle-enterprise.license \
  # [other options] (2)
1 This is the path to the .tgz Helm chart file included in the downloaded airgap bundle.
2 Further options:
  • If SSL certificate files are being used, and are not embedded in the values.yaml, these should also be passed here using --set-file. See the installation guide for an example.

  • See the appendix for extra parameters if you are using unattended installation.

Verify system status

Persistent volume binding

Checking the persistent volumes should show them all bound again:

kubectl get pv | grep " gradle-enterprise/"
pvc-a004b6d8-94e8-4f9d-9c4c-77f0a67a6015   10Gi       RWO            Retain           Bound    gradle-enterprise/gradle-test-distribution-broker-file-cache-volume   local-path              57m
pvc-342ba3e8-5646-4b71-8c90-cfa92c50e41f   10Gi       RWO            Retain           Bound    gradle-enterprise/gradle-database-backups-volume                      local-path              57m
pvc-c6d74ff6-f8c9-4366-b07a-ca86c8c48a3f   200Mi      RWO            Retain           Bound    gradle-enterprise/gradle-metrics-volume                               local-path              57m
pvc-6eb4b99e-32db-4ef5-bc5c-e653e63d1098   200Mi      RWO            Retain           Bound    gradle-enterprise/gradle-build-cache-node-logs-volume                 local-path              56m
pvc-36ce81f7-1e74-407a-84cc-41678bd802d9   200Mi      RWO            Retain           Bound    gradle-enterprise/gradle-database-logs-volume                         local-path              57m
pvc-aeb436f9-c084-4b41-83a2-050e3a062661   10Gi       RWO            Retain           Bound    gradle-enterprise/gradle-build-cache-volume                           local-path              56m
pvc-1da2bfc4-41f8-469a-a8e5-bd4544f42a2a   10Gi       RWO            Retain           Bound    gradle-enterprise/gradle-database-volume                              local-path              57m
pvc-6f2df0c5-4e8e-48b3-8896-3983b665b9e3   200Mi      RWO            Retain           Bound    gradle-enterprise/gradle-enterprise-operator-logs-volume              local-path              56m
pvc-8df76bb3-7132-4ff9-88d8-27ebce374508   200Mi      RWO            Retain           Bound    gradle-enterprise/gradle-test-distribution-logs-volume                local-path              57m
pvc-83750521-8b28-45c9-9860-ade8add0e08b   500Mi      RWO            Retain           Bound    gradle-enterprise/logs-gradle-proxy-0                                 local-path              57m
pvc-0a0e05f1-d8aa-4407-b66a-3d7f275c7000   200Mi      RWO            Retain           Bound    gradle-enterprise/logs-gradle-enterprise-app-0                        local-path              57m
pvc-8e13739c-f445-4537-acfb-27cb6f0cea54   200Mi      RWO            Retain           Bound    gradle-enterprise/logs-gradle-keycloak-0                              local-path              57m
Gradle Enterprise service availability

You can inspect the status of the Gradle Enterprise pods by running kubectl get pods:

kubectl --namespace gradle-enterprise get pods
NAME                                              READY   STATUS    RESTARTS   AGE
gradle-enterprise-operator-5646785cc5-hk7br       1/1     Running   0          8m39s
gradle-database-5946778f79-5nfbf                  2/2     Running   0          8m39s
gradle-proxy-0                                    1/1     Running   0          8m39s
gradle-metrics-7478b7875b-vp7j9                   1/1     Running   0          8m39s
gradle-enterprise-app-0                           1/1     Running   0          8m39s
gradle-build-cache-node-7bcb768f55-hb7zv          1/1     Running   0          8m39s
gradle-test-distribution-broker-5698459b8-z9skv   1/1     Running   0          8m39s
gradle-keycloak-0                                 1/1     Running   0          8m39s

The app will be ready once all pods report as Running.

Service connectivity verification

Please verify that your system is being connected-to correctly. Which services to check will depend on which you use:

  • If authentication is required, can users log in?

  • Are build scans being collected correctly? See /scans.

  • Are build cache nodes connected? See /cache-admin.

  • Are test distribution agents connected? /admin/test-distribution.

Data verification

Please inspect your system to validate that historical data has been migrated. Viewing /scans and ordering by oldest build scan will show the oldest scans in your system.

Support

If any steps do not result in the expected state, please contact Gradle support.

Appendix A: Unattended installation

If you are configuring Gradle Enterprise using an Unattended installation file, you must add additional parameters to the helm install commands above:

--set-file=global.unattended.configuration=/path/to/unattended.yaml
--set-file=global.unattended.key=/path/to/unattended.key

Appendix B: Contacting support

Contact Gradle support by creating a support ticket at support.gradle.com, including:

  • Details of the type of migration

  • The version being migrated from/to

  • Steps taken so far

  • Errors or unexpected behavior

Appendix C: Verifying the airgap bundle

You can verify the downloaded file by downloading a SHA256 checksum and using the sha256sum utility to verify the bundle file:

curl -LOJd @/path/to/gradle-enterprise.license https://registry.gradle.com/airgap/gradle-enterprise-2022.3-bundle.tar.gz.sha256
sha256sum -c gradle-enterprise-2022.3-bundle.tar.gz.sha256

or, for the standalone bundle:

curl -LOJd @/path/to/gradle-enterprise.license https://registry.gradle.com/airgap/gradle-enterprise-standalone-2022.3-bundle.tar.gz.sha256
sha256sum -c gradle-enterprise-standalone-2022.3-bundle.tar.gz.sha256