Chiến lược Scaling tự động cho Trino Workers và Iceberg Catalog
Trino Coordinator thường chỉ cần 1-2 instance với cấu hình cố định, nhưng Workers cần mở rộng theo tải lượng truy vấn. Chúng ta sẽ sử dụng Kubernetes HPA (Horizontal Pod Autoscaler) để tự động tăng/giảm số lượng Pod dựa trên CPU và RAM.
Trước tiên, cần cài đặt Metrics Server để HPA lấy được số liệu từ Kubernetes. Nếu chưa có, chạy lệnh:
helm install metrics-server metrics-server/metrics-server --namespace kube-system --set metrics.scrapeInterval=15s
Để Trino Workers có thể scale, cần đảm bảo Pod đã có request và limit rõ ràng. Chỉnh sửa deployment Trino Worker trong namespace `trino` của bạn.
Tạo file HPA cho Trino Workers tại đường dẫn: `./config/hpa/trino-worker-hpa.yaml`
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: trino-worker-hpa
namespace: trino
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: trino-worker
minReplicas: 2
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Pods
value: 2
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Pods
value: 5
periodSeconds: 15
Áp dụng cấu hình HPA vào cluster:
kubectl apply -f ./config/hpa/trino-worker-hpa.yaml
Đối với Iceberg REST Catalog, đây là service stateless nhưng xử lý metadata. Nếu traffic cao, ta cũng áp dụng HPA tương tự, nhưng với ngưỡng thấp hơn để đảm bảo độ trễ metadata thấp.
Tạo file HPA cho Iceberg Catalog tại: `./config/hpa/iceberg-catalog-hpa.yaml`
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: iceberg-catalog-hpa
namespace: trino
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: iceberg-rest-catalog
minReplicas: 2
maxReplicas: 5
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
Áp dụng cấu hình:
kubectl apply -f ./config/hpa/iceberg-catalog-hpa.yaml
Verify kết quả bằng cách xem trạng thái HPA:
kubectl get hpa -n trino
Kết quả mong đợi: Cột `REPLICAS` thay đổi khi tải tăng, và `TARGETS` hiển thị % CPU/RAM hiện tại.
Tối ưu chi phí lưu trữ với Lifecycle Policy trên S3
Data Fabric sử dụng S3 làm storage layer cho Iceberg. Chi phí S3 tăng theo thời gian lưu trữ. Chúng ta sẽ cấu hình Lifecycle Policy để tự động chuyển đổi dữ liệu từ Standard (đắt) sang Glacier (rẻ) hoặc xóa metadata cũ.
Trước tiên, cần xác định bucket S3 đang dùng (ví dụ: `my-data-fabric-bucket`). Cấu hình này thực hiện trực tiếp trên AWS Console hoặc qua AWS CLI.
Tạo file cấu hình JSON cho Lifecycle Policy tại: `./config/s3/lifecycle-policy.json`
{
"Rules": [
{
"ID": "Move-to-IA-after-30-days",
"Status": "Enabled",
"Filter": {
"Prefix": "data/"
},
"Transitions": [
{
"Days": 30,
"StorageClass": "STANDARD_IA"
}
]
},
{
"ID": "Move-to-Glacier-after-90-days",
"Status": "Enabled",
"Filter": {
"Prefix": "data/"
},
"Transitions": [
{
"Days": 90,
"StorageClass": "GLACIER"
}
]
},
{
"ID": "Delete-old-manifests",
"Status": "Enabled",
"Filter": {
"Prefix": "metadata/"
},
"Expiration": {
"Days": 365
}
}
]
}
Áp dụng policy vào bucket S3 (thay thế `YOUR_BUCKET_NAME` bằng tên bucket thực tế):
aws s3api put-bucket-lifecycle-configuration --bucket YOUR_BUCKET_NAME --lifecycle-configuration file://./config/s3/lifecycle-policy.json
Verify kết quả bằng cách đọc lại cấu hình:
aws s3api get-bucket-lifecycle-configuration --bucket YOUR_BUCKET_NAME
Kết quả mong đợi: JSON trả về chứa các rule đã định nghĩa ở trên với trạng thái `Enabled`.
Lưu ý: Khi dữ liệu được chuyển sang Glacier, việc truy vấn trực tiếp (Read) sẽ chậm hơn. Cần cấu hình Trino để xử lý latency này hoặc dùng phiên bản S3 Glacier Instant Retrieval nếu cần truy vấn ngẫu nhiên.
Sử dụng Spot Instances cho các tác vụ tính toán không quan trọng
Spot Instances (AWS) hoặc Preemptible VMs (GCP) rẻ hơn 70-90% so với On-Demand. Chúng ta sẽ sử dụng Spot cho Trino Workers để giảm chi phí tính toán, chấp nhận rủi ro bị reclaim (thu hồi) bất ngờ.
Chiến lược: Dùng Kubernetes Node Selector hoặc Taints/Tolerations để chỉ định Pod chạy trên Spot Nodes. Hoặc sử dụng Cluster Autoscaler với Spot Fleet.
Đầu tiên, tạo một Node Group hoặc Node Pool riêng cho Spot Instances. Giả sử ta dùng AWS EKS với Node Group tên `trino-spot-nodes`.
Chỉnh sửa Deployment của Trino Worker để chỉ định chạy trên Spot Nodes. Tạo file: `./config/deployments/trino-worker-spot.yaml`
apiVersion: apps/v1
kind: Deployment
metadata:
name: trino-worker
namespace: trino
labels:
app: trino-worker
spec:
replicas: 2
selector:
matchLabels:
app: trino-worker
template:
metadata:
labels:
app: trino-worker
tier: compute
spec:
nodeSelector:
spot: "true"
tolerations:
- key: "spot"
operator: "Equal"
value: "true"
effect: "NoSchedule"
containers:
- name: trino-worker
image: trinodb/trino:latest
resources:
requests:
memory: "8Gi"
cpu: "4"
limits:
memory: "16Gi"
cpu: "8"
env:
- name: LOG_LEVEL
value: "INFO"
- name: JVM_MEMORY_HEAP_SIZE
value: "6G"
Áp dụng deployment mới này (chú ý: nếu đã có deployment cũ, cần xóa hoặc merge):
kubectl apply -f ./config/deployments/trino-worker-spot.yaml
Để tránh mất dữ liệu khi Spot Node bị reclaim, cần cấu hình Trino Worker để lưu trạng thái query vào external storage hoặc đảm bảo query có thể restart. Tuy nhiên, với kiến trúc Trino stateless, việc mất Pod chỉ làm gián đoạn query đang chạy, không mất dữ liệu.
Verify kết quả bằng cách xem Pod đang chạy trên Node nào:
kubectl get pods -n trino -o wide | grep trino-worker
Kết quả mong đợi: Cột `NODE` phải là tên của các node trong nhóm Spot (thường có suffix `-spot` hoặc label tương ứng).
Cấu hình Resource Quotas và LimitRanges trong Kubernetes
Để tránh tình trạng một tenant hoặc một job chiếm hết tài nguyên cluster, cần đặt giới hạn cứng (Hard Limit) và giới hạn mềm (Soft Limit) cho namespace `trino`.
Resource Quota giới hạn tổng tài nguyên của toàn namespace. LimitRanges giới hạn tài nguyên tối thiểu và tối đa cho từng container.
Tạo file cấu hình tại: `./config/namespace/trino-quota.yaml`
apiVersion: v1
kind: ResourceQuota
metadata:
name: trino-quota
namespace: trino
spec:
hard:
requests.cpu: "50"
requests.memory: "200Gi"
limits.cpu: "100"
limits.memory: "400Gi"
persistentvolumeclaims: "10"
pods: "50"
Tạo file LimitRanges tại: `./config/namespace/trino-limits.yaml`
apiVersion: v1
kind: LimitRange
metadata:
name: trino-limits
namespace: trino
spec:
limits:
- default:
memory: "4Gi"
cpu: "2"
defaultRequest:
memory: "1Gi"
cpu: "500m"
max:
memory: "16Gi"
cpu: "8"
min:
memory: "512Mi"
cpu: "250m"
type: Container
Áp dụng cả hai cấu hình:
kubectl apply -f ./config/namespace/trino-quota.yaml && kubectl apply -f ./config/namespace/trino-limits.yaml
Verify kết quả bằng cách thử tạo một Pod vượt quá giới hạn (nó sẽ bị lỗi):
kubectl run test-pod --image=busybox --requests=cpu=100 --namespace=trino
Kết quả mong đợi: Lỗi `exceeded quota: requests.cpu` hoặc `exceeded the limits of the LimitRange`. Điều này chứng tỏ bảo vệ tài nguyên đã hoạt động.
Xóa Pod test sau khi kiểm tra:
kubectl delete pod test-pod -n trino
Lập kế hoạch bảo trì và nâng cấp phiên bản các thành phần
Với hệ thống sản xuất, việc nâng cấp không được gây downtime. Chúng ta sẽ sử dụng chiến lược Rolling Update và Blue-Green Deployment cho các thành phần quan trọng.
Kịch bản nâng cấp Trino: Cập nhật version image trong Helm Chart hoặc Deployment, Kubernetes sẽ tự động thay thế Pod cũ bằng Pod mới từ từ.
Tạo file script nâng cấp tự động: `./scripts/upgrade-trino.sh`
#!/bin/bash
set -e
NEW_VERSION="425" # Thay bằng version mới nhất
NAMESPACE="trino"
echo "Starting rolling upgrade for Trino to version ${NEW_VERSION}..."
# 1. Update Helm Release (nếu dùng Helm)
# helm upgrade trino trino/trino --namespace ${NAMESPACE} --set trino.version=${NEW_VERSION}
# 2. Nếu dùng Deployment thuần, update image
kubectl set image deployment/trino-coordinator trino-coordinator=trinodb/trino:${NEW_VERSION} -n ${NAMESPACE}
kubectl set image deployment/trino-worker trino-worker=trinodb/trino:${NEW_VERSION} -n ${NAMESPACE}
# 3. Wait for rollout to complete
echo "Waiting for rollout to finish..."
kubectl rollout status deployment/trino-coordinator -n ${NAMESPACE} --timeout=300s
kubectl rollout status deployment/trino-worker -n ${NAMESPACE} --timeout=300s
echo "Upgrade completed successfully."
Cấp quyền thực thi và chạy script:
chmod +x ./scripts/upgrade-trino.sh && ./scripts/upgrade-trino.sh
Đối với Iceberg REST Catalog, quy trình tương tự. Tuy nhiên, cần chú ý đến tính tương thích của Catalog API. Luôn test trên môi trường Staging trước.
Kịch bản bảo trì định kỳ (Backup metadata): Iceberg lưu metadata trong S3, nhưng cần backup cấu hình Catalog (H2DB hoặc Postgres nếu dùng). Nếu dùng H2DB (file-based), cần backup file `mv.db` vào S3 trước khi upgrade.
Tạo script backup metadata: `./scripts/backup-iceberg-metadata.sh`
#!/bin/bash
BACKUP_DIR="/tmp/iceberg-backup-$(date +%Y%m%d_%H%M%S)"
CATALOG_POD=$(kubectl get pods -n trino -l app=iceberg-rest-catalog -o jsonpath='{.items[0].metadata.name}')
echo "Backing up Iceberg Catalog metadata from pod ${CATALOG_POD}..."
# Mount volume chứa H2DB hoặc Postgres data vào container tạm
# Giả sử volume name là 'catalog-data'
kubectl cp ${CATALOG_POD}:data/catalog ${BACKUP_DIR}/ -n trino
# Upload backup lên S3
aws s3 cp ${BACKUP_DIR}/ s3://my-data-fabric-bucket/backups/iceberg-catalog/ --recursive
echo "Backup completed to s3://my-data-fabric-bucket/backups/iceberg-catalog/"
Chạy script backup trước khi bảo trì:
chmod +x ./scripts/backup-iceberg-metadata.sh && ./scripts/backup-iceberg-metadata.sh
Verify kết quả bằng cách kiểm tra S3 bucket xem có file backup mới nhất không:
aws s3 ls s3://my-data-fabric-bucket/backups/iceberg-catalog/ --recursive
Kết quả mong đợi: Danh sách file backup với timestamp gần nhất xuất hiện.
Điều hướng series:
Mục lục: Series: Xây dựng nền tảng Data Fabric hiện đại với Apache Iceberg, Trino và Kubernetes
« Phần 8: Giám sát, Logging và Troubleshooting nâng cao