Linux Namespace와 PID namespace에서 발생하는 fork 오류 해결하기

greenTea·2025년 5월 28일

Linux Namespace란?

Linux Namespace는 프로세스들의 시스템 리소스를 격리하는 커널 기능입니다. 같은 물리적 서버에서 실행되는 프로세스들이 마치 독립적인 시스템에서 실행되는 것처럼 보이게 만들어줍니다. Docker와 같은 컨테이너 기술의 핵심 구성 요소이기도 합니다.

Namespace의 종류

Linux에서는 현재 7가지 타입의 namespace를 제공합니다:

Namespace설명격리 대상
PIDProcess ID namespace프로세스 ID와 프로세스 트리
NETNetwork namespace네트워크 인터페이스, IP주소, 라우팅 테이블
MNTMount namespace파일시스템 마운트 포인트
UTSUnix Timesharing Systemhostname, domain name
IPCInter-Process Communication메시지 큐, 세마포어, 공유 메모리
USERUser namespace사용자 ID, 그룹 ID
CGROUPControl Group namespacecgroup 계층 구조

기본 사용법

# 현재 프로세스의 namespace 확인
ls -la /proc/$/ns/

# 새로운 namespace에서 실행
unshare --net bash        # 네트워크 격리
unshare --uts bash        # hostname 격리  
unshare --pid --fork bash # 프로세스 격리

# 기존 namespace에 진입
nsenter -t [PID] --all bash

# 모든 namespace 목록 확인
lsns

실제 활용 예시

1. 네트워크 격리 테스트

# 네트워크 namespace 생성
unshare --net bash
ip addr show  # lo 인터페이스만 존재
ping 8.8.8.8  # 연결 불가

2. hostname 독립 설정

# UTS namespace 생성
unshare --uts bash
hostname my-container     # 다른 터미널에는 영향 없음

3. 완전한 격리 환경

# 여러 namespace 조합
unshare --pid --net --mount --uts --ipc --fork bash

문제 발생

Linux에서 namespace 기능을 테스트하던 중 PID namespace를 사용할 때 아래와 같은 오류가 발생하면서 프로세스가 제대로 실행되지 않는 상황이 발생하였습니다.

[root@localhost cgroup]# unshare --pid sh
sh-5.1# whoami
root
sh-5.1# whoami
sh: fork: 메모리를 할당할 수 없습니다
sh-5.1# 

첫 번째 whoami 명령은 성공하지만, 두 번째부터는 "메모리를 할당할 수 없습니다"라는 fork 오류가 발생했습니다.

원인 분석

구글링과 테스트를 통해 알아본 바 --fork 옵션이 누락되어서 발생한 문제였습니다.

문제가 발생하는 이유

unshare --pid sh 명령을 실행하면:

  1. 새로운 PID namespace가 생성됩니다
  2. 하지만 현재 프로세스(sh)는 여전히 호스트의 PID를 유지합니다
  3. 새 namespace에서 PID 1(init 프로세스)이 없는 상태가 됩니다
  4. 새 프로세스 생성 시 커널이 불완전한 namespace 상태를 감지하여 fork()를 거부합니다

프로세스 트리 비교

잘못된 방법 (--fork 없음):

# 호스트에서 ps 확인
802 ?        00:00:00 sshd
   2854 pts/0    00:00:00  |    \_ unshare
   2855 pts/0    00:00:00  |        \_ sh    # 호스트 PID 유지

올바른 방법 (--fork 있음):

# namespace 내에서 독립적인 프로세스 트리 생성
PID 1: sh (init 역할)
PID 2: whoami

첫 번째 whoami가 성공하는 이유

  • 불완전한 namespace 진입: 프로세스가 namespace는 바뀌었지만 PID는 그대로 유지
  • 일시적 성공: 첫 번째 실행은 특별한 커널 처리나 캐시된 결과로 성공할 수 있음
  • 두 번째부터 실패: 새로운 프로세스 생성이 필요할 때 커널의 엄격한 검사로 실패

해결 방법

unshare 명령에 --fork 옵션을 추가해주시면 됩니다.

올바른 명령어

unshare --pid --fork sh

해결 후 결과

[root@localhost cgroup]# unshare --pid --fork sh
sh-5.1# whoami
root
sh-5.1# whoami
root
sh-5.1# echo $$
1
sh-5.1# ps aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.0  12196  3584 pts/0    S    10:30   0:00 sh
root           2  0.0  0.0  44768  3456 pts/0    R+   10:30   0:00 ps aux

--fork 옵션의 역할

  • 새로운 프로세스 생성: namespace 내에서 새 프로세스가 PID 1이 됩니다
  • init 프로세스 역할: PID 1이 있어야 다른 프로세스들을 관리할 수 있습니다
  • 정상적인 프로세스 트리: fork()가 제대로 작동합니다

다른 namespace와의 차이점

# UTS, Network namespace는 --fork 불필요
unshare --uts sh         # 정상 작동
unshare --net sh         # 정상 작동

# PID namespace는 --fork 필수!
unshare --pid --fork sh  # 정상 작동

추가 팁

PID namespace 확인 방법

# 현재 PID 확인
echo $$                    # namespace 내에서는 1

# namespace ID 확인  
readlink /proc/self/ns/pid

# 프로세스 목록 확인
ps aux                     # 독립적인 프로세스 트리

완전한 컨테이너 환경 구성

# 여러 namespace를 함께 사용
unshare --pid --net --mount --uts --ipc --fork bash

위 방법을 통해 PID namespace에서 발생하는 fork 오류 문제를 해결할 수 있었습니다.

참고자료

profile
greenTea입니다.

0개의 댓글