기본적으로 Linux OOM 킬러를 끄시겠습니까?


37

리눅스에서 OOM 킬러는 종종 다양한 응용 프로그램으로 혼란을 겪고 있으며,이를 개선하기 위해 커널 개발 측면에서 실제로 많은 일이 수행되지 않는 것으로 보입니다. 새 서버를 설정할 때 모범 사례로서 메모리 오버 커밋의 기본값을 바꾸는 것이 vm.overcommit_memory=2좋습니다. 즉, 특정 용도로 사용하려는 것을 알지 않는 한 끄십시오 ( ). 그리고 초과 사용을 원한다는 것을 알고있는 사용 사례는 무엇입니까?

보너스는 스왑 공간 에 vm.overcommit_memory=2따라 달라 vm.overcommit_ratio지기 때문에 후자의 두 가지 크기를 조정하는 데있어 가장 좋은 방법은 무엇입니까?

답변:


63

흥미로운 비유 ( http://lwn.net/Articles/104179/ ) :

항공기 회사는 적은 연료로 비행기를 타는 것이 더 저렴하다는 것을 발견했습니다. 비행기가 가벼워지고 연료 소비가 줄어 돈이 절약되었습니다. 그러나 드문 경우이지만 연료량이 부족하여 비행기가 추락했습니다. 이 문제는 특수 OOF (연료) 메커니즘을 개발하여 회사 엔지니어가 해결했습니다. 비상 사태의 경우 승객이 선발되어 비행기에서 내 렸습니다. (필요한 경우 절차가 반복되었다.) 대규모 이론이 개발되었고 배출 될 피해자를 올바르게 선택하는 문제에 관한 많은 출판물이 전념되었다. 피해자를 무작위로 선택해야합니까? 아니면 가장 무거운 사람을 선택해야합니까? 아니면 가장 오래된? 승객이 출국하지 않기 위해 지불해야하는 경우 피해자가 가장 가난한 사람이 될 수 있도록? 예를 들어 가장 무거운 사람을 선택했다면 조종사 인 경우 특별한 예외가 있어야합니까? 일등석 승객이 면제되어야합니까? 이제 OOF 메커니즘이 존재하기 때문에 매번 활성화되어 연료 부족이없는 경우에도 승객을 배출합니다. 엔지니어들은 여전히이 오작동의 원인을 정확하게 연구하고 있습니다.


11
나는 그것을 많이 찾아 주셔서 감사합니다.
Nick Bolton

32

OOM 킬러는 시스템에 과부하가 걸리면 혼란을 초래합니다. 충분한 스왑을 제공하고 갑자기 대량의 RAM을 먹기로 결정한 응용 프로그램을 실행하지 마십시오. 문제가 없습니다.

질문에 구체적으로 답변하려면 :

  • 일반적인 경우에는 초과 커밋을 해제하는 것이 좋지 않다고 생각합니다. brk(2) (및 malloc(3) 과 같은 응용 프로그램 을 사용하는 래퍼 )에서 오류 를 올바르게 처리하도록 작성된 응용 프로그램은 거의 없습니다. 이전 작업에서 이것을 실험했을 때 OOM의 결과를 처리하는 것보다 메모리 부족 오류를 처리 할 수있는 모든 것을 얻는 것이 더 번거로운 것으로 간주되었습니다. OOM이 발생하면 가끔 서비스를 다시 시작해야하는 것보다 훨씬 더 나빴습니다.
  • 메모리를 초과 커밋하는 프로세스에 대해 초과 커밋을 수행하려고합니다. 여기서 가장 일반적인 두 가지 원인은 Apache와 JVM이지만 많은 앱이이를 다소간 또는 그 이하로 수행합니다. 그들은 생각하는 사람들이 있습니다 그들은 큰 덩어리 오른쪽의 해제를 잡아, 그래서 미래의 어떤 시점에서 많은 메모리가 필요합니다. 오버 커밋이 가능한 시스템에서 커널은 "어떻든간에, 당신이 실제로 그 페이지에 쓰려고 할 때 나를 귀찮게합니다". 오버 커밋 오프 시스템에서 커널은 "아니오, 만약 당신이 미래에 어느 시점에서 쓰기를한다면 메모리가 충분하지 않을 것입니다." 할당이 실패합니다. 아무것도 없기 때문에"아, 그래, 더 적은 양의 프로세스 데이터 세그먼트를 가질 수 있습니까?"가되면 프로세스는 (a) 메모리 부족 오류로 종료되거나 (b)에서 리턴 코드를 확인하지 않습니다. malloc은 가도 좋다고 생각하고 잘못된 메모리 위치에 기록하여 segfault를 발생시킵니다. 고맙게도 JVM은 시작시 사전 할당을 모두 수행하므로 JVM은 즉시 시작되거나 죽습니다. 일반적으로 알 수 있지만 Apache는 새 자식마다 펑키 한 작업을 수행하므로 생산에 흥미 진진한 영향을 줄 수 있습니다. "흥분의 유형).
  • overcommit_ratio를 기본값 인 50 %보다 높게 설정하고 싶지 않습니다. 다시 한 번, 테스트에서 약 80 또는 90으로 설정하면 멋진 아이디어처럼 들릴 수 있지만 커널에는 불편한 시간에 큰 메모리 덩어리가 필요하며 오버 커밋 비율이 높은 완전히로드 된 시스템에는 여분의 메모리가 충분하지 않을 수 있습니다 커널에 필요할 때 (두려움, 역병 및 oopses로 이어짐) 따라서 오버 커밋을 사용하면 메모리가 부족할 때 OOM 된 프로세스를 다시 시작하는 것이 아니라 이제 시스템이 충돌하여 시스템의 모든 것이 중단됩니다. 대박!
  • 초과 커밋없는 시스템의 스왑 공간은 응용 프로그램에 요청되었지만 사용하지 않은 메모리의 양과 안전한 안전 마진에 따라 다릅니다. 특정한 경우에 필요한 것을 해결하는 것은 독자를위한 연습으로 남습니다.

기본적으로 저의 경험은 초과 커밋을 끄는 것이 이론적으로 들리는 것처럼 실제로는 거의 효과가없는 훌륭한 실험이라는 것입니다. 이것은 커널의 다른 튜너 블에 대한 나의 경험과 잘 일치합니다. 리눅스 커널 개발자는 항상 당신보다 똑똑하고 기본값은 방대한 대다수의 경우에 가장 좋습니다 . 그것들을 내버려두고 대신 누출이있는 프로세스를 찾아서 고치십시오.


2
누군가 내 웹 서버를 DoS하고 있기 때문에 백업 프로세스가 종료되는 것을 원하지 않습니다. 예외는 괜찮지 만 기본값은 안전과 일관성이어야합니다. OOM과 같은 최적화는 IMHO를 수동으로 켜야합니다. 코딩과 마찬가지로 깔끔하게 코딩 한 다음 최적화합니다. 초과 커밋은 훌륭한 기능이지만 기본값이 아니어야합니다.
Aki

1
누군가 웹 서버를 DoS로 사용하여 백업 프로세스가 종료되지 않게하려면 DoS가 시스템의 자원을 압도 할 수있는 방식으로 웹 서버를 구성하지 마십시오.
womble

8GB의 RAM이 있고 Firefox를 실행하면 가상 시스템에서 OOM 킬러가 VM을 죽이는 경우가 있습니다. 언리얼 엔진 4를 컴파일 할 때, 각 클랜 호출은 1 ~ 1.5GB의 메모리를 사용하고 다시 한번, OOM 킬러는 매번 하나씩 죽입니다. 이제는 일반적으로 OOM 킬러가 없으면 어쨌든 segfault 일 것입니다. OOM 킬러가 프로세스를 종료하려고 할 때마다 잘못된 프로세스가 실제로 종료되기 전에 시스템이 10 분 동안 정지됩니다. 아마도 버그? 가능성이 높습니다. 내가 원하는가요? 기필코 아니다. 이것이 OOM 킬러를 비활성화하려는 이유입니다.
Shahbaz

1
상자에서 모든 작업을 수행하는 경우 더 많은 RAM이 필요하며 오버 커밋을 비활성화하면 더 악화됩니다.
Ben Lutgens

6

흠, 나는 overcommit과 OOM killer를지지하는 주장에 완전히 확신하지 못한다.

"OOM 오버 킬러는 시스템에 과부하가 걸린 경우 혼란을 초래할뿐입니다. 충분한 스왑을 제공하고 갑자기 대량의 RAM을 먹기로 결정한 응용 프로그램을 실행하지 마십시오. 문제가 없습니다."

그는 오버 커밋 및 OOM 킬러가 적용되지 않거나 실제로 동작하지 않는 환경 시나리오를 설명하고 있습니다 (모든 응용 프로그램이 필요에 따라 메모리를 할당하고 할당 할 가상 메모리가 충분하면 메모리 쓰기는 메모리 할당을 거의 따르지 않습니다. 초과 커밋 전략이 활성화 된 경우에도 실제로 초과 커밋 된 시스템에 대해 말할 수 없었습니다). 그것은 overcommit과 OOM killer가 그들의 개입이 필요하지 않을 때 가장 잘 작동한다는 암묵적 인 승인에 관한 것입니다. 이것은 내가 알 수있는 한이 전략을지지하는 대부분의 사람들이 공유합니다 (그리고 나는 말할 수 없습니다 ...). Morover, 메모리를 사전 할당 할 때 특정 동작이있는 응용 프로그램을 언급하면 ​​특정 처리가 기본값이 아닌 배포 수준에서 조정될 수 있다고 생각합니다.

JVM과 관련하여 가상 머신이므로 어느 정도 시동에 필요한 모든 리소스를 할당 해야 하므로 애플리케이션에 대한 '가짜'환경을 만들고 사용 가능한 리소스를 호스트와 분리 할 수 ​​있습니다 가능한 한 환경. 따라서 '외부'OOM 상태 (과잉 커밋 / OOM 킬러 / 무엇으로 인해 발생)의 결과로 잠시 후가 아닌 시작시 실패하거나 어쨌든 자체 상태를 방해하는 이러한 상태로 고통받는 것이 바람직 할 수 있습니다. 내부 OOM 처리 전략 (일반적으로 VM은 처음부터 필요한 리소스를 가져와야하며 호스트 시스템은 끝까지 '무시'해야합니다. 그래픽 카드와 공유되는 물리적 램의 양은 절대로 없습니다. -OS에 의해 감동 됨).

아파치에 관해서는 단일 연결과 함께 단일 자식이 (= 자식 / 연결) 시작에서 완전히 새로운 인스턴스 인 것처럼 실패하는 것보다 전체 서버가 때때로 종료되고 다시 시작되는 것이 낫습니다. 다른 인스턴스가 잠시 동안 실행 된 후 생성 된 JVM). 최고의 '솔루션'은 특정 상황에 따라 달라질 수 있습니다. 예를 들어, 전자 상거래 서비스를 고려할 때 때때로 전체 주문을 잃지 않고 쇼핑 차트와의 연결이 약간 실패하는 것이 바람직 할 수 있습니다. 예를 들어 진행중인 주문 완료를 방해하거나 (심지어 더 나쁘게) 모든 경우에 발생하는 지불 과정 (해를 끼치 지 않지만 해를 끼칠 수 있음)-문제가 발생했을 때,

같은 방식으로 워크 스테이션에서 가장 많은 리소스를 소비하는 프로세스이므로 OOM 킬러를위한 첫 번째 선택 인 테일링은 비디오 트랜스 코더 또는 렌더링 소프트웨어와 같은 메모리 집약적 응용 프로그램 일 수 있습니다. 사용자가 손대지 않고 싶어합니다. 이 고려 사항은 OOM 킬러 기본 정책이 너무 공격적이라는 것을 나타냅니다. 이 방법은 일부 파일 시스템의 접근 방식과 비슷한 "최악의 적합"접근 방식을 사용합니다 (OOMK는 가능한 한 많은 메모리를 사용하여 사용 가능한 여유 공간을 확보 함). fs는 파일이 커지면 조각화를 방지하기 위해 특정 파일에 실제로 필요한 것보다 많은 디스크 공간을 할당 할 수 있습니다.

그러나 특정 시점에서 필요한 정확한 메모리를 확보하고 '큰'프로세스를 방해하지 않기 위해 '최적의'접근 방식과 같은 반대 정책이 바람직 할 수 있다고 생각합니다. 메모리는 있지만 그렇지 않을 수도 있으며 커널은 알 수 없습니다 (흠, 페이지 액세스 추적 횟수와 시간을 유지하면 프로세스가 메모리를 할당하는 경우 더 이상 필요하지 않다는 것을 암시 할 수 있습니다. 메모리를 낭비하거나 많이 사용하고 있지만 메모리 CPU를 많이 사용하는 응용 프로그램 메모리 낭비를 구별하기 위해 CPU 사이클에 액세스 지연을 적용해야 하지만 잠재적으로 부정확 한 경우 이러한 휴리스틱은 과도한 오버 헤드를 가질 수 있습니다.

또한, 가능한 적은 프로세스를 죽이는 것이 항상 좋은 선택이라는 것은 사실이 아닐 수도 있습니다. 예를 들어, 데스크탑 환경 (샘플을 위해 제한된 리소스가있는 넷탑 또는 넷북을 생각하자)에서 사용자는 여러 탭이있는 브라우저를 실행 중일 수 있습니다 (따라서 메모리 소비-OOMK의 첫 번째 선택이라고 가정합니다) , 몇 가지 다른 응용 프로그램 (비 저장 데이터가있는 워드 프로세서, 메일 클라이언트, pdf 리더, 미디어 플레이어 등)과 몇 가지 (시스템) 데몬 및 몇 가지 파일 관리자 인스턴스가 있습니다. 이제 OOM 오류가 발생하고 OOMK는 사용자가 인터넷을 통해 '중요한'것으로 간주되는 동안 브라우저를 종료하도록 선택합니다. 사용자는 실망 할 것입니다. 반면에, 소수의 파일 관리자를 닫으면

어쨌든, 사용자는해야 할 일에 대해 스스로 결정을 내릴 수 있어야한다고 생각합니다. 데스크톱 (= 대화식) 시스템에서는 사용자가 응용 프로그램을 닫도록 요청하기 위해 충분한 리소스가 예약되어 있지만 (몇 개의 탭을 닫아도 충분할 수 있음) 자신의 선택 (옵션은 충분한 공간이있는 경우 추가 스왑 파일을 작성하십시오. 서비스 (및 일반적으로)의 두 가지 추가 개선 사항도 고려할 것입니다. 하나는 OOM 킬러 개입을 로깅하고 실패를 쉽게 디버깅 할 수있는 방식으로 실패를 시작 / 포크하는 프로세스입니다 (예 : API 프로세스에 새로운 프로세스 생성 또는 분기를 알리십시오. 따라서 적절한 패치를 가진 Apache와 같은 서버는 특정 오류에 대해 더 나은 로깅을 제공 할 수 있습니다. 이것은 오버 커밋 / OOMK가 노력하는 동안 독립적으로 수행 될 수있다. 두 번째로 중요하지는 않지만 OOMK 알고리즘을 미세 조정하는 메커니즘을 설정할 수 있습니다. 프로세스별로 프로세스별로 특정 정책을 정의하는 것이 가능하다는 것을 알고 있습니다. 하나 이상의 응용 프로그램 이름 (또는 ID) 목록을 기반으로 관련 프로세스를 식별하고 나열된 속성에 따라 어느 정도의 중요도를 부여하는 '중앙 집중식'구성 메커니즘. 이러한 메커니즘은 최상위 수준 사용자 정의 목록, 시스템 (배포) 정의 목록 및 (아래) 응용 프로그램 정의 항목이있을 수 있도록 계층화 (또는 적어도 가능)해야합니다. 예를 들어 DE 파일 관리자는 OOMK에게 인스턴스를 안전하게 종료하도록 지시 할 수 있습니다.

Morover, API는 애플리케이션이 런타임시 (메모리 관리 목적 및 실행 우선 순위에 관계없이) '중요도'수준을 높이거나 낮추도록하기 위해 제공 될 수 있습니다. 예를 들어 워드 프로세서는 '중요도'는 낮지 만 파일을 플러시하기 전에 일부 데이터를 보유하거나 쓰기 작업을 수행 할 때 데이터가 증가하고 이러한 작업이 종료되면 다시 중요도가 낮아집니다 (유사하게는 파일 관리자가 별도의 프로세스를 사용하는 대신 파일을 처리하는 데 데이터를 처리하거나 그 반대의 경우 Apache는 다른 어린이에게 다른 수준의 중요성을 부여하거나 sysadmins가 결정하고 Apache 또는 다른 종류의 서버를 통해 노출되는 일부 정책에 따라 자식 상태를 변경할 수 있습니다 -설정). 물론이야, 이러한 API는 남용 / 오용 될 수 있지만 시스템에서 발생하는 상황 (및 메모리 소비 / 생성 시간 또는 이와 유사한 시간)에 대한 관련 정보없이 커널이 임의로 프로세스를 강제 종료하여 메모리를 해제하는 것과 비교할 때 사소한 문제라고 생각합니다 '충분히 관련성이 없거나'유효성 '인 경우)-사용자, 관리자 및 프로그램 작성자 만이 프로세스가 어떤 이유로 든 여전히'필요한지 '여부, 이유가 무엇인지 및 / 또는 애플리케이션이 상태를 주도하고 있는지 확인할 수 있습니다. 사망시 데이터 손실 또는 기타 손상 / 문제; 그러나 프로세스에 의해 획득 된 특정 종류의 리소스 (파일 디스크립터, 네트워크 소켓 등)를 찾고 계류중인 작업으로 프로세스가 프로세스가 '상태'보다 높은 상태에 있는지 여부를 알 수있는 등 일부 가정은 아직 이루어지지 않았습니다. 한 세트

또는 오버 커밋을 피하고 커널이 커널이 수행해야하는 작업을 수행하도록하고 리소스를 할당하지만 (OOM 킬러와 같이 임의로 리소스를 구조하지는 않음) 프로세스를 예약하고 기아와 교착 상태를 방지 (또는 구조화)하여 완전한 선점 및 보장 메모리 공간 분리 등

또한 초과 커밋 방식에 대해 더 많은 단어를 사용합니다. 다른 토론에서 나는 초과 커밋에 대한 주요 관심사 중 하나 (원하는 이유와 가능한 문제의 원인)가 포크 처리로 구성된다는 생각을했습니다. 솔직히 말해서 정확히 쓰기 전략이 구현되었지만 공격적인 (또는 낙관적 인) 정책은 스왑과 같은 지역 전략으로 완화 될 수 있다고 생각합니다. 즉, 포크 처리 된 프로세스 코드 페이지 및 스케줄링 구조를 복제 (및 조정)하는 대신 실제 쓰기 전에 몇 개의 다른 데이터 페이지를 복사하여 상위 프로세스가 더 자주 쓰기 위해 액세스하는 페이지 중에서 선택합니다 (즉, 쓰기 작업에 카운터 사용).

물론 IMHO.


5
"Morover, 응용 프로그램이 런타임시 '중요도'수준을 높이거나 낮추기 위해 API를 제공 할 수 있습니다 /proc/$PID/oom_adj. "중요도는 입니다.
Vi.

1
JVM과 관련하여 경우에 따라 메모리 오버 커밋을 요구하는 문제가 있습니다. 원래 JVM에서 다른 JVM을 생성하려는 경우 fork ()를 호출합니다. 포크 호출은 실제로 프로세스를 시작할 때까지 원래 프로세스 (첫 번째)만큼 많은 메모리를 할당합니다. 따라서 4GB JVM을 가지고 있고 새로운 512KB JVM을 만들고 싶다고 가정 해
봅시다.

4
@Vi. 지금 보인다/proc/$PID/oom_score_adj
erm3nda

1

프로세스가 시스템의 안정성을 위협 할 수있는 정도로 메모리가 완전히 소모되면 OOM 킬러가 나타납니다. 나머지 프로세스의 원활한 기능을 위해 충분한 메모리가 확보 될 때까지 프로세스를 종료하는 것은 OOM Killer의 작업입니다. OOM Killer는 죽일 "최상의"프로세스를 선택해야합니다. 여기서 "최상"은 종료시 최대 메모리를 확보하고 시스템에 가장 중요하지 않은 프로세스를 나타냅니다. 주요 목표는 수행되는 손상을 최소화하고 동시에 사용 가능한 메모리 양을 최대화하는 프로세스 수를 최소화하는 것입니다. 이를 용이하게하기 위해 커널은 각 프로세스마다 oom_score를 유지합니다. pid 디렉토리 아래의 / proc 파일 시스템에있는 각 프로세스의 oom_score를 볼 수 있습니다

# cat /proc/10292/oom_score

모든 프로세스의 oom_score 값이 높을수록 메모리 부족 상황에서 OOM Killer에 의해 종료 될 가능성이 높습니다.

크레딧 :- 리눅스 커널이 OOM 킬러를 시작합니다

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.