Cách khắc phục và phòng tránh lỗi OOMKilled Kubernetes chi tiết

Đã kiểm duyệt nội dung
Đánh giá
OOMKilled là một trạng thái lỗi phổ biến trong Kubernetes, báo hiệu rằng một container đã bị hệ điều hành chủ động kết thúc do tiêu thụ bộ nhớ vượt quá giới hạn cho phép. Khi một container vượt quá giới hạn bộ nhớ được khai báo trong resources.limits.memory hoặc khi node cạn kiệt RAM, Linux OOM Killer sẽ gửi tín hiệu SIGKILL để buộc dừng tiến trình. Trong bài viết này, mình sẽ giúp bạn hiểu rõ hơn các nguyên nhân dẫn đến lỗi OOMkilled Kubernetes, cách khắc phục và phòng tránh hiệu quả.
Những điểm chính
- Khái niệm OOMKilled Kubernetes: Hiểu rõ OOMKilled là trạng thái lỗi do thiếu bộ nhớ, giúp bạn nhanh chóng xác định nguyên nhân gốc rễ khiến container bị dừng đột ngột.
- Nguyên nhân gây lỗi: Nắm vững các nguyên nhân phổ biến từ cấu hình sai đến rò rỉ bộ nhớ, giúp bạn có một danh sách kiểm tra hiệu quả để khoanh vùng và chẩn đoán sự cố.
- Quy trình chẩn đoán: Nắm vững các bước kiểm tra từ kubectl describe đến phân tích metrics, giúp bạn thu thập đầy đủ thông tin để xác định chính xác nguyên nhân gây ra lỗi.
- Cách khắc phục: Tìm hiểu các giải pháp hiệu quả từ việc điều chỉnh giới hạn tài nguyên đến tối ưu hóa mã nguồn ứng dụng, giúp bạn có những hành động cụ thể để xử lý triệt để sự cố.
- Cách phòng tránh lỗi: Nắm được các phương pháp hay nhất trong việc cấu hình và giám sát, giúp bạn chủ động phòng tránh sự cố và xây dựng một hệ thống ổn định, bền vững hơn.
- Biết thêm Vietnix là nhà cung cấp Cloud Server mạnh mẽ, giúp bạn có một nền tảng hạ tầng đáng tin cậy để phòng tránh các lỗi OOMKilled.
- Câu hỏi thường gặp: Giải đáp các thắc mắc liên quan đến OOMKilled Kubernetes.

OOMKilled Kubernetes là gì?
OOMKilled (Out Of Memory Killed) trong Kubernetes là trạng thái cho biết container hoặc pod đã bị Linux Kernel kết thúc do vượt quá giới hạn bộ nhớ được phân bổ hoặc nút hệ thống gặp phải tình trạng quá tải bộ nhớ. Trạng thái này thường được hệ thống báo cáo kèm theo mã lỗi Exit Code 137.
Thực chất, cơ chế này được điều khiển bởi tính năng OOM Killer của nhân Linux. Khi hệ thống phát hiện một container tiêu thụ nhiều RAM hơn mức giới hạn đã thiết lập hoặc khi toàn bộ Node bị cạn kiệt bộ nhớ, Linux OOM Killer sẽ can thiệp và tiêu diệt tiến trình ngốn nhiều RAM nhất để bảo vệ sự ổn định của toàn hệ thống. Sau đó, Kubernetes sẽ ghi nhận trạng thái của Pod chứa container đó là OOMKilled.

Để giảm thiểu lỗi OOMKilled, Kubernetes cần được chạy trên một hạ tầng mạnh mẽ. Enterprise Cloud của Vietnix cung cấp nền tảng IaaS với CPU AMD EPYC và ổ cứng 100% NVMe Enterprise hiệu năng cao. Đặc biệt, dịch vụ hỗ trợ tự triển khai, quản lý các cụm Kubernetes trực tiếp ngay trên giao diện, đảm bảo tài nguyên cho container luôn được phân bổ một cách ổn định và mượt mà.
Nguyên nhân phổ biến gây lỗi OOMKilled Kubernetes
Container dùng vượt giới hạn bộ nhớ cấu hình
Trong nhiều trường hợp, container bị OOMKilled vì workload tiêu thụ RAM vượt quá giá trị resources.limits.memory được khai báo trong manifest pod/deployment. Khi đó, dù node vẫn còn bộ nhớ tổng thể, kernel vẫn kích hoạt OOM Killer để kết thúc tiến trình container vượt limit, dẫn tới trạng thái OOMKilled và exit code 137.
Một nguyên nhân liên quan khác là ứng dụng có nhu cầu bộ nhớ đỉnh (peak) cao hơn cấu hình limit, ví dụ khi load tăng đột biến, xử lý batch lớn hoặc cache nội bộ mở rộng, khiến container thường xuyên chạm ngưỡng limit. Nếu limit đặt quá thấp so với hành vi thực tế của ứng dụng, hiện tượng OOMKilled sẽ lặp lại kể cả khi node chưa thực sự thiếu RAM.
Rò rỉ bộ nhớ trong ứng dụng
Lỗi trong code ứng dụng hoặc thư viện có thể gây rò rỉ bộ nhớ, khiến lượng RAM sử dụng tăng dần theo thời gian mà không được giải phóng, cuối cùng chạm limit container hoặc làm node thiếu bộ nhớ. Các workload chạy lâu (long‑running service, worker xử lý queue) đặc biệt dễ gặp tình trạng này nếu không có cơ chế quản lý bộ nhớ và chu kỳ restart hợp lý.
Ngoài ra, những thao tác tốn nhiều bộ nhớ như deserialization lớn, xử lý file/buffer kích thước cao, join dữ liệu nặng hoặc cấu hình JVM/GC không phù hợp (heap quá lớn so với limit) cũng góp phần đẩy container vào trạng thái OOMKilled. Việc thiếu quan sát về pattern sử dụng bộ nhớ theo thời gian khiến các spike bất ngờ này khó được phát hiện sớm.
Cấu hình giới hạn bộ nhớ quá thấp
Khi request/limit của pod được đặt không cân đối (limit quá thấp, request quá cao hoặc ngược lại), scheduler có thể đưa pod lên node không thực sự đủ “headroom” cho các đỉnh bộ nhớ, làm node thường xuyên bị áp lực RAM. Trong bối cảnh nhiều pod cùng chia sẻ tài nguyên, chỉ cần một số workload sử dụng vượt dự kiến cũng đủ làm kernel kích hoạt OOM Killer để giải phóng bộ nhớ trên node.
Ngoài cấu hình pod, bản thân node có thể bị thiếu tài nguyên do overcommit (quá nhiều pod so với khả năng RAM vật lý) hoặc các tiến trình hệ thống/daemon ngoài Kubernetes tiêu thụ đáng kể bộ nhớ. Khi tổng dung lượng sử dụng tiến gần 100%, OOM Killer sẽ chọn một hoặc nhiều process để terminate, dẫn đến việc một số container trong cluster bị gắn trạng thái OOMKilled dù chính chúng không vượt limit riêng của mình.
Ứng dụng tiêu thụ tài nguyên không kiểm soát
Một số ứng dụng được thiết kế để sử dụng tài nguyên một cách tích cực (ví dụ: các ứng dụng lưu trữ cache trong bộ nhớ hoặc xử lý dữ liệu hàng loạt). Nếu lập trình viên không thiết lập cơ chế giới hạn số lượng kết nối hoặc kích thước tệp xử lý trong mã nguồn, ứng dụng sẽ tiêu thụ bộ nhớ vô hạn và dẫn đến lỗi OOMKilled.

Quy trình kiểm tra và chẩn đoán lỗi OOMKilled Kubernetes
Kiểm tra trạng thái pod, container và sự kiện
Bước 1: Bạn chạy kubectl get pods -n <namespace> và xác định pod có trạng thái CrashLoopBackOff, Error hoặc OOMKilled trong cột STATUS.
Bước 2: Bạn dùng kubectl describe pod <tên-pod> -n <namespace> để xem chi tiết, chú ý phần Containers và Last State có Reason = OOMKilled và exit code 137 hay không.
Bước 3: Kiểm tra phần Events trong output kubectl describe để ghi nhận thời điểm xảy ra OOM, số lần restart và node mà pod đang chạy.
Bước 4: Chạy kubectl top pod <tên-pod> -n <namespace> để xem mức sử dụng RAM hiện tại, sau đó đối chiếu với giá trị resources.requests.memory và resources.limits.memory trong manifest deployment/statefulset.
Bước 5: Bạn chạy kubectl top node để kiểm tra tổng tài nguyên bộ nhớ trên node, từ đó đánh giá node có đang trong trạng thái thiếu RAM hay container chỉ đơn thuần vượt limit riêng.
Phân tích log, metric và lịch sử sử dụng bộ nhớ
Bước 1: Bạn dùng kubectl logs <tên-pod> -c <tên-container> -n <namespace> để xem log hiện tại. Nếu pod đã restart, bạn dùng thêm --previous để xem log của lần chạy trước khi bị OOMKilled.
Bước 2: Tìm kiếm trong log các dấu hiệu tăng tải, thao tác xử lý dữ liệu lớn, lỗi ngoại lệ hoặc cảnh báo liên quan đến bộ nhớ, GC, heap (đặc biệt với JVM, Node.js, Python).
Bước 3: Mở dashboard Prometheus/Grafana hoặc công cụ quan sát đang dùng, truy vấn metric memory (ví dụ container_memory_usage_bytes, container_memory_working_set_bytes) cho pod/container trong khoảng thời gian trước khi xảy ra OOM.
Bước 4: Quan sát biểu đồ để xác định pattern: tăng dần theo thời gian (nghi rò rỉ bộ nhớ), spike đột ngột tại một thời điểm (workload nặng) hay thường xuyên chạm sát giá trị limit.
Bước 5: Bạn ghi lại mối tương quan giữa lượng request, job xử lý và footprint bộ nhớ để chuẩn bị cho bước điều chỉnh request/limit hoặc tối ưu mã nguồn.
Sử dụng công cụ monitoring và profiling chuyên sâu
Bước 1: Đầu tiên bạn tích hợp cluster với nền tảng monitoring/APM như Lumigo, Komodor hoặc công cụ tương tự nếu chưa có, đảm bảo các pod gửi metric, log và trace đầy đủ.
Bước 2: Bạn mở dashboard hoặc màn hình chuyên cho sự cố OOMKilled/exit code 137 (nếu nền tảng hỗ trợ), lọc theo namespace, deployment hoặc service gặp sự cố.
Bước 3: Xem timeline sự kiện: thời điểm pod bị OOMKilled, biểu đồ memory usage, CPU, số request/throughput và các thay đổi cấu hình gần đó (deploy mới, scaling…).
Bước 4: Nếu nghi ngờ rò rỉ bộ nhớ, bạn bật cơ chế profiling của runtime (heap dump, allocation profiling) trong môi trường staging hoặc môi trường production được kiểm soát, sau đó phân tích đối tượng chiếm dụng RAM bất thường.
Bước 5: Dựa trên kết quả monitoring và profiling, phân loại nguyên nhân (limit quá thấp, memory leak, workload đỉnh, node thiếu tài nguyên) để lựa chọn giải pháp phù hợp ở các bước xử lý tiếp theo.
Cách khắc phục OOMKilled cho pod
Tăng giới hạn bộ nhớ cho Container
Cách xử lý trực tiếp nhất là rà soát lại resources.requests.memory và resources.limits.memory của pod/deployment dựa trên số liệu sử dụng thực tế từ metric. Nếu pod thường xuyên chạm limit nhưng node vẫn còn tài nguyên, có thể tăng dần limit (và nếu cần thì cả request) đến mức đáp ứng được đỉnh sử dụng bộ nhớ quan sát được, tránh tăng bộ nhớ không theo dữ liệu.
Với các workload cùng chia sẻ node, cần đảm bảo tổng request không vượt quá dung lượng RAM của node và phân bổ phù hợp theo mức độ ưu tiên từng ứng dụng. Trong một số trường hợp, việc tách workload nặng sang node pool riêng hoặc sử dụng QoS Class cao hơn (Guaranteed) cho dịch vụ quan trọng cũng góp phần giảm rủi ro bị OOMKilled.
Tối ưu ứng dụng và runtime
Khi metric cho thấy ứng dụng sử dụng bộ nhớ tăng dần ngay cả khi lưu lượng không đổi, cần kiểm tra và xử lý rò rỉ bộ nhớ trong code hoặc thư viện. Các biện pháp thường dùng gồm: giải phóng tài nguyên sau khi dùng (kết nối, buffer, đối tượng lớn), giới hạn kích thước batch, stream dữ liệu thay vì load toàn bộ vào RAM và sử dụng cấu trúc dữ liệu phù hợp hơn.
Với ứng dụng chạy trên JVM, Node.js hoặc runtime có tham số heap, cần cấu hình kích thước heap/bộ nhớ nội bộ tương ứng với limit của container, tránh để runtime tự động lấy gần hết RAM dẫn đến OOMKilled. Trong một số kịch bản, có thể áp dụng chiến lược restart định kỳ cho worker lâu sống hoặc phân tách chức năng thành nhiều pod nhỏ hơn để giảm mức tiêu thụ bộ nhớ mỗi instance.
Cấu hình probe và chiến lược restart phù hợp
Liveness và readiness probe cần được cấu hình cẩn thận để tránh tình trạng pod bị restart liên tục khi tạm thời chạm ngưỡng bộ nhớ hoặc trong lúc GC đang chạy. Nên điều chỉnh timeout, period và failureThreshold phù hợp với đặc tính ứng dụng, đồng thời đảm bảo readiness chỉ báo sẵn sàng khi pod có đủ tài nguyên hoạt động ổn định.
Bên cạnh đó, có thể xem xét cấu hình restartPolicy, backoffLimit và chiến lược rollout (rolling update, canary) để hạn chế tác động khi xảy ra chuỗi OOMKilled liên tiếp trong quá trình triển khai phiên bản mới. Việc kết hợp probe hợp lý với autoscaling (HPA dựa trên CPU/memory hoặc custom metric) cũng giúp hệ thống thích ứng tốt hơn trước các đỉnh tải, giảm khả năng pod bị OOMKilled do đột biến lưu lượng.
Tạm thời giảm tải hoặc thu nhỏ quy mô xử lý
Trong trường hợp bạn không thể cung cấp thêm RAM ngay lập tức, bạn có thể áp dụng giải pháp tạm thời là giảm tải cho ứng dụng. Quản trị viên cần cấu hình giảm số lượng tiến trình chạy song song, giảm kích thước gói dữ liệu, hoặc vô hiệu hóa các tính năng lưu cache không cần thiết để ép ứng dụng chạy trong giới hạn RAM hiện tại.

Khắc phục lỗi rò rỉ bộ nhớ từ mã nguồn
Nếu việc tăng RAM không giải quyết được vấn đề mà chỉ làm kéo dài thời gian trước khi Pod tiếp tục bị chết, ứng dụng của bạn có thể đang bị rò rỉ bộ nhớ. Lúc này cần sử dụng các công cụ phân tích bộ nhớ để tìm ra đoạn mã gây lỗi và tiến hành vá lỗi ngay trong mã nguồn.
Bổ sung tài nguyên hoặc di dời Workload trên Node
Nếu lỗi xảy ra do toàn bộ Node bị quá tải, quản trị viên hệ thống cần can thiệp ở cấp độ cụm (Cluster). Bạn có thể mở rộng cụm bằng cách thêm Node mới, hoặc sử dụng các quy tắc ràng buộc (Taints, Tolerations, Node Affinity) để dời các Pod ngốn nhiều RAM sang các Node có cấu hình cao hơn.
Phòng tránh OOMKilled Kubernetes
Thiết lập Requests và Limits chính xác
Việc khai báo resources.requests và resources.limits cần dựa trên metric thực tế thay vì ước lượng chủ quan để giảm nguy cơ container vượt limit và bị OOMKilled. Có thể bắt đầu với giá trị bảo thủ, quan sát usage bằng kubectl top và dashboard monitoring, sau đó điều chỉnh dần để cân bằng giữa an toàn và hiệu quả sử dụng tài nguyên.
Ngoài ra, nên xây dựng guideline nội bộ về dải request/limit cho từng loại workload (web, batch, worker, DB client) và áp dụng đồng nhất qua Helm chart, Kustomize hoặc policy để tránh cấu hình lệch chuẩn. Cách làm này hỗ trợ scheduler phân bổ pod lên node hợp lý hơn, hạn chế tình trạng overcommit bộ nhớ.
Triển khai hệ thống giám sát và cảnh báo
Hệ thống monitoring cần thu thập metric memory cho pod, container và node, kèm theo cảnh báo khi mức sử dụng vượt các ngưỡng nhất định (ví dụ 70–80% limit hoặc gần 100% RAM node). Điều này cho phép nhóm vận hành phát hiện sớm xu hướng tăng bộ nhớ bất thường, can thiệp trước khi kernel kích hoạt OOM Killer.
Bên cạnh metric, nên giám sát tần suất restart, số lần OOMKilled theo namespace, deployment hoặc service để nhận diện sớm workload có rủi ro cao. Các nền tảng như Lumigo, Komodor hoặc các APM khác thường cung cấp dashboard/tổng hợp chuyên biệt cho lỗi OOMKilled, hỗ trợ trực quan hóa xu hướng theo thời gian.
Tối ưu image, runtime và kiến trúc workload
Giảm kích thước container image, bỏ bớt dependency không cần thiết và dùng base image gọn nhẹ giúp hạ mức tiêu thụ bộ nhớ nền của pod. Với ứng dụng Java, Node.js, .NET,… nên cấu hình heap và tham số runtime tương ứng với limit để tránh runtime chiếm gần hết bộ nhớ container.
Ở mức kiến trúc, có thể tách các tác vụ xử lý nặng sang job/batch hoặc worker riêng, tránh dồn quá nhiều chức năng tiêu tốn RAM vào một pod. Kết hợp autoscaling (HPA/VPA) với chiến lược phân tán tải hợp lý giúp mỗi instance giữ footprint bộ nhớ ở mức kiểm soát được, giảm khả năng chạm limit.

Áp dụng tính năng tự động mở rộng tài nguyên
Để đối phó với sự thay đổi tải trọng không lường trước, quản trị viên có thể kích hoạt Vertical Pod Autoscaler (VPA). Tính năng này sẽ tự động phân tích hành vi sử dụng tài nguyên và tự động điều chỉnh các thông số CPU/RAM (requests và limits) của Pod cho phù hợp với nhu cầu thực tế mà không cần sự can thiệp thủ công.
Cấu hình Resource Quotas cho Namespace
Để ngăn chặn một ứng dụng hoặc một nhóm phát triển làm cạn kiệt tài nguyên của toàn bộ hệ thống, quản trị viên nên thiết lập Resource Quotas. Tính năng này giúp giới hạn tổng dung lượng RAM và CPU mà một Namespace cụ thể được phép tiêu thụ, đảm bảo tính công bằng và an toàn cho các dịch vụ khác cùng chạy trên cụm.

Tối ưu hóa thư viện và hiệu suất mã nguồn
Phòng tránh lỗi từ gốc rễ đòi hỏi sự tham gia của lập trình viên. Đội ngũ phát triển cần lựa chọn các thư viện tối ưu hóa cho môi trường container, quản lý bộ nhớ hiệu quả và thường xuyên thực hiện các bài kiểm tra chịu tải trên môi trường thử nghiệm để đảm bảo ứng dụng không vượt quá giới hạn RAM khi chạy thực tế.
Chủ động mở rộng tài nguyên với Vietnix Enterprise Cloud
Khả năng cấp phát RAM linh hoạt là yếu tố cốt lõi để ngăn chặn hoàn toàn OOMKilled. Thay vì bị giới hạn không gian phần cứng như VPS truyền thống, Enterprise Cloud của Vietnix mang đến một cụm tài nguyên riêng biệt, giúp bạn tự do phân bổ bộ nhớ cho hệ thống Kubernetes chỉ trong vòng 30 giây. Nhờ kiến trúc High Availability tự động phục hồi, cơ chế Replicas 3 bảo vệ an toàn dữ liệu và chi phí cố định minh bạch, doanh nghiệp có thể chủ động mở rộng hạ tầng ngay lập tức để ứng dụng luôn dồi dào tài nguyên chịu tải.
Thông tin liên hệ:
- Website: https://vietnix.vn/
- Hotline: 1800 1093
- Email: sales@vietnix.com.vn
- Địa chỉ: 265 Hồng Lạc, Phường Bảy Hiền, Thành Phố Hồ Chí Minh
Câu hỏi thường gặp
Exit code 137 luôn luôn là OOM phải không?
Exit code 137 là mã thoát biểu diễn việc tiến trình bị kết thúc bằng tín hiệu SIGKILL (9), thường xuất hiện khi hệ thống hoặc OOM Killer buộc dừng tiến trình do thiếu bộ nhớ, nhưng cũng có thể xảy ra nếu tiến trình bị kill -9 thủ công hoặc bởi công cụ/quy trình khác ngoài OOM Killer. Vì vậy, trong Kubernetes, exit code 137 thường gắn với trạng thái OOMKilled, nhưng không thể kết luận mọi trường hợp 137 đều chắc chắn là lỗi Out Of Memory nếu không kiểm tra thêm trường OOMKilled và sự kiện trong mô tả pod/container.
Làm thế nào để tránh lỗi OOMKilled?
Để hạn chế OOMKilled, cần đặt resources.requests và resources.limits bộ nhớ dựa trên số liệu thực tế, tránh limit quá thấp so với mức sử dụng đỉnh của ứng dụng, đồng thời dùng monitoring và alerting (Prometheus, Grafana,…) để phát hiện sớm pod hoặc node gần chạm ngưỡng RAM. Bên cạnh đó, nên tối ưu mã nguồn và runtime (sửa rò rỉ bộ nhớ, giới hạn batch, tinh chỉnh heap JVM/Node.js), áp dụng autoscaling, resource quotas, QoS classes và chính sách scheduling phù hợp để phân bổ workload lên các node đủ dung lượng bộ nhớ.
Làm thế nào để xem log của một container đã bị OOMKilled và khởi động lại?
Để xem log của một container đã bị OOMKilled và khởi động lại, bạn cần sử dụng cờ --previous với lệnh kubectl logs. Lệnh đầy đủ sẽ là kubectl logs <tên-pod> --previous. Lệnh này sẽ hiển thị log của lần chạy container trước khi nó bị kết thúc và khởi động lại.
OOMKilled là một trạng thái lỗi trong Kubernetes báo hiệu các vấn đề nghiêm trọng về quản lý bộ nhớ, từ việc cấu hình request/limit không hợp lý, rò rỉ bộ nhớ trong ứng dụng đến tình trạng thiếu tài nguyên trên node. Bằng cách chủ động giám sát, tối ưu hóa ứng dụng và cấu hình tài nguyên dựa trên dữ liệu thực tế, các nhà phát triển và quản trị viên có thể phòng tránh hiệu quả lỗi OOMKilled Kubernetes, đảm bảo hệ thống luôn hoạt động hiệu quả và đáng tin cậy.
THEO DÕI VÀ CẬP NHẬT CHỦ ĐỀ BẠN QUAN TÂM
Đăng ký ngay để nhận những thông tin mới nhất từ blog của chúng tôi. Đừng bỏ lỡ cơ hội truy cập kiến thức và tin tức hàng ngày














