Trino (TSF) Installation and Configuration (Korean)

Trino (TSF) Installation and Configuration (Korean)

For Correct Installation and Optimal Configuration

Trino 사용 이유를 명확하게 파악하기

  • Trino 는 사용하는 방법에 따라서 설치, 구성 방법이 다르기 때문에 사용하는 이유를 명확하게 파악하는 것을 먼저 수행되어야 합니다.

  • 다양한 Data Source (MySQL, PostgreSQL, HDFS, Amazon S3, Cassandra, Kafka 등)로부터 데이터를 가져와 하나의 Query 로 통합하여 분석할 필요가 있는 지 파악

    • Business Intelligence Platform 에서 Data Lake (HDFS) 와 Relatational Database (i.e. MySQL) 데이터를 통합하여 분석
  • 여러 Cloud 환경 또는 On-Premise 와 Cloud 간의 데이터 통합 분석이 필요한지 파악

  • Impala 와 같이 Data Locality 가 중요한 Query 를 수행할 필요없는 지 파악 (for Trino)

    • Trino 는 In Memory 기반으로 작동하기 때문에, 일부 Query 는 Impala 보다 상대적으로 느릴 수 있습니다.

    • 실시간 Dashboard 에서 초 단위로 데이터 분석 결과 제공이 필요한지 파악

    • Data Scientist 들이 빠른 데이터 탐색 및 Prototyping 을 수행할 필요가 있는 지 파악

  • 복잡한 Batch 작업이 필요 없는 경우, 특히 ad-hoc 분석이나 데이터 검증이 필요한 지 파악

    • 복잡한 Batch 작업은 Spark 가 더 유리합니다.

    • Data Pipeline 에서 간단한 데이터 처리 및 집계 작업이 필요한 지 파악

  • 복잡한 Resource 관리 및 Query 우선 순위 설정이 필요한지 파악

    • Impala 도 어느정도 Resource 관리가 지원이 되지만, Trino 만큼 정교하게 관리하기에는 무리가 있습니다.

    • Trino 는 Resource Group 을 통해 Query 우선순위를 설정하고, 다양한 사용자 및 부서에 따라 Resource 를 배분할 수 있습니다.

  • Multi-Tenant 환경에서의 유연성이 필요한지 파악

    • 다중 사용자가 혼재 하는 대기업에서 다양한 팀과 부서가 동시에 데이터 분석을 수행을 해야 하는 경우

    • Resource 제약이 있는 환경에서 여러 사용자의 요청을 동시에 처리

Impala 또는 Spark 와 Trino 선택 기준

  • Impala

    • 대규모 Hive Table 이나 HDFS 기반 대용량 Data 를 대화형으로 빠르게 처리하는 데 적합.

    • Data Locality 를 활용하기 때문에 Computation 을 DataNode 로 이동하여 하는 것에 상당히 효율적임

      • 특히 Hadoop 환경에 깊게 통합됨
  • Spark

    • 대규모 Batch Data 처리, ETL 작업, 복잡한 데이터 변환에 적합

    • MLlib 같은 Library 를 사용한 Machine Learning workload 처리에 적합

  • Trino

    • 다양한 Data Source 간의 통합 Query 가 필요할때 적합

    • Low Latency 대화형 분석, 가벼운 ad-hoc 쿼리에 적합

    • Resource 관리가 필요한 다중 사용자 환경에 적합

Trino Installation by Apache Ambari

  • Trino 를 설치하기로 마음을 정하셨다면, 아래와 같이 진행하는 것을 추천 드립니다.

  • Trino 는 여러가지 방법으로 설치가 가능하지만, Multi Tenant 환경에서 운영하려면, Ambari 를 사용하여 설치, Ranger 와 결합하여 사용할때, 빛을 발휘합니다.

  • 기타 다른 설치 방법은 Trino Documentation 을 참고하시기 바랍니다.

    • Deploying Trino

    • Trino in a Docker container

    • Trino on Kubernetes with Helm

    • RPM package

  • Trino 설치는 Kerberized Hadoop (Secured Hadoop) 을 기준으로 설명합니다.

  • Trino Cluster 는 기본적으로 JVM 에서 실행됩니다.

    • 적당한 JDK or JRE 가 설정되어야 합니다. Java 11 version 이상 추천

Trino Installation Step by Step

  1. Ambari 에서 Trino Package 를 설치하여 Trino Cluster 를 구성합니다.

    • Trino Cluster 는 Coordinator, Worker 로 구성되어 있습니다.
  2. Trino 설치가 끝났다면, Ranger Trino Plugin 을 Trino 가 설치된 곳에 설치합니다.

  3. Trino 보안을 위해서는 Trino Documentation 에서 제안하는 Security workflow 를 따르는 것을 추천합니다.

    1. TLS/HTTPS 를 활성화 하기 위해서 인증서와 Load Balancer 를 구성합니다. (필수)

    2. Shared Secret 을 설정합니다. (필수)

    3. LDAP 과 같은 Authentication Provider 를 설정합니다. (필수)

      • Kerberos 설정은 복잡하고 어렵기 때문에 왠만하면 사용하지 않도록 합니다.
    4. 필요하다면, URL 에 접근하는 사용자에 대해서 Authorization 을 구현해도 됩니다. (Optional)

  4. Trino 를 위한 Kerberos Principal 을 생성하고, 생성한 keytab file 들을 Coordinator, Worker 에 배포합니다.

  5. Trino 인증을 위해서 관련된 설정파일을 배포합니다.

    1. Coordinator Server 에서 password-authenticator.properties file 을 생성하고 설정합니다.

    2. password-authenticator.properties file 의 내용은 아래와 같이 구성합니다. (LDAP 으로 인증을 하는 경우 입니다)

      •   # $TRINO_HOME/etc/password-authenticator.properties
          password-authenticator.name=ldap
          ldap.url=ldap://<ldap-host>:389
          ldap.allow-insecure=true
          ldap.user-bind-pattern=uid=${USER},ou=users,dc=company,dc=com
        
  6. Trino Connector 를 설정합니다. (Hive Connector 를 기준으로 설명합니다.)

    • $TRINO_HOME/etc/catalog/hive.properties 형식으로 file 을 생성하고 설정합니다.

      • Trino Hive Connector 문서를 참고 합니다.

      •   connector.name=hive
          hive.metastore.uri=thrift://<HMS-server>:9083
          hive.config.resources=$HADOOP_HOME/conf/core-site.xml,$HADOOP_HOME/conf/hdfs-site.xml
          hive.metastore.authentication.type=KERBEROS
          hive.metastore.service.principal=hive/_HOST@<REALM>
          hive.metastore.client.principal=trino@<REALM>
          hive.metastore.client.keytab=<principal keytab path>
          hive.hdfs.authentication.type=KERBEROS
          hive.hdfs.impersonation.enabled=true
          hive.hdfs.trino.principal=trino@<REALM>
          hive.hdfs.trino.keytab=<principal keytab path>
        
  7. Apache Ranger 와 잘 연동이 되어 작동하는 지 확인 합니다.

    • Ranger Trino Plugin 이 정상적으로 작동하는 지 확인

    • Ranger 에서 Policy 들을 생성하고 해당 Policy 별로 LDAP 으로 인증된 사용자들이 적합한 권한을 행사할 수 있는 지 확인

  8. Trino 에서 Audit Log 가 잘 남는 지 확인

Trino Configuration

  • Trino 설정에서 중요한 것들은 Resource, Coordinator, Worker 설정입니다.

Trino Resource Configuration

  • Trino 에서 Resource 를 관리하기 위해서는 Resource Group 이 있습니다.

  • Resource Group 을 적용하기 위해서는 Resource Group Manager 를 설정해야 합니다.

  • Resource Group Manager 는 file 기반 혹은 Database 를 사용할 수 있습니다.

  • File 기반으로 설정하려면, $TRINO_HOME/etc/resource-groups.properties 파일을 생성, 설정합니다.

  • 여기서는 file 기반으로 설정하는 것을 예를 들어 설명 하겠습니다.

    •   # resource-groups.properties
        resource-groups.configuration-manager=file
        resource-groups.config-file=$TRINO_HOME/etc/resource-groups.json
      
  • resource-groups.config-file 은 JSON 형식으로 작성하면 됩니다.

  • Resource Group config file 은 Resource group properties 라는 개념을 사용하여 설정하도록 합니다.

    • 자세한 설명은 Trino Documentation 을 참고하도록 합니다.

    • 꼭 필요한 field 설명

      • name

        • name of the group
      • maxQueued

        • maximum number of queued queries.

        • Once this limit is reached new queries are rejected.

      • hardConcurrencyLimit

        • maximum number of running queries.
      • softMemoryLimit

        • maximum amount of distributed memory this group may use, before new queries become queued.

        • May be specified as an absolute value (i.e. 1GB) or as a percentage (i.e. 10%) of the cluster’s memory.

    • Sample 설정 파일

      •   {
            "rootGroups": [
              {
                "name" : "ADD_HOC",
                "maxQueued": 50,
                "hardConcurrencyLimit": 20,
                "softMemoryLimit": "15%"
              },
              {
                "name" : "BI",
                "maxQueued": 80,
                "hardConcurrencyLimit": 40,
                "softMemoryLimit": "20%"
              }
            ]
          }
        
  • Resource group 에는 아래와 같은 특징이 있습니다.

    • Resource 사용량 제한과 Queue 정책에 대해서 강제할 수 있습니다.

    • 사용량을 Sub-Group 으로 분리도 가능합니다.

    • Query 는 하나의 Resource Group 에 속하며, 해당 Group으로부터 Resource 를 소비합니다.

    • 사용 가능한 Resource 가 부족하면 Queued 되어 대기중인 Query 들을 제외하고 실행중인 Query 의 실패를 유발하지는 않습니다.

      • 대신에 새로운 Query 들이 전부 Queued 상태가 됩니다.
    • Sub-Group 을 갖거나, 혹은 Query 를 받거나 할 수 있는데 동시에 두개는 못합니다.

      • Sub-Group 을 가지면서 Query 를 처리하는 방식은 불가능합니다.
  • Resource group name 에는 제약 사항이 있습니다.

    • Resource group 이 Tree 구조로 되어 있을 때, sub group 의 이름이 다른(sibling) sub group 의 이름과 중복되는 것은 허용되지 않습니다.

      • i.e. a.b, a.b → 허용되지 않음
    • Tree 구조에서 각 Node 는 고유한 경로를 가져야 하며, 동일한 부모 아래에 있는 sub group 들은 서로 다른 이름을 가져야 합니다.

      • i.e.a.b, a.c → 유효함
    • Resource group 의 sub group 이름이 서로 다른 부모 Node 아래에 동일 하더라도, 고유한 전체 경로로 식별 되므로 충돌이 발생하지 않습니다.

      • i.e. a.b.d, a.c.d → 유효함
  • Resource group 을 설정했다면, selector 를 설정해야 합니다.

    • 자세한 설명은 Trino Selector rules 문서 를 참고합니다.

    • Selector rule 은 Java Programming 언어의 Regular Expression 문법을 적용하여 사용합니다.

    • Selector rule 에서 필수는 group 입니다.

      • group: the group these queries will run in
    • 기본적으로 모든 rule 들은 AND 로 합쳐 집니다.

    • clientTags 는 주로 JDBC 연결 설정에서 사용하여 rule 을 적용할 때 사용합니다.

    • clientTags 는 제약사항이 있습니다.

      • 허용되지 않는 문자

        • 공백 (Whitespace), 쉼표 (Comma, ,), 슬래시 (Slash, /), 콜론 (Colon, :)

Trino Impersonation Configuration (Optional)

  • Trino 에서 HDFS 접근시 Impersonation 을 적용하기 위하여 proxy user 설정이 필요합니다.

  • HDFS 에서 Impersonation 을 설정하는 것을 예를 들어 설명 합니다.

    • Ambari → HDFS → CONFIGS → ADVANCED → core-site.xml 설정

      • hadoop.proxyuser.trino.groups: *

      • hadoop.proxyuser.trino.hosts: *

    • core-site.xml 을 수정하였기 때문에 적용을 위해서는 NameNode 를 Restart 해야 합니다.

Trino Client Configuration

  • Resource Group 을 재대로 적용하기 위해서는 Client 쪽에서도 설정을 해야 합니다.

  • Client Connector 에서 clientTags 설정을 해주는 방법이 편한 방법 중에 하나 입니다.

Trino Connection for JDBC Driver

  • The Trino JDBC driver has the following requirements

    • Java version 8 or higher

    • All users that connect to Trino with the JDBC driver must be granted access to query tables in the system.jdbc schema.

  • 위의 Trino JDBC 요구사항을 만족시키는 어떠한 JDBC Driver 도 사용가능 합니다.

Trino 에서 제공하는 trino-cli 를 사용

  • trino-cli executable jar 를 download 합니다.

  • 아래와 같이 trino 서버에 접속이 가능 합니다.

  • 접속하기 위해서 별도의 인증(i.e. Kerberos) 가 필요할 수 있습니다.

    •   ./trino --server http://trino.example.com:8080
      

Trino Python Client 를 사용

  • Client for Trino, a distributed SQL engine for interactive and batch big data processing.

  • Provides a low-level client and a DBAPI 2.0 implementation and a SQLAlchemy adapter. It supports Python>=3.8 and PyPy.

  • Trino.sqlalchemy is compatible with the latest 1.3.x, 1.4.x and 2.0.x SQLAlchemy versions at the time of release of a particular version of the client.

  • To connect to Trino using SQLAlchemy, use a connection string (URL) following this pattern

    •   trino://<username>:<password>@<host>:<port>/<catalog>/<schema>
      
  • In order to pass additional connection attributes use connect_args method.

  • Attributes can also be passed in the connection string.

  • Python Client 를 사용하여 접속 하는 예제 코드

    •   from sqlalchemy import create_engine
        from trino.sqlalchemy import URL
      
        engine = create_engine(
            URL(
                host="localhost",
                port=8080,
                catalog="system"
            ),
            connect_args={
              "session_properties": {'query_max_run_time': '1d'},
              "client_tags": ["tag1", "tag2"],
              "roles": {"catalog1": "role1"},
            }
        )
      
        # or in connection string
        engine = create_engine(
            'trino://user@localhost:8080/system?'
            'session_properties={"query_max_run_time": "1d"}'
            '&client_tags=["tag1", "tag2"]'
            '&roles={"catalog1": "role1"}'
        )
      
        # or using the URL factory method
        engine = create_engine(URL(
          host="localhost",
          port=8080,
          client_tags=["tag1", "tag2"]
        ))
      
    • 참고: https://github.com/trinodb/trino-python-client

Trino Coordinator Configuration

  • Trino 의 Coordinator Server 는 Cluster 의 중추 역할을 하므로, 하드웨어 사양에 대해 신중하게 고려해야 합니다.

  • Trino Coordinator 는 Query Scheduling, Resource Management, 사용자 요청 처리 등 다양한 중요한 역할을 수행 하므로, 그에 맞는 적절한 Hardware 사양이 요구됩니다.

  • Trino Coordinator 로 사용할 Server 의 Hardware Spec 은 아래와 같은 것을 추천합니다.

    • CPU

      • CPU Cores: 최소 8~16 Core 이상을 권장합니다.

        • Coordinator 는 Query Planning, 분석, Resource Scheduling 을 처리 하므로 Multi Core 환경에서 성능이 크게 향상됩니다.
      • CPU Clock Speed: High Clock 의 최신 Intel Xeon 또는 AMD EPYC 시리즈가 적합합니다.

      • Hyper Threading: Trino 는 Thread 를 많이 생성하는 경향이 있으므로, Hyper Threading 이 성능에 도움이 됩니다.

    • Memory

      • RAM Size: 최소 256 GB 이상이 권장됩니다.

        • Coordinator 는 큰 Memory Pool 을 사용하여 Query Planning 과 실행을 관리 하므로, 대규모 Query 를 처리할 때 더 많은 메모리가 필요합니다.
      • Memory Speed: DDR4 2933 MHz 이상의 고속 Memory 를 사용하는 것이 유리합니다. 빠를 수록 좋습니다.

      • Swap 사용 금지

        • OS 에서 Swap Memory 를 사용하지 않도록 설정하는 것이 좋습니다.

        • Swap 이 발생하면 성능 저하가 심각할 수 있습니다.

    • DISK

      • DISK 종류: NVMe 또는 SSD(Solid State Drive)가 최선의 선택입니다.

        • Coordinator 는 Log 기록과 Metadata 를 자주 Access 하기 때문에 DISK I/O 성능이 매우 중요합니다.
      • RAID 구성: RAID 1+0 구성을 권장합니다. 성능과 가용성을 모두 확보할 수 있습니다.

        • RAID 1+0 구성으로 내구성과 읽기/쓰기 성능 모두에 최적화 되기 때문에 이것을 추천합니다.
      • DISK Size 는 최소 1 TB 이상을 권장합니다.

    • Disk Partition Configuration

      • OS 와 데이터가 충돌하지 않도록 별도의 partition 을 사용하는 것이 좋습니다.

      • root partition (for OS): 100 GB 이상으로 설정하여, OS 및 기타 서비스가 안정적으로 실행되도록 합니다.

      • /var/log partition: Trino 는 log 를 많이 남기므로, /var/log에 충분한 디스크 공간을 할당합니다. 200GB 이상을 권장합니다.

      • /data partition: Trino 의 Metadata 와 Cache data 를 저장할 수 있도록 별도의 partition 을 구성합니다.

    • Network

      • Coordinator 는 여러 Worker Node 와 Data 를 주고받기 때문에 Network 성능이 중요합니다.

      • 10 GbE 네트워크 또는 그 이상의 대역폭을 갖춘 NIC(Network Interface Card)를 권장합니다.

    • 일반적인 Trino Coordinator Server 의 Spec Example (이 글에서는 이정도 Server Spec 을 기준으로 설명합니다.)

      • CPU: Intel Xeon Gold 6248 2.5 GHz, 24 Core/48 Thread

      • Memory: 512 GB DDR4 3200 MHz

      • DISK: 2 TB NVMe SSD, RAID 1+0 구성

      • Network: 10 GbE Network Interface

      • OS: CenOS 7.9, Ubuntu 20.04 LTS, RedHat Enterprise Linux 9

  • OS 는 Linux 기반이 적절합니다.

    • CentOS 7, Ubuntu 18.04 이상 또는 RedHat Enterprise Linux (RHEL)를 사용하는 것이 일반적 입니다.

    • 안정성과 성능 최적화 측면에서 Linux 기반 환경이 가장 적합합니다.

    • Kernel 설정

      • Network 성능을 최적화하기 위해 TCP Buffer Size 를 조절

      • I/O 성능을 위해서 vm.swappiness=0 와 같이 조정

  • JVM 설정

    • Java 버전은 OpenJDK 11 또는 17 을 사용하는 것이 적합하며, JVM Option 을 최적화하여 Memory 관리와 GC (Garbage Collection) 를 효율적으로 설정해야 합니다.
  • Resource Isolation

    • Trino Coordinator 가 과도한 Resource 를 소비하지 않도록 CPU 와 Memory 를 제한하는 cgroup 을 활용할 수 있습니다.

    • cgroup 을 통해 Coordinator 와 기타 System Process 간의 Resource 충돌을 방지할 수 있습니다.

  • High Availability (HA) 를 구성

    • Trino Coordinator 는 SPOF (Single Point of Failure) 입니다. 그래서 장애 대응이 필요합니다.

    • HAProxy 같은 Load Balancer 를 사용하여 다중 Coordinator Server 를 설정

  • Trino Coordinator JVM Configuration in Detail (for Optimal Performance)

    • 일반적으로 Coordinator 는 Worker 보다 Memory 사용량이 적습니다.

    • 불필요하게 큰 Heap Size 는 GC Pause Time 을 증가시킬 수 있습니다.

    • -Xmx

      • Cluster 의 Worker 규모를 30대 정도로 가정하면, 60GB 정도를 Optimal 값으로 합니다.

      • Heap Memory Size 를 60GB 를 사용하기 때문에 G1 GC 가 적절합니다.

      • -Xmx60g 로 설정합니다.

    • -XX:InitiatingHeapOccupancyPercent

      • Default 값은 45% 이지만, 30% ~ 40% 으로 조정하여 Coordinator 의 역할에 맞게 최적화 합니다.

      • Heap 사용량이 낮은 경우 GC 를 일찍 시작하여 Memory Leak 을 감지하고 Memory 관리를 효율화 할 수 있습니다.

      • -XX:InitiatingHeapOccupancyPercent=35 으로 조정합니다.

    • -XX:MaxGCPauseMillis

      • Coordinator 의 응답성을 높이기 위해 목표 GC Pause Time 을 설정 합니다.

      • 200ms 가 Default 값 이지만, 100ms ~ 200ms 으로 설정하여 조금더 빠른 응답 속도를 보이도록 조정 합니다.

      • Coordinator 는 Query Planning, Scheduling 등 Latency 에 민감한 작업을 수행하므로 짧은 Pause Time 이 바람직 합니다.

      • -XX:MaxGCPauseMillis=150 으로 현실적으로 조정 합니다.

    • -XX:G1HeapRegionSize

      • 기본적으로 G1 GC는 Heap Size 에 따라 자동으로 Heap Region Size 를 결정 합니다.

      • Heap Size 의 1/6400 의 비율이 적절 (60 GB / 6400 = 9.6 MB) 하다고 판단합니다.

      • -XX:G1HeapRegionSize=10M 으로 조정합니다.

    • -XX:+AlwaysPreTouch 추가

      • JVM 시작 시 Heap Memory 를 미리 할당하여 Runtime 성능을 향상 시킵니다.

      • -XX:+AlwaysPreTouch 을 활성화 합니다.

    • -XX:ParallelGCThreads-XX:ConcGCThreads

      • System 의 CPU Core 수에 맞게 GC Thread 수를 조정 합니다.

      • -XX:ParallelGCThreads=48 를 CPU Thread 수에 맞춥니다.

      • -XX:ConcGCThreads=12 로 CPU Thread 의 ¼ 수준으로 맞춥니다.

    • -XX:+UseStringDeduplication

      • G1 GC에서 동일한 문자열의 중복을 제거하여 Memory 사용량을 줄입니다.

      • 동일한 Query 가 비슷하게 입력으로 들어올 확률이 높기 때문입니다.

      • -XX:+UseStringDeduplication 을 활성화 합니다.

    • -Xlog

      • GC log 를 남겨서 GC 가 적절히 수행되고 있는 지 Monitoring 합니다.

      • -Xlog:gc*,safepoint:file=/var/log/trino/trino-gc.log:time,uptime,level,tags:filecount=10,filesize=10M

    • Trino Coordinator 최종 JVM Option

        -Xmx60G
        -XX:+UseG1GC
        -XX:+ExplicitGCInvokesConcurrent
        -XX:+HeapDumpOnOutOfMemoryError
        -XX:+ExitOnOutOfMemoryError
        -XX:ReservedCodeCacheSize=512M
        -Dpresto-temporarily-allow-java8=true
        -Djdk.attach.allowAttachSelf=true
        -XX:InitiatingHeapOccupancyPercent=35
        -XX:MaxGCPauseMillis=150
        -XX:G1HeapRegionSize=10M
        -XX:ParallelGCThreads=48
        -XX:ConcGCThreads=12
        -XX:+AlwaysPreTouch
        -XX:+UseStringDeduplication
        -Xlog:gc*,safepoint:file=/var/log/trino/trino-gc.log:time,uptime,level,tags:filecount=10,filesize=20M
      

Trino Worker Configuration

  • Trino Worker Server는 대용량 데이터를 처리하고 쿼리를 실행하는 핵심적인 역할을 담당합니다.

  • Worker Node 의 성능은 Traffic 양, Query 복잡성, 처리 Data 의 크기 등에 크게 영향을 받기 때문에 Hardware 사양을 신중하게 설정하는 것이 매우 중요합니다.

  • 보통 Coordinator 와 비슷한 Spec 의 Server 를 사용하지만, Coordinator 보다 CPU Clock, Core 개수가 더 많고 Memory 도 더 클 수록 좋습니다.

  • Trino Worker 로 사용할 Server 의 Hardware Spec 은 아래와 같은 것을 추천합니다.

    • CPU

      • CPU Cores: 최소 16 Core 이상, 가능하다면 24~32 Core 를 권장합니다.

        • Worker 는 병렬 처리가 매우 중요 하므로 Multi Core CPU 가 필수입니다.
      • CPU Clock Speed: 고성능 Query 를 위해서는 High Clock 의 최신 CPU가 유리합니다.

        • Intel Xeon Scalable 시리즈 또는 AMD EPYC 프로세서가 적합합니다.
      • Hyper Threading: Worker 는 Thread 를 많이 사용하기 때문에 Hyper Threading 이 성능 향상에 도움이 됩니다.

    • Memory

      • RAM 용량: Worker Node 는 Data 처리를 위한 Memory Pool 을 주로 사용 하므로, 최소 256GB 이상의 RAM 이 필요합니다. 대규모 Data 처리 작업의 경우 512GB 이상의 메모리가 필요할 수 있습니다.

      • 메모리 속도: DDR4 2933 MHz 이상의 Memory Speed 가 권장됩니다. Worker Node 의 Memory 대역폭은 Query 성능에 직접적인 영향을 미칩니다.

    • DISK

      • DISK 종류: NVMe SSD 또는 고성능 SATA SSD가 적합합니다.

        • Worker 는 DISK I/O에 큰 의존성을 가지므로, 빠른 Data Access 와 처리 성능을 위해 고속 SSD 를 사용하는 것이 좋습니다.
      • RAID 구성: RAID 1+0 을 권장합니다.

      • DISK Size: 각 Worker Node 는 최소 1TB 이상의 Disk 용량이 필요합니다. 특히 대규모 Data Set 을 처리할 때 충분한 여유 공간이 필요합니다.

    • DISK partition

      • Worker Node 의 DISK 는 I/O 성능을 최적화하기 위해 분리된 partition 을 사용하는 것이 좋습니다.

      • root partition (for OS): OS 와 기타 기본 서비스가 안정적으로 실행될 수 있도록 100GB 이상의 공간을 할당합니다.

      • /data partition: Worker 가 처리할 데이터와 중간 결과를 저장할 충분한 DISK 공간을 할당합니다.

      • /var/log partition: log file 이 많이 쌓일 수 있으므로, 100 ~ 200GB 의 공간을 별도로 할당하는 것이 좋습니다.

    • Network

      • Worker Node 는 Network Traffic 을 많이 주고 받으므로 최소 10GbE Network 또는 그 이상을 권장합니다.

      • Low Latency: Network Latency 를 최소화하기 위해 빠른 Switching 환경을 갖춘 Low Latency Network 설정이 필요합니다.

    • 일반적인 Trino Worker Server 의 사양 예시 (이 글에서는 이 정도의 Spec 을 갖춘 Worker Server 를 기준으로 설명합니다.)

      • CPU: Intel Xeon Gold 6248R 2.4GHz, 24 Core/48 Thread

      • Memory: 512GB DDR4 3200MHz

      • DISK: 2TB NVMe SSD, RAID 1+0 구성

      • Network: 10GbE Network Interface

      • OS: CenOS 7.9, Ubuntu 20.04 LTS, RedHat Enterprise Linux 9

  • OS, JVM, Resource Isolation 는 Coordinator 와 동일한 수준으로 설정하면 좋습니다.

  • Storage & Caching

    • Local Disk Storage: Worker 는 Local DISK 에서 임시 Data 를 처리 하므로, 빠른 I/O 성능이 중요 합니다.

    • 특히, SSD 나 NVMe DISK 에서 중간 데이터 저장 및 처리 성능이 크게 향상됩니다.

    • Distributed Storage Integration: HDFS, S3 와 같은 Distributed File System 을 사용할 경우, Local Cache DISK 를 적절히 활용하여 성능을 향상시킬 수 있습니다.

  • Trino Worker JVM Configuration in Detail (for Optimal Performance, G1 GC Version)

    • Trino Worker 는 대용량 데이터를 처리하며, Memory 사용 패턴이 급격하게 변할 수 있습니다.

    • Trino 는 일반적으로 대규모 Query 를 처리 하므로, 전체적인 처리량이 중요 합니다.

    • 그러나 Worker Node 의 응답성이 지나치게 느려지면 Cluster 전체의 성능에 영향을 줄 수 있습니다.

    • Worker 도 Coordinator 와 동일하게 G1 GC 를 사용할 수 있지만, ZGC 를 사용하여 성능을 더 끌어 올릴 수 있습니다.

    • -Xmx

      • 물리 메모리 용량의 약 70~80%를 사용하고, 나머지 메모리는 운영체제와 다른 프로세스에 할당되도록 남겨두는 것이 안정적 입니다.

      • Worker Memory 의 최대 가용량 = 512GB × 0.8 = 409.6GB

      • -Xmx410g 으로 설정합니다.

    • -XX:MaxGCPauseMillis

      • 최대 GC 중단 시간을 설정하여 Application 의 응답성을 향상 시킵니다.

      • 대용량 Heap 에서는 200ms 이하의 Pause Time 을 유지하기 어렵습니다.

      • 현실적인 목표인 500ms 로 Pause Time 을 설정하여 G1 GC 가 응답성과 처리량 사이의 균형을 추구 하도록 합니다.

      • -XX:MaxGCPauseMillis=500 으로 설정합니다.

    • -XX:InitiatingHeapOccupancyPercent

      • Concurrent GC 가 시작되는 Heap 사용률을 조정하여 GC 빈도를 최적화 합니다.

      • 대용량 Heap (410 GB) 에서 Heap 사용량이 급격히 증가할 수 있으므로, GC 사이클을 일찍 시작하여 메모리 부족 상황을 예방 합니다.

      • Heap 사용량이 30% 정도인 약 123GB 에 도달하면 GC 를 시작하여 Memory 관리의 안정성을 높입니다.

      • -XX:InitiatingHeapOccupancyPercent=30

    • -XX:G1HeapRegionSize

      • 대용량 Heap 에서는 최대 크기인 32MB 로 설정될 수 있는데, 이를 16 MB 로 명시적으로 줄여 더 많은 Region 으로 나누어 세밀한 GC 를 수행하도록 설정합니다.

      • -XX:G1HeapRegionSize=16M

    • -XX:ParallelGCThreads-XX:ConcGCThreads

      • GC 작업에 적절한 Thread 수를 할당하여 GC 효율을 높입니다.

      • -XX:ParallelGCThreads: 전체 CPU 코어 수와 동일하게 설정 합니다. (48)

      • -XX:ConcGCThreads: ParallelGCThreads의 1/4 로 설정합니다.

      • -XX:ParallelGCThreads=48 으로 설정

      • -XX:ConcGCThreads=12 으로 설정

    • -XX:+AlwaysPreTouch

      • JVM 시작 시 Heap Memory 를 미리 할당하여 Page Fault 로 인한 지연을 방지합니다.

      • 큰 Heap Memory 를 사용하는 경우 JVM 시작 시간을 늘리지만 Runtime 성능에 이점이 있을 수 있습니다.

    • Trino Worker 최종 JVM Option (G1 GC Version)

        -Xmx410G
        -XX:+UseG1GC
        -XX:+ExplicitGCInvokesConcurrent
        -XX:+HeapDumpOnOutOfMemoryError
        -XX:+ExitOnOutOfMemoryError
        -XX:ReservedCodeCacheSize=512M
        -Dpresto-temporarily-allow-java8=true
        -Djdk.attach.allowAttachSelf=true
        -XX:InitiatingHeapOccupancyPercent=30
        -XX:MaxGCPauseMillis=500
        -XX:G1HeapRegionSize=16M
        -XX:ParallelGCThreads=48
        -XX:ConcGCThreads=12
        -Xlog:gc*,safepoint:file=/var/log/trino/trino-gc.log:time,uptime,level,tags:filecount=10,filesize=20M
      
  • Trino Worker JVM Configuration in Detail (for Optimal Performance, ZGC Version)

    • Java 11 이상 필요: ZGC 는 JDK 11 부터 도입 되었으며, JDK 17 LTS Version 에서 더욱 안정화되고 개선되었습니다. 그래서 OpenJDK 17 을 사용하는 것을 권장합니다.

    • Trino 356 Version 이상은 JDK 11 및 JDK 17 을 지원합니다.

    • ZGC 는 Heap Memory 크기에 관계없이 매우 낮은 GC Pause Time (일반적으로 1~2ms 이하) 를 유지하도록 설계되어 있습니다.

      • Heap Memory 가 수백 GB 인 경우에도 일관된 성능을 제공합니다.

      • 이는 ZGC 가 대부분의 GC 작업을 Application Thread 와 병행하여 수행하기 때문입니다.

    • 기존에 설정 했던 G1 GC Option 중에서 필요 없는 Option 들을 제거 합니다.

    •   -XX:+UseG1GC
        -XX:MaxGCPauseMillis=500
        -XX:G1HeapRegionSize=16M
        -XX:InitiatingHeapOccupancyPercent=30
        -XX:ParallelGCThreads=48
        -XX:ConcGCThreads=12
      
    • Java 8 관련 Option 을 제거합니다.

      • -Dpresto-temporarily-allow-java8=true
    • 기타 불필요한 Option 을 제거 합니다.

      •   # ZGC에서는 기본적으로 Full GC를 피하기 때문에 필요성이 낮습니다.
          -XX:+ExplicitGCInvokesConcurrent
        
    • ZGC 를 위한 기존의 (G1 GC) JVM Option 을 변경 합니다.

      • -XX:+UseZGC

        • ZGC를 활성화합니다. JDK 17 이상에서는 -XX:+UnlockExperimentalVMOptions 옵션이 필요하지 않습니다.
      • -Xms and -Xmx

        • ZGC 에서는 Heap 의 최소값과 최대값을 동일하게 설정하여 Memory 재 할당으로 인한 Overhead 를 방지합니다.

        • -Xms410g 로 최소 Heap 설정

        • -Xmx410g 로 최대 Heap 설정

      • GC log

        • -Xlog:gc*,safepoint:file=/var/log/trino/trino-gc.log:time,uptime,level,tags:filecount=10,filesize=20M
      • -XX:+UseLargePages

        • 큰 Page Memory 를 사용하여 TLB(Translation Lookaside Buffer) Miss rate 를 줄이고 Memory Access 성능을 향상시킵니다.
      • -XX:+AlwaysPreTouch

        • JVM 이 Heap Memory 를 초기화 할 때 미리 모든 Page 를 Touch 하여 Page Fault 를 방지합니다.
      • -XX:+ParallelRefProcEnabled

        • Reference 처리의 병렬화를 활성화하여 GC 성능을 향상 시킵니다.
      • Trino Worker 최종 JVM Option (ZGC Version)

          -Xms410G
          -Xmx410G
          -XX:+UseZGC
          -XX:+HeapDumpOnOutOfMemoryError
          -XX:+ExitOnOutOfMemoryError
          -XX:ReservedCodeCacheSize=512M
          -Djdk.attach.allowAttachSelf=true
          -XX:+UseLargePages
          -XX:+AlwaysPreTouch
          -XX:+ParallelRefProcEnabled
          -Xlog:gc*,safepoint:file=/var/log/trino/trino-gc.log:time,uptime,level,tags:filecount=10,filesize=20M
        
    • ✅ OS Level 에서 최적화

      • Linux Kernel Parameter 를 수정할 수 있는 권한이 있어야 합니다.

      • Transparent Huge Pages(THP) 비활성화

        • THP 가 성능에 부정적 영향을 줄 수 있으므로 비활성화 하는 것이 좋습니다.

        • echo never > /sys/kernel/mm/transparent_hugepage/enabled

        • booting 시 자동 적용을 위해 /etc/rc.local 또는 시스템 설정 파일에 해당 명령을 추가합니다.

      • Huge Pages 활성화

        • Huge Page 를 사용하면 TLB (Translation Lookaside Buffer) Miss Rate 이 감소하여 Memory Access 성능이 향상됩니다.

        • 설정 방법

          • Heap Memory Size (410GB) 를 고려하여 필요한 Page 수를 계산합니다.

          • 예를 들어서, 2MB 의 Default Huge Page Size 를 사용하는 경우에는 아래와 같이 설정합니다.

            • 필요한 페이지 수 = (410GB * 1024MB/GB) / 2MB = 209,920
          • /etc/sysctl.conf 파일에 다음을 추가합니다.

            • vm.nr_hugepages=209920
          • 설정 적용을 위해 다음 명령어를 실행합니다.

            • sudo sysctl -p
        • JVM Option 을 추가 하여야 합니다.

          •   -XX:+UseLargePages
              -XX:LargePageSizeInBytes=2m
            
          • 시스템에서 1GB Huge Pages 를 지원하는 경우에는 아래와 같은 Option 도 추가합니다.

            • -XX:LargePageSizeInBytes=1g

            • 이 경우 vm.nr_hugepages 값도 다시 계산해야 합니다.

      • Swap Memory 비활성화를 진행 합니다.

        • Swap 사용은 GC 성능에 부정적인 영향을 미칩니다.

        • /etc/sysctl.conf 파일에 아래와 같은 내용을 추가 합니다.

          • vm.swappiness=0
        • 설정 적용을 위해 아래의 명령어를 실행합니다.

          • sudo sysctl -p
      • ulimit 설정 조정

        • File descriptor 및 process Limit 을 늘려야 할 수 있습니다.

          • Memory Mapping 및 File 사용 증가

            • ZGC 는 Memory 관리와 GC 를 위해 내부적으로 Memory-mapped Files 을 더 많이 사용합니다. 이는 Process 가 열 수 있는 File descriptor 수를 늘리게 됩니다.
          • Trino Worker 는 데이터 처리 시 많은 수의 파일과 Network Socket 을 동시에 열 수 있습니다. 이는 데이터 소스 접근, 결과 저장, Worker 간 통신 등에 필요합니다.

        • 프로세스 및 스레드 수 제한 (ulimit -u) 증가 필요

          • Thread 수 증가: ZGC 는 병행 및 병렬 GC 를 위해 더 많은 GC Thread 를 생성합니다. 또한, 대용량 Heap 을 관리하기 위해 추가적인 작업 Thread 가 필요할 수 있습니다.

          • Trino 의 Multi-Threading: Trino 는 Query 실행 시 많은 작업을 병렬로 처리하며, 각 작업은 별도의 Thread 를 사용합니다.

        •   ulimit -n 65536
            ulimit -u 4096
          
    • Memory Lock

      • memlock 설정

        • Huge Page 사용 시 Memory 잠금 제한을 늘려야 합니다. (필수)

        • ZGC 에서 Huge Pages 를 사용할 경우, Process 가 잠글 수 있는 Memory 양을 늘려야 합니다. 기본 설정으로는 충분한 Memory 를 잠글 수 없어서 Huge Pages 를 활용하지 못할 수 있습니다.

        • memlock 값을 unlimited 로 설정하여 Process 가 필요한 만큼 Memory 를 잠글 수 있도록 합니다.

        • /etc/security/limits.conf 파일에 다음을 추가합니다.

        •   soft memlock unlimited
            hard memlock unlimited
          
    • NUMA 설정

      • NUMA binding

        • Multi Socket Server 의 경우 NUMA Node 에 process 를 binding 하여 Memory Access Latency 를 최소화할 수 있습니다.

        • 이를 통해 Memory 가 모든 NUMA Node 에 균등하게 분산됩니다.

        • Trino 실행 시, 아래와 같은 numactl 을 활용하여 설정합니다.

          • numactl --interleave=all <trino command>

ZGC 를 사용할 때 잠재적인 문제

  • File descriptor 및 Thread 부족 현상

    • Error 발생 가능성: File descriptor 나 Thread 수 제한이 낮으면 다음과 같은 에러가 발생할 수 있습니다.

      • "Too many open files"

      • "Unable to create new native thread"

    • 성능 저하 및 시스템 불안정: 자원 제한으로 인해 Trino Worker Node 가 정상적으로 작동하지 못하고 성능 저하나 예기치 않은 종료가 발생할 수 있습니다.

  • ZGC 를 사용할 때는 대용량 Heap Memory 와 병렬 GC 작업으로 인해 운영체제의 자원 제한에 도달할 수 있습니다. 이를 방지하고 Trino Worker Node 의 성능과 안정성을 확보하기 위해 ulimit 설정을 늘려주는 것이 필요합니다.

  • ulimit 값을 너무 높게 설정하면 시스템 자원이 고갈될 수 있으므로, 서버의 전체 자원(CPU, Memory, File descriptor 수 등)을 고려하여 적절한 값을 설정해야 합니다.

  • 일부 환경에서는 보안이나 안정성 이유로 ulimit 값을 높이는 것이 제한될 수 있으므로, 시스템 관리자나 보안 팀과 협의하여 설정 변경을 진행해야 합니다.

참고 문서