Usecase K8s thực tế: cách tôi cải thiện hơn 23% hiệu suất

Chẳng là trong quá trình làm việc cũng có docs lại khá nhiều kiến thức, kinh nghiệm thực tế. Lại vừa được DevOps VietNam duyệt cho viết bài nên cũng muốn đóng góp công sức nhỏ bé nào đó để giúp cộng đồng mình phát triển như bao anh em vẫn đang thầm lặng chia sẻ. “Cho đi là còn mãi”.

Hôm nay mình muốn chia sẻ tới mọi người usecase này khá hay ho khi mình xử lý performance cho một cụm Kubernetes (k8s) có domain (chuyên phục vụ dịch vụ) streaming real-time, với lưu lượng khá lớn và kiến trúc microservices phức tạp.

Vấn đề gặp phải

Cụm K8s vận hành ổn định, nhưng quy mô ngày càng mở rộng:

  • Tổng số Service lên đến hơn 250, chủ yếu là backend xử lý streaming, API realtime và pipeline data.
  • Tổng băng thông đo được vào khoảng 850Mbps, chưa đến mức khủng nhưng đủ để gây áp lực lên networking layer.

Thời gian đầu, hệ thống sử dụng kube-proxy với chế độ mặc định là iptables, iptables thì anh em làm việc chắc rất quen thuộc rồi hay có thể nói là gần như các doanh nghiệp On-premise, Private cloud đều dùng cũng mạnh mẽ và tiện lợi. Mọi thứ chạy ổn… cho đến khi số lượng service bắt đầu phình to, thời gian response tăng lên, CPU load ở các node nhích dần, đặc biệt là các node chạy nhiều kube-proxy rule.

Bài toán đặt ra: Làm sao để tăng performance cho cụm k8s đó.

Biểu hiện

  • Độ trễ giữa các Pod trong cùng namespace bắt đầu dao động, nhất là ở thời điểm load cao.
  • Các Service HTTP xuất hiện hiện tượng timeout chớp nhoáng, tuy không quá thường xuyên nhưng rất khó chịu.
  • Nhìn vào Prometheus thấy CPU system tăng cao bất thường ở một vài node, trong khi ứng dụng không thay đổi gì đáng kể.

Phân tích

Sau một vài vòng profiling và kiểm tra các thành phần kube-proxy, mình nhận thấy:

  • iptables hoạt động theo dạng duyệt tuần tự rule (linear scan). Khi số lượng service nhiều, bảng rule của iptables phình to, thời gian xử lý tăng theo.
  • Thử chạy iptables-save | wc -l trên một node random thấy hơn 6.000 dòng rule.
  • Truy cập Service nhiều lần, response không đều, CPU kube-proxy không cao nhưng system CPU của node thì bất thường rõ ràng bottleneck ở lớp netfilter của kernel.

Giải pháp: chuyển sang ipvs

Mình quyết định chuyển kube-proxy sang chế độ ipvs, một chế độ hoạt động hiệu quả hơn cho các cụm có nhiều Service.

Các bước thực hiện:

1) Chỉnh lại config kube-proxy (hoặc khi dùng kubeadm thì edit configmap):

kind: KubeProxyConfiguration
mode: "ipvs"

2) Cài thêm gói hỗ trợ IPVS nếu hệ thống chưa có:

apt install ipset ipvsadm

3) Khởi động lại kube-proxy trên các node.

  • Ngay sau khi chuyển đổi, toàn bộ các rule iptables được thay thế bằng bảng IPVS routing, với khả năng lookup gần như O(1) nhờ cơ chế hash table hoặc scheduling (RR, LC,…).

Simple is not easy

Nếu bạn chưa từng chạy cụm Kubernetes production tương đối, chưa từng tự tay mổ xẻ hệ thống, chưa từng nghi ngờ chính kube-proxy, chưa từng hỏi tại sao CPU system tăng bất thường… thì bạn sẽ không bao giờ nghĩ đến chuyện phải chuyển sang IPVS.

Giải pháp đơn giản. Nhưng để tìm ra được nó, mình đã phải:

  • So sánh biểu đồ latency giữa các Pod ở cùng và khác namespace.
  • Mò vào Prometheus để phân tách CPU user vs CPU system.
  • Đào log kube-proxy, phân tích cách nó tạo rule trong chế độ iptables.
  • Chạy iptables-save | wc -l trên từng node để kiểm tra độ phình của rule.
  • Đọc lại tài liệu chính thức của Kubernetes về các mode của kube-proxy.
  • So sánh hiệu năng giữa iptables vs ipvs vs eBPF ở mặt lý thuyết.
  • Xem lại kernel netfilter hoạt động thế nào khi rule lên tới hàng nghìn dòng.
  • Kiểm tra khả năng tương thích của IPVS với CNI plugin đang dùng.
  • Tính toán rủi ro downtime khi restart kube-proxy hàng loạt.
  • Và quan trọng nhất: đủ hiểu hệ thống để dám đụng vào nó lúc đang chạy.

Đó là lý do tại sao “simple” không bao giờ đồng nghĩa với “easy”. Nó chỉ đơn giản sau khi bạn hiểu chuyện. Mà để hiểu, bạn phải trả giá bằng thời gian, mồ hôi, và đôi khi cả downtime.

Giảm overhead từ phần header (xử lý thêm)

Phần này chính là lúc thể hiện role “DevOps=Dev+Ops”. Ngoài iptables ra, team backend cũng phát hiện rằng một phần nguyên nhân nữa gây chậm là do các header truyền giữa service khá nặng:

  • Một số request HTTP truyền JWT rất dài, kèm thêm metadata trace, correlation ID,…
  • Tổng dung lượng header trong một số request lên tới hơn 3–5KB.

Do đó, mình đề xuất team backend nén các phần header này trước khi truyền, sau đó giải mã tại nơi nhận:

  • Tùy theo ngôn ngữ, có thể dùng Gzip, Brotli hoặc Base64-encoded gzip.
  • Nhiều trường hợp đơn giản chỉ cần rút gọn nội dung không cần thiết là đủ.

Kết quả thực tế

Sau khi áp dụng cả hai thay đổi:

Tốc độ xử lý tăng khoảng 23,6% so với trước (đo bằng thời gian response trung bình từ ingress gateway):

  • CPU system giảm rõ rệt ở các node bị ảnh hưởng.
  • Độ ổn định của traffic cao hơn, không còn thấy timeout ngẫu nhiên.
  • Tụi mình không cần scale thêm node mà vẫn đáp ứng được gấp đôi lưu lượng test.

Một số lưu ý quan trọng

Mục iptables ipvs
Performance khi nhiều service Chậm Tốt hơn nhiều
Dễ debug Dễ nhìn rule Phải dùng ipvsadm, ipset
Tính tương thích Rộng rãi Cần kernel hỗ trợ IPVS (đa số đã có)
Routing Tuyến tính Hỗ trợ nhiều thuật toán: RR, LC, etc
Setup ban đầu Không cần gì Cần cài thêm gói & chỉnh kube-proxy config

Tổng kết

Việc chuyển từ iptables sang ipvs là một trong những bước tối ưu “nhỏ nhưng có võ”, đặc biệt hữu ích khi bạn bắt đầu vận hành một cụm Kubernetes có số lượng service lớn và lưu lượng mạng đáng kể. Phương pháp này mình research thấy đã được benchmark nhiều lần (ví dụ bởi Alibaba Cloud, AntGroup,…), thường cho kết quả cải thiện từ 10–30% trong cụm lớn.

Ngoài ra, tối ưu về mặt dữ liệu truyền qua header (nếu ứng dụng có cấu trúc Microservice) cũng là một mảnh ghép quan trọng. Đừng chỉ nghĩ đến hạ tầng, nhiều khi vấn đề nằm ở chính payload của ứng dụng (nên tại sao mới gọi Dev+Ops=DevOps).

Hy vọng chia sẻ này sẽ giúp anh em DevOps nào đang “vật lộn” với performance của kube-proxy có thêm góc nhìn và hướng giải quyết. Thời gian tới có thời gian chia sẻ dần các thứ hữu ích thực tế để anh em cùng nhau học hỏi nhé.

Chia sẻ bài viết:
Theo dõi
Thông báo của
0 Góp ý
Được bỏ phiếu nhiều nhất
Mới nhất Cũ nhất
Phản hồi nội tuyến
Xem tất cả bình luận