본문으로 건너뛰기

Trino 설정

GenD의 Federation SQL 엔진인 Trino의 배포 구성과 접근 제어 설정입니다.

개요

Trino는 공식 Helm 차트(infra/helm/trino/values.yaml)로 배포되며, 접근 제어(rules.json)와 리소스 그룹(resource-groups.json)으로 역할별 권한과 쿼리 리소스를 관리합니다.

Helm 차트 주요 설정

설정 파일은 2단으로 적용된다 — infra/helm/trino/values.yaml(공용) 뒤에 infra/helm/trino/values-prod.yaml(prod/staging 전용)을 -f 로 덧붙인다 (infra/azure-deploy/scripts/02-deploy-k8s.sh). Kind 로컬은 base 만 쓴다.

설정값 (2026-07-31 실측)설명
chart / Trino 버전trino-1.42.2 / 480infra/helm/trino/CHART_VERSION 로 고정
server.workers1워커 수. worker.replicas 는 차트 스키마에 없는 키로 조용히 무시된다 (#2683)
server.autoscalingenabled, max 3, CPU 80%워커 HPA. 렌더 이름은 trino-worker차트가 단일 소유자
worker.gracefulShutdownenabled, 120s종료 시 실행 중 태스크 드레인 (#2776)
worker.terminationGracePeriodSeconds300차트 요구: >= 2 × gracePeriodSeconds
coordinator.jvm.maxHeapSize / worker.jvm.maxHeapSize3G / 3GJVM 힙
server.config.query.maxMemory4GB쿼리당 최대 메모리 (camelCase 키만 인식 — #1287)
catalog.managementdynamic동적 카탈로그

:::warning 워커 오토스케일 소유자는 차트 하나뿐 infra/hpa/trino-hpa.yamlinfra/keda/scaledobjects/trino-worker-scaledobject.yaml배포되지 않은 참고 설계다. apply 하면 같은 Deployment 에 오토스케일 컨트롤러가 2개가 되어 replicas 를 서로 덮어쓴다 (#2683 의 소유권 충돌과 같은 계열). 두 파일에는 적용 금지 표시가 있고, scripts/test_cross_pr_consistency.py 가 그 표시를 고정한다. :::

워커 graceful shutdown (#2776)

워커가 종료될 때 실행 중인 쿼리를 지키는 설정이다. 없으면 스케일다운 한 번에 쿼리가 실패한다 — 2026-07-30 prod 실측: 워커 pod 가 24시간에 24회 교체되는 동안 쿼리 38건PAGE_TRANSPORT_TIMEOUT / TOO_MANY_REQUESTS_FAILED 로 실패했고, 각 실패는 코디네이터가 죽은 워커를 재시도하는 305초를 소모했다.

동작 순서:

  1. K8s 가 워커 pod 에 SIGTERM 을 보내기 전에 preStop 훅이 워커의 /v1/info/state"SHUTTING_DOWN" 을 PUT 한다.
  2. 워커는 새 태스크를 받지 않고 진행 중 태스크를 끝낸다 (shutdown.grace-period=120s).
  3. terminationGracePeriodSeconds: 300 안에 종료되면 SIGKILL 없이 정상 종료된다.

운영자가 체감하는 변화

  • 워커 pod 종료가 즉시 끝나지 않고 최대 약 5분까지 걸린다. kubectl delete pod, 노드 드레인, helm upgrade 롤아웃이 그만큼 느려지는 것이 정상이다.
  • 스케일다운이 느려진다 — HPA behavior.scaleDown 안정화 창 600초 + 5분에 1대. 워커가 놀고 있어도 바로 줄지 않는다(의도된 동작).
  • 차트는 shutdown API 호출을 인가하려고 워커에만 파일 접근제어 (system_information: write)를 붙인다. 코디네이터의 쿼리 인가 경로는 건드리지 않는다 (코디네이터 파일 ACL 활성화는 ADR-0030 Step 3 사안).

확인 방법:

kubectl -n gend get deploy trino-worker \
-o jsonpath='{.spec.template.spec.terminationGracePeriodSeconds}{"\n"}' # 300
kubectl -n gend exec deploy/trino-worker -- \
grep shutdown /etc/trino/config.properties # shutdown.grace-period=120s
kubectl -n gend get hpa trino-worker -o jsonpath='{.spec.behavior}{"\n"}' # scaleDown 600s

카탈로그 구성

values.yamladditionalCatalogs에서 정의합니다.

카탈로그커넥터용도
icebergiceberg (Hive Metastore)메인 데이터 레이크
nessieiceberg (REST)Git-like 브랜칭 카탈로그
tpch / tpcds벤치마크성능 테스트 데이터
sourcedbpostgresqlCDC 소스 DB 연결

접근 제어 (rules.json)

역할별 카탈로그 접근 권한을 정의합니다 (infra/trino/rules.json).

역할카탈로그권한
admin.* (전체)all
analysticeberg, nessie, tpch, tpcdsread-only
viewericeberg, tpchread-only
etliceberg, nessieall
etltpch, tpcds, sourcedbread-only

리소스 그룹 (resource-groups.json)

역할별 쿼리 리소스 제한입니다 (infra/trino/resource-groups.json).

그룹메모리동시 실행대기열
admin50%20100
analyst30%1050
viewer15%520

GenD API 연동 설정

GEND_TRINO_HOST=trino
GEND_TRINO_PORT=8080
GEND_TRINO_USER=gend-api
GEND_TRINO_RULES_JSON_PATH=/etc/trino/access-control/rules.json
GEND_TRINO_RESOURCE_GROUPS_JSON_PATH=/etc/trino/resource-groups/resource-groups.json

접근제어(ACL) 활성화·검증 (v1.1+)

파일 기반 ACL 을 켜거나 재배포할 때는 infra/trino/ 의 두 스크립트를 쓴다. 직접 helm upgrade 를 치지 말 것 — 아래 게이트를 건너뛰면 2026-08-06 과 같은 전 사용자 차단이 재현된다.

bash infra/trino/activate-acl.sh # 활성화 (게이트 5개 내장)
bash infra/trino/verify-acl.sh # 검증만 단독 실행

activate-acl.sh 가 강제하는 게이트

#게이트막는 사고
0릴리스가 deployed 상태인가 + 롤백 리비전 기록다른 배포가 진행 중일 때 잘못된 롤백 지점을 기억
1gend-api:latest 가 main HEAD 이후 빌드인가옛 생성기가 만든 규칙으로 배포
2acl-sync Job 1회 실행ConfigMap 이 낡은 채로 반영
3역할이 실제로 얻는 권한을 첫-매칭 시뮬레이션으로 검증★ 2026-08-06 롤백의 정확한 지점
4checksum/coordinator-config 변경 + access-control.name=file + refresh-period 확인ConfigMap 만 바뀌고 재시작이 안 걸린 경우
5verify-acl.sh 전 프로브 통과인가가 의도와 다르게 걸린 경우

게이트 3 이 핵심이다. 규칙 ConfigMap 은 trino-acl-sync CronJob 이 5분마다 data_grants 기준으로 재생성하므로, 리포에서 확인한 규칙과 배포 시점의 규칙이 다를 수 있다. 실제로 그래서 analyst 38명 + viewer 6명이 전면 차단됐다.

게이트 3 은 group 이름을 문자열로 세지 않는다 — admin-analyst 같은 이름이 통과하고 규칙의 catalog·privileges 가 깨져도 못 잡기 때문이다. 대신 각 역할이 실제로 무엇을 얻는가를 본다: iceberg 읽기 O · gendpg.public.intel_* O · ws_secrets 등 X · users/audit_logsadmin 포함 전원 X.

게이트 4 는 파드 annotation checksum/coordinator-config 를 본다. 묻고 싶은 것이 "파드가 바뀌었나" 가 아니라 "coordinator 설정이 바뀌었나" 이기 때문이다. 파드 UID 는 노드 드레인·eviction 으로도 바뀌고, pod-template-hash 는 설정과 무관한 템플릿 변경 (리소스·라벨)에도 바뀐다 — 둘 다 대리 지표다. 체크섬은 질문 그 자체다.

게이트 0 의 릴리스 상태 확인은 스텝 4 직전에 한 번 더 수행한다. 그 사이 acl-sync Job 등으로 수 분이 흐르므로, 처음 한 번만 보면 그동안 시작된 다른 배포를 놓친다.

verify-acl.sh 의 프로브 설계

음성(차단돼야 함)만 있으면 "전부 막아서 통과" 를 못 잡는다 — 롤백 사고가 정확히 그 형태였다. 그래서 양성 프로브를 함께 둔다.

  • 양성: analyst/viewer/admin → iceberg, analyst → gendpg.public.intel_*, 서비스 계정(gend-api·dagster) → iceberg
  • 음성: analyst → gendpg.public.ws_secrets·access_policies, viewer → gendpg.public.gitea_pat·system.runtime.queries, 미등록 사용자 → 전부

gendpg.public.users 같은 테이블은 프로브로 쓰지 않는다 — PG 계층 (gend_trino_readonly)이 이미 숨겨서 ACL on/off 를 구분하지 못한다.

환경변수

두 스크립트 모두 기본값이 prod 를 가리킨다. 다른 클러스터에 쓰려면 아래를 덮어쓴다.

변수기본값적용설명
GEND_KUBE_CONTEXTaks-genos-prod양쪽kubectl/helm 컨텍스트
GEND_NAMESPACEgend양쪽대상 네임스페이스
GEND_EXEC_TIMEOUT60s양쪽kubectl --request-timeout
TRINO_CHART_VERSION1.42.2activatehelm 차트 버전
TRINO_HELM_WAIT_MIN5activatehelm --timeout (분). 외부 상한은 여기서 유도(+2분). 양의 정수만 — 아니면 exit 2
REPO_DIR스크립트의 리포 루트activatevalues*.yaml 위치
GEND_PROBE_TABLEiceberg.bronze.intel_ohlcv_rawverify양성 프로브용 테이블
GEND_PROBE_ANALYST
GEND_PROBE_VIEWER
GEND_PROBE_ADMIN
없음verify프로브에 쓸 Trino user. 미지정 시 trino-group-provider ConfigMap 에서 각 group 의 첫 멤버를 읽는다
NO_COLORactivate설정 시 ANSI 색상 비활성 (비-TTY 에서는 자동)

GEND_PROBE_*기본값을 두지 않는 것이 의도다. 리포에 운영 사용자의 Keycloak sub 를 평문으로 남기지 않기 위해서다. 멤버를 못 찾으면 exit 2(판정 불가)로 끝난다.

--help 로도 같은 목록을 볼 수 있다.

종료코드

자동화·알림 라우팅이 상황을 구분할 수 있도록 코드를 나눠 둡니다.

코드의미대응
0성공
1게이트/검증 실패 — 클러스터는 안전한 상태 (자동 롤백 성공했거나 애초에 미변경)원인 수정 후 재시도
2인자 오류·준비 실패 등 판정 불가환경 확인 (컨텍스트·권한·kubectl)
3자동 롤백까지 실패사람이 즉시 개입 — 아래 수동 롤백

★ 1 과 3 을 섞으면 안 됩니다. 1 은 재시도 대상이고 3 은 호출 대상입니다.

롤백

helm --kube-context aks-genos-prod -n gend rollback trino <직전 리비전>

activate-acl.sh 는 시작할 때 그 번호를 출력한다.

관련 문서