Triển khai Apache Iceberg Catalog trên Kubernetes
Cấu hình và deploy REST Catalog
Chúng ta sẽ sử dụng Apache Iceberg REST Catalog vì nó cung cấp khả năng mở cao, hỗ trợ nhiều backend (Hive, Glue, JDBC) và quản lý phiên bản tốt hơn cho môi trường multi-tenant.
Tạo file cấu hình catalog tại /etc/iceberg/catalog.properties với nội dung sau để định nghĩa kết nối đến backend lưu trữ metadata (ở đây dùng Hive Metastore giả lập hoặc Glue) và cơ chế xác thực.
cat > /etc/iceberg/catalog.properties
File credentials sẽ chứa token JWT để xác thực với REST Catalog. Tạo file này tại /etc/iceberg/credentials.json.
cat > /etc/iceberg/credentials.json
Deploy dịch vụ REST Catalog lên Kubernetes bằng Helm chart chính thức. Command này cài đặt catalog vào namespace iceberg-platform và mount config file vào container.
helm repo add apache-iceberg https://apache.github.io/iceberg-helm-charts/
helm repo update
helm install iceberg-catalog apache-iceberg/iceberg-rest-catalog \
--namespace iceberg-platform \
--set service.type=ClusterIP \
--set service.port=8080 \
--set catalog.config.name=iceberg-rest-catalog \
--set catalog.config.type=rest \
--set catalog.config.uri=http://iceberg-catalog-service:8080 \
--set storageClass=local-storage \
--set persistence.size=10Gi \
--set auth.type=bearer \
--set auth.publicKey=/etc/iceberg/public.key \
--set auth.privateKey=/etc/iceberg/private.key
Verify: Kiểm tra trạng thái pod và dịch vụ, đảm bảo container đang chạy và có thể resolve DNS nội bộ.
kubectl get pods -n iceberg-platform -l app.kubernetes.io/name=iceberg-rest-catalog
kubectl get svc -n iceberg-platform iceberg-catalog-service
Cấu hình Iceberg Table với Versioning và Snapshot Isolation
Tạo Table và thiết lập chính sách Snapshot
Sử dụng Iceberg CLI hoặc Spark SQL để tạo table đầu tiên. Chúng ta sẽ thiết lập các property để kích hoạt snapshot-retention và expiring-snapshots nhằm quản lý chi phí lưu trữ và đảm bảo khả năng rollback.
Tạo file script Spark SQL /opt/iceberg/setup-table.sql để định nghĩa schema và các property bảo vệ dữ liệu.
cat > /opt/iceberg/setup-table.sql
Chạy script này thông qua Spark Shell hoặc Trino để tạo table. Command dưới đây giả định bạn đang chạy Spark trong container đã có kết nối đến Catalog.
spark-sql --catalog iceberg_catalog --database default < /opt/iceberg/setup-table.sql
Kết quả mong đợi: Table được tạo thành công, hệ thống tự động tạo snapshot đầu tiên (Snapshot 0) khi có dữ liệu ghi vào. Tính năng format-version=2 cho phép tối ưu hóa merge-on-read và snapshot isolation mạnh mẽ.
Xác minh Snapshot Isolation
Thực hiện ghi dữ liệu, sau đó tạo một snapshot mới và kiểm tra xem query cũ có còn thấy dữ liệu cũ hay không (nếu dùng reader snapshot cũ).
-- Chèn dữ liệu phiên bản 1
spark-sql --catalog iceberg_catalog -e "INSERT INTO sales_data VALUES (1, 'C001', 'P001', 10, 100.00, 'TENANT_A', current_timestamp());"
-- Lấy snapshot ID hiện tại
spark-sql --catalog iceberg_catalog -e "SELECT snapshot_id FROM sales_data.snapshots ORDER BY committed_at DESC LIMIT 1;"
-- Chèn dữ liệu phiên bản 2 (update)
spark-sql --catalog iceberg_catalog -e "UPDATE sales_data SET quantity = 20 WHERE order_id = 1;"
-- Query với snapshot cũ (giả sử snapshot_id lấy ở bước trên là 12345)
spark-sql --catalog iceberg_catalog -e "SELECT * FROM sales_data.history WHERE snapshot_id = 12345 LIMIT 1;"
Verify: Query sử dụng snapshot cũ phải trả về quantity = 10, trong khi query hiện tại trả về quantity = 20. Điều này chứng minh cơ chế snapshot isolation hoạt động đúng, ngăn chặn "dirty read" giữa các phiên bản.
Thiết lập ACL (Access Control List) Column và Row
Cấu hình Row-Level Security (RLS)
Trong môi trường Multi-Tenant, mỗi tenant chỉ được phép truy xuất dữ liệu có tenant_id khớp với ID của họ. Chúng ta sử dụng tính năng filter của Iceberg kết hợp với ACL của Catalog.
Cấu hình file /etc/iceberg/tenants-acl.yaml để định nghĩa quyền truy cập dựa trên role.
cat > /etc/iceberg/tenants-acl.yaml
Đẩy cấu hình này vào REST Catalog API để áp dụng chính sách. Command này giả định catalog có endpoint quản lý ACL (cần mở rộng REST Catalog hoặc dùng plugin authorization).
curl -X POST http://iceberg-rest-catalog-service:8080/v1/namespaces/default/tables/sales_data/acl \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $(cat /etc/iceberg/credentials.json | jq -r '.token')" \
-d @/etc/iceberg/tenants-acl.yaml
Kết quả mong đợi: API trả về 200 OK. Khi tenant A query table, Iceberg tự động thêm WHERE tenant_id = 'TENANT_A' vào query plan trước khi đọc dữ liệu từ storage.
Cấu hình Column-Level Security (CLS)
Ẩn các cột nhạy cảm như price hoặc customer_id khỏi tenant bình thường, chỉ cho phép Admin thấy.
Cập nhật file ACL để bao gồm danh sách cột được phép xem (visible_columns).
cat > /etc/iceberg/tenants-acl-cls.yaml
Áp dụng cấu hình mới lên Catalog.
curl -X PUT http://iceberg-rest-catalog-service:8080/v1/namespaces/default/tables/sales_data/acl \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $(cat /etc/iceberg/credentials.json | jq -r '.token')" \
-d @/etc/iceberg/tenants-acl-cls.yaml
Verify: Chạy query với role TENANT_A, kết quả trả về không bao gồm cột price và customer_id. Chạy với role ADMIN, tất cả cột đều hiển thị.
Tích hợp Iceberg với Spark và Trino để truy xuất an toàn
Cấu hình Spark với Iceberg Catalog và ACL
Để Spark tuân thủ ACL đã cấu hình, cần thiết lập spark.sql.catalog và iceberg.rest.auth.token trong spark-defaults.conf.
Tạo file /etc/spark/conf/spark-defaults.conf cho tenant worker.
cat > /etc/spark/conf/spark-defaults.conf
Chạy Spark Submit với role tenant cụ thể (thông qua biến môi trường hoặc header HTTP tùy thuộc vào cách REST Catalog map token).
export SPARK_SUBMIT_OPTIONS="--conf spark.sql.catalog.iceberg_catalog.token=$(cat /etc/iceberg/tenant_a_token)"
spark-submit --conf spark.sql.catalog.iceberg_catalog.token=$(cat /etc/iceberg/tenant_a_token) \
--class org.apache.spark.sql.hive.thriftserver.HiveThriftServer2 \
--deploy-mode cluster \
spark-iceberg-connector.jar
Kết quả mong đợi: Khi tenant A truy xuất bảng sales_data, Spark engine tự động áp dụng filter row và mask column dựa trên token JWT gửi đi.
Cấu hình Trino với Iceberg Connector
Trino sử dụng connector riêng để kết nối với Iceberg. Cần cấu hình catalog.iceberg.properties trong /etc/trino/catalog/iceberg.properties.
cat > /etc/trino/catalog/iceberg.properties
Tạo file token cho tenant cụ thể tại /etc/trino/iceberg-token.jwt (nội dung token của tenant đó).
echo "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.TENANT_A_TOKEN" > /etc/trino/iceberg-token.jwt
chown trino:trino /etc/trino/iceberg-token.jwt
chmod 600 /etc/trino/iceberg-token.jwt
Khởi động lại Trino để áp dụng cấu hình.
systemctl restart trino
journalctl -u trino -f | grep "Catalog iceberg loaded"
Verify: Truy cập Trino CLI với user tenant A và chạy query SELECT * FROM iceberg_catalog.sales_data LIMIT 10. Kết quả chỉ hiện các hàng có tenant_id='TENANT_A' và ẩn cột price.
Điều hướng series:
Mục lục: Series: Series: Xây dựng nền tảng Secure Multi-Tenant Data Platform với Kubernetes, Falco, OPA và Apache Iceberg để bảo vệ dữ liệu doanh nghiệp trong môi trường chia sẻ tài nguyên
« Phần 2: Triển khai Kubernetes với cơ chế Namespace và Resource Quota cho Multi-Tenant
Phần 4: Áp dụng OPA Gatekeeper để thực thi chính sách bảo mật và tuân thủ »