Hiệu ứng của việc định cấu hình vm.overcommit_memory


41

Máy chủ web VPS của tôi chạy trên CentOS 5.4 (nhân Linux 2.6.16.33-xenU) không thường xuyên (như mỗi tháng một lần hoặc mất vài tuần) trở nên không phản hồi do bị kẻ giết người tấn công. Theo dõi máy chủ cho thấy nó không hoạt động bình thường hết bộ nhớ, chỉ là rất thường xuyên.

Tôi đã đọc một vài blog trỏ đến trang này , trong đó thảo luận về việc định cấu hình kernel để quản lý tốt hơn các phần mềm sử dụng các cài đặt sysctl sau:

vm.overcommit_memory = 2
vm.overcommit_ratio = 80

Sự hiểu biết của tôi về điều này (có thể sai, nhưng tôi không thể tìm thấy một định nghĩa chính tắc để làm rõ) là điều này ngăn hạt nhân phân bổ quá mức bộ nhớ ngoài trao đổi + 80% bộ nhớ vật lý.

Tuy nhiên, tôi cũng đã đọc một số nguồn khác cho rằng các cài đặt này không phải là một ý tưởng hay - mặc dù những người chỉ trích phương pháp này dường như đang nói "đừng làm gì để phá vỡ hệ thống của bạn, thay vì cố gắng loại bỏ" này trong giả định rằng nhân quả luôn được biết đến.

Vì vậy, câu hỏi của tôi là, những ưu và nhược điểm của phương pháp này là gì , trong bối cảnh máy chủ web Apache2 lưu trữ khoảng 10 trang web có lưu lượng truy cập thấp? Trong trường hợp cụ thể của tôi, máy chủ web có RAM 512Mb, với không gian hoán đổi 1024Mb. Điều này dường như là đủ cho phần lớn thời gian.

Câu trả lời:


32

Đặt overcommit_ratiothành 80 có thể không phải là hành động đúng. Đặt giá trị thành bất cứ thứ gì dưới 100 hầu như luôn luôn không chính xác.

Lý do cho điều này là các ứng dụng linux phân bổ nhiều hơn mức chúng thực sự cần. Nói rằng họ phân bổ 8kb để lưu trữ một chuỗi ký tự của một vài ký tự. Vâng, đó là vài KB không được sử dụng ngay tại đó. Các ứng dụng làm điều này rất nhiều, và đây là những gì overcommit được thiết kế cho.

Vì vậy, về cơ bản với overcommit ở mức 100, kernel sẽ không cho phép các ứng dụng phân bổ bất kỳ bộ nhớ nào nhiều hơn bạn có (trao đổi + ram). Đặt nó ở mức dưới 100 có nghĩa là bạn sẽ không bao giờ sử dụng tất cả bộ nhớ của mình. Nếu bạn định đặt cài đặt này, bạn nên đặt cài đặt cao hơn 100 vì kịch bản được đề cập trước, khá phổ biến.

Bây giờ, đối với vấn đề của bạn với trình kích hoạt sát thủ OOM, cài đặt thủ công quá mức sẽ không thể khắc phục điều này. Cài đặt mặc định (xác định heuristic) khá thông minh.

Nếu bạn muốn xem liệu đây có thực sự là nguyên nhân của vấn đề hay không, hãy nhìn vào /proc/meminfokhi kẻ giết người OOM chạy. Nếu bạn thấy nó Committed_ASgần CommitLimit, nhưng freevẫn hiển thị bộ nhớ trống, thì có, bạn có thể tự điều chỉnh phần thừa cho kịch bản của mình. Đặt giá trị này quá thấp sẽ khiến kẻ giết OOM bắt đầu giết các ứng dụng khi bạn vẫn còn nhiều bộ nhớ. Đặt nó quá cao có thể khiến các ứng dụng ngẫu nhiên bị chết khi chúng cố gắng sử dụng bộ nhớ mà chúng được phân bổ, nhưng thực tế không có sẵn (khi tất cả bộ nhớ thực sự đã sử dụng hết).


1
Cảm ơn - Tôi đang thử mọi thứ với overcommit_ratio được đặt thành 100 để xem điều gì sẽ xảy ra. Vấn đề chính tôi gặp phải là khi oom-killer bắt đầu, nó luôn giết chết sshd ngăn tôi truy cập vào máy chủ và xem những gì đang xảy ra. Tôi đoán những gì tôi thực sự cần là ngăn chặn kẻ giết người chạy và một số phương tiện ghi lại những gì xảy ra khi nó chạy để tôi có thể tìm ra nguyên nhân của vấn đề.
dunxd

4
@dunxd bạn có thể sử dụng /proc/<PID>/oom_score_adjcho mục đích này. Ví dụ: nếu bạn đặt oom_score_adj thành -1000 cho sshd, kẻ giết người oom sẽ không bao giờ nhắm mục tiêu sshd khi nó muốn giết một cái gì đó. Ngăn chặn hoàn toàn kẻ giết người oom không phải là một ý tưởng hay vì khi đó các chương trình của bạn sẽ không thể chiếm được bộ nhớ malloc, và dù sao chúng cũng sẽ chết.
Patrick

4
@dunxd nó được thừa hưởng. có tập lệnh init của bạn tự đặt nó và bất cứ điều gì được bắt đầu bởi tập lệnh init đều kế thừa nó.
Patrick

4
Ví dụ 4 KB của bạn là sai. Bộ nhớ ảo được sử dụng với các trang và kích thước (nhỏ nhất) của một trang trong Linux là 4 KB. Điều đó có nghĩa là lưu trữ một vài ký tự yêu cầu 4 KB được ánh xạ ở đâu đó bất kể cài đặt quá mức. Một ví dụ thích hợp về bộ nhớ theo cam kết sẽ là ví dụ bạn phân bổ 10 KB và chỉ sử dụng 4100 byte đầu tiên. Điều đó có nghĩa là hai trang 4 KB cần lưu trữ dữ liệu và một trang phụ không được sử dụng. Các hệ thống không hoạt động quá mức sẽ luôn có trang thứ ba sẵn sàng lưu trữ dữ liệu nếu nhu cầu đến, các hệ thống cam kết sẽ không thực thi điều đó.
jlliagre

2
/ Proc / self trỏ đến quy trình hiện tại, vì vậy / Proc / self / oom_score_adj có thể được sử dụng để thay đổi oom_score_adj của quy trình hiện tại.
r_2

23

Phần 9.6 "Overcommit và OOM" trong tài liệu mà @dunxd đề cập là đặc biệt đồ họa về sự nguy hiểm của việc cho phép overcommit. Tuy nhiên, 80trông tôi cũng thú vị, vì vậy tôi đã tiến hành một vài thử nghiệm.

Những gì tôi tìm thấy là overcommit_ratioảnh hưởng đến tổng RAM có sẵn cho TẤT CẢ các quy trình. Các quy trình root dường như không được đối xử khác với các quy trình người dùng thông thường.

Đặt tỷ lệ thành 100hoặc ít hơn sẽ cung cấp ngữ nghĩa cổ điển trong đó các giá trị trả về malloc/sbrklà đáng tin cậy. Đặt tỷ lệ thấp hơn 100có thể là một cách để dự trữ thêm RAM cho các hoạt động không xử lý như bộ nhớ đệm và vv.

Vì vậy, trên máy tính của tôi có 24 GiB RAM, bị vô hiệu hóa trao đổi, 9 GiB đang sử dụng, tophiển thị

Mem:  24683652k total,  9207532k used, 15476120k free,    19668k buffers
Swap:        0k total,        0k used,        0k free,   241804k cached

Dưới đây là một số overcommit_ratiocài đặt và mức độ RAM mà chương trình người tiêu dùng ram của tôi có thể lấy (chạm vào từng trang) - trong mỗi trường hợp, chương trình thoát ra một cách sạch sẽ một lần mallocthất bại.

 50    ~680 MiB
 60   ~2900 MiB
 70   ~5200 MiB
100  ~12000 MiB

Chạy nhiều lần cùng một lúc, ngay cả với một số người dùng root, đã không thay đổi tổng số tiền họ tiêu thụ cùng nhau. Thật thú vị khi nó không thể tiêu thụ 3+ GiB cuối cùng; những freekhông thả hơn nhiều so gì được hiển thị ở đây:

Mem:  24683652k total, 20968212k used,  3715440k free,    20828k buffers

Các thử nghiệm rất lộn xộn - bất cứ điều gì sử dụng malloc tại thời điểm tất cả RAM đang sử dụng đều có xu hướng bị sập, vì nhiều lập trình viên rất tệ trong việc kiểm tra lỗi malloc trong C, một số thư viện bộ sưu tập phổ biến bỏ qua hoàn toàn, và C ++ và nhiều ngôn ngữ khác thậm chí còn tệ hơn

Hầu hết các triển khai ban đầu của RAM tưởng tượng mà tôi thấy là xử lý một trường hợp rất cụ thể, trong đó một quy trình lớn duy nhất - nói 51% + bộ nhớ khả dụng - cần thiết để fork()thực hiện exec()một số chương trình hỗ trợ, thường là một chương trình nhỏ hơn nhiều. Các hệ điều hành với ngữ nghĩa sao chép khi ghi sẽ cho phép fork(), nhưng với điều kiện là nếu quá trình rẽ nhánh thực sự cố gắng sửa đổi quá nhiều trang bộ nhớ (mỗi trang sẽ phải được khởi tạo thành một trang mới độc lập với quy trình lớn ban đầu) nó sẽ bị giết Quá trình cha mẹ chỉ gặp nguy hiểm nếu phân bổ thêm bộ nhớ và có thể xử lý hết, trong một số trường hợp chỉ cần chờ một chút để một quá trình khác chết, và sau đó tiếp tục. Quá trình con thường chỉ thay thế nó bằng một chương trình (thường nhỏ hơn) thông quaexec() và sau đó được miễn phí của proviso.

Khái niệm overcommit của Linux là một cách tiếp cận cực đoan để cho phép cả hai fork()xảy ra cũng như cho phép các quy trình đơn lẻ được tổng thể hóa một cách ồ ạt. Trường hợp tử vong oom-killer-gây ra xảy ra không đồng bộ, thậm chí để chương trình làm phân bổ bộ nhớ xử lý trách nhiệm. Cá nhân tôi ghét sự quá tải trên toàn hệ thống nói chung và kẻ giết người nói riêng - nó thúc đẩy cách tiếp cận ma quỷ có thể quan tâm đến việc quản lý bộ nhớ lây nhiễm các thư viện và thông qua chúng mọi ứng dụng sử dụng chúng.

Tôi khuyên bạn nên đặt tỷ lệ thành 100 và có phân vùng trao đổi cũng thường chỉ được sử dụng bởi các quy trình lớn - thường chỉ sử dụng một phần rất nhỏ của chính chúng bị nhồi vào trao đổi, và do đó bảo vệ phần lớn các quy trình khỏi hành vi giết người OOM. Điều này sẽ giữ cho máy chủ web của bạn an toàn khỏi cái chết ngẫu nhiên và nếu nó được viết để xử lý có malloctrách nhiệm, thậm chí an toàn khỏi việc tự sát (nhưng không đặt cược vào cái sau).

Điều đó có nghĩa là tôi đang sử dụng cái này trong /etc/sysctl.d/10-no-overcommit.conf

vm.overcommit_memory = 2
vm.overcommit_ratio = 100

Và bạn có khuyên bạn nên giữ vm.overcommit_memory thành 2 không?
Út xD

1
Lưu ý tốt - đó thực sự là những gì tôi đang sử dụng; Tôi nghĩ rằng tôi đã bỏ qua nó trong câu trả lời của mình vì nó đã có trong câu hỏi
Alex North-Keys
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.