Triển khai PostgreSQL StatefulSet với Persistent Volume
Chúng ta sẽ khởi tạo một instance PostgreSQL sử dụng StatefulSet để đảm bảo tính ổn định và lưu trữ dữ liệu lâu dài trên Kubernetes.
Bước này tạo ra một pod database có tên cố định, IP ổn định và gắn kết với Persistent Volume Claim (PVC) để dữ liệu không mất khi pod bị restart.
Tạo file cấu hình StatefulSet và Service tại đường dẫn: /root/database-mesh/postgres-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres-db
namespace: default
labels:
app: postgres
spec:
serviceName: postgres-db
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
istio-injection: disabled
spec:
containers:
- name: postgres
image: postgres:15-alpine
ports:
- containerPort: 5432
name: postgres
env:
- name: POSTGRES_USER
value: "db_user"
- name: POSTGRES_PASSWORD
value: "secure_password_123"
- name: POSTGRES_DB
value: "mesh_db"
volumeMounts:
- name: postgres-storage
mountPath: /var/lib/postgresql/data
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- postgres
topologyKey: kubernetes.io/hostname
volumeClaimTemplates:
- metadata:
name: postgres-storage
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
---
apiVersion: v1
kind: Service
metadata:
name: postgres-db
namespace: default
labels:
app: postgres
spec:
ports:
- port: 5432
targetPort: 5432
name: postgres
selector:
app: postgres
type: ClusterIP
Áp dụng cấu hình vừa tạo để khởi động PostgreSQL trong cluster.
kubectl apply -f /root/database-mesh/postgres-statefulset.yaml
Verify kết quả bằng cách kiểm tra trạng thái của Pod và PVC. Pod phải ở trạng thái "Running" và PVC ở trạng thái "Bound".
kubectl get pods -l app=postgres
kubectl get pvc -l app=postgres
Cấu hình Service Account và Network Policy cho Database
Để chuẩn bị cho mTLS trong tương lai, chúng ta cần tạo Service Account riêng và gắn nhãn cho Service để Istio có thể nhận diện traffic vào database.
Tạo Service Account giúp quản lý quyền truy cập và xác thực (authentication) khi các ứng dụng khác gọi đến database qua sidecar proxy.
Tạo file cấu hình Service Account tại đường dẫn: /root/database-mesh/postgres-sa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: postgres-sa
namespace: default
labels:
app: postgres
---
apiVersion: networking.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: postgres-mtls
namespace: default
spec:
selector:
matchLabels:
app: postgres
mtls:
mode: STRICT
Áp dụng Service Account và PeerAuthentication để bật chế độ mTLS bắt buộc (STRICT) cho database.
kubectl apply -f /root/database-mesh/postgres-sa.yaml
Verify bằng cách kiểm tra PeerAuthentication resource đã được tạo thành công.
kubectl get peerauthentication postgres-mtls -o yaml
Triển khai Envoy Proxy cho Database (Sidecar Pattern)
Trong môi trường Database Mesh, chúng ta không chạy Envoy như một service độc lập mà sử dụng cơ chế Sidecar Injection của Istio để bảo vệ traffic vào Database.
Vì PostgreSQL thường không hỗ trợ native mTLS, việc inject Envoy Proxy vào pod Database là bắt buộc để proxy xử lý handshake TLS trước khi forward sang port 5432.
Chúng ta cần đánh nhãn (label) `istio-injection: enabled` vào StatefulSet của PostgreSQL. Lưu ý: Cần restart pod để injection.
Cập nhật file StatefulSet đã tạo ở phần 1. Thay đổi label trong metadata của template spec từ `disabled` sang `enabled`.
kubectl edit statefulset postgres-db
Trong trình soạn thảo, tìm dòng `istio-injection: disabled` và đổi thành `istio-injection: enabled`. Lưu lại và thoát.
Hoặc dùng lệnh trực tiếp để patch label mà không cần edit file:
kubectl patch statefulset postgres-db -p '{"spec":{"template":{"metadata":{"labels":{"istio-injection":"enabled"}}}}}'
Verify bằng cách kiểm tra số lượng containers trong pod. Pod PostgreSQL giờ sẽ có 2 container: 1 container PostgreSQL và 1 container Envoy Proxy (thường có tên `istio-proxy` hoặc `envoy`).
kubectl get pods -l app=postgres
kubectl describe pod | grep -A 20 "Containers:"
Cấu hình mTLS giữa Ứng dụng và Database
Bước cuối cùng là thiết lập cấu hình để ứng dụng (Client) có thể kết nối mTLS tới Database qua Envoy Proxy.
Vì chúng ta đã bật `mode: STRICT` cho database, mọi kết nối không có mTLS sẽ bị từ chối. Cần đảm bảo Service Mesh của Istio đã được cấu hình đúng để tự động tạo chứng chỉ cho các service.
Tạo file VirtualService để định tuyến traffic từ ứng dụng vào database qua Envoy proxy. Đây là bước quan trọng để xác định cách traffic đi vào port 5432.
Tạo file cấu hình VirtualService tại đường dẫn: /root/database-mesh/postgres-virtualservice.yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: postgres-vs
namespace: default
spec:
hosts:
- postgres-db
- postgres-db.default.svc.cluster.local
gateways:
- mesh
http:
- match:
- port: 5432
route:
- destination:
host: postgres-db
port:
number: 5432
Áp dụng VirtualService để kích hoạt định tuyến qua Envoy Proxy.
kubectl apply -f /root/database-mesh/postgres-virtualservice.yaml
Verify kết quả bằng cách kiểm tra trạng thái của VirtualService và đảm bảo không có lỗi cấu hình.
kubectl get virtualservice postgres-vs
kubectl get peerauthentication postgres-mtls
Để test kết nối mTLS thực tế, bạn có thể chạy một pod client tạm thời có sidecar istio injection và cố gắng kết nối đến postgres-db qua port 5432.
kubectl run -i --tty --rm test-client --image=busybox:1.36 --restart=Never --env ISTIO_INJECTION=enabled -- bash
echo "Thử kết nối TCP (sẽ fail nếu không có mTLS đúng cách, nhưng với STRICT mode, Envoy sẽ handshake trước):"
nc -vz postgres-db 5432
exit
Điều hướng series:
Mục lục: Series: Triển khai Database Mesh với Envoy và Istio trên Ubuntu 24.04
« Phần 3: Cài đặt Istio Service Mesh bằng Helm trên Kubernetes
Phần 5: Cấu hình Policy và Traffic Management cho Database »