Configure Kerberos and SSL for Trino on Kubernetes using CLI

Prerequisites

To access Trino web UI and allow JDBC connections, generate a certificate for Ingress:

$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout trino-cloud.ru-central1.internal.key -out trino-cloud.ru-central1.internal.crt -subj "/CN=trino-cloud.ru-central1.internal"
NOTE
The Kerberos and LDAP authentications are mutually exclusive.

Step 1. Install Kerberos operator

  1. Unpack and push the Kerberos operator image to your repository.

  2. Initialize Kerberos operator:

    $ ./adc init --kerberos-operator -o kerberos-operator.yaml

    This operation creates the kerberos-operator.yaml file with a configuration template.

  3. Edit the configuration file to your needs:

    kerberos-operator.yaml
    apiVersion: adc.arenadata.io/v1alpha1
    kind: KerberosOperator
    metadata:
      name: kerberos-operator
      namespace: kerberos-operator (1)
    spec:
      image: hub.arenadata.io/adc-enterprise/kerberos-operator:<tag> (2)
    
      # Number of replicas
      # replicas: 1
    
      resources:
        limits:
          cpu: 500m
          memory: 256Mi
    
      # Operator ServiceAccount. create: true (default) also creates the manager and per-payload-namespace Role/RoleBinding bound to it; create: false skips all three - name then refers to a ServiceAccount (and RBAC) managed entirely outside the CLI.
      serviceAccount: (3)
        create: true
        name: "kerberos-operator"
    
      # Whether the CLI creates the product namespace.
      # The namespace name is set in metadata.namespace.
      namespace:
        create: true
    
      # Create namespaces to run the payload.
      createPayloadNamespaces: true
    
      # List of namespaces to run the payload in.
      payloadNamespaces: (4)
        - trino
    
      ## Image pull secret for a private registry.
      ## Set 'externalSecretName' to reference an existing Secret,
      ## or set 'credentials' and optionally 'secretName' to let the CLI create one.
      #imagePullSecret:
      #  # Use a Secret managed outside ADC.
      #  externalSecretName: existing-registry-secret
      #
      #  ## Or let ADC create the Secret.
      #  #secretName: custom-registry-secret
      #
      #  #credentials:
      #  #  registry: registry.example.com
      #  #  username: user
      #  #  password: pass
    
      ## Operator monitoring configuration. Supports product-specific metrics export and optional vmagent delivery to an external ADM.
      #monitoring:
      #  # Expose the Kerberos operator metrics endpoint on port 8443.
      #  exportMetrics: true
      #
      #  # Renders a namespace-scoped vmagent that sends metrics to an external ADM.
      #  vmagent:
      #    remoteWrite:
      #      url: http://vminsert.example.com/insert/0/prometheus/api/v1/write
      #    scrapeInterval: 15s
      #    image: hub.arenadata.io/adm-enterprise/vmagent:1.136.0-adm-5.0.0-x86_64
      #
      #    ## HTTPS settings used by vmagent when scraping product metrics.
      #    #tls:
      #    #  ## CA certificate source used to verify the metrics endpoint.
      #    #  #ca:
      #    #  #  # Use a Secret managed outside ADC.
      #    #  #  externalSecretName: existing-product-metrics-ca
      #    #  #
      #    #  #  ## Or let ADC create the Secret.
      #    #  #  #secretName: product-metrics-ca
      #    #  #
      #    #  #  # Key containing the CA certificate in the referenced Secret.
      #    #  #  certificateKey: ca.crt
      #    #  #
      #    #  #  ## Local CA certificate read by ADC to create the configured Secret.
      #    #  #  #files:
      #    #  #  #  certificatePath: /path/to/ca.crt
      #    #
      #    #  ## Server name used to verify the metrics endpoint certificate hostname.
      #    #  #serverName: metrics.example.com
      #    #
      #    #  # Skip verification of the metrics endpoint certificate. Do not use together with ca.
      #    #  insecureSkipVerify: true
    
      ## TLS certificate configuration for metrics endpoint.
      ## Set externalSecretName to reference an existing Secret,
      ## or set files and optional secretName to have ADC create it.
      #metricsTLS:
      #  ## Optional name of the Secret ADC creates from local files.
      #  #secretName: custom-metrics-tls-secret
      #  externalSecretName: existing-metrics-tls-secret
      #
      #  # Key in the Secret containing the TLS certificate.
      #  certificateKey: tls.crt
      #
      #  # Key in the Secret containing the TLS private key.
      #  privateKey: tls.key
      #
      #  ## Local files 'adc apply' puts into the Secret named by metricsTLS.secretName.
      #  ## Relative paths are resolved against the config file.
      #  #files:
      #  #  certificatePath: /path/to/tls.crt
      #  #  privateKeyPath: /path/to/tls.key
    
      ## Defines the Kerberos realm configuration and krb5.conf-related settings.
      kdc: (5)
        realm: AD.RANGER-TEST
        labelSelector:
          env: prod
        realms:
          AD.RANGER-TEST: |-
            kdc = ad01.adsw.io
            admin_server = ad01.adsw.io
        domainRealm:
          ad.ranger-test: AD.RANGER-TEST
        libdefaults:
      #    debug: "false"
          default_realm: AD.RANGER-TEST
      #    default_tgs_enctypes: aes256-cts-hmac-sha1-96
      #    dns_lookup_kdc: "false"
    
      ## Defines connection and authentication details for the LDAP server (backend for Kerberos KDC).
      ldapSecret: (6)
        secretName: ldap-credentials
        provider: ad
        address: ldaps://ad01.adsw.io:636
        adminUser: stikhomirov@AD.RANGER-TEST
        adminPassword: <password>
        baseDN: OU=stikhomirov_ou,OU=kerberos,OU=adh,DC=ad,DC=ranger-test
        ca: "" (7)
      #
      #  # Local file paths consumed by the CLI during 'adc apply'.
      #  # Paths are relative to the config file. The CLI reads this file
      #  # and creates the Secret named by ldapSecret.secretName.
      #  files:
      #    certificatePath: /path/to/ca.pem
    1 Namespace settings.
    2 URL to the Kerberos operator image in your repository.
    3 Service account settings.
    4 Payload namespace settings. The listed namespaces will be available to the Kerberos operator instance.
    5 KDC settings.
    6 LDAP settings. If you don’t use SSL, change the protocol to ldap and port to 389.
    7 A PEM-encoded CA certificate if LDAP is secured with SSL.
  4. You can check the configuration about to be applied by running the apply command with the --dry-run option:

    $ ./adc apply -f kerberos-operator.yaml --dry-run > kerberos-operator-render.yaml
    kerberos-operator-render.yaml
    ---
    apiVersion: v1
    kind: Namespace
    metadata:
      name: kerberos-operator
    spec: {}
    status: {}
    ---
    apiVersion: v1
    kind: Namespace
    metadata:
      name: trino
    spec: {}
    status: {}
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: kerberos-operator
      namespace: kerberos-operator
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: kerberos-operator-kerberos-operator-manager
      namespace: kerberos-operator
    rules:
    - apiGroups:
      - events.k8s.io
      resources:
      - events
      verbs:
      - create
      - patch
    - apiGroups:
      - coordination.k8s.io
      resources:
      - leases
      verbs:
      - create
      - delete
      - get
      - list
      - patch
      - update
      - watch
    - apiGroups:
      - ""
      resources:
      - secrets
      verbs:
      - get
      - list
      - watch
    - apiGroups:
      - krb5.arenadata.io
      resources:
      - kdcconfigs
      verbs:
      - get
      - list
      - patch
      - update
      - watch
    - apiGroups:
      - krb5.arenadata.io
      resources:
      - kdcconfigs/status
      verbs:
      - get
      - patch
      - update
    - apiGroups:
      - krb5.arenadata.io
      resources:
      - kdcconfigs/finalizers
      verbs:
      - update
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: kerberos-operator-kerberos-operator-manager
      namespace: kerberos-operator
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: kerberos-operator-kerberos-operator-manager
    subjects:
    - kind: ServiceAccount
      name: kerberos-operator
      namespace: kerberos-operator
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: kerberos-operator-kerberos-operator-payload
      namespace: trino
    rules:
    - apiGroups:
      - events.k8s.io
      resources:
      - events
      verbs:
      - create
      - patch
    - apiGroups:
      - ""
      resources:
      - secrets
      verbs:
      - create
      - delete
      - get
      - list
      - patch
      - update
      - watch
    - apiGroups:
      - krb5.arenadata.io
      resources:
      - keytabs
      verbs:
      - get
      - list
      - patch
      - update
      - watch
    - apiGroups:
      - krb5.arenadata.io
      resources:
      - keytabs/status
      verbs:
      - get
      - patch
      - update
    - apiGroups:
      - krb5.arenadata.io
      resources:
      - keytabs/finalizers
      verbs:
      - update
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: kerberos-operator-kerberos-operator-payload
      namespace: trino
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: kerberos-operator-kerberos-operator-payload
    subjects:
    - kind: ServiceAccount
      name: kerberos-operator
      namespace: kerberos-operator
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app.kubernetes.io/component: operator
        app.kubernetes.io/managed-by: adc-cli
        arenadata.io/operator-type: kerberos
      name: kerberos-operator-kerberos-operator
      namespace: kerberos-operator
    spec:
      selector:
        matchLabels:
          app.kubernetes.io/component: operator
          app.kubernetes.io/managed-by: adc-cli
          app.kubernetes.io/name: kerberos-operator-kerberos-operator
      strategy: {}
      template:
        metadata:
          labels:
            app.kubernetes.io/component: operator
            app.kubernetes.io/managed-by: adc-cli
            app.kubernetes.io/name: kerberos-operator-kerberos-operator
        spec:
          containers:
          - args:
            - -ns=trino
            image: hub.arenadata.io/adc-enterprise/kerberos-operator:<tag>
            imagePullPolicy: Always
            livenessProbe:
              httpGet:
                path: /healthz
                port: 8081
              initialDelaySeconds: 5
              periodSeconds: 10
            name: app
            readinessProbe:
              httpGet:
                path: /readyz
                port: 8081
              initialDelaySeconds: 5
              periodSeconds: 10
            resources:
              limits:
                cpu: 500m
                memory: 256Mi
              requests:
                cpu: 500m
                memory: 256Mi
            securityContext:
              allowPrivilegeEscalation: false
              capabilities:
                drop:
                - ALL
              readOnlyRootFilesystem: true
              runAsGroup: 10001
              runAsNonRoot: true
              runAsUser: 10001
          securityContext:
            fsGroup: 10001
            runAsGroup: 10001
            runAsNonRoot: true
            runAsUser: 10001
          serviceAccountName: kerberos-operator
          terminationGracePeriodSeconds: 10
    status: {}
    ---
    apiVersion: krb5.arenadata.io/v1alpha1
    kind: KDCConfig
    metadata:
      name: kerberos-operator-kdc
      namespace: kerberos-operator
    spec:
      domainRealm:
        ad.ranger-test: AD.RANGER-TEST
      labelSelector:
        env: prod
      libdefaults:
        default_realm: AD.RANGER-TEST
      realm: AD.RANGER-TEST
      realms:
        AD.RANGER-TEST: |-
          kdc = ad01.adsw.io
          admin_server = ad01.adsw.io
    ---
    apiVersion: v1
    kind: Secret
    metadata:
      annotations:
        krb5.arenadata.io/provider: ad
      labels:
        env: prod
      name: ldap-credentials
      namespace: kerberos-operator
    stringData:
      addr: ldaps://ad01.adsw.io:636
      adminDN: stikhomirov@AD.RANGER-TEST
      adminPW: <password>
      baseDN: OU=stikhomirov_ou,OU=kerberos,OU=adh,DC=ad,DC=ranger-test
    type: krb5.arenadata.io/ldap-credentials
  5. If the manifest is correct, apply the configuration and deploy Kerberos operator:

    $ ./adc apply -f kerberos-operator.yaml

Step 2. Update the Trino cluster configuration

  1. Prepare an updated version of the hadoop_conf.yaml Hadoop configuration file:

    hadoop_conf.yaml
    • HDFS

    • S3

    include::ROOT:partial$k8s/hadoop-conf-kerberos-ssl.adoc

    sites:
      core:
        hadoop.security.authentication: kerberos
        fs.defaultFS: s3a://demo-s3
        fs.s3a.impl: org.apache.hadoop.fs.s3a.S3AFileSystem
        fs.s3a.access.key: p.petrov@RU-CENTRAL1.INTERNAL
        fs.s3a.secret.key: 3ab197f82fac43374519b4ad3015a76c778acf51897cf73f409ecba827e64255
      hive:
        hive.metastore.uris: thrift://hms-adh-nia-01.ru-central1.internal:9083
        metastore.use.SSL: true
        hive.metastore.sasl.enabled: true
        hive.metastore.kerberos.principal: hive/_HOST@AD.RANGER-TEST
        fs.s3a.endpoint: http://adh-ctrl-nia-02.ru-central1.internal:9879
        fs.s3a.path.style.access: true
        hive.metastore.warehouse.dir: s3a://demo-s3/apps/hive/warehouse
  2. Initialize the Trino cluster:

    $ ./adc init --trino-cluster --hadoop-file hadoop_conf.yaml -o trino-cluster.yaml

    This operation creates the trino-cluster.yaml file with a configuration template.

  3. Edit the configuration file to your needs:

    trino-cluster.yaml
    • HDFS

    • S3

    apiVersion: adc.arenadata.io/v1alpha1
    kind: TrinoCluster
    metadata:
      name: trino
      namespace: trino (1)
    spec:
      image: hub.arenadata.io/adc-enterprise/trino:<tag> (2)
    
      ## Image pull secret for a private registry.
      ## Set 'externalSecretName' to reference an existing Secret,
      ## or set 'credentials' and optionally 'secretName' to let the CLI create one.
      #imagePullSecret:
      #  # Use a Secret managed outside ADC.
      #  externalSecretName: existing-registry-secret
      #
      #  ## Or let ADC create the Secret.
      #  #secretName: custom-registry-secret
      #
      #  #credentials:
      #  #  registry: registry.example.com
      #  #  username: user
      #  #  password: pass
    
      hadoop: (3)
        core:
          dfs.client.failover.proxy.provider.adh: org.apache.hadoop.hdfs.server.namenode.ha.ObserverReadProxyProvider
          dfs.datanode.kerberos.principal: hdfs-datanode/_HOST@AD.RANGER-TEST
          dfs.ha.namenodes.adh: nn_tsn-adh-k8s-1,nn_tsn-adh-k8s-3
          dfs.journalnode.kerberos.principal: hdfs-journalnode/_HOST@AD.RANGER-TEST
          dfs.namenode.kerberos.principal: hdfs-namenode/_HOST@AD.RANGER-TEST
          dfs.namenode.rpc-address.adh.nn_tsn-adh-k8s-1: tsn-adh-k8s-1.ru-central1.internal:8020
          dfs.namenode.rpc-address.adh.nn_tsn-adh-k8s-3: tsn-adh-k8s-3.ru-central1.internal:8020
          dfs.nameservices: adh
          fs.defaultFS: hdfs://adh
          fs.s3a.aws.credentials.provider: org.apache.hadoop.fs.s3a.SimpleAWSCredentialsProvider
          hadoop.proxyuser.trino.groups: '*'
          hadoop.proxyuser.trino.hosts: '*'
          hadoop.security.authentication: kerberos
          hadoop.ssl.enabled: "true"
        hdfs:
          dfs.client.read.shortcircuit: "false"
        hive:
          hive.metastore.kerberos.principal: hive/_HOST@AD.RANGER-TEST
          hive.metastore.sasl.enabled: "true"
          hive.metastore.uris: thrift://tsn-adh-k8s-1.ru-central1.internal:9083
          metastore.use.SSL: "true"
        ozone:
          ozone.om.address.adh.om_tsn-adh-k8s-1: tsn-adh-k8s-1.ru-central1.internal:9862
          ozone.om.address.adh.om_tsn-adh-k8s-2: tsn-adh-k8s-2.ru-central1.internal:9862
          ozone.om.address.adh.om_tsn-adh-k8s-3: tsn-adh-k8s-3.ru-central1.internal:9862
          ozone.om.kerberos.principal: om/_HOST@AD.RANGER-TEST
          ozone.om.nodes.adh: om_tsn-adh-k8s-1,om_tsn-adh-k8s-2,om_tsn-adh-k8s-3
          ozone.om.service.ids: adhom
    
      ## Kerberos configuration for authentication.
      kerberos: (4)
        realm: AD.RANGER-TEST
      #
      #  # Service name in the Kerberos principal. Defaults to the product name.
        service: trino
      #
      #  # Hostname in the Kerberos principal.
      #  # Required for a fixed service principal; leave it empty only to derive one principal per pod from the cluster domain.
        hostname: trino-cloud.ru-central1.internal
        keytab: (5)
      #    # true - kerberos-operator creates the keytab Secret.
      #    # false (default) - reference an existing keytab Secret with name keytab.secretName.
          create: true
      #
      #    # Name of the keytab Secret.
      #    # Optional when create: true - names the generated Secret (default: <name>-keytab).
      #    # Required when create: false - must reference an existing Secret.
          secretName: kerberos-secret
      #
      #    # Label selector for the Pod that generates the keytab.
      #    # Required when create: true; ignored when create: false.
          labelSelector:
            env: prod
          additionalPrincipals:
            - HTTP/trino-cloud.ru-central1.internal
            - trino/trino-cloud.ru-central1.internal
      #
          rotation:
            interval: 24h
            checkInterval: 1h
    
      ## LDAP authentication configuration.
      ## Uncomment and fill url and userBindPattern.
      ## For ldaps:// URLs the ssl: or ca: section must also be configured (depends on product)
      #ldap:
      #  # LDAP service url.
      #  url: ldaps://ldap.example.com:636
      #
      #  # LDAP user Bind pattern.
      #  userBindPattern: uid=${USER},cn=users,dc=example,dc=com
    
      ## Ranger plugin configuration.
      ## Uncomment and fill the lines below. adc apply derives the rest.
      #ranger:
      #  # fill ranger.plugin.trino.policy.rest.url below with Ranger endpoint, e.g. https://adps-adc.ru-central1.internal:6182
      #  # fill ranger.plugin.trino.service.name below with Ranger service name you want to use for product, e.g. adc_trino_id_1
      #  security:
      #    ranger.plugin.trino.policy.rest.url: ""
      #    ranger.plugin.trino.service.name: ""
      #
      #  # fill xasecure.audit.destination.solr.zookeepers below with Zookeepers endpoints to resolve solr service, e.g. adps-adc.ru-central1.internal:2181/Arenadata.Hadoop-2.solr.server
      #  audit:
      #    xasecure.audit.destination.solr.zookeepers: ""
      #
      #  # Local Ranger files 'adc apply' writes into the configs Secret.
      #  # Relative paths are resolved against the config file.
      #  files:
      #    jceksStorePath: /path/to/ranger.jceks
    
      ## Java KeyStore/TrustStore certificate configuration.
      ## Set externalSecretName to reference an existing Secret,
      ## or set files and optional secretName to have ADC create it.
      ssl: (6)
      #  ## Name of the Secret containing Java keystores.
        secretName: ssl-secret
      #  externalSecretName: existing-ssl-secret
      #
      #  # Key in the Secret containing the truststore file.
        trustStoreKey: truststore.jks
      #
      #  ## Password for the truststore (optional).
        trustStorePassword: bigdata
      #
      #  ## Key in the Secret containing the keystore file (optional).
      #  #keyStoreKey: keystore.jks
      #
      #  ## Password for the keystore (optional).
      #  #keyStorePassword: bigdata
      #
      #  ## Alias of the key entry inside the keystore. Required by the Trino JMX exporter when scrape TLS is enabled.
      #  #keyStoreAlias: trino
      #
      #  ## Local files 'adc apply' puts into the Secret named by ssl.secretName.
      #  ## Relative paths are resolved against the config file.
        files:
          trustStorePath: /etc/ssl/truststore.jks
      #  #  #keyStorePath: /path/to/keystore.jks
    
      ## Use an external complete configs Secret instead of the one rendered by ADC.
      #configsSecret:
      #  # Use a Secret managed outside ADC.
      #  externalSecretName: existing-trino-configs
      #
      #  ## Or let ADC create the Secret.
      #  #secretName: custom-trino-configs
    
      coordinator:
        replicas: 1
        #resources:
        #  limits:
        #    cpu: 500m
        #    memory: 4Gi
        #  requests:
        #    cpu: 250m
        #    memory: 512Mi
    
        ## Component arguments. Key-value pairs passed to the component configuration.
        #args:
        #  http-server.http.port: "8080"
    
        ## Environment variables passed to the component container.
        #envs:
        #  - name: JAVA_TOOL_OPTIONS
        #    value: |-
        #      -Djavax.net.ssl.trustStore=/etc/ssl/truststore.jks
        #      -Djavax.net.ssl.trustStorePassword=bigdata
      worker:
        replicas: 1
        #resources:
        #  limits:
        #    cpu: 500m
        #    memory: 4Gi
        #  requests:
        #    cpu: 250m
        #    memory: 512Mi
    
        ## Component arguments. Key-value pairs passed to the component configuration.
        #args:
        #  http-server.http.port: "8080"
    
        ## Environment variables passed to the component container.
        #envs:
        #  - name: JAVA_TOOL_OPTIONS
        #    value: |-
        #      -Djavax.net.ssl.trustStore=/etc/ssl/truststore.jks
        #      -Djavax.net.ssl.trustStorePassword=bigdata
    
      ## Trino catalogs (one entry per .properties file).
      ## adc apply derives Kerberos/SSL fields for iceberg catalogs from the surrounding cluster config.
      catalogs: (7)
        iceberg.properties:
          connector.name: iceberg
          fs.hadoop.enabled: "true"
          hive.config.resources: /opt/trino-server/etc/catalog/core-site.xml
          hive.hdfs.authentication.type: KERBEROS
          hive.hdfs.impersonation.enabled: "true"
          hive.hdfs.trino.keytab: /opt/trino-server/kerberos/keytab
          hive.metastore.authentication.type: KERBEROS
          hive.metastore.client.keytab: /opt/trino-server/kerberos/keytab
          hive.metastore.service.principal: hive/_HOST@AD.RANGER-TEST
          hive.metastore.thrift.client.ssl.enabled: "true"
          hive.metastore.thrift.client.ssl.trust-certificate: /etc/ssl/truststore.jks
          hive.metastore.thrift.client.ssl.trust-certificate-password: bigdata
          hive.metastore.thrift.impersonation.enabled: "true"
          hive.metastore.uri: thrift://tsn-adh-k8s-1.ru-central1.internal:9083
    
      ## Monitoring configuration.
      #monitoring:
      #  # Enables Prometheus metrics export from this product's pods.
      #  exportMetrics: true
    
      ## HTTPS on the Trino coordinator web endpoint.
      ## Set externalSecretName to reference a keystore Secret,
      ## or set files and optional secretName to have ADC create it.
      #webTLS:
      #  #secretName: custom-trino-web-tls
      #  externalSecretName: existing-trino-web-tls
      #  keystoreKey: keystore.p12
      #  #keystorePassword: changeit
      #
      #  ## Local keystore 'adc apply' puts into the Secret named by webTLS.secretName.
      #  ## A relative path is resolved against the config file.
      #  #files:
      #  #  keystorePath: ./keystore.p12
    
      ## Controls whether Secret/ConfigMap changes restart pods.
      ## Set enabled: false to update referenced Secrets without restarting
      ## the workload; pods keep running the previous configuration until
      ## the policy is re-enabled. Defaults to enabled.
      #configurationRollout:
      #  enabled: false
    1 Namespace that the Trino cluster will use.
    2 Settings for pulling the Trino cluster image.
    3 Hadoop settings that were taken from the previously created hadoop_conf.yaml.
    4 Kerberos settings.
    5 If keytab.create is set to true, Kerberos operator will generate a secret with the name specified in keytab.secretName; if keytab.secretName is not specified, the name will be <metadata.name>-keytab. If keytab.create is set to false, an existing keytab.secretName secret will be referenced to obtain a keytab.
    6 SSL settings.
    7 Iceberg catalog settings.
    apiVersion: adc.arenadata.io/v1alpha1
    kind: TrinoCluster
    metadata:
      name: trino
      namespace: trino (1)
    spec:
      image: hub.arenadata.io/adc-enterprise/trino:<tag> (2)
    
      ## Image pull secret for a private registry.
      ## Set 'externalSecretName' to reference an existing Secret,
      ## or set 'credentials' and optionally 'secretName' to let the CLI create one.
      #imagePullSecret:
      #  # Use a Secret managed outside ADC.
      #  externalSecretName: existing-registry-secret
      #
      #  ## Or let ADC create the Secret.
      #  #secretName: custom-registry-secret
      #
      #  #credentials:
      #  #  registry: registry.example.com
      #  #  username: user
      #  #  password: pass
    
      hadoop: (3)
        core:
          fs.defaultFS: s3a://demo-s3
          fs.s3a.access.key: p.petrov@RU-CENTRAL1.INTERNAL
          fs.s3a.aws.credentials.provider: org.apache.hadoop.fs.s3a.SimpleAWSCredentialsProvider
          fs.s3a.impl: org.apache.hadoop.fs.s3a.S3AFileSystem
          fs.s3a.secret.key: 3ab197f82fac43374519b4ad3015a76c778acf51897cf73f409ecba827e64255
          hadoop.proxyuser.trino.groups: '*'
          hadoop.proxyuser.trino.hosts: '*'
          hadoop.security.authentication: kerberos
        hive:
          fs.s3a.endpoint: http://adh-ctrl-nia-02.ru-central1.internal:9879
          fs.s3a.path.style.access: "true"
          hive.metastore.kerberos.principal: hive/_HOST@AD.RANGER-TEST
          hive.metastore.sasl.enabled: "true"
          hive.metastore.uris: thrift://hms-adh-nia-01.ru-central1.internal:9083
          hive.metastore.warehouse.dir: s3a://demo-s3/apps/hive/warehouse
          metastore.use.SSL: "true"
    
      ## Kerberos configuration for authentication.
      kerberos: (4)
        realm: AD.RANGER-TEST
      #
      #  # Service name in the Kerberos principal. Defaults to the product name.
        service: trino
      #
      #  # Hostname in the Kerberos principal.
      #  # Required for a fixed service principal; leave it empty only to derive one principal per pod from the cluster domain.
        hostname: trino-cloud.ru-central1.internal
        keytab: (5)
      #    # true - kerberos-operator creates the keytab Secret.
      #    # false (default) - reference an existing keytab Secret with name keytab.secretName.
          create: true
      #
      #    # Name of the keytab Secret.
      #    # Optional when create: true - names the generated Secret (default: <name>-keytab).
      #    # Required when create: false - must reference an existing Secret.
          secretName: kerberos-secret
      #
      #    # Label selector for the Pod that generates the keytab.
      #    # Required when create: true; ignored when create: false.
          labelSelector:
            env: prod
          additionalPrincipals:
            - HTTP/trino-cloud.ru-central1.internal
            - trino/trino-cloud.ru-central1.internal
      #
          rotation:
            interval: 24h
            checkInterval: 1h
    
      ## LDAP authentication configuration.
      ## Uncomment and fill url and userBindPattern.
      ## For ldaps:// URLs the ssl: or ca: section must also be configured (depends on product)
      #ldap:
      #  # LDAP service url.
      #  url: ldaps://ldap.example.com:636
      #
      #  # LDAP user Bind pattern.
      #  userBindPattern: uid=${USER},cn=users,dc=example,dc=com
    
      ## Ranger plugin configuration.
      ## Uncomment and fill the lines below. adc apply derives the rest.
      #ranger:
      #  # fill ranger.plugin.trino.policy.rest.url below with Ranger endpoint, e.g. https://adps-adc.ru-central1.internal:6182
      #  # fill ranger.plugin.trino.service.name below with Ranger service name you want to use for product, e.g. adc_trino_id_1
      #  security:
      #    ranger.plugin.trino.policy.rest.url: ""
      #    ranger.plugin.trino.service.name: ""
      #
      #  # fill xasecure.audit.destination.solr.zookeepers below with Zookeepers endpoints to resolve solr service, e.g. adps-adc.ru-central1.internal:2181/Arenadata.Hadoop-2.solr.server
      #  audit:
      #    xasecure.audit.destination.solr.zookeepers: ""
      #
      #  # Local Ranger files 'adc apply' writes into the configs Secret.
      #  # Relative paths are resolved against the config file.
      #  files:
      #    jceksStorePath: /path/to/ranger.jceks
    
      ## Java KeyStore/TrustStore certificate configuration.
      ## Set externalSecretName to reference an existing Secret,
      ## or set files and optional secretName to have ADC create it.
      ssl: (6)
      #  ## Name of the Secret containing Java keystores.
        secretName: ssl-secret
      #  externalSecretName: existing-ssl-secret
      #
      #  # Key in the Secret containing the truststore file.
        trustStoreKey: truststore.jks
      #
      #  ## Password for the truststore (optional).
        trustStorePassword: bigdata
      #
      #  ## Key in the Secret containing the keystore file (optional).
      #  #keyStoreKey: keystore.jks
      #
      #  ## Password for the keystore (optional).
      #  #keyStorePassword: bigdata
      #
      #  ## Alias of the key entry inside the keystore. Required by the Trino JMX exporter when scrape TLS is enabled.
      #  #keyStoreAlias: trino
      #
      #  ## Local files 'adc apply' puts into the Secret named by ssl.secretName.
      #  ## Relative paths are resolved against the config file.
        files:
          trustStorePath: /etc/ssl/truststore.jks
      #  #  #keyStorePath: /path/to/keystore.jks
    
      ## Use an external complete configs Secret instead of the one rendered by ADC.
      #configsSecret:
      #  # Use a Secret managed outside ADC.
      #  externalSecretName: existing-trino-configs
      #
      #  ## Or let ADC create the Secret.
      #  #secretName: custom-trino-configs
    
      coordinator:
        replicas: 1
        #resources:
        #  limits:
        #    cpu: 500m
        #    memory: 4Gi
        #  requests:
        #    cpu: 250m
        #    memory: 512Mi
    
        ## Component arguments. Key-value pairs passed to the component configuration.
        #args:
        #  http-server.http.port: "8080"
    
        ## Environment variables passed to the component container.
        #envs:
        #  - name: JAVA_TOOL_OPTIONS
        #    value: |-
        #      -Djavax.net.ssl.trustStore=/etc/ssl/truststore.jks
        #      -Djavax.net.ssl.trustStorePassword=bigdata
      worker:
        replicas: 1
        #resources:
        #  limits:
        #    cpu: 500m
        #    memory: 4Gi
        #  requests:
        #    cpu: 250m
        #    memory: 512Mi
    
        ## Component arguments. Key-value pairs passed to the component configuration.
        #args:
        #  http-server.http.port: "8080"
    
        ## Environment variables passed to the component container.
        #envs:
        #  - name: JAVA_TOOL_OPTIONS
        #    value: |-
        #      -Djavax.net.ssl.trustStore=/etc/ssl/truststore.jks
        #      -Djavax.net.ssl.trustStorePassword=bigdata
    
      ## Trino catalogs (one entry per .properties file).
      ## adc apply derives Kerberos/SSL fields for iceberg catalogs from the surrounding cluster config.
      catalogs: (7)
        iceberg.properties:
          connector.name: iceberg
          fs.hadoop.enabled: "true"
          hive.config.resources: /opt/trino-server/etc/catalog/core-site.xml
          hive.hdfs.authentication.type: KERBEROS
          hive.hdfs.impersonation.enabled: "true"
          hive.hdfs.trino.keytab: /opt/trino-server/kerberos/keytab
          hive.metastore.authentication.type: KERBEROS
          hive.metastore.client.keytab: /opt/trino-server/kerberos/keytab
          hive.metastore.service.principal: hive/_HOST@AD.RANGER-TEST
          hive.metastore.thrift.client.ssl.enabled: "true"
          hive.metastore.thrift.client.ssl.trust-certificate: /etc/ssl/truststore.jks
          hive.metastore.thrift.client.ssl.trust-certificate-password: bigdata
          hive.metastore.thrift.impersonation.enabled: "true"
          hive.metastore.uri: thrift://hms-adh-nia-01.ru-central1.internal:9083
    
      ## Monitoring configuration.
      #monitoring:
      #  # Enables Prometheus metrics export from this product's pods.
      #  exportMetrics: true
    
      ## HTTPS on the Trino coordinator web endpoint.
      ## Set externalSecretName to reference a keystore Secret,
      ## or set files and optional secretName to have ADC create it.
      #webTLS:
      #  #secretName: custom-trino-web-tls
      #  externalSecretName: existing-trino-web-tls
      #  keystoreKey: keystore.p12
      #  #keystorePassword: changeit
      #
      #  ## Local keystore 'adc apply' puts into the Secret named by webTLS.secretName.
      #  ## A relative path is resolved against the config file.
      #  #files:
      #  #  keystorePath: ./keystore.p12
    
      ## Controls whether Secret/ConfigMap changes restart pods.
      ## Set enabled: false to update referenced Secrets without restarting
      ## the workload; pods keep running the previous configuration until
      ## the policy is re-enabled. Defaults to enabled.
      #configurationRollout:
      #  enabled: false
    1 Namespace that the Trino cluster will use.
    2 Settings for pulling the Trino cluster image.
    3 Hadoop settings that were taken from the previously created hadoop_conf.yaml.
    4 Kerberos settings.
    5 If keytab.create is set to true, Kerberos operator will generate a secret with the name specified in keytab.secretName; if keytab.secretName is not specified, the name will be <metadata.name>-keytab. If keytab.create is set to false, an existing keytab.secretName secret will be referenced to obtain a keytab.
    6 SSL settings.
    7 Iceberg catalog settings.
  4. If you use Trino with Ranger, update the Ranger configuration according to the instruction.

  5. You can check the configuration about to be applied by running the apply command with the --dry-run option:

    $ ./adc apply -f trino-cluster.yaml --dry-run > trino-cluster-render.yaml
    trino-cluster-render.yaml
    ---
    apiVersion: v1
    kind: Secret
    metadata:
      name: trino-configs
      namespace: trino
    stringData:
      core-site.xml: |-
        <configuration>
          <property>
            <name>dfs.client.failover.proxy.provider.adh</name>
            <value>org.apache.hadoop.hdfs.server.namenode.ha.ObserverReadProxyProvider</value>
          </property>
          <property>
            <name>dfs.client.read.shortcircuit</name>
            <value>false</value>
          </property>
          <property>
            <name>dfs.datanode.kerberos.principal</name>
            <value>hdfs-datanode/_HOST@AD.RANGER-TEST</value>
          </property>
          <property>
            <name>dfs.ha.namenodes.adh</name>
            <value>nn_tsn-adh-k8s-1,nn_tsn-adh-k8s-3</value>
          </property>
          <property>
            <name>dfs.journalnode.kerberos.principal</name>
            <value>hdfs-journalnode/_HOST@AD.RANGER-TEST</value>
          </property>
          <property>
            <name>dfs.namenode.kerberos.principal</name>
            <value>hdfs-namenode/_HOST@AD.RANGER-TEST</value>
          </property>
          <property>
            <name>dfs.namenode.rpc-address.adh.nn_tsn-adh-k8s-1</name>
            <value>tsn-adh-k8s-1.ru-central1.internal:8020</value>
          </property>
          <property>
            <name>dfs.namenode.rpc-address.adh.nn_tsn-adh-k8s-3</name>
            <value>tsn-adh-k8s-3.ru-central1.internal:8020</value>
          </property>
          <property>
            <name>dfs.nameservices</name>
            <value>adh</value>
          </property>
          <property>
            <name>fs.defaultFS</name>
            <value>hdfs://adh</value>
          </property>
          <property>
            <name>fs.s3a.aws.credentials.provider</name>
            <value>org.apache.hadoop.fs.s3a.SimpleAWSCredentialsProvider</value>
          </property>
          <property>
            <name>hadoop.proxyuser.trino.groups</name>
            <value>*</value>
          </property>
          <property>
            <name>hadoop.proxyuser.trino.hosts</name>
            <value>*</value>
          </property>
          <property>
            <name>hadoop.security.authentication</name>
            <value>kerberos</value>
          </property>
          <property>
            <name>hadoop.ssl.enabled</name>
            <value>true</value>
          </property>
          <property>
            <name>ozone.om.address.adh.om_tsn-adh-k8s-1</name>
            <value>tsn-adh-k8s-1.ru-central1.internal:9862</value>
          </property>
          <property>
            <name>ozone.om.address.adh.om_tsn-adh-k8s-2</name>
            <value>tsn-adh-k8s-2.ru-central1.internal:9862</value>
          </property>
          <property>
            <name>ozone.om.address.adh.om_tsn-adh-k8s-3</name>
            <value>tsn-adh-k8s-3.ru-central1.internal:9862</value>
          </property>
          <property>
            <name>ozone.om.kerberos.principal</name>
            <value>om/_HOST@AD.RANGER-TEST</value>
          </property>
          <property>
            <name>ozone.om.nodes.adh</name>
            <value>om_tsn-adh-k8s-1,om_tsn-adh-k8s-2,om_tsn-adh-k8s-3</value>
          </property>
          <property>
            <name>ozone.om.service.ids</name>
            <value>adhom</value>
          </property>
        </configuration>
      iceberg.properties: |
        connector.name=iceberg
        fs.hadoop.enabled=true
        hive.config.resources=/opt/trino-server/etc/catalog/core-site.xml
        hive.hdfs.authentication.type=KERBEROS
        hive.hdfs.impersonation.enabled=true
        hive.hdfs.trino.keytab=/opt/trino-server/kerberos/keytab
        hive.hdfs.trino.principal=trino/trino-cloud.ru-central1.internal@AD.RANGER-TEST
        hive.metastore.authentication.type=KERBEROS
        hive.metastore.client.keytab=/opt/trino-server/kerberos/keytab
        hive.metastore.client.principal=trino/trino-cloud.ru-central1.internal@AD.RANGER-TEST
        hive.metastore.service.principal=hive/_HOST@AD.RANGER-TEST
        hive.metastore.thrift.client.ssl.enabled=true
        hive.metastore.thrift.client.ssl.trust-certificate=/etc/ssl/truststore.jks
        hive.metastore.thrift.client.ssl.trust-certificate-password=bigdata
        hive.metastore.thrift.impersonation.enabled=true
        hive.metastore.uri=thrift://tsn-adh-k8s-1.ru-central1.internal:9083
    type: Opaque
    ---
    apiVersion: v1
    data:
      truststore.jks: <encoded-truststore>
    kind: Secret
    metadata:
      name: ssl-secret
      namespace: trino
    type: Opaque
    ---
    apiVersion: krb5.arenadata.io/v1alpha1
    kind: Keytab
    metadata:
      name: kerberos-secret
      namespace: trino
    spec:
      items:
      - labelSelector:
          env: prod
        principals:
        - trino/trino-cloud.ru-central1.internal
        - HTTP/trino-cloud.ru-central1.internal
        - HTTP/trino-cloud.ru-central1.internal
        - trino/trino-cloud.ru-central1.internal
        realm: AD.RANGER-TEST
      rotation:
        checkInterval: 1h
        interval: 24h
    ---
    apiVersion: trino.arenadata.io/v1alpha1
    kind: Cluster
    metadata:
      name: trino
      namespace: trino
    spec:
      configsSecretName: trino-configs
      coordinator:
        metadata: {}
        replicas: 1
        spec:
          image: hub.arenadata.io/adc-enterprise/trino:<tag>
          imagePullPolicy: Always
      kerberos:
        hostname: trino-cloud.ru-central1.internal
        kerberosSecretName: kerberos-secret
        realm: AD.RANGER-TEST
        service: trino
      ssl:
        secretName: ssl-secret
        trustStoreKey: truststore.jks
      worker:
        metadata: {}
        replicas: 1
        spec:
          image: hub.arenadata.io/adc-enterprise/trino:<tag>
          imagePullPolicy: Always
    status: {}
  6. If the manifest is correct, apply the configuration and deploy the Trino cluster:

    $ ./adc apply -f trino-cluster.yaml

    The expected output contains a confirmation of success:

    time="20260518133858UTC" level="info" msg="cluster trino applied to namespace trino"
  7. Delete old pods so that Trino operator creates new ones from an updated config:

    $ kubectl delete pods -n <trino-cluster-ns> -l app.kubernetes.io/instance=trino-cluster
  8. Verify the Trino cluster pods:

    $ kubectl get pods -n trino

    The expected output is:

    trino-cluster-coordinator-0   1/1     Running   0          4m49s
    trino-cluster-worker-0        1/1     Running   0          4m49s

Step 3. Check the JDBC connection

  1. Connect to the Trino cluster over JDBC, for example, using DBeaver. After enabling Kerberos and SSL, the JDBC connection string looks as follows:

    jdbc:trino://trino-cloud.ru-central1.internal:443?SSL=true&SSLTrustStorePath=<SSLTrustStorePath>/truststore.jks&SSLTrustStorePassword=<SSLTrustStorePassword>&KerberosPrincipal=<KerberosPrincipal>&KerberosRemoteServiceName=HTTP&KerberosKeytabPath=<KerberosKeytabPath>

    where:

    • <SSLTrustStorePath> — path to the truststore with certificates used by DBeaver.

    • <SSLTrustStorePassword> — password for accessing the truststore.

    • <KerberosPrincipal> — Kerberos principal used by DBeaver for the connection.

    • <KerberosKeytabPath> — path to a user keytab file.

  2. Once connected, verify the Trino cluster operability:

    SHOW CATALOGS;

    The expected output:

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

Delete instances

To delete Kerberos operator, run the command below:

$ ./adc delete -f kerberos-operator.yaml
Found a mistake? Seleсt text and press Ctrl+Enter to report it