Linux Namespace는 프로세스들의 시스템 리소스를 격리하는 커널 기능입니다. 같은 물리적 서버에서 실행되는 프로세스들이 마치 독립적인 시스템에서 실행되는 것처럼 보이게 만들어줍니다. Docker와 같은 컨테이너 기술의 핵심 구성 요소이기도 합니다.
Linux에서는 현재 7가지 타입의 namespace를 제공합니다:
| Namespace | 설명 | 격리 대상 |
|---|---|---|
| PID | Process ID namespace | 프로세스 ID와 프로세스 트리 |
| NET | Network namespace | 네트워크 인터페이스, IP주소, 라우팅 테이블 |
| MNT | Mount namespace | 파일시스템 마운트 포인트 |
| UTS | Unix Timesharing System | hostname, domain name |
| IPC | Inter-Process Communication | 메시지 큐, 세마포어, 공유 메모리 |
| USER | User namespace | 사용자 ID, 그룹 ID |
| CGROUP | Control Group namespace | cgroup 계층 구조 |
# 현재 프로세스의 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 명령을 실행하면:
잘못된 방법 (--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
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
# UTS, Network namespace는 --fork 불필요
unshare --uts sh # 정상 작동
unshare --net sh # 정상 작동
# PID namespace는 --fork 필수!
unshare --pid --fork sh # 정상 작동
# 현재 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 오류 문제를 해결할 수 있었습니다.
참고자료