Chạy Kafka trên VM đã dạy chúng tôi điều gì về tư duy hệ thống

Công nghệ28 tháng 8, 2026·13 phút đọc

Bài viết chia sẻ hành trình của đội ngũ kỹ thuật tại Moniepoint khi quyết định chuyển hệ thống Kafka từ các máy ảo (VM) truyền thống sang nền tảng Strimzi trên Kubernetes. Quyết định này không xuất phát từ sự cố mà từ nhận thức sâu sắc rằng cách vận hành thủ công đang kìm hãm khả năng mở rộng và tư duy hệ thống. Tác giả nhấn mạnh bài học cốt lõi: khi cơ sở hạ tầng được viết dưới dạng mã và vận hành một cách khai báo, đội ngũ có thể chuyển từ trạng thái chữa cháy sang thiết kế hệ thống tự vận hành.

Chạy Kafka trên VM đã dạy chúng tôi điều gì về tư duy hệ thống

Chạy Kafka trên VM đã dạy chúng tôi điều gì về tư duy hệ thống

Hầu hết các câu chuyện về hạ tầng thường được viết sau khi có sự cố. Câu chuyện này thì khác. Không ai gọi đội ngũ của Celestina Amadi lúc 3 giờ sáng vì Kafka. Các VM vẫn hoạt động, nhưng cô đã quyết định xây dựng lại toàn bộ vì cô có thể nhìn thấy vấn đề trước khi chúng trở thành thảm họa. Đây là bài học về sự chủ động, tư duy hệ thống và giá trị của việc chuyển từ vận hành thủ công sang tự động hóa.

Celestina Amadi dẫn dắt đội ngũ Cloud Engineering chịu trách nhiệm về hạ tầng cho các sản phẩm thanh toán và tiết kiệm của Moniepoint. Hệ thống của họ xử lý dữ liệu giao dịch và tiết kiệm một cách đáng tin cậy cho hàng triệu khách hàng mỗi ngày. Cô cũng là Grafana Champion, HashiCorp Ambassador và IBM Champion 2026.

Tại sao chúng tôi chuyển sang Strimzi: Đó không phải khủng hoảng, mà là quyết định

Chúng tôi chuyển sang Strimzi vì đã nhìn nhận một cách trung thực cách chúng tôi vận hành Kafka và đưa ra lựa chọn có chủ đích: cách này không thể mở rộng được nữa, và chúng tôi có thể làm tốt hơn.

Loại quyết định này thực ra khó hơn là phản ứng với một cuộc khủng hoảng. Sự cố thì rõ ràng — có gì đó hỏng, bạn sửa nó. Thay đổi kiến trúc mang tính chủ động đòi hỏi bạn phải nhìn đủ rõ để hành động dựa trên sự bất tiện trước khi nó thành thảm họa. Nó đòi hỏi bạn phải nói rằng "cái này đang hoạt động, nhưng chưa đủ tốt" và thực sự tin điều đó.

Đây là câu chuyện về những gì chúng tôi thấy, những gì chúng tôi xây dựng, và những gì nó dạy chúng tôi về tư duy hệ thống.

Cách chúng tôi vận hành Kafka trước đây

Thiết lập Kafka của chúng tôi bắt đầu theo cách giống như hầu hết các đội ngũ kỹ thuật phát triển nhanh: thực dụng. Chúng tôi cần các pipeline CDC (Change Data Capture). Di chuyển dữ liệu từ Database A đến Kafka rồi đến Database B, từ Database C đến Kafka rồi đến Database D. Nhiều pipeline, mỗi pipeline phục vụ một luồng nghiệp vụ khác nhau. Chúng tôi khởi tạo các instance Kafka trên VM và quản lý bằng Docker Compose khi cần. Chúng hoạt động. Chúng tôi tiếp tục công việc khác.

Theo thời gian, các vết nứt bắt đầu lộ ra:

  • Mọi thay đổi đều cần SSH và port-forwarding. Các instance Kafka không có URL. Bạn truy cập chúng qua localhost. Để thực hiện bất kỳ thay đổi nào — thêm source connector, thêm sink, hay cập nhật cấu hình — bạn phải SSH vào server, port-forward để truy cập cục bộ, rồi thay đổi thủ công. Lần nào cũng vậy, ở mọi instance.
  • Downtime chỉ cách một lệnh docker compose restart. Quản lý Kafka bằng Docker Compose hoạt động cho đến khi nó không còn hoạt động. Bất kỳ bản cập nhật hay sửa lỗi nào yêu cầu khởi động lại stack đồng nghĩa với việc hy vọng quá trình khởi động lại diễn ra suôn sẻ. Đối với một pipeline dữ liệu, đó không phải là một vị trí thoải mái.
  • Phiên bản ngày càng cũ và việc nâng cấp phải làm từng instance. Kafka phát triển liên tục, nhưng vì mỗi instance là một VM riêng được quản lý độc lập, nâng cấp có nghĩa là phải vào từng máy một. Tệ hơn, các instance của chúng tôi còn không nhất quán: một số chạy ZooKeeper, một số đã áp dụng Raft khi Kafka phát triển. Các mô hình đồng thuận khác nhau, hành vi vận hành khác nhau, và những điều cần biết trước khi đụng vào cũng khác nhau.
  • Cấp phát một pipeline mới giống như phát minh lại bánh xe. Không có quy trình chuẩn, không có cấu hình dùng chung. Mỗi pipeline CDC mới là một loạt quyết định: dùng phiên bản nào, mô hình đồng thuận nào, cấu hình ra sao. Kiến thức về cách mỗi cluster hoạt động nằm trong đầu người thiết lập nó.
  • Giám sát hoàn toàn thủ công. Chúng tôi dùng JMX Exporter để lấy metrics và sau đó chuyển log sang Loki. Những công cụ này có ích, nhưng chúng chỉ là lớp phủ trên một mô hình vận hành vẫn đòi hỏi bạn phải SSH vào đúng instance để chẩn đoán bất cứ thứ gì. Không có một cái nhìn thống nhất về toàn bộ hệ thống.

Không có gì trong số này "hỏng" theo cách kích hoạt báo động. Nó chỉ chậm, thủ công và ngày càng thiếu nhất quán khi hệ thống phát triển. Chúng tôi đang tiêu tốn thời gian kỹ thuật cho các tác vụ vận hành lẽ ra phải tự động.

Strimzi là gì?

Trước khi đi vào chi tiết triển khai, cần hiểu ý tưởng cốt lõi. Strimzi là Kafka chạy trên một cụm Kubernetes, được quản lý bởi một Kubernetes operator. Operator là một phần mềm chạy bên trong cụm và liên tục quản lý một ứng dụng khác thay cho bạn. Nó theo dõi một tập hợp các file cấu hình và đảm bảo trạng thái thực tế của Kafka deployment luôn khớp với những gì bạn khai báo. Nếu có sự lệch lạc, operator sẽ tự sửa. Nếu một broker gặp sự cố, operator sẽ đưa nó trở lại.

Sự thay đổi then chốt: bạn không còn là người vận hành nữa. Phần mềm trở thành người vận hành.

Strimzi là mã nguồn mở và là một phần của CNCF — không mất phí bản quyền, không bị khóa vào nhà cung cấp. Mọi thứ được thể hiện thông qua Kubernetes custom resources (CRDs), nghĩa là toàn bộ thiết lập Kafka của bạn là mã nằm trong Git.

Cách chúng tôi triển khai

Chúng tôi không chỉ đơn giản thả Strimzi vào một cụm có sẵn và coi như xong. Chúng tôi đã đưa ra những quyết định có chủ đích về cấu trúc:

  • Cụm Kubernetes riêng biệt: Chúng tôi tạo một cụm chuyên dụng cho khối lượng công việc Kafka trên GCP/GKE. Việc tách Kafka sang cụm riêng giúp ranh giới tài nguyên rõ ràng và dễ quản lý dung lượng độc lập với các workload ứng dụng khác.
  • Cô lập namespace cho từng pipeline: Trong cụm đó, mỗi Kafka deployment nằm trong một namespace riêng. Pipeline từ DB A đến DB B có namespace riêng. DB C đến DB D có namespace khác. Thay vì "một VM cho một pipeline", giờ là "một namespace cho một pipeline" — với sự cô lập thực sự. Một cấu hình sai trong namespace này không thể tiêu tốn tài nguyên hoặc ảnh hưởng đến tính khả dụng của namespace khác.
  • Template YAML làm chuẩn: Chúng tôi tạo các template cluster Strimzi chuẩn hóa. Khi cần một instance Kafka mới cho pipeline, bạn lấy template, điền các trường liên quan và áp dụng. Mỗi template bao gồm toàn bộ stack: định nghĩa Kafka cluster, Kafka Connect, node pool và cấu hình metrics. Mọi instance mới đều nhất quán vì chúng xuất phát từ cùng một điểm khởi đầu.
  • ArgoCD cho sources, sinks và cấu hình: Mọi connector (source, sink, cấu hình) được định nghĩa trong một file YAML và nằm trong Git repository. Để thêm source hoặc sink mới, bạn viết một file YAML và mở một merge request. Khi nó được merge, ArgoCD tự động nhận thay đổi và đồng bộ lên cluster. Operator áp dụng từ đó.
  • Image Kafka Connect tùy chỉnh như một nguồn sự thật duy nhất: Chúng tôi mở rộng image Strimzi Kafka chính thức và nhúng tất cả các connector chúng tôi dùng, bao gồm Debezium connectors cho CDC (PostgreSQL, MySQL và Spanner) cùng ClickHouse, MongoDB, S3 và Confluent JDBC connector kèm JDBC drivers tương ứng. Tất cả phiên bản connector được khai báo rõ ràng trong Dockerfile. Khi cần nâng cấp connector, chúng tôi chỉnh một dòng trong Dockerfile và build image mới. Khi có phiên bản Kafka mới, chúng tôi rebase lên image Strimzi cập nhật. Một nơi duy nhất, một PR duy nhất, operator triển khai trên toàn bộ cluster.

Điều gì thay đổi trong công việc hàng ngày

Sự khác biệt trong vận hành hàng ngày là ngay lập tức:

  • Không còn SSH: Hết cảnh port-forwarding. Để thêm source hoặc sink, bạn viết YAML và push. Operator áp dụng nó. Việc từng đòi hỏi truy cập terminal vào VM giờ chỉ là một pull request được review và merge.
  • Không còn restart Docker Compose: Strimzi quản lý vòng đời broker. Bạn không còn phải docker compose down một production data pipeline nữa.
  • Scale chỉ là một con số trong file: Cần thêm broker? Đổi một giá trị trong YAML. Operator xử lý việc đặt chỗ và đảm bảo trạng thái cluster nhất quán. Cần giảm? Tương tự, nó xử lý việc loại bỏ một cách nhẹ nhàng (graceful decommissioning).
  • Logging không còn là khảo cổ học: Log của mọi broker có sẵn qua công cụ Kubernetes tiêu chuẩn — kubectl logs từ terminal, hoặc trực tiếp trong Lens hoặc k9s nếu bạn thích giao diện. Chúng tôi vẫn gửi log đến Loki để lưu trữ lâu dài và truy vấn xuyên cluster.
  • Một giao diện duy nhất hiển thị mọi thứ: Chúng tôi dùng Kafbat nội bộ, cho cái nhìn thống nhất về tất cả cluster: sức khỏe broker, trạng thái connector, độ trễ consumer và metadata topic. Khi connector lỗi, bạn thấy lý do tại sao, kiểm tra cấu hình và hiểu vấn đề ngay từ trình duyệt. Không cần terminal.
  • Rolling updates không downtime: Nâng cấp Kafka diễn ra từng broker một, operator đảm bảo quorum được duy trì trong suốt quá trình. Hầu hết các bản cập nhật cluster giờ đây diễn ra mà hệ thống downstream không hề nhận ra.
  • Tự phục hồi: Nếu broker sập, operator khởi động lại. Nếu Kubernetes không thể sắp xếp lịch trên node hiện tại, nó chuyển đến nơi khác. Bạn nhận được cảnh báo rằng có sự cố đã xảy ra và đã được xử lý — chứ không phải một cuộc gọi lúc nửa đêm yêu cầu bạn tự sửa.

Mô tả kiến trúcMô tả kiến trúc

Một vài lý do đáng nói thêm

Phần trên đã bao quát phần lớn câu chuyện, nhưng có ba điểm không xuất hiện trong câu chuyện hàng ngày:

  • Tiết kiệm chi phí: Strimzi là mã nguồn mở, không mất phí bản quyền. Chạy Kafka trong cùng Kubernetes cluster với consumers và producers cũng cắt giảm chi phí egress mạng mà bạn phải trả nếu lưu lượng đi qua ranh giới VPC để đến một Kafka endpoint bên ngoài.
  • Độ trễ thấp hơn: Khi producers và consumers nằm trong cùng cluster với Kafka, đường mạng giữa chúng ngắn. Thiết lập bên ngoài có thêm các bước nhảy (hops). Đối với pipeline CDC throughput cao, sự khác biệt này là đo lường được.
  • Môi trường nhất quán: Vì toàn bộ thiết lập là YAML trong Git và được đồng bộ bởi ArgoCD, việc nhân bản từ production sang staging rất đơn giản — điền template, trỏ đến namespace khác và áp dụng. Cùng cấu hình chạy production có thể chạy local trong Minikube để gỡ lỗi.

Đây là quyết định đúng cho chúng tôi, nhưng không phải ai cũng vậy

Strimzi đáng dùng nếu:

  • Bạn đã chạy Kubernetes hoặc thực sự cam kết với nó
  • Bạn đang quản lý nhiều Kafka pipeline với cấu hình không nhất quán
  • Đội ngũ của bạn đang tiêu tốn thời gian thực cho SSH, quản lý connector thủ công, hoặc cập nhật phiên bản từng instance
  • Bạn muốn GitOps trở thành thực hành thực sự — không chỉ là khái niệm
  • Bạn có đủ độ chín về Kubernetes để quản lý operators một cách an toàn

Strimzi có lẽ không phù hợp nếu:

  • Kafka chỉ là phụ trợ cho sản phẩm của bạn. Hãy dùng Confluent Cloud được quản lý hoặc Amazon MSK
  • Tổ chức của bạn chưa thoải mái với Kubernetes
  • Bạn có một cluster duy nhất, đơn giản, được tối ưu tốt và không gây vấn đề
  • Bạn cần SLA hỗ trợ thương mại. Strimzi được cộng đồng hậu thuẫn, không có hỗ trợ thương mại
  • Bạn muốn các tích hợp sẵn có cho giám sát, cảnh báo hoặc schema registry ngay khi cài đặt. Với Strimzi, bạn phải tự nối chúng

Với chúng tôi, các tín hiệu đã rõ ràng: nhiều pipeline chạy không nhất quán, SSH và Docker Compose ngốn thời gian kỹ thuật, không có tầm nhìn thống nhất, và chúng tôi đã có sẵn khoản đầu tư Kubernetes. Câu hỏi thực sự duy nhất là tại sao chúng tôi không làm sớm hơn.

Bài học: Bạn không thể tư duy hệ thống khi đang chìm trong vận hành

Nhìn lại, điều lớn nhất mà việc chạy Kafka trên VM dạy chúng tôi không phải về Kafka. Nó nói về chi phí hạ tầng thủ công mà bạn khó đo lường được.

Mỗi tác vụ riêng lẻ đều quản lý được. Nhưng nhìn chung, công việc thủ công đã tiêu thụ không gian nhận thức lẽ ra nên dành cho việc suy nghĩ về hệ thống như một tổng thể. Chúng tôi quá bận quản lý trạng thái hiện tại đến mức không bao giờ lùi lại để thiết kế cách chúng nên hoạt động.

Kafka trên cloudKafka trên cloud

Việc chuyển sang Strimzi không chỉ giảm gánh nặng vận hành; nó thay đổi những gì đội ngũ của chúng tôi có thể nghĩ đến.

Khi hạ tầng là mã, bạn có thể lập luận về nó. Khi vận hành là khai báo, bạn có thể dự đoán chúng. Khi sự phức tạp hiển thị rõ trong Kafbat thay vì bị chôn vùi trong các instance rời rạc, bạn có thể đưa ra quyết định kiến trúc thay vì chỉ chữa cháy. Kỹ sư mới có thể đọc YAML và hiểu toàn bộ thiết lập Kafka. Các thay đổi được review trước khi diễn ra. Hệ thống cho bạn biết khi có gì sai và thường tự sửa trước khi bạn kịp tham gia.

Đó chính là sự thay đổi quan trọng: từ những người vận hành giữ cho hệ thống chạy, thành những kỹ sư thiết kế hệ thống tự chạy.

Kết nốiKết nối

Những quyết định như trong bài viết này không đến từ việc săn lùng sự cố. Chúng đến từ một đội ngũ có tiêu chuẩn đặt câu hỏi "điều này có thực sự đủ tốt không?" trước khi có thứ gì đó buộc phải đặt câu hỏi đó.

Nếu bạn muốn xây dựng các hệ thống tự vận hành thay vì dành cả sự nghiệp để giữ cho hệ thống không sụp đổ, Moniepoint đang tìm kiếm những con người như bạn. Hãy khám phá các vị trí kỹ thuật đang tuyển tại Moniepoint.

Chia sẻ:FacebookX
Nội dung tổng hợp bằng AI, mang tính tham khảo. Xem bài gốc ↗