"Resource temporarily unavailable": 리눅스 PID 고갈, 더 이상 당황하지 마세요!

2026. 5. 22. 08:00IT_Issue

반응형

안녕하세요, 여러분! 개발과 운영의 경계를 넘나들며 다양한 시스템 문제를 해결해 온 저에게도 등골이 오싹해지는 순간은 찾아옵니다. 특히나 리눅스 서버에서 겪었던 PID(Process ID) 고갈 및 사용자 프로세스 제한 장애는 그야말로 ‘조용한 재앙’이었습니다. 겉으로는 멀쩡해 보이는데, 실제로는 아무것도 할 수 없는 최악의 상황, 저와 함께 이 악몽 같은 경험의 원인을 파헤치고 확실한 해결책을 찾아봅시다!

상상해 보세요. 한가로운 주말 오후, 갑자기 모니터링 시스템에서 긴급 알람이 울립니다. 서비스 WAS에서 요청 처리가 실패하고 있다는 메시지입니다. 당황해서 서버에 SSH로 접속해보니, 어라? 접속은 됩니다. 하지만 ls, ps, sudo 같은 기본적인 명령어조차 "Resource temporarily unavailable" 에러를 뿜어내며 실행되지 않습니다. 마치 서버가 나를 밀어내는 듯한 느낌이랄까요? CPU 사용률은 10% 미만, 메모리 사용량도 평소와 다름없이 안정적입니다. '이게 대체 무슨 일이지?' 머릿속은 새하얘지고, 등에서는 식은땀이 흐르기 시작합니다.

당시 저는 CPU나 메모리 오버로드 문제를 의심했습니다. 하지만 자원 사용량은 너무나 평온했죠. 이 미스터리한 상황은 저를 한동안 헤매게 했습니다. 결국, 밤샘 분석 끝에 원인을 찾아냈을 때의 안도감과 허탈감은 이루 말할 수 없었습니다. 바로 '프로세스 생성 제한' 문제였습니다. 시스템은 여유롭지만, 새로운 프로세스를 만들 수 있는 권한이나 한계에 도달해버린 것이죠. 마치 텅 빈 넓은 주차장에 들어갈 수 있는 차량 대수에 제한이 걸려 있어, 아무리 공간이 많아도 더 이상 들어갈 수 없는 상황과 같았습니다. 이 경험을 통해 저는 리눅스 시스템의 심오한 작동 방식을 다시 한번 깨달았습니다.

PID 고갈 및 프로세스 제한 장애: 현상 (Symptom)

PID 고갈 및 프로세스 제한 장애: 현상 (Symptom)

이 문제의 가장 큰 특징은 사용자에게 혼란을 준다는 점입니다. 일반적으로 서버 장애라고 하면 CPU나 메모리, 디스크 I/O 같은 자원 사용량이 치솟는 것을 떠올리지만, 이 장애는 정반대의 모습을 보입니다.

  • "Resource temporarily unavailable" 에러: ls, ps, sudo, top 등 핵심 명령어 실행 시 이 에러 메시지가 나타납니다. 새로운 프로세스를 생성하지 못하기 때문에 명령어 실행이 불가능해지는 것이죠.
  • 신규 프로세스 생성 불가: 웹 애플리케이션(WAS)은 신규 요청을 처리하기 위해 쓰레드를 생성하거나 자식 프로세스를 띄우는데, 이 과정이 모두 실패합니다. 배치 작업 또한 새로운 프로세스를 시작하지 못해 멈춰버립니다.
  • CPU, 메모리 사용량은 정상: 이 점이 초기 원인 파악을 어렵게 만드는 주범입니다. 눈에 보이는 자원은 멀쩡한데 서비스만 죽는 기묘한 상황에 직면하게 됩니다.

원인 분석 (Root Cause Analysis)

원인분석

자, 그렇다면 왜 이런 이상한 현상이 발생하는 것일까요? 원인은 크게 세 가지로 분류할 수 있습니다.

  • 기술적 원인: `nproc` 제한 도달
    리눅스 시스템은 각 사용자가 생성할 수 있는 최대 프로세스/쓰레드 수를 제한합니다. 이 제한 값은 nproc이라고 불리며, 특정 사용자 계정(예: WAS를 실행하는 계정)이 이 제한에 도달하면 더 이상 새로운 프로세스를 만들 수 없습니다. 심지어 SSH 세션도 새로운 셸 프로세스를 띄워야 하기 때문에 접속은 되더라도 명령어 실행이 막히는 것이죠.
  • 구조적 원인: 애플리케이션의 비정상적인 동작
    이것이 가장 흔하고 복잡한 원인 중 하나입니다.
    • 쓰레드 풀 관리 부실: 애플리케이션이 쓰레드 풀을 제대로 관리하지 못하거나, 특정 로직에서 쓰레드가 무한정 생성되고 소멸되지 않아 좀비 프로세스처럼 누적되는 경우가 있습니다.
    • 무한 루프 또는 비정상적인 로직: 특정 코드 로직이 잘못되어 단시간 내에 수만 개의 쓰레드나 프로세스를 생성하고 종료하지 않는 버그가 있을 수 있습니다. 예를 들어, 외부 시스템과의 연결이 끊어졌을 때 재시도 로직에서 무한정 연결 시도 쓰레드를 생성하는 경우 등이 이에 해당합니다.
  • 설정적 원인: 너무 낮게 설정된 `nproc` 값
    /etc/security/limits.conf 파일에는 시스템의 사용자별 자원 제한이 정의되어 있습니다. 여기에 설정된 nproc soft/hard 제한 값이 운영 환경의 트래픽이나 애플리케이션의 특성을 고려하지 않고 너무 낮게(예: 기본값인 1024) 설정된 경우 문제가 발생할 수 있습니다. 특히 컨테이너 환경이나 마이크로서비스 아키텍처에서는 각 서비스가 독립적인 프로세스를 많이 생성할 수 있으므로, 이 제한 값을 더 높게 설정해야 합니다.

핵심 인사이트: PID 고갈은 단순히 프로세스가 많아서 생기는 문제가 아닙니다. '프로세스를 더 이상 생성할 수 없다'는 시스템의 굳건한 선언이며, 이는 시스템 자원이 충분해 보여도 발생할 수 있는 논리적인 한계점에 도달했음을 의미합니다.

문제 진단 방법 (How to Analyze)

장애 발생 시 침착하게 다음 단계를 따라 원인을 분석할 수 있습니다. 물론, 명령어 실행 자체가 어렵다면 재부팅이 먼저겠지만요.

  • 현재 프로세스 수 확인:
    • 전체 프로세스/쓰레드 수: ps -efL | wc -l
    • 특정 사용자 계정의 프로세스 점유 확인: ps -eo user,pid,cmd --sort=+user | grep | wc -l 이 명령어로 특정 서비스 계정이 얼마나 많은 프로세스를 점유하고 있는지 파악할 수 있습니다.
  • 커널 파라미터 점검:
    • ulimit -a 명령어를 실행하여 max user processes 값을 확인합니다. 이 값이 현재 문제의 주범인 nproc soft limit입니다. 기본값인 4096이 아니라 1024 등으로 낮게 설정된 경우 문제의 원인이 될 수 있습니다.
    • 시스템 전체의 최대 PID 값도 확인합니다: cat /proc/sys/kernel/pid_max. 이 값은 시스템이 할당할 수 있는 PID의 총량입니다.
  • 로그 분석:
    • /var/log/messages 또는 /var/log/syslog 파일을 확인합니다. `fork` 관련 시스템 에러 메시지(예: `kernel: pid_max limit reached` 또는 `kernel: Possible unhandled exception: fork() failed`)나 `task: XXXXX: (daemon) blocked for more than 120 seconds` 같은 로그가 포착된다면 PID 고갈을 강력하게 의심할 수 있습니다.

긴급 조치 및 재발 방지 (Action Plan)

조치방안
w

문제 발생 시 서비스 중단을 최소화하기 위한 긴급 조치와 함께, 장기적인 재발 방지 대책을 세우는 것이 중요합니다.

긴급 조치

  • 비정상 프로세스 강제 종료: 로그 분석이나 ps -efL (간신히 실행된다면) 결과로 비정상적으로 많은 프로세스를 점유하고 있는 사용자 계정이나 프로세스를 찾아 kill -9 명령어로 강제 종료하여 여유 PID를 확보합니다. (단, 명령어 실행이 어려운 상황이 많습니다.)
  • 서버 재부팅: 다른 방법이 없다면 최후의 수단으로 서버를 재부팅합니다. 이는 프로세스 테이블을 초기화하고 모든 제한을 초기 상태로 되돌립니다. 물론 서비스 중단이 수반되지만, 빠르게 정상화할 수 있는 가장 확실한 방법입니다.

설정 변경 및 재발 방지

  • `limits.conf` 파일 수정: /etc/security/limits.conf 파일에서 해당 서비스 계정(예: `wasuser`)의 nproc 값을 적정 수준으로 상향 조정합니다. 일반적으로 65535 이상으로 설정하여 충분한 여유를 두는 것이 좋습니다.
    # /etc/security/limits.conf 예시
    wasuser soft nproc 65535
    wasuser hard nproc 65535
    이후 서버 재부팅 또는 해당 계정으로 새로 로그인해야 변경 사항이 적용됩니다.
  • `sys.kernel.pid_max` 검토: 시스템 전체의 최대 PID 값인 /proc/sys/kernel/pid_max도 함께 검토하여 충분한지 확인합니다. 이 값은 일반적으로 32768 또는 65536으로 설정되어 있지만, 매우 큰 시스템에서는 더 높일 수도 있습니다.
  • 애플리케이션 코드 수정: 가장 근본적인 해결책은 애플리케이션 코드 레벨에서 쓰레드/프로세스 생성 후 반드시 자원을 적절히 반납(close/exit)하도록 로직을 수정하는 것입니다. 특히 쓰레드 풀을 사용하는 경우, 풀의 크기 및 반납 로직을 꼼꼼히 검토해야 합니다.
  • 모니터링 시스템 강화: 프로세스 수(Process Count) 항목을 모니터링 시스템에 추가하고, nproc 제한 값의 80% 정도에 도달하면 조기 알람을 발생시키도록 설정합니다. 이는 장애 발생 전 예방적 조치를 취할 수 있도록 도와줍니다.

결론 (Verdict)

리눅스 PID 고갈 및 사용자 프로세스 제한 장애는 겉으로 드러나는 증상과 실제 원인이 달라 초기 대응에 어려움을 겪게 만드는 까다로운 문제입니다. 하지만 시스템의 nproc 제한, 애플리케이션의 프로세스/쓰레드 관리 방식, 그리고 커널 파라미터에 대한 이해를 바탕으로 충분히 예방하고 해결할 수 있습니다.

저는 이 경험을 통해 시스템의 '보이지 않는' 제한 사항들이 얼마나 치명적인 서비스 장애를 유발할 수 있는지 뼈저리게 느꼈습니다. 여러분도 이러한 지식을 바탕으로 더욱 견고하고 안정적인 시스템을 구축하시길 바랍니다. 사전에 예방하고 모니터링을 강화하는 것이 가장 중요합니다!

FAQ (자주 묻는 질문)

Q: PID 고갈은 왜 CPU, 메모리 사용량은 낮게 보이나요?
A: PID 고갈은 프로세스 생성 자체에 문제가 있는 것이지, 생성된 프로세스들이 CPU나 메모리를 과도하게 사용하는 문제가 아니기 때문입니다. 새로운 프로세스를 시작할 수 없는 상황이므로, 기존 프로세스들이 자원을 적게 쓰고 있다면 전체적인 사용량은 낮게 보일 수 있습니다. 이는 시스템의 '자원 부족'이 아니라 '권한/한계 부족'에 가깝습니다.
Q: `nproc` 값은 어느 정도로 설정하는 것이 좋나요?
A: 서비스의 특성(사용하는 쓰레드/프로세스 수)과 시스템의 규모에 따라 다르지만, 일반적으로 웹 서비스 WAS 계정의 nproc 값은 65535 이상으로 설정하여 충분한 여유를 두는 것이 안전합니다. 이는 대부분의 운영 환경에서 충분한 값으로 사용됩니다.
Q: `limits.conf` 변경 후 재부팅이 필수인가요?
A: limits.conf 파일의 변경 사항은 일반적으로 새 로그인 세션부터 적용됩니다. 따라서 이미 로그인된 세션이나 시스템 시작 시 데몬으로 실행되는 서비스에는 즉시 적용되지 않을 수 있습니다. 확실한 적용을 위해서는 해당 서비스 계정으로의 재로그인, 서비스 재시작, 또는 서버 재부팅이 권장됩니다.
Q: 개발 환경에서도 이 문제를 겪을 수 있나요?
A: 네, 물론입니다. 개발 중인 애플리케이션에 쓰레드나 프로세스 관리 버그(예: 무한 루프로 쓰레드를 생성하거나 자원을 반환하지 않는 코드)가 있다면, 로컬 개발 환경에서도 nproc 제한에 도달하여 비슷한 문제를 겪을 수 있습니다. 개발 단계에서부터 이러한 잠재적 문제를 인지하고 테스트하는 것이 중요합니다.

 

반응형