Skip to content

Thiết kế Cluster

Cluster Staging (3 node)

Cluster tối thiểu dành cho kiểm thử nội bộ, demo, và kiểm thử tích hợp.

Node PoolSố lượngCấu hìnhTaintWorkload
default24 vCPU, 8 GBnginx-ingress, Traefik, backend, frontend, cert-manager, monitoring
stateful18 vCPU, 16 GBPostgreSQL, Redis, Kafka ×3, Typesense

Staging giữ mọi thứ đơn giản — không có node riêng cho system hay monitoring. Mọi thứ ngoại trừ dữ liệu chạy trên node default. Tất cả dịch vụ dữ liệu (bao gồm 3 Kafka broker) chạy chung trên một node stateful duy nhất với bộ nhớ tăng cường. Triển khai thủ công qua kubectl apply -k.

Cluster Production (7+ node)

Cluster cấp production toàn diện với node pool riêng biệt, HA, autoscaling, và observability đầy đủ.

Node PoolSố lượngCấu hìnhTaintWorkload
system22 vCPU, 4 GBdedicated=system:NoSchedulenginx-ingress (HA), cert-manager, Sealed Secrets controller
app3+4 vCPU, 8 GBTraefik, backend service, frontend app
stateful28 vCPU, 16 GBPostgreSQL, Redis, Kafka, Typesense
monitoring14 vCPU, 8 GBdedicated=monitoring:NoSchedulePrometheus, Grafana, Loki, Tempo, OTel, Promtail

Tại sao cần Node Pool Riêng biệt (Production)

  • Node system (có taint): Ingress và cert-manager không bao giờ bị đẩy ra bởi workload ứng dụng. Taint đảm bảo chỉ pod system được lên lịch tại đây.
  • Node monitoring (có taint): Stack observability tiêu tốn nhiều tài nguyên. Cô lập nó ngăn monitoring chiếm tài nguyên của ứng dụng (và ngược lại).
  • Node app (có thể autoscale): Cluster autoscaler có thể thêm app-4, app-5, v.v. khi lưu lượng tăng đột biến. Không rủi ro mở rộng node chứa dữ liệu stateful.
  • Node stateful: Dành riêng cho dịch vụ dữ liệu. Pod anti-affinity phân tán Kafka broker trên cả hai node để đảm bảo chịu lỗi.

Label & Taint của Node

System nodes
yaml
# System nodes
node.kubernetes.io/pool: system
taint: dedicated=system:NoSchedule

# App nodes
node.kubernetes.io/pool: app

# Stateful nodes
node.kubernetes.io/pool: stateful

# Monitoring node
node.kubernetes.io/pool: monitoring
taint: dedicated=monitoring:NoSchedule

Phân bổ Node Stateful

Staging — một node duy nhất, tất cả dữ liệu chạy chung:

Production — phân tán trên 2 node để đảm bảo chịu lỗi:

Chiến lược Namespace

Cả hai cluster sử dụng cùng 7 namespace:

NamespaceMục đíchNội dung
nx-internalHạ tầngnginx-ingress, Traefik (API gateway), cert-manager, API Portal
nx-backendWorkload backendTất cả backend service
nx-appWorkload frontendFrontend nginx pod (client, bo, overture, sale-renderer, wiki)
nx-persistentCơ sở dữ liệuPostgreSQL primary + replica, PgBouncer
nx-brokerMessage broker & cacheRedis Cluster, Kafka KRaft
nx-searchTìm kiếm & CDCTypesense, Debezium
nx-watcherStack observability(chưa triển khai)

YAML Namespace

Namespace: nx-internal
yaml
apiVersion: v1
kind: Namespace
metadata:
  name: nx-internal
  labels:
    app.kubernetes.io/part-of: bana
---
apiVersion: v1
kind: Namespace
metadata:
  name: nx-backend
  labels:
    app.kubernetes.io/part-of: bana
---
apiVersion: v1
kind: Namespace
metadata:
  name: nx-app
  labels:
    app.kubernetes.io/part-of: bana
---
apiVersion: v1
kind: Namespace
metadata:
  name: nx-persistent
  labels:
    app.kubernetes.io/part-of: bana
---
apiVersion: v1
kind: Namespace
metadata:
  name: nx-broker
  labels:
    app.kubernetes.io/part-of: bana
---
apiVersion: v1
kind: Namespace
metadata:
  name: nx-search
  labels:
    app.kubernetes.io/part-of: bana
---
apiVersion: v1
kind: Namespace
metadata:
  name: nx-watcher
  labels:
    app.kubernetes.io/part-of: bana

Phân bổ Tài nguyên

Workload Ứng dụng (node default/app)

WorkloadBản sao (staging)Bản sao (prod)CPU yêu cầuCPU giới hạnMem yêu cầuMem giới hạn
traefik12100m1128Mi512Mi
identity12200m2256Mi1Gi
commerce11200m2256Mi1Gi
sale12200m2256Mi1Gi
finance11200m2256Mi1Gi
inventory11200m2256Mi1Gi
ledger11200m2384Mi1Gi
pricing11200m2320Mi1Gi
payment-api12200m2256Mi1Gi
payment-worker11100m1256Mi1Gi
signal12100m1256Mi512Mi
client1150m500m64Mi256Mi
bo1150m500m64Mi256Mi
overture1150m500m64Mi256Mi
sale-renderer1150m500m64Mi256Mi
wiki1150m500m64Mi256Mi

Workload Dữ liệu (node stateful)

md
| Workload | Số lượng | CPU yêu cầu | Mem yêu cầu | Lưu trữ |
|----------|-----------|---------|---------|---------|
| PG Primary | 1 | 500m | 1Gi | 20Gi |
| PG Replica | 1 | 250m | 512Mi | 20Gi |
| PgBouncer | 1 | 100m | 256Mi | - |
| Redis | 3 | 300m | 1.125Gi | 15Gi |
| Kafka | 3 | 1.5 CPU | 3.75Gi | 30Gi |
| Typesense | 1 | 200m | 512Mi | 5Gi |
| Debezium | 1 | 250m | 512Mi | - |
md
| Workload | Số lượng | CPU yêu cầu | Mem yêu cầu | Lưu trữ |
|----------|-----------|---------|---------|---------|
| PostgreSQL (CNPG) | 3 (1 primary + 2 replica) | 1.5 CPU | 3Gi | 60Gi + 15Gi WAL |
| Redis + Sentinel | 3 + 3 | 750m | 1.7Gi | 15Gi |
| Kafka (Strimzi) | 3 | 1.5 CPU | 3.75Gi | 30Gi |
| Typesense (raft) | 3 | 600m | 1.5Gi | 15Gi |

Xem Tầng Dữ liệu để biết chi tiết cấu hình operator, cơ chế failover, và chiến lược backup.

Phân bổ Lưu trữ

PVCStagingProduction
pg-data20Gi (×1)20Gi (×3) + 5Gi WAL (×3)
redis-data5Gi (×1)5Gi (×3)
kafka-data10Gi (×3)10Gi (×3)
typesense-data5Gi (×1)5Gi (×3)
prometheus-data10Gi10Gi
grafana-data5Gi5Gi
loki-data5Gi5Gi
tempo-data10Gi
Tổng cộng80Gi170Gi

Quản trị Tài nguyên

ResourceQuota

Mỗi namespace có ResourceQuota để ngăn workload vượt kiểm soát tiêu thụ hết tài nguyên cluster.

nx-backend — namespace lớn nhất (tất cả dịch vụ backend)
yaml
# nx-backend — namespace lớn nhất (tất cả dịch vụ backend)
apiVersion: v1
kind: ResourceQuota
metadata:
  name: nx-backend-quota
  namespace: nx-backend
spec:
  hard:
    requests.cpu: "12"
    requests.memory: 16Gi
    limits.cpu: "24"
    limits.memory: 32Gi
    pods: "30"
---
# nx-app — ứng dụng frontend (pod nginx nhẹ)
apiVersion: v1
kind: ResourceQuota
metadata:
  name: nx-app-quota
  namespace: nx-app
spec:
  hard:
    requests.cpu: "2"
    requests.memory: 4Gi
    limits.cpu: "4"
    limits.memory: 8Gi
    pods: "12"
---
# nx-persistent — PostgreSQL + PgBouncer
apiVersion: v1
kind: ResourceQuota
metadata:
  name: nx-persistent-quota
  namespace: nx-persistent
spec:
  hard:
    requests.cpu: "4"
    requests.memory: 8Gi
    limits.cpu: "8"
    limits.memory: 16Gi
    pods: "8"
    persistentvolumeclaims: "10"
---
# nx-broker — Redis + Kafka
apiVersion: v1
kind: ResourceQuota
metadata:
  name: nx-broker-quota
  namespace: nx-broker
spec:
  hard:
    requests.cpu: "4"
    requests.memory: 8Gi
    limits.cpu: "8"
    limits.memory: 12Gi
    pods: "12"
    persistentvolumeclaims: "12"
---
# nx-search — Typesense + Debezium
apiVersion: v1
kind: ResourceQuota
metadata:
  name: nx-search-quota
  namespace: nx-search
spec:
  hard:
    requests.cpu: "1"
    requests.memory: 2Gi
    limits.cpu: "2"
    limits.memory: 4Gi
    pods: "4"
---
# nx-internal — nginx-ingress, Traefik, cert-manager, API Portal
apiVersion: v1
kind: ResourceQuota
metadata:
  name: nx-internal-quota
  namespace: nx-internal
spec:
  hard:
    requests.cpu: "2"
    requests.memory: 4Gi
    limits.cpu: "4"
    limits.memory: 8Gi
    pods: "6"
---
# nx-watcher — stack observability (chưa triển khai)
apiVersion: v1
kind: ResourceQuota
metadata:
  name: nx-watcher-quota
  namespace: nx-watcher
spec:
  hard:
    requests.cpu: "2"
    requests.memory: 4Gi
    limits.cpu: "4"
    limits.memory: 8Gi
    pods: "8"

LimitRange

LimitRange đặt request/limit mặc định cho container không khai báo, và áp dụng giới hạn min/max.

Mặc định cho nx-backend
yaml
# Mặc định cho nx-backend
apiVersion: v1
kind: LimitRange
metadata:
  name: nx-backend-limits
  namespace: nx-backend
spec:
  limits:
    - type: Container
      default:
        cpu: 500m
        memory: 512Mi
      defaultRequest:
        cpu: 100m
        memory: 128Mi
      min:
        cpu: 50m
        memory: 64Mi
      max:
        cpu: "2"
        memory: 2Gi
---
# Mặc định cho nx-app (giới hạn nhẹ hơn cho frontend nginx)
apiVersion: v1
kind: LimitRange
metadata:
  name: nx-app-limits
  namespace: nx-app
spec:
  limits:
    - type: Container
      default:
        cpu: 200m
        memory: 256Mi
      defaultRequest:
        cpu: 50m
        memory: 64Mi
      min:
        cpu: 25m
        memory: 32Mi
      max:
        cpu: "1"
        memory: 1Gi
---
# Mặc định cho nx-broker
apiVersion: v1
kind: LimitRange
metadata:
  name: nx-broker-limits
  namespace: nx-broker
spec:
  limits:
    - type: Container
      default:
        cpu: 500m
        memory: 768Mi
      defaultRequest:
        cpu: 200m
        memory: 256Mi
      min:
        cpu: 100m
        memory: 128Mi
      max:
        cpu: "2"
        memory: 2Gi
---
# Mặc định cho nx-persistent
apiVersion: v1
kind: LimitRange
metadata:
  name: nx-persistent-limits
  namespace: nx-persistent
spec:
  limits:
    - type: Container
      default:
        cpu: 500m
        memory: 1Gi
      defaultRequest:
        cpu: 250m
        memory: 512Mi
      min:
        cpu: 100m
        memory: 256Mi
      max:
        cpu: "2"
        memory: 4Gi
---
# Mặc định cho nx-search
apiVersion: v1
kind: LimitRange
metadata:
  name: nx-search-limits
  namespace: nx-search
spec:
  limits:
    - type: Container
      default:
        cpu: 200m
        memory: 512Mi
      defaultRequest:
        cpu: 100m
        memory: 256Mi
      min:
        cpu: 50m
        memory: 128Mi
      max:
        cpu: "1"
        memory: 2Gi
---
# Mặc định cho nx-internal
apiVersion: v1
kind: LimitRange
metadata:
  name: nx-internal-limits
  namespace: nx-internal
spec:
  limits:
    - type: Container
      default:
        cpu: 500m
        memory: 512Mi
      defaultRequest:
        cpu: 100m
        memory: 128Mi
      min:
        cpu: 50m
        memory: 64Mi
      max:
        cpu: "2"
        memory: 2Gi
---
# Mặc định cho nx-watcher
apiVersion: v1
kind: LimitRange
metadata:
  name: nx-watcher-limits
  namespace: nx-watcher
spec:
  limits:
    - type: Container
      default:
        cpu: 200m
        memory: 256Mi
      defaultRequest:
        cpu: 50m
        memory: 64Mi
      min:
        cpu: 25m
        memory: 32Mi
      max:
        cpu: "1"
        memory: 1Gi

TIP

LimitRange áp dụng cho pod không khai báo tài nguyên rõ ràng. Tất cả workload BANA đều khai báo tài nguyên, nên LimitRange đóng vai trò mạng lưới an toàn cho pod debug hoặc job ad-hoc.

Cấu trúc Thư mục Manifest

Triển khai thực tế sử dụng các thư mục manifest được đánh số, áp dụng tuần tự bằng kubectl apply -f, không dùng Kustomize overlay.

infrastructure/deployments/staging/
├── 00-cluster-setup/        # Namespace, ResourceQuota, LimitRange
├── 01-network-policies/     # NetworkPolicy cho từng namespace
├── 02-persistent/           # PostgreSQL, PgBouncer StatefulSet & Service
├── 03-broker/               # Redis Cluster, Kafka KRaft StatefulSet
├── 04-search/               # Typesense, Debezium
├── 05-internal/             # nginx-ingress, Traefik, cert-manager, API Portal
├── 06-backend/              # Tất cả backend service Deployment & Service
├── 07-app/                  # Frontend nginx Deployment (client, bo, overture, v.v.)
├── 08-watcher/              # Stack observability (chưa triển khai)
├── 09-jobs/                 # Job chạy một lần (DDL migration, seed, Kafka topic init)
└── kc                       # Script wrapper kubectl (thiết lập kubeconfig)

Triển khai

bash
# Áp dụng tất cả manifest theo thứ tự
for dir in 00-* 01-* 02-* 03-* 04-* 05-* 06-* 07-*; do
  ./kc apply -f "$dir/"
done

Production (dự kiến)

  • Áp dụng taint cho system + monitoring
  • nginx-ingress HA (2 bản sao trên node system)
  • Traefik HA (2 bản sao trên node app)
  • HPA cho các dịch vụ quan trọng (identity, sale, payment-api, signal)
  • PodDisruptionBudget (minAvailable: 1 cho các dịch vụ HA)
  • topologySpreadConstraints + podAntiAffinity
  • Triển khai qua pipeline GitLab CI/CD

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.