Cấu hình Prometheus và Grafana cho Trino và Iceberg
Bước đầu tiên là triển khai Prometheus để thu thập metrics từ Trino Coordinator và Worker, cũng như Iceberg REST Catalog. Chúng ta sẽ sử dụng cơ chế scraping tiêu chuẩn qua endpoint HTTP.
Trino mặc định expose metrics tại endpoint /v1/prometheus. Iceberg REST Catalog cũng expose metrics tương tự. Chúng ta cần cấu hình Prometheus để định kỳ pull dữ liệu từ các endpoint này.
Tạo file cấu hình prometheus.yml tại đường dẫn /etc/prometheus/prometheus.yml với nội dung hoàn chỉnh như sau:
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'trino-coordinator'
static_configs:
- targets: ['trino-coordinator:8080']
metrics_path: '/v1/prometheus'
scheme: 'http'
- job_name: 'trino-worker'
static_configs:
- targets: ['trino-worker:8080']
metrics_path: '/v1/prometheus'
scheme: 'http'
- job_name: 'iceberg-rest-catalog'
static_configs:
- targets: ['iceberg-rest-catalog:8181']
metrics_path: '/prometheus'
scheme: 'http'
Kết quả mong đợi: Prometheus sẽ bắt đầu scrape metrics từ các target đã cấu hình. Bạn có thể verify bằng cách truy cập giao diện Prometheus (thường ở port 9090), vào tab "Status" -> "Targets", và thấy tất cả các target đều có trạng thái UP.
Triển khai Grafana để visualize dữ liệu. Cài đặt Grafana và cấu hình DataSource trỏ về Prometheus.
Chạy lệnh để khởi động Grafana và tạo DataSource (giả sử bạn đang chạy trong container hoặc có quyền root để cấu hình file):
mkdir -p /etc/grafana/provisioning/datasources
cat > /etc/grafana/provisioning/datasources/prometheus.yaml
Kết quả mong đợi: Khi truy cập Grafana, bạn sẽ thấy DataSource "Prometheus" đã được tự động tạo và kết nối thành công. Nhấn nút "Save & Test" sẽ hiện thông báo Data source is working.
Cấu hình Dashboard giám sát hiệu năng
Chúng ta cần theo dõi các chỉ số quan trọng: độ trễ query (Query Latency), sử dụng CPU, và bộ nhớ (Memory). Trino expose các metrics này dưới dạng trino_query_latency_seconds và trino_node_system_memory_used_bytes.
Tạo file JSON định nghĩa Dashboard tại /etc/grafana/provisioning/dashboards/trino-monitoring.json:
{
"dashboard": {
"id": null,
"uid": "trino-monitoring",
"title": "Trino & Iceberg Performance Monitor",
"tags": ["trino", "iceberg", "data-fabric"],
"timezone": "browser",
"schemaVersion": 38,
"version": 0,
"panels": [
{
"id": 1,
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 0},
"title": "Query Latency (P95)",
"type": "graph",
"targets": [
{
"expr": "histogram_quantile(0.95, sum(rate(trino_query_latency_seconds_bucket[5m])) by (le))",
"legendFormat": "P95 Latency (s)",
"refId": "A"
}
],
"yaxes": [{"format": "s", "label": "Seconds", "logBase": 1, "min": 0}]
},
{
"id": 2,
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 0},
"title": "Active Queries",
"type": "singlestat",
"targets": [
{
"expr": "sum(trino_query_stats_running)",
"refId": "A"
}
]
},
{
"id": 3,
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 8},
"title": "Node Memory Usage",
"type": "graph",
"targets": [
{
"expr": "trino_node_system_memory_used_bytes",
"legendFormat": "{{instance}}",
"refId": "A"
}
],
"yaxes": [{"format": "bytes", "label": "Memory"}]
},
{
"id": 4,
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 8},
"title": "Iceberg Catalog Errors",
"type": "graph",
"targets": [
{
"expr": "rate(iceberg_catalog_requests_total{status=~\"5..\"}[5m])",
"legendFormat": "Server Errors",
"refId": "A"
}
]
}
],
"refresh": "10s"
},
"apiVersion": 1,
"folder": {
"id": 0,
"name": "Data Fabric"
},
"orgId": 1,
"inputs": []
}
Cấu hình tự động provision dashboard này bằng file /etc/grafana/provisioning/dashboards/dashboards.yaml:
apiVersion: 1
providers:
- name: 'Data Fabric Dashboards'
folder: 'Data Fabric'
type: file
disableDeletion: false
updateIntervalSeconds: 10
options:
path: /etc/grafana/provisioning/dashboards
Kết quả mong đợi: Restart Grafana, vào tab "Dashboards", bạn sẽ thấy folder "Data Fabric" và dashboard "Trino & Iceberg Performance Monitor". Các biểu đồ sẽ hiển thị dữ liệu realtime từ Prometheus.
Phân tích log lỗi thường gặp trong Trino và Iceberg
Log của Trino và Iceberg chứa thông tin chi tiết về lỗi runtime, lỗi kết nối catalog, và lỗi phân mảnh dữ liệu. Chúng ta sẽ cấu hình tập trung log vào stdout hoặc file log để phân tích.
Trino lưu log theo định dạng JSON hoặc Text tùy cấu hình log.level trong catalog.properties hoặc node.properties. Để debug lỗi, hãy tăng mức log lên DEBUG hoặc INFO.
Sửa file /etc/trino/node.properties (hoặc biến môi trường trong Kubernetes):
node.environment=production
node.id=worker-1
node.data-dir=/var/trino/data
log.level=DEBUG
Đối với Iceberg REST Catalog, log được ghi ra stdout. Để lọc các lỗi cụ thể như "Catalog unavailable" hoặc "Schema mismatch", sử dụng lệnh grep hoặc journalctl (nếu chạy systemd) hoặc kubectl logs.
Lệnh kiểm tra log lỗi liên quan đến catalog hoặc query failed trên container Trino:
kubectl logs -f trino-coordinator-0 --tail=100 | grep -i "error\|exception\|failed" | grep -v "INFO"
Kết quả mong đợi: Bạn sẽ thấy các dòng log chứa từ khóa lỗi. Ví dụ: com.trino.spi.TrinoException: Catalog 'iceberg_catalog' not found hoặc java.net.ConnectException: Connection refused.
Phân tích log Iceberg để tìm lỗi về transaction hoặc version conflict:
kubectl logs -f iceberg-rest-catalog-0 | grep -E "Snapshot\|Commit\|Conflict\|Transaction"
Kết quả mong đợi: Nếu có lỗi commit, log sẽ hiện thông báo CommitFailedException kèm lý do (ví dụ: version conflict). Điều này giúp xác định nguyên nhân do nhiều client ghi cùng lúc mà không xử lý optimistic locking đúng cách.
Xử lý vấn đề phân mảnh dữ liệu (Data Skew)
Data Skew xảy ra khi một partition hoặc một node xử lý lượng dữ liệu lớn hơn đáng kể so với các node khác, gây nghẽn cổ chai (bottleneck). Trong Iceberg, điều này thường do partition key không đồng đều hoặc file size quá lớn.
Để phát hiện skew, truy vấn bảng metadata của Iceberg qua Trino để kiểm tra kích thước file và số lượng row theo partition.
SELECT
partition,
COUNT(*) as row_count,
SUM(file_size_in_bytes) as total_size_bytes
FROM
iceberg_catalog.schema_name.table_name\$files
GROUP BY
partition
ORDER BY
total_size_bytes DESC
LIMIT 10;
Kết quả mong đợi: Nếu thấy một partition có total_size_bytes lớn hơn gấp 10 lần so với trung bình, bạn đã gặp vấn đề skew. Ví dụ: Partition "2023-10-01" có 50GB, trong khi các ngày khác chỉ có 2GB.
Khắc phục Data Skew bằng cách thực hiện Rewrite Data Files (Compact) trên Iceberg để gom các file nhỏ và cân bằng lại kích thước file.
CALL iceberg_catalog.system.rewrite_data_files(
table => 'schema_name.table_name',
options => map('target_size_in_bytes', '1073741824') -- 1GB target size
);
Hoặc sử dụng Optimize để xử lý skew cụ thể trên các partition nặng:
CALL iceberg_catalog.system.rewrite_data_files(
table => 'schema_name.table_name',
options => map(
'target_size_in_bytes', '1073741824',
'strategy', 'binpack',
'partition_filters', "year = '2023' AND month = '10'"
)
);
Kết quả mong đợi: Sau khi chạy lệnh, số lượng file sẽ giảm, kích thước file đồng đều hơn. Query tiếp theo sẽ nhanh hơn vì Trino phân phối công việc đều hơn giữa các worker. Kiểm tra lại bằng lệnh SELECT COUNT(*) FROM ... để thấy độ trễ giảm.
Mẹo khắc phục sự cố trên môi trường Production
Trong môi trường production, ưu tiên số 1 là duy trì tính sẵn sàng (High Availability) và tránh làm gián đoạn dịch vụ (Zero Downtime).
1. Xử lý lỗi "Too many open files" trên Trino Worker:
Trino mở nhiều file descriptor để đọc nhiều file Parquet/ORC. Nếu hệ điều hành giới hạn quá thấp, worker sẽ crash.
Chỉnh sửa limit trong file /etc/security/limits.conf hoặc trong Kubernetes Pod Spec:
cat > /etc/security/limits.conf
Kết quả mong đợi: Restart Trino worker, kiểm tra lại bằng lệnh ulimit -n sẽ thấy giá trị 65536. Worker không còn crash do hết file descriptor.
2. Xử lý lỗi "Query exceeded memory limit":
Trino giới hạn memory để tránh OOM (Out of Memory) gây sập toàn cluster. Nếu query bị kill do hết memory, hãy tăng query.max-memory hoặc tối ưu query.
Cấu hình trong /etc/trino/config/catalog/iceberg.properties:
query.max-memory=100GB
query.max-memory-per-node=20GB
exchange.max-block-size=10MB
3. Kiểm tra connectivity giữa Trino và Iceberg Catalog:
Sử dụng curl từ bên trong container Trino để test kết nối đến Iceberg REST Catalog.
kubectl exec -it trino-coordinator-0 -- curl -v http://iceberg-rest-catalog:8181/v1/catalogs
Kết quả mong đợi: Nếu thấy HTTP/1.1 200 OK, kết nối tốt. Nếu thấy Connection refused hoặc 503 Service Unavailable, kiểm tra lại Service Discovery hoặc Health Check của Iceberg Catalog.
4. Xử lý lỗi "Catalog not found" do DNS hoặc Service name sai:
Đảm bảo hostname trong catalog.properties khớp với Kubernetes Service name. Nếu dùng Kubernetes DNS, tên service phải là <service-name>.<namespace>.svc.cluster.local.
cat > /etc/trino/catalog/iceberg.properties
Kết quả mong đợi: Restart Trino, chạy lệnh SHOW CATALOGS trong Trino CLI. Catalog iceberg_catalog sẽ hiện ra danh sách. Nếu vẫn lỗi, kiểm tra lại log Trino để xem lỗi DNS resolution.
Đ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 7: Tích hợp ETL và Data Pipeline tự động với Airflow
Phần 9: Tối ưu chi phí và mở rộng quy mô (Scaling) cho sản xuất »