Install Trino on Kubernetes

This article describes how to deploy the ADH Trino service in Kubernetes.

Prerequisites

To deploy Trino on Kubernetes, you need:

  • A Kubernetes cluster 1.32 or later with access configured through kubectl.

  • Helm (3.8.0 or higher) — a package manager for Kubernetes that allows quick deployment of Docker images in Kubernetes.

  • Trino artifacts (Docker images and Helm charts) loaded to your private OCI registry. These artifacts can be found in offline packages, which can be requested from the Arenadata support team. To deploy Trino components on Kubernetes, you need to unpack the following images:

    • hub.arenadata.io/adh-enterprise/trino-docker:<version>

    • hub.arenadata.io/adc-enterprise/trino-operator:<version>

    Also, the following Helm charts must be extracted and loaded to your private registry:

    • hub.arenadata.io/adc-enterprise/charts/trino-cluster:<version>

    • hub.arenadata.io/adc-enterprise/charts/trino-operator:<version>

  • An up-and-running ADH cluster (4.2.0 or later) with the following services:

    • Core configuration

    • ADPG

    • Zookeeper

    • HDFS

    • YARN

    • Hive

    Trino runs outside the ADH cluster — in Kubernetes pods, and communicates with ADH over the network.

Deployment steps

The steps below describe how to install and configure Trino components on Kubernetes. Configurations related to providing external access, Ingress controllers, load balancers, DNS, and cloud annotations should be performed with respect to your Kubernetes infrastructure.

Step 1. Install Trino operator

  1. Create trino_operator_values.yaml:

    # Default values for ad-trino-operator.
    # This is a YAML-formatted file.
    # Declare variables to be passed into your templates.
    
    # This will set the replicaset count more information can be found here: https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/
    replicas: 1
    payloadNamespaces: (1)
      # Managed namespaces for Trino payload resources.
      names:
        - trino
      # Explicit opt-in for cluster-wide RBAC when payloadNamespaces.names is empty.
      # When false, chart rendering fails until namespaces are specified.
      allowClusterRole: false
      deleteProtection: false
      avoidCreation: false
    
    # This sets the container image more information can be found here: https://kubernetes.io/docs/concepts/containers/images/
    image:
      registry: "<registry>" (2)
      repository: "<image>" (3)
      # This sets the pull policy for images.
      pullPolicy: IfNotPresent
      # Overrides the image tag whose default is the chart appVersion.
      tag: "<tag>"
      # This is for the secrets for pulling an image from a private repository more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
      pullSecret: (4)
        name: ""
        ## List of secrets to create for image pulling in all product namespaces
        credentials: {}
    #      registry: private-docker-registry
    #      username: user
    #      password: pass
    
    # This is to override the chart name.
    nameOverride: ""
    fullnameOverride: ""
    
    # This section builds out the service account more information can be found here: https://kubernetes.io/docs/concepts/security/service-accounts/
    serviceAccount:
      # Automatically mount a ServiceAccount's API credentials?
      automount: true
      # Annotations to add to the service account
      annotations: {}
      # The name of the service account to use.
      # If not set and create is true, a name is generated using the fullname template
      name: ""
    
    # This is for setting Kubernetes Annotations to a Pod.
    # For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/
    podAnnotations: {}
    # This is for setting Kubernetes Labels to a Pod.
    # For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
    podLabels: {}
    
    podSecurityContext: {}
      # fsGroup: 2000
    
    securityContext:
      readOnlyRootFilesystem: true
      privileged: false
      allowPrivilegeEscalation: false
      runAsNonRoot: true
      runAsUser: 65532
      capabilities:
        drop:
          - ALL
      seccompProfile:
        type: RuntimeDefault
    
    
    # This is for setting up a service more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/
    service:
      # This sets the service type more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types
      type: ClusterIP
      # This sets the ports more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/#field-spec-ports
      port: 8443
    
    resources: {}
      # We usually recommend not to specify default resources and to leave this as a conscious
      # choice for the user. This also increases chances charts run on environments with little
      # resources, such as Minikube. If you do want to specify resources, uncomment the following
      # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
      # limits:
      #   cpu: 100m
      #   memory: 128Mi
      # requests:
      #   cpu: 100m
      #   memory: 128Mi
    
    nodeSelector: {}
    
    tolerations: []
    
    affinity: {}
    
    terminationGracePeriodSeconds: 10
    1 List of namespaces for the operator to manage resources.
    2 The address of your OCI registry to pull images from.
    3 The name of repository in your registry.
    4 Provide credentials to access your private Docker registry.
  2. Install Trino operator:

    $ helm upgrade --install trino-operator oci://<registry-address>/adc-enterprise/charts/trino-operator:<version> --version <version> -f trino_operator_values.yaml --namespace trino-operator --create-namespace

    where <registry-address> is the address of your OCI registry with loaded Trino Helm charts.

    Example output:

    Release "trino-operator" does not exist. Installing it now.
    Pulled: hub.arenadata.io/adc-enterprise/charts/trino-operator:<version>
    Digest: sha256:0ad904dadfe7d8120864445e3f780f331061a7b66383aede35ca5db28a471a8a
    NAME: trino-operator
    LAST DEPLOYED: Wed May 6 14:06:11 2026
    NAMESPACE: trino-operator
    STATUS: deployed
    REVISION: 1
    DESCRIPTION: Install complete
    TEST SUITE: None
    NOTES:
  3. Verify the Trino operator installation using the command below:

    $ kubectl get pods -n trino-operator

    The output:

    NAME                                 READY   STATUS    RESTARTS   AGE
    trino-operator-7698f97987-ff6kz   1/1     Running   0          78s

Step 2. Create Kubernetes secrets with ADH configurations

To allow Trino in Kubernetes to communicate with your ADH cluster, it is necessary to provide ADH configurations to every Kubernetes pod. A way to do this is through Kubernetes secrets. In this case, ADH configuration files will be available in every pod at /opt/trino-server/etc/catalog/.

For this:

  1. Create the core-site.xml and iceberg.properties configuration files, using the following templates. Use configuration values from your ADH cluster.

    core-site.xml

     

    <?xml version="1.0"?>
    <configuration>
            <property>
                    <name>fs.defaultFS</name>
                    <value>hdfs://adh</value> (1)
            </property>
            <property>
                    <name>hadoop.security.authentication</name>
                    <value>simple</value>
            </property>
            <property>
                    <name>dfs.ha.namenodes.adh</name>
                    <value>nn_ka-adh-1,nn_ka-adh-2</value>
            </property>
            <property>
                    <name>dfs.namenode.rpc-address.adh.nn_ka-adh-1</name>
                    <value>ka-adh-1.ru-central1.internal:8020</value>
            </property>
            <property>
                    <name>dfs.namenode.rpc-address.adh.nn_ka-adh-2</name>
                    <value>ka-adh-2.ru-central1.internal:8020</value>
            </property>
            <property>
                    <name>dfs.nameservices</name>
                    <value>adh</value>
            </property>
                    <property>
                    <name>dfs.client.failover.proxy.provider.adh</name>
                    <value>org.apache.hadoop.hdfs.server.namenode.ha.ObserverReadProxyProvider</value>
            </property>
                    <property>
                    <name>hadoop.proxyuser.trino.groups</name>
                    <value>*</value>
            </property>
            <property>
                    <name>hadoop.proxyuser.trino.hosts</name>
                    <value>*</value>
            </property>
    </configuration>
    1 Replace with a value from your ADH cluster’s /etc/hadoop/conf/core-site.xml.
    iceberg.properties

     

    connector.name=iceberg
    hive.metastore.uri=thrift://ka-adh-2.ru-central1.internal:9083 (1)
    hive.metastore.authentication.type=NONE
    hive.metastore.thrift.impersonation.enabled=true
    fs.hadoop.enabled=True
    hive.hdfs.authentication.type=NONE
    hive.hdfs.wire-encryption.enabled=true
    hive.hdfs.impersonation.enabled=True
    hive.config.resources=/opt/trino-server/etc/catalog/core-site.xml
    hive.metastore.thrift.client.ssl.enabled=False
    1 Specify your Hive Metastore address. For this, use the hive.metastore.uris property from your ADH cluster’s /etc/hive/conf/hive-site.xml.
    TIP
    Your ADH cluster’s configuration files can be found on cluster hosts at /etc/hadoop/conf/ and /etc/trino/conf/catalog/.
  2. Create secrets:

    $ kubectl -n trino create secret generic trino-configs --from-file=core-site.xml --from-file=iceberg.properties

    Verify the secrets:

    $ kubectl get secrets -n trino

    The output:

    NAME            TYPE     DATA   AGE
    trino-configs   Opaque   2      16m

Step 3. Install Trino cluster

  1. Create trino_cluster_values.yaml:

    image:
      registry: "<registry>" (1)
      repository: "<image>" (2)
      tag: "<tag>"
      pullPolicy: Always
      pullSecret: (3)
        name: ""
        ## List of secrets to create for image pulling in all product namespaces
        credentials: {}
    #      registry: private-docker-registry
    #      username: user
    #      password: pass
    
    useRanger: false
    configsSecretName: "trino-configs"
    
    securityContext: {}
      # capabilities:
      #   drop:
      #   - ALL
      # readOnlyRootFilesystem: true
      # runAsNonRoot: true
      # runAsUser: 1000
    
    worker:
      replicas: 2
      resources:
        requests:
          cpu: 500m
          memory: 1Gi
        limits:
          cpu: "2"
          memory: 4Gi
    coordinator:
      replicas: 1
      resources:
        requests:
          cpu: 500m
          memory: 1Gi
        limits:
          cpu: "2"
          memory: 4Gi
    1 The address of your OCI registry to pull images from.
    2 The name of repository in your registry.
    3 Provide credentials to access your private Docker registry.
  2. Install Trino cluster:

    $ helm upgrade --install trino-cluster oci://<registry-address>/adc-enterprise/charts/trino-cluster:<version> --version <version> -f trino_cluster_values.yaml --namespace trino --create-namespace

    where <registry-address> is the address of your registry with Helm charts for Trino.

    Example output:

    Release "trino-cluster" does not exist. Installing it now.
    Pulled: hub.arenadata.io/adc-enterprise/charts/trino-cluster:<version>
    Digest: sha256:bb3a10be127d8c9937d615f41f31393251d59753480f2a02ec6d874200c0a354
    NAME: trino-cluster
    LAST DEPLOYED: Fri May  8 15:06:24 2026
    NAMESPACE: trino
    STATUS: deployed
    REVISION: 1
    DESCRIPTION: Install complete
    TEST SUITE: None
  3. Verify the installation using the commands below:

    $ kubectl get clusters.trino.arenadata.io -n trino
    $ kubectl get pods -n trino

    The output:

    kubectl get clusters.trino.arenadata.io -n trino
    NAME               READY   AGE
    trino-cluster   True    4m41s
    konstantin@ka-trino-k8s-1:~/trino$ kubectl get pods -n trino
    NAME                             READY   STATUS    RESTARTS   AGE
    trino-cluster-coordinator-0   1/1     Running   0          4m49s
    trino-cluster-worker-0        1/1     Running   0          4m49s
    trino-cluster-worker-1        1/1     Running   0          4m20s

    Ensure that the Trino cluster pods are in the Running state.

To inspect Trino logs within a pod, use the following command:

$ kubectl logs <pod-name> -n trino

Step 4. Allow JDBC connection to Trino

For external JDBC access to the Trino Coordinator, you need to expose the service using one of the supported publication methods, for example, through a load balancer or Ingress controller. All configurations related to exposing a service, including DNS, annotations, Ingress settings, TLS certificates, load balancing rules, and other platform-specific settings, must be specified according to your Kubernetes environment.

  1. Get the external IP address of your load balancer or Ingress controller. For example:

    NAME            CLASS   HOSTS                                 ADDRESS       PORTS   AGE
    trino-ingress   nginx   ka-trino-k8s-1.ru-central1.internal   10.92.41.95   80      57s

    Copy the external IP address (10.92.41.95 in this example) for the next steps.

  2. Connect to the Trino cluster over JDBC, for example, using DBeaver. For this, the JDBC connection string looks as follows:

    jdbc:trino://<external-ip>:80

    where <external-ip> is the Ingress/load balancer IP address from the previous step.

  3. Once connected, verify the Trino cluster operability:

    SHOW CATALOGS;

    The output:

    Catalog   |
    ----------+
    iceberg   |
    system    |

Step 5. Provide access to Trino web UI

To access Trino web interface, you need to expose the service using one of the supported publication methods, for example, through a load balancer or Ingress controller. All configurations related to exposing a service, including DNS, annotations, Ingress settings, load balancing rules, and other platform-specific settings, must be specified according to your Kubernetes environment.

  1. Get the external IP address of your load balancer or Ingress controller. For example:

    NAME            CLASS   HOSTS                                 ADDRESS       PORTS   AGE
    trino-ingress   nginx   ka-trino-k8s-1.ru-central1.internal   10.92.41.95   80      42m

    Copy the external IP address for the next steps.

  2. Add a line to your /etc/hosts:

    <external-ip> ka-trino-k8s-1.ru-central1.internal

    where <external-ip> is the Ingress/load balancer IP address from the previous step.

  3. Open Trino Coordinator web UI in your browser, using the URL: http://ka-trino-k8s-1.ru-central1.internal:80.

    Trino web UI
    Trino web UI

Delete instances

IMPORTANT

Delete the operator only after all the resources it manages have been deleted.

To delete the Trino cluster, run the command below:

$ helm uninstall trino-cluster --namespace trino

To delete the Trino operator, run the command below:

$ helm uninstall trino-operator --namespace trino-operator

To delete the Trino cluster CRD, run the command below:

$ kubectl delete crd clusters.trino.arenadata.io
Found a mistake? Seleсt text and press Ctrl+Enter to report it