Skip to main content

Command Palette

Search for a command to run...

Những lưu ý khi đưa MongoDB lên K8s

Updated
43 min read

Warning: Bài viết này dành cho SRE, DBA và Platform Engineer đã có kinh nghiệm vận hành Kubernetes và MongoDB. Nội dung nặng về kỹ thuật, tập trung vào các vấn đề khi tự host MongoDB trên K8s để tận dụng khả năng tự phục hồi, mở rộng và chuẩn hóa vận hành của nền tảng này. Nếu tổ chức chưa sẵn sàng về năng lực vận hành hoặc muốn giảm gánh nặng hạ tầng, MongoDB Atlas (DBaaS) có thể là lựa chọn phù hợp hơn.


tl;dv:
Bài viết tổng hợp những lưu ý kỹ thuật khi đưa MongoDB lên Kubernetes, bao gồm: đánh giá mức độ sẵn sàng của tổ chức, lựa chọn Operator, thiết kế storage layer cho WiredTiger, cấu hình kernel và tài nguyên Pod, xây dựng quy trình backup cho sharded cluster, bảo mật TLS/secret, thiết lập observability, và migration với minimal downtime.

Nhờ khả năng mở rộng mạnh mẽ, mức độ tự động hóa cao và đặc biệt là giúp tổ chức phá vỡ rào cản vendor lock-in, Kubernetes đã biến container trở thành tiêu chuẩn workload được ưu tiên hàng đầu. Nền tảng này linh hoạt đến mức bạn gần như có thể triển khai mọi thứ lên đó, miễn là có một Operator phù hợp.

Trong bối cảnh đó, việc dịch chuyển cơ sở dữ liệu từ máy chủ vật lý truyền thống sang Kubernetes đánh dấu một bước ngoặt lớn trong tư duy quản trị hệ thống. Tuy nhiên, MongoDB - một hệ quản trị cơ sở dữ liệu NoSQL phân tán và có trạng thái (stateful) - lại đặt ra những thách thức kỹ thuật phức tạp hơn hẳn so với các ứng dụng không trạng thái (stateless) thông thường. Sự thành công của quá trình chuyển dịch này không chỉ dừng lại ở việc đóng gói ứng dụng (containerization). Nó đòi hỏi đội ngũ vận hành phải trang bị một sự am hiểu sâu sắc về cách thức tương tác giữa ba lớp cốt lõi: ứng dụng, hệ điều hành container và hạ tầng lưu trữ vật lý.

Ảnh: Generate by Google Gemini

1. Khi nào có thể xem xét đưa MongoDB lên K8s?

Quyết định đưa MongoDB lên Kubernetes không thể đơn thuần là để chạy theo xu hướng công nghệ thuần túy, mà phải dựa trên sự cân nhắc kỹ lưỡng về năng lực vận hành và yêu cầu kinh doanh. Kubernetes mang lại khả năng tự phục hồi và mở rộng mạnh mẽ, nhưng cũng làm tăng đáng kể mức độ phức tạp trong việc quản lý I/O và tính nhất quán của dữ liệu.

1.1. Checklist đánh giá mức độ sẵn sàng vận hành

Trước khi triển khai, các tổ chức cần thực hiện đánh giá dựa trên các tiêu chí kỹ thuật để đảm bảo hệ thống có thể duy trì trong môi trường production. Tùy vào đặc điểm nghiệp vụ của mỗi tổ chức, có thể có các tiêu chí khác nhau, tuy nhiên bảng sau có thể sử dụng như một checklist gợi ý để đánh giá mức độ phù hợp cho giải pháp host MongoDB trên K8s:

Tiêu chí đánh giá Yêu cầu kỹ thuật Hệ quả nếu thiếu hụt
Năng lực SRE/DBA Có hiểu biết rõ ràng về CSI drivers, K8s networking và MongoDB internals components. Khó khăn khi xử lý split-brain hoặc PVC bị kẹt.
Hạ tầng lưu trữ Hỗ trợ volume expansion và có độ trễ I/O thấp (NVMe/SSD). Hiệu suất ghi giảm, gây nghẽn cổ chai toàn hệ thống.
Yêu cầu RPO/RTO Khả năng khôi phục tại một thời điểm cụ thể (PITR). Mất dữ liệu quan trọng khi xảy ra lỗi logic.
Mức độ tự động hóa Áp dụng GitOps và CI/CD cho hạ tầng dữ liệu. Sai lệch cấu hình giữa các môi trường (configuration drift).

Việc tự host MongoDB trên Kubernetes yêu cầu đội ngũ vận hành của tổ chức phải làm chủ hoàn toàn các quy trình day 2 operations như nâng cấp version (cần zero downtime), mở rộng shard và thực hiện backup định kỳ mà không ảnh hưởng đến hiệu suất. Nếu như ưu tiên tính tối giản và muốn giảm bớt gánh nặng vận hành hạ tầng, MongoDB Atlas (DBaaS) là một lựa chọn đáng xem xét hơn, ngay cả khi vẫn sử dụng Kubernetes, thông qua Atlas Kubernetes Operator để quản lý tài nguyên theo cách declarative.

Tham chiếu: MongoDB Atlas Kubernetes Operator - https://www.mongodb.com/docs/atlas/atlas-operator/

1.2. Phân tích các mô hình triển khai phổ biến

Tùy thuộc vào nhu cầu về tính năng (backup/PITR, quản trị tập trung, bảo mật) và ngân sách, có một số hướng triển khai MongoDB trên Kubernetes. Dưới đây là hai lựa chọn phổ biến:

1.2.1. MongoDB Controllers for Kubernetes (MCK) (https://github.com/mongodb/mongodb-kubernetes)

MongoDB Controllers for Kubernetes (MCK) là operator do MongoDB phát triển, thuộc nhóm giải pháp chính thức để triển khai và vận hành MongoDB trên Kubernetes (thay thế các operator MongoDB trước đó). MCK có thể được sử dụng để vận hành các triển khai MongoDB theo nhu cầu của tổ chức và có thể kết hợp với các thành phần quản trị trong hệ sinh thái MongoDB như Ops Manager hoặc Cloud Manager, tùy mô hình triển khai.

Lưu ý về giấy phép (dual-license)

MCK được công bố theo mô hình dual-license, cần hiểu theo đúng nghĩa hai lớp điều khoản:

  • Apache 2.0: áp dụng cho mã nguồn/operator trong repository.

  • LICENSE-MCK / MongoDB Customer Agreement: quy định điều kiện sử dụng phần mềm trong các bối cảnh như evaluation/development hoặc khi bạn có Subscription phù hợp để quản lý các cluster thuộc phạm vi subscription (đặc biệt khi liên quan các sản phẩm/tính năng thương mại).

Vì vậy, trước khi dùng MCK cho production, cần kiểm tra kĩ thông tin về license của MCK và MongoDB Customer Agreement để xác định phạm vi sử dụng hợp lệ.

Tham chiếu:

  1. MongoDB Controllers for Kubernetes - https://github.com/mongodb/mongodb-kubernetes

  2. MCK License File - https://github.com/mongodb/mongodb-kubernetes/blob/master/LICENSE-MCK

  3. MCK Documentation - https://www.mongodb.com/docs/kubernetes/current/

1.2.2. Percona Operator for MongoDB

Percona Operator for MongoDB là một lựa chọn phổ biến trong hệ sinh thái open-source để tự động hóa vận hành MongoDB/Percona Server for MongoDB trên Kubernetes, bao gồm cả các topology như sharded cluster. Operator này sử dụng Percona Backup for MongoDB (PBM) để thực hiện backup/restore và hỗ trợ Point-in-Time Recovery (PITR) theo cấu hình. Ngoài ra, operator cũng hỗ trợ cấu hình các cơ chế HA/scheduling (ví dụ PodDisruptionBudget, anti-affinity, topology spread) thông qua Custom Resource để chuẩn hóa triển khai cho môi trường production.

Tham chiếu: Percona Operator for MongoDB - https://docs.percona.com/percona-operator-for-mongodb/

1.3 So sánh MCK và Percona Operator for MongoDB

Ghi chú: MCK (MongoDB Controllers for Kubernetes) là operator thế hệ mới, thay thế cả MongoDB Enterprise Kubernetes Operator và Community Operator trước đó. Các tài liệu tham chiếu operator cũ (v1.31 trở về trước) có thể không còn phản ánh đúng kiến trúc hiện tại của MCK.

Tiêu chí MCK Percona Operator
Nhà phát triển MongoDB Inc. (chính hãng) Percona (open-source)
Giấy phép Dual-license (Apache 2.0 + LICENSE-MCK), cần xác nhận phạm vi sử dụng production Apache 2.0
Topology hỗ trợ ReplicaSet, Sharded Cluster ReplicaSet, Sharded Cluster
Backup / PITR Backup chuẩn và PITR dựa vào Ops Manager hoặc Cloud Manager; không tích hợp sẵn trong Operator Tích hợp sẵn PBM, hỗ trợ PITR, incremental backup, lưu trực tiếp lên S3/Azure Blob
Monitoring Dựa vào Ops Manager / Cloud Manager Tích hợp PMM (Percona Monitoring and Management)
Quản trị tập trung Ops Manager (self-hosted) hoặc Cloud Manager (SaaS) Không yêu cầu thành phần quản trị riêng
TLS / cert rotation Hỗ trợ qua Custom Resource (CR) Hỗ trợ, tích hợp cert-manager
Vault integration Tùy mô hình triển khai Hỗ trợ trực tiếp qua CR
HA scheduling (PDB, anti-affinity, topology spread) Hỗ trợ qua CR Hỗ trợ qua CR
Cộng đồng / tài liệu Tài liệu chính hãng MongoDB, community đang phát triển Cộng đồng open-source lớn, tài liệu chi tiết
Phù hợp khi Đã có MongoDB Enterprise Subscription và đang vận hành Ops Manager / Cloud Manager Muốn full open-source, tự chủ vận hành, không phụ thuộc license thương mại

Lựa chọn trong thực tế:

Nếu tổ chức đã có MongoDB Enterprise subscription và đang vận hành Ops Manager hoặc Cloud Manager, MCK là lựa chọn tốt hơn. Backup, PITR và monitoring trong mô hình này được xử lý bởi Ops Manager — Operator chịu trách nhiệm triển khai và điều phối cluster trên Kubernetes, còn các tác vụ day-2 nặng về dữ liệu vẫn đi qua hệ sinh thái quản trị của MongoDB.

Ngược lại, nếu ưu tiên tự chủ vận hành và không muốn phụ thuộc vào license thương mại, Percona Operator là hướng đi thực tế hơn. Điểm khác biệt lớn nhất là backup/PITR được tích hợp native trong Operator thông qua PBM — không cần thêm thành phần quản trị bên ngoài. Kết hợp với PMM cho monitoring, toàn bộ stack (Operator + PBM + PMM) đều là open-source, giảm rủi ro về chi phí license khi mở rộng quy mô cluster. Đây cũng là lựa chọn phổ biến trong các tổ chức đang vận hành MongoDB Community Edition trên Kubernetes.

Lưu ý: cả hai Operator đều đang được phát triển tích cực, tính năng và giới hạn có thể thay đổi theo phiên bản. Nên đối chiếu tài liệu chính thức theo version đang triển khai trước khi quyết định.

2. Operator pattern và state managment

Trong Kubernetes, các workload controller phổ biến như Deployment/ReplicaSet được thiết kế cho ứng dụng stateless, nơi Pod có thể bị thay thế và tái tạo mà không cần giữ identity cố định. Với cơ sở dữ liệu (stateful), yêu cầu về định danh mạng ổn định và lưu trữ bền vững quan trọng hơn nhiều, do đó Deployment hoặc ReplicaSet sẽ ít phù hợp hơn trong trường hợp này. Thay vào đó, chúng ta nên sử dụng StatefulSet. StatefulSet giúp giải quyết một phần bằng cách cung cấp:

  • Tên Pod ổn định theo thứ tự (ví dụ pod-0, pod-1),

  • DNS ổn định,

  • Thường gắn PersistentVolumeClaim theo từng replica.

Tuy vậy, chỉ StatefulSet là chưa đủ để vận hành MongoDB day-2 ready, vì Kubernetes không tự hiểu và tự thực thi các logic đặc thù của MongoDB (ví dụ khởi tạo replica set, thay đổi cấu hình replica set, rotate TLS/secret theo quy trình, hoặc điều phối các thành phần của sharded cluster). Đây là lý do Operator pattern được dùng để đóng gói kiến thức vận hành (Operator giống như một sysadmin ảo) vào một controller chuyên dụng.

2.1. Cơ chế hoạt động của Operator trong quản trị cơ sở dữ liệu

Operator hoạt động theo mô hình reconciliation loop: liên tục so sánh trạng thái mong muốn (desired state) khai báo trong Custom Resource (CR) với trạng thái thực tế (actual state) trong cluster, rồi thực hiện các hành động cần thiết để kéo hệ thống về đúng desired state.

Ví dụ, khi bạn tăng số member của một MongoDB replica set, operator không chỉ tạo thêm Pod/PVC ở tầng Kubernetes mà còn (tùy operator và cấu hình) thực hiện các bước cần thiết ở tầng MongoDB để member mới tham gia replica set và đồng bộ dữ liệu. Cách tiếp cận này giúp chuẩn hóa vận hành, giảm thao tác thủ công và giảm rủi ro sai sót.

Lưu ý về containers/sidecars và requests/limits

Theo khuyến nghị trong tài liệu của MongoDB Kubernetes Operator, trong Kubernetes bạn nên khai báo rõ requestslimits cho các container trong Pod để kiểm soát cận dưới/cận trên tài nguyên. Điều này đặc biệt quan trọng với các Pod có nhiều container (ví dụ mô hình containers của MongoDB Kubernetes Operator có thể gồm mongodb-agent và container chạy MongoDB server). Nếu không kiểm soát hợp lý requests/limits, các container trong cùng Pod có thể cạnh tranh CPU/RAM, gây ảnh hưởng tới độ ổn định hoặc độ trễ của các tác vụ vận hành.

Tham chiếu: MongoDB Kubernetes Operator Architecture - https://www.mongodb.com/docs/kubernetes/current/tutorial/plan-k8s-op-considerations/

2.2. Vai trò của Headless Service và SRV Records

Để các node trong MongoDB cluster có thể giao tiếp với nhau, Kubernetes sử dụng Headless Service (clusterIP: None) (https://kubernetes.io/docs/concepts/services-networking/service/#headless-services). Thay vì cung cấp một IP ảo duy nhất để cân bằng tải, Headless Service cho phép hệ thống DNS của Kubernetes trả về danh sách địa chỉ IP trực tiếp của tất cả các Pod thuộc StatefulSet.

Cấu trúc định danh mạng cho các thành viên trong ReplicaSet thường có dạng:

<pod-name>.<service-name>.<namespace>.svc.cluster.local

Các driver của MongoDB sử dụng bản ghi DNS SRV để khám phá toàn bộ topology của cụm. Khi một Pod bị dời sang node khác và nhận IP mới, bản ghi DNS sẽ tự động cập nhật, giúp các thành viên còn lại vẫn có thể kết nối với nó thông qua định danh DNS không đổi.

Tham chiếu:

2.3. PodDisruptionBudget (PDB)

PDB là cơ chế của Kubernetes để giới hạn số Pod có thể bị gián đoạn đồng thời trong các voluntary disruptions (ví dụ drain node khi bảo trì). Mục tiêu là tránh tình huống bảo trì làm giảm số member healthy xuống dưới ngưỡng cần thiết ( nếu không có PDB, Kubernetes có thể đồng thời drain 2 node chứa 2 thành viên, cluster mất quorum), khiến cụm mất khả năng ghi.

Với replica set 3 member, cấu hình thường gặp là:

podDisruptionBudget:
  maxUnavailable: 1

Lưu ý quan trọng theo docs Kubernetes: PDB không bảo vệ khỏi mọi sự cố (ví dụ node chết đột ngột), mà chủ yếu kiểm soát voluntary evictions.

Tham chiếu:

  1. Percona Operator - Anti-affinity and PDB (PDB config trong CR, khuyến nghị maxUnavailable: 1) - https://docs.percona.com/percona-operator-for-mongodb/constraints.html

  2. Kubernetes PDB Documentation - https://kubernetes.io/docs/tasks/run-application/configure-pdb/

2.4. Pod Anti-Affinity và Topology Spread Constraints

Để tăng khả năng chịu lỗi, các member của replica set (hoặc các thành phần sharded cluster) nên được phân tán trên các failure domain khác nhau (node/zone/region). Kubernetes hỗ trợ hai nhóm cơ chế chính:

  • Pod anti-affinity (tránh đặt các Pod cùng nhóm lên cùng topology),

  • Topology spread constraints (topologySpreadConstraints) để kiểm soát mức độ phân tán (skew) theo vùng lỗi.

Percona Operator hỗ trợ 2 cách:

  • Cách đơn giản: dùng antiAffinityTopologyKey (ví dụ kubernetes.io/hostname, topology.kubernetes.io/zone, topology.kubernetes.io/region, hoặc none).

  • Cách nâng cao hơn: dùng cấu hình affinity/anti-affinity và topologySpreadConstraints chuẩn của Kubernetes ngay trong CR (và operator sẽ áp các cấu hình đó vào Pod template).

Tham chiếu:

3. Quản lý lưu trữ

Hiệu suất và độ ổn định của MongoDB trên Kubernetes phụ thuộc nhiều vào storage layer (loại volume, latency, throughput/IOPS, filesystem, mount options, và giới hạn của node/instance). Cấu hình storage không phù hợp có thể dẫn đến nghẽn I/O, tăng độ trễ truy vấn, kéo dài thời gian recovery, và làm tăng rủi ro sự cố khi node/volume gặp vấn đề. MongoDB cũng nhấn mạnh các khuyến nghị cụ thể ở tầng filesystem và mount options cho triển khai self-managed.

3.1. XFS vs EXT4 (WiredTiger)

MongoDB hỗ trợ cả XFS và EXT4 trên Linux/Unix, nhưng khuyến nghị ưu tiên XFS:

  • MongoDB Production Checklist nêu rõ: “format your drives into XFS or EXT4. If possible, use XFS as it generally performs better with MongoDB.”

  • Với WiredTiger, MongoDB recommend dùng XFS để tránh các vấn đề hiệu năng đã ghi nhận khi dùng EXT4 với WiredTiger.

Trong Kubernetes, filesystem cho volume thường do CSI driver format khi cấp phát volume. Nhiều CSI driver hỗ trợ chỉ định filesystem thông qua tham số CSI csi.storage.k8s.io/fstype: xfs trong StorageClass (nếu driver hỗ trợ).

Về mount options:

  • MongoDB khuyến nghị dùng noatime cho mount point chứa dbPath để giảm overhead ghi metadata truy cập.

  • Có thể cân nhắc sử dụng thêm nodiratime (Linux)

Tham chiếu:

3.2. StorageClass trên các nền tảng đám mây

Mỗi cloud provider có đặc tính block storage khác nhau; mục tiêu là chọn loại volume phù hợp workload và cấu hình đúng để tránh tăng IOPS nhưng không dùng được vì bị chặn bởi instance/node.

AWS (EKS)

  • EBS gp3: AWS docs nêu gp3 có baseline IOPS 3,000 (kèm baseline throughput tùy theo giới hạn của volume type và cấu hình). gp3 cho phép provision IOPS/throughput độc lập với dung lượng, nhưng hiệu năng thực tế vẫn bị giới hạn bởi băng thông EBS của EC2 instance (EBS-optimized / instance throughput). Vì vậy cần kiểm tra giới hạn instance trước khi đẩy IOPS/throughput ở StorageClass.

  • EBS io2 / io2 Block Express: phù hợp workload cần độ trễ thấp và IOPS cao, nhưng có giới hạn theo volume type, dung lượng, và loại instance (cần đối chiếu giới hạn hiện hành của AWS theo region/instance/volume).

Tham chiếu (AWS gp3 performance): https://docs.aws.amazon.com/ebs/latest/userguide/general-purpose.html

Azure (AKS)

  • Premium SSD v2: Microsoft mô tả Premium SSD v2 được thiết kế để cung cấp provisioned IOPS/throughput và sub-millisecond latencies.

  • Lưu ý: việc set IOPS and throughput limits cho Premium SSD v2 hiện không được hỗ trợ thông qua AKS (tức không cấu hình trực tiếp bằng manifest AKS để chỉnh perf), và muốn chỉnh performance cần dùng az disk update với các tham số IOPS/MBps sau khi disk đã được tạo/cấp phát.

Tham chiếu:

Mô phỏng StorageClass

Lưu ý: tham số cụ thể (nhất là provisioned IOPS/throughput) phụ thuộc CSI driver, giới hạn volume type, và giới hạn node/instance.

AWS EKS (EBS gp3 + XFS)

  • Dùng provisioner ebs.csi.aws.com

  • csi.storage.k8s.io/fstype: xfs

  • allowVolumeExpansion: true

  • mountOptions: có thể khai báo noatime (và tùy nhu cầu có thể cân nhắc nodiratime)

Sample:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ebs-gp3-xfs-mongodb
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
parameters:
  type: gp3
  iops: "6000"       # Tùy chỉnh theo giới hạn của EC2 Instance
  throughput: "250"  # Tính bằng MiB/s
  csi.storage.k8s.io/fstype: xfs
mountOptions:
  - noatime
  - nodiratime

Azure AKS (Premium SSD v2 + XFS)

  • Dùng provisioner disk.csi.azure.com

  • skuName: PremiumV2_LRS

  • csi.storage.k8s.io/fstype: xfs

  • Lưu ý: chỉnh IOPS/throughput cho Premium SSD v2 cần thực hiện bằng az disk update theo tài liệu AKS (không thực hiện trực tiếp qua manifest để set performance).

Sample:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: azure-premium-v2-xfs-mongodb
provisioner: disk.csi.azure.com
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
parameters:
  skuName: PremiumV2_LRS
  cachingMode: None  # Premium v2 không hỗ trợ host caching, bắt buộc cấu hình None
  csi.storage.k8s.io/fstype: xfs
mountOptions:
  - noatime
  - nodiratime

Tham chiếu:

3.3. Local NVMe / Local Persistent Volumes

Local NVMe (local PV) thường cho latency/IOPS tốt hơn network-attached storage, nhưng đánh đổi khả năng portable của Pod:

  • Nếu node chứa local PV gặp sự cố, Pod không thể đơn giản được reschedule sang node khác và gắn lại đúng volume cũ, vì dữ liệu nằm trên đĩa local của node đó.

  • Với MongoDB replica set/sharding, nếu topology được thiết kế đúng (replication, writeConcern/journaling, phân tán node/zone…), hệ thống có thể phục hồi bằng cách tạo member mới trên node khác và thực hiện initial sync để lấy lại dữ liệu từ các member còn sống. Điều này phù hợp với chiến lược ưu tiên hiệu năng, chấp nhận rebuild node của một số hệ thống.

4. Kernel và tài nguyên của pod

4.1. Quản lý bộ nhớ và WiredTiger Cache

Với WiredTiger, MongoDB sử dụng song song:

  • WiredTiger internal cache

  • filesystem cache của hệ điều hành.

WiredTiger cache mặc định được mô tả như sau:

  • Cache mặc định = giá trị lớn hơn giữa:

    • 50% × (RAM − 1GB), hoặc

    • 0.256 GB (256MB).

MongoDB khuyến nghị tránh tăng WiredTiger cache vượt mức mặc định nếu không có lý do cụ thể. Khi cần cấu hình cache một cách tường minh, MongoDB cung cấp 2 nhóm tuỳ chọn (chỉ chọn một trong hai, không dùng đồng thời):

  • Theo dung lượng tuyệt đối:

    • -wiredTigerCacheSizeGB hoặc storage.wiredTiger.engineConfig.cacheSizeGB
  • Theo phần trăm:

    • -wiredTigerCacheSizePct hoặc storage.wiredTiger.engineConfig.cacheSizePct (tối đa 80% available memory)

Lưu ý:

Trong một số trường hợp, khi chạy trong container (cgroups/Docker/…), WiredTiger có thể không account đúng giới hạn bộ nhớ của container. Vì vậy, nếu container không được phép dùng toàn bộ RAM của host, bạn nên cấu hình cache explicit (cacheSizeGB hoặc cacheSizePct) nhỏ hơn memory mà container thực sự được cấp, và chừa headroom cho các phần ngoài cache (filesystem cache, allocator/runtime, và các tiến trình/sidecar khác). Nếu cache đặt quá sát memory limit, container có thể gặp OOM/OOMKilled.

Do option/flag có thể thay đổi theo phiên bản MongoDB bạn đang chạy, cách an toàn khi viết tài liệu vận hành là ghi thêm: hãy xác nhận option có tồn tại trên version hiện tại bằng mongod --help hoặc đọc đúng trang docs theo version.

Tham chiếu:

4.2. Transparent Huge Pages (THP)

Một trong những hành động kinh điển của các DBA là tắt Transparent Huge Pages (THP) để tránh các vấn đề về phân mảnh bộ nhớ. Tuy nhiên, khuyến nghị THP của MongoDB phụ thuộc phiên bản:

MongoDB 7.0 và các phiên bản trước đó

  • MongoDB khuyến nghị disable THP để đạt hiệu năng tốt nhất (tránh hiện tượng phân mảnh bộ nhớ và suy giảm hiệu suất), và hướng dẫn cách đảm bảo THP được tắt trước khi mongod khởi động.

MongoDB 8.0 và các phiên bản sau đó

  • Từ MongoDB 8.0, MongoDB dùng TCMalloc được nâng cấp với per-CPU caches (thay vì per-thread caches) để giảm memory fragmentation và tăng khả năng chịu tải.

  • MDB 8.0 trở về sau: Bật để tận dụng TCMalloc per-CPU caches mới, giúp tăng hiệu suất.

  • Theo tài liệu tối ưu TCMalloc của MongoDB 8.0, để dùng TCMalloc mới cần:

    • Enable THP ở cấp hệ thống trước khi mongod start, và

    • Đảm bảo per-CPU caches hoạt động.

Điều kiện/thiết lập để per-CPU caches hoạt động đúng (theo docs MongoDB 8.0):

  • Linux kernel 4.18+.

  • Để đảm bảo TCMalloc có thể đăng ký rseq và dùng per-CPU caches, cần disable glibc rseq trước khi start mongod bằng:

    • GLIBC_TUNABLES=glibc.pthread.rseq=0

Một số OS/architecture dùng legacy TCMalloc (ví dụ RHEL 8/Oracle 8 trên PPC64LE và s390x; RHEL 9/CentOS 9/Oracle 9 trên PPC64LE). Trên các hệ này, MongoDB yêu cầu disable THP.

Lưu ý vận hành mixed versions

THP là cấu hình cấp hệ thống (không bật/tắt theo từng process) và là một thiết lập ở cấp độ kernel của máy chủ vật lý. Vì vậy nếu bạn chạy đồng thời MongoDB 7.x (khuyến nghị tắt THP) và 8.x (yêu cầu bật THP theo TCMalloc 8.0) trong cùng một cluster Kubernetes, nên tách node pool và dùng node affinity/taints-tolerations để mỗi phiên bản chạy trên nhóm node có cấu hình THP phù hợp.

Tham chiếu:

4.3. Cấu hình giới hạn tài nguyên hệ thống (ulimits)

MongoDB yêu cầu số lượng file descriptors và threads tương đối lớn để hoạt động ổn định. Khi giá trị nofile hoặc nproc quá thấp, MongoDB (hoặc ứng dụng client) có thể gặp các lỗi kiểu “Too many open files” hoặc “can’t create new thread”, đặc biệt ở môi trường nhiều kết nối đồng thời.

Các giá trị ulimit khuyến nghị cho môi trường production (tham khảo MongoDB docs):

  • n (open files): 64,000

  • u (processes/threads): 64,000

  • f (file size): unlimited

  • t (CPU time): unlimited

  • v (virtual memory): unlimited

  • m (memory size): unlimited

  • (tuỳ môi trường) l (memlock): unlimited

Thiết lập ulimits trong Kubernetes

Tính đến hiện tại, Kubernetes chưa cung cấp một trường API chuẩn trong Pod spec để khai báo ulimit/rlimit (ví dụ nofile, nproc), kể cả trong securityContext. securityContext chủ yếu cấu hình các khía cạnh bảo mật và kernel settings như sysctls, Linux capabilities, SELinux, Seccomp, AppArmor… chứ không bao gồm ulimit.

Về mặt Linux, ulimit (rlimit) là thuộc tính gắn với từng process và thường được container runtime thiết lập khi khởi tạo process trong container. Vì vậy, nếu cần thay đổi ulimit một cách ổn định cho workload, hướng tiếp cận phổ biến là cấu hình ở tầng node/container runtime (tuỳ môi trường và distro có thể khác nhau).

Lưu ý: sysctls và ulimits là hai cơ chế độc lập. Việc cấu hình securityContext.sysctls không thay thế cho việc tăng nofile/nproc.

Có hai cách thường dùng để thiết lập ulimits cho MongoDB containers trên Kubernetes (cần kiểm chứng theo runtime/phiên bản cụ thể đang dùng):

Cấu hình systemd unit của container runtime (khuyến nghị trong đa số môi trường self-managed)

  • Mục tiêu: nâng giới hạn rlimit cho service runtime (ví dụ containerd). Tuỳ runtime và cấu hình runc/CRI, các giới hạn này có thể trở thành mặc định mà container nhận được.

  • Ví dụ với containerd:

    • sudo systemctl edit containerd

    • Thêm:

      • LimitNOFILE=64000

      • LimitNPROC=64000

      • LimitMEMLOCK=infinity

  • Áp dụng thay đổi:

    • sudo systemctl daemon-reload && sudo systemctl restart containerd

Ghi chú: /etc/security/limits.d là cơ chế PAM/session, thường phù hợp cho login sessions; không phải lúc nào cũng tác động trực tiếp lên process do systemd quản lý. Vì vậy trong môi trường Kubernetes, cấu hình qua systemd unit của runtime thường đúng tầng hơn.

Cấu hình default ulimits ở container runtime (nếu runtime/phiên bản hỗ trợ)

  • Một số phiên bản/cấu hình containerd+runc cho phép đặt default ulimits trong /etc/containerd/config.toml (cú pháp phụ thuộc phiên bản).

  • Ví dụ minh hoạ (cần xác nhận với containerd version đang chạy):

    • Trong section runtime options, đặt DefaultUlimits = ["nofile=64000:64000", "nproc=64000:64000"]
  • Sau đó restart containerd để áp dụng.

Tại sao không dùng init container để set ulimit?

  • ulimit chỉ áp dụng cho process hiện tại và các process con do nó spawn ra trong cùng container.

  • Init container chạy xong sẽ exit; main container được runtime tạo thành một process mới với rlimit riêng. Vì vậy init container không phải cơ chế chuẩn để set ulimit cho main container (init container vẫn hữu ích cho sysctl/chuẩn bị filesystem, nhưng không giải quyết bài toán ulimit theo cách bền vững).

Về Percona Operator và MongoDB Community Operator (MCK)

Operator chủ yếu tạo và điều phối Kubernetes resources. Khi Kubernetes không có API ulimit trong Pod spec, operator cũng không thể set ulimit theo cách chuẩn chỉ bằng manifest. Một số chart/operator có thể yêu cầu hoặc hướng dẫn node/runtime tuning như một phần prerequisite; cần đối chiếu docs theo phiên bản operator và môi trường triển khai thực tế.


Tham chiếu:

  1. MongoDB ulimit Reference — https://www.mongodb.com/docs/manual/reference/ulimit/

  2. MongoDB Production Notes — https://www.mongodb.com/docs/manual/administration/production-notes/

  3. Kubernetes Security Context — https://kubernetes.io/docs/tasks/configure-pod-container/security-context/

  4. Using sysctls in a Kubernetes Cluster — https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/

  5. systemd.exec — Limit options — https://www.freedesktop.org/software/systemd/man/systemd.exec.html

Note: Với môi trường EKS/managed nodes, cần nhắc việc propagate cấu hình qua launch template/user-data để new nodes scale up cũng nhận đúng giá trị.

5. Backup & disaster recovery

Trong một môi trường thay đổi nhanh như Kubernetes, dữ liệu là tài sản duy nhất không thể thay thế. Việc chỉ dựa vào snapshot của ổ đĩa mà không có sự điều phối với database engine tiềm ẩn nguy cơ không đảm bảo tính nhất quán của dữ liệu tại thời điểm snapshot.

5.1. Percona Backup for MongoDB (PBM)

PBM là một giải pháp backup phân tán hỗ trợ cả ReplicaSet và Sharded Cluster. Nó hoạt động thông qua kiến trúc sidecar, mỗi Pod MongoDB có một pbm-agent chạy song song.

Quy trình incremental backup của PBM:

  1. Base Backup: Thực hiện một bản sao lưu toàn bộ dữ liệu lần đầu tiên.

  2. Backup incremental: Chỉ sao lưu các thay đổi so với bản gần nhất, giúp tiết kiệm dung lượng lưu trữ và băng thông mạng.

  3. Point-in-Time Recovery (PITR): PBM liên tục đẩy các đoạn Oplog lên Object Storage (S3/Azure Blob). Điều này cho phép khôi phục dữ liệu về bất kỳ thời điểm nào trong quá khứ, giúp bảo vệ hệ thống trước các lỗi thao tác của con người như xóa nhầm dữ liệu.

Tham chiếu: PBM PITR Tutorial — https://docs.percona.com/percona-backup-mongodb/usage/pitr-tutorial.html

5.2. Đảm bảo tính nhất quán trong sharded cluster

Backup một sharded cluster khó hơn replica set vì dữ liệu và metadata được phân tán trên nhiều shard. Một bản backup chỉ thực sự usable khi có thể khôi phục về một trạng thái nhất quán tại cùng một thời điểm logic (cluster-wide consistency), thay vì mỗi shard bị chụp ở một mốc thời gian khác nhau.

5.2.1. Nguyên tắc: freeze → snapshot → unfreeze

Trong self-managed, một quy trình thường được dùng là đóng băng tạm thời (freeze) trước khi chụp snapshot ở tầng storage, rồi mở lại ngay sau khi snapshot xong.

Ở phía MongoDB, cơ chế hay dùng là fsyncfsyncUnlock (thường gọi là fsyncLock):

  • fsync flush dữ liệu ra đĩa và chặn ghi trong thời gian lock ở mức storage engine.

  • Trong cửa sổ lock, thao tác ghi có thể bị block hoặc tăng độ trễ, nên mục tiêu vận hành là giữ cửa sổ lock ngắn nhất có thể.

5.2.2. Cluster-wide lock qua mongos (và các phiên bản hỗ trợ)

MongoDB hỗ trợ chạy fsync/fsyncUnlock trực tiếp trên mongos để lock/unlock một sharded cluster. Theo MongoDB docs, tính năng này bắt đầu từ MongoDB 7.1 và cũng khả dụng từ 7.0.2, 6.0.11, 5.0.22. Khi chạy trên mongos, mongos sẽ gửi thao tác fsync tới từng shard và trả về kết quả tổng hợp (bao gồm thông tin lockCount/lock status theo từng shard).

5.2.3. Prerequisites trước khi lock (theo MongoDB docs)

Để backup self-managed có thể sử dụng được, trước khi lock cần:

  • Đảm bảo không có chunk migration, resharding hoặc DDL operations đang chạy.

  • Dừng balancer để ngăn các chunk migration mới init trong lúc backup.

5.2.4. Lock config server primary và bước xác nhận lock (confirm)

Theo MongoDB docs, để lock sharded cluster cần thực hiện lock:

  • Trên mongos (cluster-wide), và

  • Trên primary của config servers.

Sau khi lock, cần xác nhận trạng thái lock đúng như mong đợi trên cảmongos, và primary mongod của config servers, đảm bảo các trường trạng thái thể hiện đang locked (ví dụ fsyncLocked = truefsyncUnlocked = false theo hướng dẫn trong docs). Bước confirm này giúp tránh trường hợp quy trình lock chưa đủ điều kiện nhưng vẫn thực hiện snapshot.

5.2.5. Rủi ro operational: primary failover trong lúc lock

Nếu primary đang giữ fsyncLock bị down, primary mới không kế thừa lock và có thể xử lý ghi. Khi election xảy ra trong cửa sổ backup, bản backup có thể inconsistent hoặc không thể sử dụng.

Vì vậy, ngoài việc giữ lock window ngắn, cần hạn chế tối đa các nguyên nhân gây failover trong thời điểm snapshot (maintenance, node drain không kiểm soát, hạ tầng không ổn định…).

5.2.6. Exact point-in-time vs approximate

Nếu bạn cần một snapshot đúng chính xác tại một thời điểm (exact moment-in-time), bạn cần dừng toàn bộ writes trước khi chụp filesystem snapshots; nếu không, snapshot chỉ xấp xỉ một thời điểm (approximate).

Thực tế vận hành thường là trade-off giữa tính chính xác và mức độ gián đoạn ghi mà hệ thống chấp nhận được.

5.2.7. Dữ liệu lớn: snapshot-based physical backup thường được ưu tiên

Với dữ liệu hàng TB, backup logic kiểu mongodump thường chậm và kéo dài thời gian restore. Nếu ưu tiên RTO thấp hơn, physical backup dựa trên snapshot ở tầng storage thường được cân nhắc, kết hợp với quy trình freeze/snapshot/unfreeze ở trên.

Tham chiếu:

  1. MongoDB — fsync command (cluster-wide lock từ mongos, khả dụng từ 7.1/7.0.2/6.0.11/5.0.22) — https://www.mongodb.com/docs/manual/reference/command/fsync/

  2. MongoDB — Backup Sharded Cluster with Filesystem Snapshots — https://www.mongodb.com/docs/manual/tutorial/backup-sharded-cluster-with-filesystem-snapshots/

6. TLS, authentication và quản lý secret

Bảo mật là thành phần không thể tách rời khi đưa dữ liệu lên Kubernetes. Một cụm MongoDB không được bảo mật đúng cách có thể trở thành kẽ hở cho các cuộc tấn công đánh cắp dữ liệu quy mô lớn.

6.1. Tự động hóa TLS với cert-manager

Tất cả các lưu lượng truy cập giữa ứng dụng và cơ sở dữ liệu, cũng như lưu lượng nội bộ giữa các node MongoDB, bắt buộc phải được mã hóa bằng TLS. Việc quản lý thủ công các chứng chỉ này là không khả thi và dễ dẫn đến sự cố khi chứng chỉ hết hạn.

Tích hợp với cert-manager cho phép:

  • Tự động cấp phát và gia hạn chứng chỉ từ các nguồn tin cậy như Let's Encrypt hoặc CA nội bộ của doanh nghiệp.

  • Tự động khởi động lại (rolling restart) các node MongoDB khi chứng chỉ được cập nhật để áp dụng cấu hình mới mà không gây downtime.

  • Đảm bảo tính nhất quán về CA trên toàn bộ cụm, một yêu cầu bắt buộc để các node có thể xác thực lẫn nhau (Internal Authentication).

6.2. Quản lý Secret tập trung với HashiCorp Vault và ESO

Mặc dù Kubernetes cung cấp tài nguyên Secret, nhưng về cơ bản chúng chỉ được mã hóa base64 và có thể bị truy cập bởi bất kỳ ai có quyền quản trị cluster. Đối với các hệ thống nhạy cảm, việc sử dụng HashiCorp Vault làm source of truth cho các thông tin xác thực là một bước đi đúng đắn.

External Secrets Operator (ESO) đóng vai trò như một lớp trung gian: quản trị viên lưu mật khẩu MongoDB và chứng chỉ trong Vault, sau đó ESO xác thực với Vault và đồng bộ chúng thành Kubernetes Secret cục bộ để Pod sử dụng. Khi thông tin trong Vault thay đổi, ESO sẽ tự động cập nhật Kubernetes Secret tương ứng.

Percona Operator cũng hỗ trợ tích hợp trực tiếp với Vault để đồng bộ system user credentials, không cần ESO làm trung gian trong một số trường hợp.

Tham chiếu:

  1. Percona Operator - Vault Integration - https://docs.percona.com/percona-operator-for-mongodb/operator.html

  2. External Secret Operator: https://external-secrets.io/latest/

6.3. Tích hợp với môi trường Service Mesh (Istio / Linkerd)

Nếu cụm Kubernetes sử dụng Service Mesh như Istio hoặc Linkerd, cần đặc biệt lưu ý khả năng chồng lấn giữa TLS do MongoDB (Operator) cấu hình và mTLS do mesh force. MongoDB traffic chủ yếu là TCP binary, và khi vừa có TLS ở tầng ứng dụng vừa có mTLS ở tầng sidecar, rất dễ phát sinh policy mismatch hoặc hành vi proxy không như kỳ vọng, dẫn đến lỗi kết nối/handshake giữa các member của ReplicaSet hoặc giữa các thành phần sharded cluster.

Rủi ro thường gặp (TLS chồng TLS / policy mismatch)

MongoDB Operator thường bật TLS/mTLS để mã hóa lưu lượng nội bộ giữa các node. Trong khi đó, mesh có thể yêu cầu mTLS giữa các proxy sidecar. Nếu cấu hình không khớp, ví dụ mesh yêu cầu STRICT mTLS trên port mà MongoDB đang tự quản TLS, kết nối local có thể bị chặn hoặc fail handshake.

Istio (Envoy sidecar)

  • Tình huống hay gặp: áp PeerAuthentication ở chế độ STRICT cho namespace/workload chứa MongoDB StatefulSet trong khi MongoDB đã dùng TLS riêng → xung đột mTLS policy, gây lỗi kết nối.

  • Hướng xử lý (tùy mục tiêu bảo mật):

    • PERMISSIVE khi migrate policy: dùng PERMISSIVE như trạng thái trung gian khi chuyển giữa DISABLESTRICT, để tránh gián đoạn dịch vụ trong lúc rollout.

    • Port-level override: nếu muốn giữ STRICT cho workload/namespace nhưng không ép mTLS trên port MongoDB, dùng PeerAuthentication.portLevelMtls để đặt DISABLE hoặc UNSET cho container port MongoDB (thường là 27017), trong khi các port khác vẫn theo STRICT.

Linkerd: ưu tiên opaque-ports, skip-ports chỉ dùng khi bất khả kháng

  • Bối cảnh kỹ thuật:

    MongoDB sử dụng wire protocol nhị phân riêng (OP_MSG/BSON), không phải HTTP/HTTP2/gRPC. Linkerd thực hiện protocol detection bằng cách đọc bytes đầu tiên từ client để phân loại traffic là HTTP/HTTP2/gRPC hay opaque TCP. Với MongoDB wire protocol, Linkerd không nhận ra được format này, vì vậy có thể bị delay khoảng ~10 giây do protocol detection timeout trước khi proxy như một TCP stream nếu không cấu hình thêm.

    Ngoài ra, port 27017 không nằm trong danh sách default opaque ports của Linkerd. As of phiên bản 2.11, danh sách mặc định gồm: 25/587 (SMTP), 3306 (MySQL), 4444 (Galera), 5432 (Postgres), 6379 (Redis), 9300 (ElasticSearch), 11211 (Memcache) - và có thể thay đổi theo phiên bản - nhưng không bao gồm 27017. Do đó cần cấu hình tường minh.

    Lưu ý: MongoDB không phải server-speaks-first protocol (client gửi bytes trước). Tuy nhiên, vì wire protocol của MongoDB là binary non-HTTP, Linkerd vẫn không thể phân loại được qua detection - và đây là lý do thực sự cần mark opaque.

  • Ưu tiên 1 - opaque-ports (khuyến nghị):

    Đánh dấu port MongoDB là opaque để Linkerd bỏ qua protocol detection và proxy ngay lập tức như một TCP stream. Cách này vẫn giữ được mTLS của meshTCP-level metrics/policy; chỉ là không có observe layer 7.

    # Annotate ở cả Service và Pod/StatefulSet
    annotations:
      config.linkerd.io/opaque-ports: "27017"
    

    Nên annotate đồng thời ở cả ServicePod/StatefulSet để đảm bảo hành vi nhất quán. Nếu chỉ annotate một phía, hành vi có thể không nhất quán tùy theo cách traffic được route (qua ClusterIP Service hay headless Service trực tiếp tới Pod).

  • Ưu tiên 2 - skip-ports (last resort):

    Chỉ dùng skip-inbound-ports / skip-outbound-ports khi buộc phải bypass proxy hoàn toàn, ví dụ khi MongoDB nằm ngoài cluster (off-cluster destination), nơi opaque-ports annotation không áp dụng được vì không có Service resource trong cluster để annotate. Khi bypass proxy, Linkerd không áp mTLS và không thu metrics cho traffic trên các port đó.

7. Observability

Để vận hành ổn định lâu dài, chúng ta cần một cái nhìn thấu đáo vào bên trong chiếc “hộp đen” mang tên MongoDB trên Kubernetes thông qua các chỉ số hiệu suất thời gian thực.

7.1. Thu thập metrics (Prometheus)

Với mô hình self-managed MongoDB (chạy trong K8s), cách phổ biến là triển khai Prometheus exporter (ví dụ Percona mongodb_exporter) để scrape các số liệu mà MongoDB cung cấp qua các command nội bộ như serverStatus, replSetGetStatus, getDiagnosticData, \(collStats, \)indexStats.

Lưu ý:

  • Với MongoDB Atlas, có thể dùng Prometheus integration chính thức của Atlas thay vì tự chạy exporter trong cluster.

  • Tên metric phụ thuộc exporter version và chế độ chạy. Với Percona mongodb_exporter, cần phân biệt:

    • Exporter mới hơn có thể dùng naming scheme mới (ví dụ nhóm mongodb_rs_*).

    • Khi bật -compatible-mode, exporter có thể expose thêm các metric theo naming scheme cũ để tương thích với dashboard/rule cũ. Vì vậy nếu tài liệu/rule đang dùng tên cũ, cần ghi rõ điều kiện -compatible-mode hoặc pin exporter version.

    • Cách đúng để chốt metric name là đối chiếu reference metrics đúng với image tag bạn đang deploy.

7.2. Các nhóm chỉ số quan trọng

Các nhóm chỉ số cần theo dõi (mô tả theo ý nghĩa, không theo tên metric vì phụ thuộc exporter version/mode):

ReplicaSet health

  • Member state / my state: theo dõi node đang PRIMARY/SECONDARY/ARBITER/… (tên metric có thể đổi theo version; ví dụ có các tên như mongodb_mongod_replset_member_state hoặc mongodb_rs_members_state tùy exporter/version).

  • Replication lag: số giây secondary chậm hơn primary (seconds a secondary is behind the primary).

    • Lưu ý: tên metric replication lag phụ thuộc exporter version (trong PMM/Percona ecosystem từng thấy các metric kiểu mongodb_mongod_replset_member_replication_lag, nhưng không nên coi là cố định).

WiredTiger cache & memory pressure

  • Theo dõi các chỉ số trong serverStatus.wiredTiger.cache (bytes in cache, dirty bytes, eviction, …) để đánh giá áp lực bộ nhớ và rủi ro nghẽn I/O khi flush/checkpoint.

  • Cache hit ratio: thường là derived metric tính từ WiredTiger counters (ví dụ hits / (hits + misses)), không phải một metric native MongoDB xuất thẳng ra.

Connections

MongoDB expose các trường serverStatus.connections.current, available, totalCreated (exporter sẽ map sang Prometheus metrics tương ứng).

Ops & data growth / I/O signals

Theo dõi opcounters và các chỉ báo tăng trưởng dữ liệu (data size, document metrics, operation metrics…) để bắt xu hướng tăng tải, tăng dữ liệu và correlate với latency/throttling IOPS.

7.3. Alerting

  • Critical (Cần xử lý ngay lập tức)

    • NoPrimary/Lost Primary: ReplicaSet mất primary → mất khả năng ghi.

    • Disk usage > 90%: rủi ro write fail/crash loop/recovery kéo dài.

    • Replication lag rất cao (ví dụ > 300s): dấu hiệu secondary không theo kịp, ảnh hưởng failover và consistency (tùy hệ thống có thể cần ngưỡng thấp hơn).

  • Warning (Xử lý trong ngày)

    • Replication lag > 10s (baseline theo Percona/PMM): Percona PMM advisor và dashboard coi mốc 10s là dấu hiệu cần chú ý (cũng là ngưỡng mặc định nơi flow control bắt đầu can thiệp).

    • Connection utilization > 70%: sớm chạm trần connections dẫn đến lỗi ứng dụng (tune theo maxIncomingConnections và đặc thù traffic).

    • Cache hit ratio giảm/cache pressure tăng: nếu dùng cache hit ratio (derived) thì nên coi là tín hiệu xu hướng, kết hợp thêm dirty bytes/evictions để tránh false positive.

Cuối cùng, dùng Grafana để correlate các biến động metrics với sự kiện hạ tầng Kubernetes (pod restart/reschedule, node drain, PV detach/attach, storage throttling…) giúp khoanh vùng nguyên nhân nhanh hơn.

Tham chiếu:

8. Data migration và triển khai multicloud

Di chuyển dữ liệu từ môi trường cũ lên Kubernetes là một trong những tác vụ rủi ro nhất. Mục tiêu luôn là giảm thiểu tối đa thời gian gián đoạn dịch vụ (downtime).

8.1. Sử dụng mongosync và Percona ClusterSync for MongoDB (PCSM)

Phương pháp migrate truyền thống (backup/restore) thường gây downtime kéo dài tỉ lệ thuận với kích thước dữ liệu. Để giảm downtime, hướng tiếp cận phổ biến là 3 giai đoạn: data clone → real-time replication → cut-over/finalize.

MongoDB mongosync (official)

  • mongosync là công cụ chính thức của MongoDB để thực hiện one-time migration giữa các MongoDB clusters với minimal downtime, đồng bộ dữ liệu và writes từ source sang destination cho đến khi finalize/commit.

  • Phạm vi hỗ trợ (quan trọng):

    • Nếu các cluster là self-managed, chúng phải là MongoDB Enterprise clusters.

    • mongosync chỉ được hỗ trợ trên MongoDB Community Edition trong một số trường hợp giới hạn. Nếu muốn dùng với Community Edition, cần liên hệ MongoDB sales để thảo luận yêu cầu và individualized options.

  • Tương thích phiên bản: mongosync chỉ tương thích với MongoDB major versionskhông hỗ trợ rapid/minor releases như 8.1, 8.2.

Percona ClusterSync for MongoDB (PCSM)

  • PCSM là công cụ mã nguồn mở của Percona để clone dữ liệu ban đầuđồng bộ thay đổi theo thời gian thực giữa các MongoDB deployments.

  • PCSM sử dụng MongoDB Change Streams (abstraction layer dựa trên oplog) để theo dõi và replicate các thay đổi từ source sang target.

  • PCSM 0.7.0 được Percona công bố GA cho replication giữa replica sets vào 2026-01-14. Trong release này, replication cho sharded clusters được giới thiệu ở mức tech preview (chưa GA).

Quy trình migrate (áp dụng cho cả mongosync/PCSM theo cùng pattern)

  1. Giai đoạn data clone: sao chép toàn bộ dữ liệu hiện có từ source sang target.

  2. Giai đoạn real-time replication: đồng bộ các thay đổi phát sinh liên tục từ source sang target (CDC qua Change Streams).

  3. Giai đoạn cut-over (finalize/commit): khi độ trễ đồng bộ đủ nhỏ, chuyển hướng ứng dụng sang cluster mới; đây là thời điểm duy nhất có gián đoạn nhẹ.

Tham chiếu

8.2. Lưu ý đặc thù khi triển khai trên AWS và Azure

Khi vận hành MongoDB trên Kubernetes ở môi trường Public Cloud, phần khó thường nằm ở điểm giao giữa Kubernetes và hạ tầng của nhà cung cấp (IAM, storage, networking, availability zones). Vì vậy, cần làm rõ các quyết định hạ tầng ngay từ đầu để tránh rủi ro vận hành về sau.

Trên AWS EKS:

  • Với các thành phần cần gọi AWS API (đặc biệt là Amazon EBS CSI driver), nên cấp quyền theo mô hình pod có IAM role riêng thay vì dùng access key tĩnh. AWS hiện khuyến nghị dùng EKS Pod Identity (phương pháp được ưu tiên hiện tại) hoặc IRSA (IAM Roles for Service Accounts - vẫn được hỗ trợ đầy đủ) để driver/pod lấy credential tạm thời và bám theo nguyên tắc least privilege.

  • Về storage, EBS gp3 là lựa chọn đáng ưu tiên cho đa số workload vì cho phép tách dung lượng khỏi hiệu năng: bạn có thể provision IOPS/throughput theo nhu cầu mà không cần tăng dung lượng (giống như gp2). Lưu ý khi tuning: hiệu năng cuối cùng vẫn cần đối chiếu với giới hạn I/O của loại EC2 instance/node đang dùng.

Trên Azure AKS:

  • Nếu triển khai theo mô hình HA (ReplicaSet/Sharding) và muốn tăng khả năng chịu lỗi ở cấp datacenter, nên thiết kế cluster/node pool theo Availability Zones, đồng thời cấu hình cơ chế dàn trải pod như podAntiAffinity hoặc topologySpreadConstraints để các member không bị dồn vào cùng một zone/node. Cách này giúp giảm rủi ro mất quorum khi một zone gặp sự cố; đổi lại, độ trễ liên zone thường cao hơn intra-zone nên cần cân nhắc theo SLO của workload.

  • Với các workload yêu cầu storage có thông lượng cao/ổn định, Azure NetApp Files (ANF) có thể là một lựa chọn đáng cân nhắc. Tuy nhiên, cần lưu ý rõ sự khác biệt về loại storage: ANF là file storage (truy cập qua NFS/SMB), còn Managed Disks là block storage. Quyết định nên dựa trên access pattern thực tế (random read/write, latency, throughput, khả năng scale, chi phí).

9. Lời kết

Việc đưa MongoDB lên Kubernetes không phải là đích đến, mà là điểm khởi đầu của một hành trình vận hành dựa trên mã nguồn (Operation as Code). Kubernetes chỉ phát huy được giá trị khi đội ngũ làm chủ được ba lớp nền tảng: tự động hóa vận hành, ổn định của lớp lưu trữ, và kỷ luật trong bảo vệ dữ liệu.

Tóm lại, để xây dựng một hạ tầng MongoDB bền vững trên Kubernetes, có thể xem đây là các nguyên tắc cốt lõi:

  1. Ưu tiên sử dụng Operator cho production (MCK hoặc Percona Operator) để chuẩn hóa day-2 operations như nâng cấp, mở rộng, backup, TLS và health reconciliation. Việc tự viết YAML thủ công cho hệ thống stateful thường làm tăng đáng kể rủi ro và chi phí vận hành.

  2. Đầu tư nghiêm túc vào storage layer: ưu tiên XFS cho các data-bearing nodes (WiredTiger), chọn volume type phù hợp và cấu hình IOPS/throughput theo nhu cầu thực tế, đồng thời luôn đối chiếu giới hạn ở tầng node/instance để tránh provision cao nhưng không đạt được hiệu năng mong muốn.

  3. Thiết kế backup/restore ngay từ ngày đầu: bật PITR và duy trì lịch backup định kỳ. Với dataset lớn, nên ưu tiên snapshot-based/physical backup (ví dụ CSI snapshot) để giảm RTO, nhưng cần kết hợp cơ chế đảm bảo nhất quán dữ liệu (quiesce/fsync/lock theo topology) thay vì chỉ snapshot volume.

  4. Thiết kế HA đúng nghĩa: dùng PodDisruptionBudget để kiểm soát voluntary evictions và dùng anti-affinity / topology spread để tránh dồn replica vào cùng failure domain. Lưu ý PDB không bảo vệ khỏi mọi sự cố (involuntary disruptions), vì vậy vẫn cần replication topology và chiến lược phục hồi phù hợp.

  5. Không được bỏ qua việc monitoring: thiết lập observability end-to-end (metrics/logs/alerts). Tối thiểu cần theo dõi replica set health, replication lag, disk usage, cache pressure/memory pressure và các tín hiệu I/O để phát hiện sớm xu hướng suy giảm.

  6. Luôn đọc kỹ release notes khi nâng version: các khuyến nghị ở tầng kernel/cgroup có thể thay đổi theo major version. Đặc biệt, THP là thiết lập cấp hệ thống: MongoDB 7.x và 8.x có khuyến nghị khác nhau, nên nếu chạy mixed versions cần tách nhóm node/pool theo baseline kernel tuning để tránh xung đột.

Khi các nguyên tắc này được thực thi nhất quán, Kubernetes sẽ trở thành một bệ phóng phù hợp để MongoDB mở rộng linh hoạt và duy trì tính sẵn sàng cao, đáp ứng các yêu cầu production khắt khe trong doanh nghiệp.

Link hữu ích: https://github.com/mongodb/helm-charts/tree/main/charts