Kích hoạt chế độ TLS cho giao tiếp nội bộ và Client
Để bảo mật luồng truyền tải dữ liệu giữa các node YugabyteDB và giữa client với server, chúng ta cần cấu hình TLS (Transport Layer Security). YugabyteDB yêu cầu chứng chỉ tự ký (self-signed) hoặc chứng chỉ từ CA đáng tin cậy.
Tạo thư mục chứa chứng chỉ trên máy trạm của bạn để chuẩn bị upload lên Kubernetes:
mkdir -p ~/yugabyte-certs && cd ~/yugabyte-certs
Thư mục `yugabyte-certs` được tạo để lưu trữ file key và cert.
Sử dụng OpenSSL để tạo Private Key và Certificate Signing Request (CSR) cho CA (Certificate Authority):
openssl genrsa -out ca-key.pem 4096
openssl req -x509 -new -nodes -key ca-key.pem -sha256 -days 1024 -out ca-cert.pem -subj "/CN=YugabyteDB-CA"
File `ca-key.pem` là khóa bí mật của CA, `ca-cert.pem` là chứng chỉ gốc dùng để ký các chứng chỉ khác.
Tạo Private Key và CSR cho từng thành phần trong cụm (t-master, t-node, t-tserver):
openssl genrsa -out tmaster-key.pem 2048
openssl req -new -key tmaster-key.pem -out tmaster.csr -subj "/CN=tmaster-0.yb-tmaster.t.yugabyte.svc.cluster.local"
openssl genrsa -out tnode-key.pem 2048
openssl req -new -key tnode-key.pem -out tnode.csr -subj "/CN=t-node-0.yb-tserver.t.yugabyte.svc.cluster.local"
openssl genrsa -out ttserver-key.pem 2048
openssl req -new -key ttserver-key.pem -out ttserver.csr -subj "/CN=t-tserver-0.yb-tserver.t.yugabyte.svc.cluster.local"
Các file `.csr` được tạo với Common Name (CN) khớp với hostname nội bộ của Pod trong Kubernetes để xác thực hostname.
Dùng CA đã tạo để ký cho các CSR và tạo file chứng chỉ hoàn chỉnh (PEM):
openssl x509 -req -in tmaster.csr -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out tmaster-cert.pem -days 1024 -sha256 -extfile
File `.pem` đầu ra chứa chứng chỉ đã ký, bao gồm cả thông tin Subject Alternative Name (SAN) để Kubernetes và YugabyteDB xác thực đúng dịch vụ.
Tạo Kubernetes Secrets từ chứng chỉ
YugabyteDB cần các chứng chỉ này được lưu dưới dạng Kubernetes Secret để Pod có thể mount vào filesystem.
Tạo Secret cho CA (dùng cho tất cả các component để xác thực):
kubectl create secret generic yb-ca-cert --from-file=ca-cert.pem --namespace=yugabyte
Secret `yb-ca-cert` được tạo trong namespace `yugabyte` chứa file `ca-cert.pem`.
Tạo Secret riêng cho từng role (tmaster, tnode, ttserver) chứa cả key và cert tương ứng:
kubectl create secret generic yb-tmaster-cert --from-file=tmaster-key.pem --from-file=tmaster-cert.pem --namespace=yugabyte
kubectl create secret generic yb-tnode-cert --from-file=tnode-key.pem --from-file=tnode-cert.pem --namespace=yugabyte
kubectl create secret generic yb-ttserver-cert --from-file=ttserver-key.pem --from-file=ttserver-cert.pem --namespace=yugabyte
Các secret này chứa cặp khóa bí mật và chứng chỉ công khai cho từng loại node, đảm bảo an toàn khi phân phối.
Verify kết quả TLS
Kiểm tra xem các Secret đã được tạo đúng chưa:
kubectl get secrets -n yugabyte | grep yb-
Đầu ra phải liệt kê các secret: `yb-ca-cert`, `yb-tmaster-cert`, `yb-tnode-cert`, `yb-ttserver-cert`.
Cấu hình xác thực người dùng (Authentication)
Sau khi có TLS, cần bật cơ chế xác thực để đảm bảo chỉ người dùng hợp lệ mới được kết nối. YugabyteDB hỗ trợ xác thực qua Password (SCRAM-SHA-256) hoặc Certificate (Client Cert).
Chỉnh sửa file giá trị Helm (`values.yaml`) để kích hoạt TLS và Authentication. Giả sử bạn đang deploy lại hoặc update cluster:
cat > yb-values-secure.yaml
File `yb-values-secure.yaml` được tạo với cấu hình bật `enableTLS` và `enableAuth` cho tất cả các component, trỏ đến các Secret đã tạo ở phần trước.
Update Helm Release để áp dụng cấu hình mới:
helm upgrade yb yugabyte/yugabyte-db -f yb-values-secure.yaml --namespace yugabyte --wait
Cluster YugabyteDB sẽ khởi động lại các Pod để áp dụng cấu hình TLS và Auth. Quá trình này có thể mất 2-5 phút.
Verify kết quả Authentication
Sử dụng `yugabyte` CLI để kiểm tra xem yêu cầu xác thực đã được bật chưa. Thử kết nối không có thông tin đăng nhập:
yugabyte shell -host tmaster.yb-tmaster.t.yugabyte.svc.cluster.local -port 9042
Kết quả mong đợi: Kết nối bị từ chối với lỗi "Authentication failed" hoặc "Need authentication", chứng tỏ Auth đã được bật.
Thử kết nối với user mặc định `yugabyte` (password mặc định thường là `yugabyte` nếu không đổi):
yugabyte shell -host tmaster.yb-tmaster.t.yugabyte.svc.cluster.local -port 9042 -user yugabyte -password yugabyte
Kết quả mong đợi: Kết nối thành công và hiển thị prompt `yugabyte-shell>`.
Tạo role và cấp quyền (GRANT)
Trong môi trường production, không nên sử dụng user mặc định. Cần tạo user riêng cho ứng dụng và phân quyền theo nguyên tắc Least Privilege.
Kết nối vào cụm YugabyteDB với quyền admin để tạo user mới:
yugabyte shell -host tmaster.yb-tmaster.t.yugabyte.svc.cluster.local -port 9042 -user yugabyte -password yugabyte
Hệ thống mở shell YCQL (Yugabyte Cassandra Query Language).
Tạo user mới `app_user` với mật khẩu mạnh:
CREATE USER app_user WITH PASSWORD 'SuperSecurePassword123!';
User `app_user` được tạo trong hệ thống.
Tạo role (nhóm) `read_only` để gán cho các user chỉ cần quyền đọc:
CREATE ROLE read_only;
Role `read_only` được tạo, chưa có quyền gì.
Cấp quyền đọc (SELECT) cho role `read_only` trên keyspace (database) cụ thể, ví dụ `testdb`:
GRANT SELECT ON KEYSPACE testdb TO read_only;
Role `read_only` giờ có quyền SELECT trên keyspace `testdb`.
Gán role `read_only` cho user `app_user` (nếu muốn user này chỉ đọc):
GRANT read_only TO app_user;
User `app_user` thừa kế quyền của role `read_only`.
Tạo user `admin_app` và cấp quyền toàn bộ (ALL) trên keyspace `testdb`:
CREATE USER admin_app WITH PASSWORD 'AdminSecurePassword456!';
GRANT ALL ON KEYSPACE testdb TO admin_app;
User `admin_app` được tạo và có quyền CRUD đầy đủ trên `testdb`.
Thoát khỏi shell YCQL:
exit;
Thoát khỏi phiên kết nối YCQL.
Verify kết quả GRANT
Thử kết nối bằng user `app_user` và thực hiện lệnh INSERT (dự kiến sẽ bị lỗi):
yugabyte shell -host tmaster.yb-tmaster.t.yugabyte.svc.cluster.local -port 9042 -user app_user -password 'SuperSecurePassword123!'
CREATE TABLE testdb.permission_test (id int PRIMARY KEY);
Kết quả mong đợi: Lỗi "Unauthorized operation" hoặc "Permission denied" vì `app_user` chỉ có quyền SELECT.
Thử kết nối bằng user `admin_app` và thực hiện lệnh INSERT:
yugabyte shell -host tmaster.yb-tmaster.t.yugabyte.svc.cluster.local -port 9042 -user admin_app -password 'AdminSecurePassword456!'
CREATE TABLE testdb.permission_test (id int PRIMARY KEY);
Kết quả mong đợi: Lệnh thực thi thành công, bảng được tạo.
Cấu hình Firewall và Network Policy
Trong Kubernetes, Firewall được thực hiện thông qua Network Policy để kiểm soát lưu lượng vào/ra các Pod, ngăn chặn truy cập trái phép từ bên ngoài hoặc từ các Pod không liên quan.
Đảm bảo Cluster của bạn đã có CNI (Container Network Interface) hỗ trợ Network Policy (như Calico, Cilium, hoặc Weave Net). Kiểm tra:
kubectl get networkpolicy -n yugabyte
Đầu ra có thể là danh sách trống nếu chưa cấu hình, hoặc danh sách các policy hiện có.
Tạo Network Policy chỉ cho phép lưu lượng từ namespace `app` (nơi chứa ứng dụng của bạn) truy cập vào các Pod YugabyteDB trên cổng 9042 (YCQL) và 9043 (YSQL):
cat > yb-network-policy.yaml
File `yb-network-policy.yaml` định nghĩa policy chỉ cho phép traffic từ namespace `app` và pod có label `app: my-app` vào YugabyteDB trên cổng 9042 và 9043.
Áp dụng Network Policy vào cluster:
kubectl apply -f yb-network-policy.yaml
Policy được áp dụng thành công, kube-proxy hoặc CNI sẽ bắt đầu lọc gói tin.
Để cho phép truy cập từ Pod khác trong cùng namespace `yugabyte` (ví dụ để backup hoặc monitoring nội bộ), cần thêm rule:
cat > yb-network-policy-internal.yaml
File `yb-network-policy-internal.yaml` cho phép giao tiếp nội bộ giữa các node YugabyteDB để duy trì tính nhất quán của cluster.
Áp dụng policy nội bộ:
kubectl apply -f yb-network-policy-internal.yaml
Cluster YugabyteDB vẫn hoạt động bình thường vì lưu lượng nội bộ được phép đi qua.
Verify kết quả Network Policy
Thử truy cập từ một Pod không nằm trong namespace `app` (ví dụ từ Pod `busybox` trong namespace `default`):
kubectl run -it --rm --restart=Never test-client --image=busybox --namespace=default -- /bin/sh -c "wget -q -O - tmaster.yb-tmaster.t.yugabyte.svc.cluster.local:9042 || echo 'Connection refused'"
Kết quả mong đợi: Kết nối bị từ chối hoặc timeout, chứng tỏ Network Policy đã chặn truy cập trái phép.
Thử truy cập từ Pod trong namespace `app` (giả sử bạn đã deploy Pod `my-app` vào đó):
kubectl exec -it -n app my-app -- wget -q -O - tmaster.yb-tmaster.t.yugabyte.svc.cluster.local:9042
Kết quả mong đợi: Kết nối thành công (hoặc ít nhất là nhận được phản hồi từ server), chứng tỏ policy cho phép đúng đối tượng.
Quản lý Secret và Certificate trong Kubernetes
Certificate có thời hạn (validity period). Cần có quy trình xoay vòng (rotation) chứng định và quản lý Secret để đảm bảo an toàn lâu dài.
Để đổi mật khẩu cho user đã tạo mà không cần restart cluster, sử dụng lệnh YCQL:
yugabyte shell -host tmaster.yb-tmaster.t.yugabyte.svc.cluster.local -port 9042 -user admin_app -password 'AdminSecurePassword456!'
ALTER USER admin_app WITH PASSWORD 'NewSuperSecurePassword789!';
exit;
Mật khẩu của `admin_app` đã được cập nhật ngay lập tức trong metadata store.
Để cập nhật Secret chứa Certificate mới (ví dụ khi cert hết hạn), cần tạo Secret mới với cùng tên hoặc cập nhật Secret cũ:
kubectl create secret generic yb-ttserver-cert --from-file=ttserver-key.pem --from-file=ttserver-cert.pem --namespace=yugabyte --dry-run=client -o yaml > new-cert.yaml
kubectl apply -f new-cert.yaml
Lệnh này tạo manifest YAML cho Secret mới và áp dụng vào cluster, cập nhật nội dung của Secret hiện có.
Để kích hoạt việc mount chứng chỉ mới vào Pod, cần restart Pod đó (tuy nhiên Helm thường tự động phát hiện thay đổi của Secret nếu cấu hình `restartPolicy` hoặc `volumeMounts` đúng cách, nhưng an toàn nhất là restart pod):
kubectl delete pod -n yugabyte -l app=t-tserver
Pod `t-tserver` sẽ bị xóa và Kubernetes sẽ tạo Pod mới, mount chứng chỉ mới từ Secret đã cập nhật.
Verify kết quả quản lý Secret
Kiểm tra thời gian tạo/lần cập nhật của Secret:
kubectl get secret yb-ttserver-cert -n yugabyte -o jsonpath='{.metadata.resourceVersion}'
ResourceVersion tăng lên sau khi bạn chạy lệnh `kubectl apply`, chứng tỏ Secret đã được cập nhật.
Kiểm tra xem Pod mới đã mount chứng chỉ mới chưa bằng cách exec vào Pod và kiểm tra thời gian file:
kubectl exec -it -n yugabyte -- ls -la /var/yugabyte/certs/
File cert và key trong thư mục `/var/yugabyte/certs/` phải có thời gian tạo mới hơn thời điểm bạn cập nhật Secret.
Điều hướng series:
Mục lục: Series: Xây dựng hệ thống Database phân tán với YugabyteDB và Kubernetes
« Phần 2: Triển khai cụm YugabyteDB trên Kubernetes bằng Helm
Phần 4: Kết nối ứng dụng và thực thi truy vấn YSQL/YCQL »