Object storage và IAM: nền móng của data lake trên cloud

Xem thử

Nhóm dữ liệu của GDev Mart chuyển dữ liệu thô lên Amazon S3. Tuần đầu mọi thứ tốt đẹp. Rồi một đồng nghiệp tạo bucket gdevmart-data, bật "public" cho tiện chia sẻ với đối tác, và quên tắt. Ba ngày sau, cảnh báo bảo mật báo rằng tệp khách hàng 2 triệu dòng có thể tải về từ internet. Một đồng nghiệp khác thì chạy mọi script bằng khóa truy cập của tài khoản quản trị, nên một script lỗi đã có thể xóa cả bucket.

Hãy dự đoán trước khi đọc tiếp: cần áp dụng nguyên tắc nào để mỗi script, mỗi người, mỗi dịch vụ chỉ được phép làm đúng việc của mình, và làm sao tránh việc dữ liệu vô tình thành công khai? Viết ra ít nhất hai biện pháp.

Sau bài này, bạn có thể

  • Giải thích vì sao object storage có không gian tên phẳng, không có thư mục thật và không rename nguyên tử.
  • Đọc từng khối của một policy IAM quyền tối thiểu và dự đoán yêu cầu nào bị từ chối.
  • Chọn cách chia sẻ dữ liệu cho đối tác mà không công khai bucket (Block Public Access, URL có chữ ký).

Cần biết trước: bài Git trong dự án dữ liệu: nhánh, pull request và những thứ không được commit (vì sao khóa truy cập không được nằm trong mã nguồn) và bài Parquet, caching và đọc Spark UI để tối ưu (định dạng Parquet). Bài này chỉ đọc và phân tích, chưa cần tài khoản AWS; lab cuối chương mới cần AWS CLI.

Mô hình tư duy 1: object storage là một kho khóa-giá trị khổng lồ, không phải ổ đĩa

Object storage (S3 của AWS, Cloud Storage của GCP, Blob Storage của Azure) lưu dữ liệu dưới dạng object: một khối nhị phân kèm siêu dữ liệu, được định danh bởi một khóa (key) duy nhất trong một bucket. Những điều cần hiểu để thiết kế đúng:

  • Không gian tên phẳng: bronze/orders/ingest_date=2026-09-01/part-0001.parquet chỉ là một chuỗi khóa dài; "thư mục" chỉ là ảo giác do dấu / trong khóa. Vì vậy liệt kê "thư mục" thực chất là lọc theo tiền tố.
  • Không có rename nguyên tử: đổi tên một object là sao chép rồi xóa, và đổi tên "thư mục" là thao tác trên từng object. Đây là lý do ghi dữ liệu lên object storage cần cơ chế commit riêng và là động lực của các định dạng bảng mở ở bài sau.
  • Độ bền cực cao, chi phí thấp: S3 hứa độ bền 99,999999999% (11 số chín) và giá lưu trữ rẻ hơn nhiều so với đĩa của máy chủ cơ sở dữ liệu; đổi lại độ trễ mỗi lần truy cập cao hơn ổ đĩa cục bộ, và nó không có truy vấn.
  • Tính nhất quán: từ cuối năm 2020, S3 đọc sau ghi nhất quán mạnh: vừa ghi xong là đọc thấy ngay.
  • Hạng lưu trữ (storage class): dữ liệu hay dùng ở hạng chuẩn; dữ liệu ít truy cập chuyển sang hạng rẻ hơn (Infrequent Access, các hạng Glacier) với giá lưu thấp hơn nhưng phí truy xuất hoặc độ trễ cao hơn; quy tắc lifecycle chuyển tự động theo tuổi.

Đang tải sơ đồ…

Cách đọc hình: bucket chứa nhiều object, mỗi object một khóa dài. Ba tiền tố bronze/, silver/, gold/ là quy ước đặt tên giúp phân tầng và phân quyền, không phải thư mục vật lý.

Mô hình tư duy 2: IAM, quyền tối thiểu theo danh tính

IAM (Identity and Access Management) quyết định ai được làm gì trên tài nguyên nào. Ba khái niệm:

  • User / Role: danh tính. Role là danh tính tạm thời mà dịch vụ (job Glue, máy chủ EC2) hoặc người "mượn" để làm việc, không có mật khẩu lâu dài.
  • Policy: văn bản JSON liệt kê quyền, gồm Effect (Allow/Deny), Action (hành động), Resource (đối tượng áp dụng).
  • Nguyên tắc quyền tối thiểu (least privilege): chỉ cấp những quyền thật sự cần, trên đúng tài nguyên cần.

Đây là chính sách cho role của job Glue chuyển dữ liệu từ bronze sang silver: chỉ đọc bronze và chỉ ghi silver, không đụng gold hay các bucket khác.

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:ListBucket"],
      "Resource": "arn:aws:s3:::gdevmart-lake",
      "Condition": {"StringLike": {"s3:prefix": ["bronze/*", "silver/*"]}}
    },
    {
      "Effect": "Allow",
      "Action": ["s3:GetObject"],
      "Resource": "arn:aws:s3:::gdevmart-lake/bronze/*"
    },
    {
      "Effect": "Allow",
      "Action": ["s3:PutObject", "s3:DeleteObject"],
      "Resource": "arn:aws:s3:::gdevmart-lake/silver/*"
    }
  ]
}

Đọc từng khối: khối đầu cho phép liệt kê bucket nhưng chỉ với tiền tố bronze và silver; khối hai cho đọc object dưới bronze/; khối ba cho ghi và xóa object dưới silver/. Nếu script lỗi cố ghi vào bronze/ hoặc xóa gold/, yêu cầu bị từ chối vì không có quyền, nên phạm vi thiệt hại của một lỗi được giới hạn. Đây mới là phần S3 của policy: role Glue thực tế còn cần quyền ghi log CloudWatch (thường gắn managed policy AWSGlueServiceRole) và có thể cần thêm s3:AbortMultipartUpload trên silver/* khi ghi tệp lớn.

Đang tải sơ đồ…

Cách đọc hình: mỗi hàng là một danh tính (bên trái) và những gì policy của nó cho phép hoặc chặn (bên phải). Analyst chỉ đọc được gold và không thấy dữ liệu thô chứa thông tin khách hàng, đây là cách IAM hỗ trợ phân tầng quyền truy cập theo độ nhạy cảm của dữ liệu.

Đang tải Animation…

Giải đáp câu hỏi đầu bài

  • Quyền tối thiểu: mỗi script, người, dịch vụ dùng role hoặc danh tính riêng với policy hẹp theo tiền tố và hành động; không dùng khóa quản trị cho công việc hằng ngày; không dùng tài khoản gốc (root).
  • Tránh công khai nhầm: bật Block Public Access ở cấp tài khoản để mọi bucket mặc định không công khai; chia sẻ dữ liệu bằng URL có chữ ký, có thời hạn hoặc chính sách theo tài khoản đối tác, không bao giờ mở bucket cho cả thế giới; bật mã hóa (SSE) và versioning cho dữ liệu quan trọng; bật ghi log truy cập để điều tra.

Những hiểu lầm thường gặp

  • "S3 là ổ đĩa trên mạng." Nó là kho object: không rename nguyên tử, không có thư mục thật, độ trễ cao hơn đĩa cục bộ.
  • "Cứ cấp s3:* cho chắc để khỏi lỗi quyền." Đó là cách một script lỗi xóa cả bucket; hãy cấp đúng hành động và tiền tố.
  • "Khóa truy cập lâu dài trong mã nguồn cho tiện." Khóa lọt vào Git (như bài tuần 1) là sự cố; hãy dùng role gắn vào dịch vụ, khóa tạm thời hoặc trình quản lý bí mật.
  • "Bucket private nghĩa là mọi người trong công ty đều đọc được." Quyền truy cập do IAM quyết định; private chỉ nghĩa là không công khai ra internet.

Tự kiểm tra (có đáp án)

Câu 1. Vì sao đổi tên một "thư mục" lớn trên S3 chậm và không nguyên tử? Đáp án: vì "thư mục" chỉ là tiền tố khóa; đổi tên nghĩa là sao chép từng object sang khóa mới rồi xóa khóa cũ, thao tác trên nhiều object riêng lẻ.

Câu 2. Vì sao role của job Glue không nên có s3:* trên toàn bucket? Đáp án: vì khi script lỗi hoặc bị lợi dụng, nó có thể xóa hoặc ghi đè mọi tầng; quyền tối thiểu giới hạn phạm vi thiệt hại ở tiền tố mà job thật sự cần.

Câu 3. Cách chia sẻ một tệp cho đối tác mà không mở bucket công khai là gì? Đáp án: tạo URL có chữ ký với thời hạn ngắn (pre-signed URL) hoặc cấp quyền cho đúng tài khoản/role của đối tác qua chính sách.

Nếu chỉ nhớ 3 điều

  1. S3 là kho object khóa-giá trị: không gian tên phẳng, không rename nguyên tử, rẻ và bền nhưng độ trễ cao hơn đĩa cục bộ.
  2. IAM cấp quyền theo danh tính + hành động + tài nguyên; dùng role và quyền tối thiểu thay cho khóa quản trị.
  3. Bật Block Public Access, mã hóa và versioning; chia sẻ bằng URL có chữ ký có thời hạn thay vì công khai bucket.

Nguồn tham khảo