13년차의 서버실

서버, 인프라, 홈랩 기술 블로그

[태그:] Linux Namespace

  • [Linux] 컨테이너 없이 리눅스 네임스페이스로 프로세스 격리하기: 실제 사례 연구

    [Linux] 컨테이너 없이 리눅스 네임스페이스로 프로세스 격리하기: 실제 사례 연구

    [리눅스] 컨테이너 없이 네임스페이스로 프로세스 격리하기

    리눅스 네임스페이스 사례를 찾다 보면 대부분 Docker나 Kubernetes 이야기로 바로 넘어가더라고요. 근데 현장에서는 꼭 컨테이너 런타임(container runtime)이 있어야만 프로세스 격리를 할 수 있는 건 아닙니다. 저도 홈랩에서 작은 배치 작업, 외부에서 받은 스크립트 검증, 네트워크가 민감한 유지보수 작업을 분리할 때 처음부터 컨테이너를 올리기엔 오버헤드가 애매한 경우가 있었거든요.

    그래서 이번 글에서는 컨테이너 원리의 핵심인 Namespace(네임스페이스, 커널 자원 뷰 분리)를 직접 써서 프로세스를 격리한 사례를 정리해보겠습니다. 제가 직접 해보니 처음엔 이게 뭔가 싶었는데, 구조를 한 번 이해하고 나니까 특정 작업을 빠르게 샌드박스(sandbox, 제한된 실행 공간)로 감싸는 데 꽤 유용했습니다. 특히 보안 강화와 시스템 설계 관점에서 어디까지 가능한지 감이 잡히더라고요.

    리눅스 네임스페이스 사례를 설명하는 프로세스 격리 아키텍처 개요 이미지

    호스트와 격리된 프로세스가 PID, 네트워크, 마운트 관점에서 어떻게 분리되는지 보여주는 개요 이미지입니다.

    1. 왜 컨테이너 없이 격리를 보려고 했는가

    실무에서 늘 Docker가 정답은 아니었습니다. 예를 들어 이런 경우가 있었습니다.

    • 운영 서버에 컨테이너 엔진 설치를 최소화해야 하는 경우
    • 일회성 스크립트를 네트워크에서 분리해 실행하고 싶은 경우
    • 빌드 작업이나 백업 검증 작업을 호스트와 다른 PID 뷰로 띄우고 싶은 경우
    • 문제 재현용 프로세스를 빠르게 분리해 테스트하고 싶은 경우

    저는 홈랩에서 외부 저장소에서 받은 백업 복구 스크립트를 바로 호스트에서 돌리기 좀 꺼려졌습니다. 사실 스크립트 한 줄 잘못되면 마운트 포인트를 건드리거나, 예상 못 한 네트워크 접근을 할 수도 있거든요. 그때 느낀 게, “아 컨테이너 이미지를 만들기 전에 커널 기능만으로도 1차 격리는 가능하겠구나”였습니다.

    2. 네임스페이스 개념 설명: 쉽게 말해 무엇이 분리되나

    쉽게 말해 Namespace(네임스페이스)는 프로세스가 보는 세상 자체를 따로 만드는 기능입니다. 같은 리눅스 커널 위에서 돌지만, 프로세스 입장에서는 자기만의 PID 목록, 네트워크 인터페이스, 호스트 이름, 마운트 뷰를 보게 되는 거죠.

    컨테이너 원리를 아주 거칠게 줄이면 이겁니다. Namespace로 보이는 범위를 나누고, Cgroup(컨트롤 그룹, 자원 사용 제한)으로 CPU/메모리를 제한하고, 파일시스템 레이어를 얹는다. 오늘은 그중 Namespace 쪽에 집중해보겠습니다.

    자주 쓰는 네임스페이스 종류

    • PID Namespace: 프로세스 ID 공간 분리
    • Mount Namespace: 마운트 포인트 뷰 분리
    • Network Namespace: 네트워크 인터페이스, 라우팅 테이블 분리
    • UTS Namespace: hostname, domainname 분리
    • IPC Namespace: 프로세스 간 통신 자원 분리
    • User Namespace: 사용자/권한 매핑 분리

    여기서 중요한 포인트! 네임스페이스만 쓴다고 완전한 보안 샌드박스가 되는 건 아닙니다. 그래도 적어도 “호스트와 같은 뷰를 그대로 공유하지 않게 한다”는 점에서 상당히 큰 차이가 납니다.

    기술별 차이 한눈에 보기

    기술 격리 범위 장점 한계
    chroot(루트 변경) 파일 경로 중심 단순함 보안 격리 수단으로는 약함
    Namespace(네임스페이스) PID, 네트워크, 마운트 등 커널 자원 뷰 가볍고 빠름 자원 제한은 별도 구성 필요
    Container(컨테이너) Namespace + Cgroup + 이미지/런타임 운영 자동화에 유리 런타임 의존성과 운영 복잡도 증가

    3. 실제 사례 연구: 백업 검증 스크립트를 안전하게 분리하기

    제가 실험한 시나리오는 이렇습니다. 백업 파일 무결성을 확인하고 압축을 풀어보는 스크립트를 테스트해야 했는데, 호스트 네트워크를 그대로 쓰게 두고 싶지 않았고, /tmp 아래에서 이것저것 생성하는 것도 호스트와 분리하고 싶었습니다. 그래서 아래 목표를 잡았습니다.

    1. 호스트와 다른 PID 공간에서 실행할 것
    2. 호스트 네트워크를 끊거나 별도 네트워크만 사용할 것
    3. 마운트 뷰를 분리해서 /proc, 작업 디렉터리를 별도로 보이게 할 것
    4. 가능하면 hostname도 바꿔서 “격리된 환경”임을 명확히 할 것

    이 작업은 컨테이너 엔진 없이도 unshare와 nsenter만으로 꽤 깔끔하게 구성할 수 있었습니다.

    리눅스 네임스페이스 사례의 실전 구성과 unshare 기반 프로세스 격리 이미지

    unshare 실행 후 PID, UTS, Mount, Network 네임스페이스가 분리되는 흐름을 설명하는 구성 이미지입니다.

    4. 실전 구현: unshare로 프로세스 격리 만들기

    실제로 써보니까 첫 진입점은 unshare가 제일 직관적이었습니다. 아래 예시는 격리된 셸(shell, 명령 실행 환경)을 띄우는 기본 형태입니다.

    4-1. 가장 기본적인 격리 셸 실행

    sudo unshare \
      --fork \
      --pid \
      --mount \
      --uts \
      --ipc \
      --net \
      --mount-proc \
      bash

    옵션 의미는 이렇습니다.

    • --fork: 새로운 프로세스로 진입
    • --pid: 새로운 PID Namespace 생성
    • --mount: 새로운 Mount Namespace 생성
    • --uts: hostname 분리
    • --ipc: IPC 자원 분리
    • --net: Network Namespace 분리
    • --mount-proc: 새 PID 공간에 맞는 /proc 마운트

    이 상태로 들어가서 ps를 치면, 호스트 전체 프로세스가 아니라 격리된 프로세스 뷰만 보입니다. 처음 확인했을 때 “오, 진짜 분리됐네” 싶더라고요. 이런 순간이 좀 재밌습니다 ㅎㅎ

    4-2. 격리 환경 안에서 hostname 바꾸기

    hostname isolated-lab
    uname -n

    UTS Namespace 덕분에 호스트 이름을 바꿔도 호스트 본체에는 영향이 없습니다. 작은 부분 같아도 테스트 로그를 볼 때 꽤 유용합니다.

    4-3. 마운트 뷰 분리와 작업 디렉터리 고립

    제가 삽질했던 부분이 여기였습니다. Mount Namespace를 만들었는데도 기존 마운트 전파(propagation) 설정 때문에 예상과 다르게 보이는 경우가 있더라고요. 그래서 보통은 아래처럼 먼저 private으로 바꿔주는 쪽이 안전했습니다.

    mount --make-rprivate /
    mkdir -p /tmp/lab-root
    mount -t tmpfs tmpfs /tmp/lab-root
    cd /tmp/lab-root

    이렇게 하면 작업 디렉터리를 메모리 기반 tmpfs로 띄워서 테스트 흔적을 최소화할 수 있습니다. 외부 스크립트를 검증할 때 꽤 편했습니다.

    4-4. 네트워크를 완전히 막고 실행하기

    Network Namespace를 새로 만들면 기본적으로 인터페이스가 거의 없는 상태로 시작합니다. “네트워크 없는 환경에서 이 스크립트가 깨끗하게 도는지” 확인할 때 딱 좋습니다.

    ip link set lo up
    ip addr
    ping -c 1 8.8.8.8

    루프백(loopback)만 올리고 외부 인터페이스를 연결하지 않으면 외부 통신은 되지 않습니다. 저는 백업 검증 스크립트가 혹시라도 외부로 뭔가 호출하는지 확인할 때 이 방법을 자주 썼습니다.

    4-5. 실제 테스트 스크립트 실행 예시

    cat > /tmp/verify-backup.sh <<'EOF'
    #!/usr/bin/env bash
    set -euo pipefail
    mkdir -p work
    cd work
    echo "test file" > sample.txt
    tar -czf sample.tar.gz sample.txt
    tar -xzf sample.tar.gz
    ps -ef
    ip addr || true
    hostname
    EOF
    
    chmod +x /tmp/verify-backup.sh
    /tmp/verify-backup.sh

    여기서 보게 되는 ps, ip addr, hostname 결과가 전부 호스트와 다르게 보이면 1차 격리는 성공입니다. 이게 컨테이너 원리 이해에도 정말 도움이 됩니다.

    프로세스 격리 결과를 보여주는 리눅스 네임스페이스 사례 터미널 이미지

    격리된 프로세스 공간과 제한된 네트워크 환경이 실제 명령 결과에서 어떻게 보이는지 보여주는 예시 이미지입니다.

    5. 조금 더 현실적인 시스템 설계 포인트

    단순 데모를 넘어서 실제 운영에 붙이려면 몇 가지를 같이 봐야 합니다.

    • User Namespace를 함께 검토해서 권한 매핑을 분리할 것
    • Cgroup으로 CPU/메모리 제한을 따로 둘 것
    • seccomp 같은 시스템 콜 필터링까지 가면 더 단단해질 것
    • 파일시스템은 가능하면 읽기 전용(read-only) 바인드 마운트도 고려할 것

    즉, Namespace는 시작점입니다. 보안 강화라는 말이 과장되지 않으려면, “무엇을 분리했고 무엇은 아직 공유하는가”를 명확히 이해해야 합니다. 저도 처음엔 네임스페이스만 쓰면 거의 컨테이너랑 같은 줄 알았는데, 운영 관점에서는 그 사이에 꽤 많은 층이 있더라고요.

    6. ⚠️ 주의사항과 트러블슈팅: 제가 실제로 막혔던 지점

    여기서는 진짜 삽질 포인트만 적어보겠습니다. 혹시 비슷한 경험 있으신가요? 아래 부분에서 많이 막힙니다.

    6-1. /proc가 기대와 다르게 보이는 문제

    원인: 새 PID Namespace를 만들었는데 /proc를 새로 마운트하지 않은 경우입니다.

    해결: --mount-proc 옵션을 쓰거나, 진입 후 직접 proc를 마운트합니다.

    mount -t proc proc /proc

    6-2. 네트워크가 완전히 끊긴 줄 알았는데 아니었던 문제

    원인: 별도 네임스페이스를 안 만들고 호스트 네트워크를 그대로 쓴 경우입니다.

    해결: --net 사용 여부를 먼저 확인하세요. 그리고 격리 환경 안에서 ip addr를 꼭 확인해야 합니다.

    6-3. 마운트가 호스트까지 영향을 주는 것처럼 보이는 문제

    원인: 마운트 전파 설정이 공유(shared) 상태인 경우입니다.

    해결: 작업 초기에 아래 명령으로 전파 범위를 조정합니다.

    mount --make-rprivate /

    6-4. 이게 보안 경계인가요? 라는 질문

    중요한 답은 “상황에 따라 다릅니다”입니다. Namespace만으로 충분한 경우도 있지만, 신뢰할 수 없는 코드를 장시간 돌리거나 외부 입력이 많은 환경이라면 추가 방어 계층이 필요합니다. 그래서 저는 보통 아래 순서로 생각합니다.

    1. Namespace로 뷰 분리
    2. Cgroup으로 자원 제한
    3. 권한 최소화
    4. 읽기 전용 마운트, 임시 작업 공간 분리
    5. 필요시 VM(가상머신) 수준 격리 검토

    7. 검증과 결과: 무엇이 달라졌는지 확인하기

    격리가 제대로 되었는지는 감으로 보면 안 됩니다. 저는 아래 항목을 체크리스트처럼 확인했습니다.

    1. ps -ef 출력에서 호스트 전체 프로세스가 보이지 않는지
    2. hostname 결과가 격리된 값으로 나오는지
    3. ip addr 결과에 호스트 인터페이스가 안 보이는지
    4. 작업 중 생성한 파일이 의도한 임시 공간에만 남는지
    5. 작업 종료 후 흔적 정리가 쉬운지

    결론부터 말하면, 컨테이너 없이도 특정 목적의 프로세스 격리는 충분히 실용적이었습니다. 특히 테스트성 작업, 분석성 작업, 외부 스크립트 검증 같은 용도에서는 빠르게 적용할 수 있었고요. 반대로 이미지 배포, 재현 가능한 패키징, 대규모 운영 자동화까지 가면 컨테이너 쪽이 더 낫습니다.

    리눅스 네임스페이스 사례의 검증 결과와 프로세스 격리 비교 요약 이미지

    PID, 네트워크, 마운트, hostname 항목별로 격리 전후 차이를 정리한 결과 요약 이미지입니다.

    8. 자주 묻는 질문 정리

    Q1. chroot만 쓰면 안 되나요?

    chroot는 파일 경로 뷰를 바꾸는 데는 유용하지만, PID나 네트워크까지 분리해주지는 않습니다. 그래서 프로세스 격리 목적이면 네임스페이스가 훨씬 적합합니다.

    Q2. 이게 Docker를 완전히 대체하나요?

    아닙니다. Docker 같은 컨테이너 도구는 이미지 관리, 배포, 네트워크 구성, 볼륨 운영까지 묶어서 편의성을 제공합니다. 네임스페이스는 그 아래 레이어를 이해하고 직접 다루는 방식에 가깝습니다.

    Q3. 어떤 상황에서 특히 유용했나요?

    저는 홈랩에서 아래 같은 상황에 잘 맞았습니다.

    • 일회성 유지보수 스크립트 검증
    • 네트워크 차단 상태 재현
    • 호스트 프로세스 목록과 분리된 테스트 셸 구성
    • 컨테이너 엔진 없는 환경에서의 임시 샌드박스

    9. 마무리: 네임스페이스를 알면 컨테이너가 더 잘 보입니다

    이번 리눅스 네임스페이스 사례를 통해 느낀 건, 컨테이너는 갑자기 하늘에서 떨어진 기술이 아니라는 점이었습니다. 결국 커널 기능을 조합해서 보안 강화와 운영 편의성을 만든 결과물이더라고요. 제가 직접 해보니 Docker 명령어만 외우던 때보다, 장애를 볼 때도 구조가 훨씬 잘 읽혔습니다.

    처음엔 unshare 옵션이 낯설고, /proc나 마운트 전파 때문에 좀 헷갈릴 수 있습니다. 저도 처음엔 꽤 헤맸거든요. 근데 한 번 손으로 만들어보면 시스템 설계 감각이 정말 좋아집니다. 다음 글에서는 이 흐름을 이어서 Cgroup(컨트롤 그룹, 자원 제한)과 함께 묶어 더 실전적인 샌드박스를 만드는 방법도 다뤄볼 예정입니다. 이전 글에서 다룬 리눅스 프로세스 관리 글이 있다면 같이 보셔도 흐름이 잘 이어질 겁니다. ✅

  • [Linux] Linux Namespace 격리 기술, 실제 적용과 검증 방법

    [Linux] Linux Namespace 격리 기술, 실제 적용과 검증 방법

    Linux Namespace 격리 기술, 실제 적용과 검증 방법

    Linux Namespace는 요즘 컨테이너 기술 이야기할 때 거의 빠지지 않는 핵심 요소입니다. Docker를 쓰든, containerd를 쓰든, Kubernetes 위에서 파드를 띄우든 결국 밑바닥에는 이런 격리 기술이 깔려 있거든요. 근데 운영하다 보면 막연히 “컨테이너는 분리돼 있다” 정도로만 이해해서는 한계가 옵니다. 장애가 났을 때 왜 프로세스는 안 보이는지, 왜 네트워크가 따로 노는지, 왜 마운트가 호스트랑 다르게 보이는지 알아야 하더라고요.

    저도 처음엔 이게 뭔가 싶었습니다. 컨테이너는 많이 올려봤는데, 정작 Linux Namespace를 직접 까보지 않으면 문제 원인을 제대로 못 잡겠더라고요. 특히 홈랩에서 테스트할 때 네트워크 네임스페이스를 잘못 건드려서 통신이 안 붙고, 마운트 네임스페이스 때문에 파일이 보였다 안 보였다 해서 삽질 좀 했습니다 ㅎㅎ 이번 글에서는 이론만 나열하지 않고, Linux Namespace를 실제로 어떻게 적용하고 검증하는지, 그리고 현업이나 홈랩에서 어디에 유용한지 경험 기준으로 풀어보겠습니다.

    Linux Namespace 격리 구조와 컨테이너 기술 아키텍처 개요 이미지

    프로세스, 네트워크, 마운트가 각각 분리되는 구조를 한눈에 보여주는 개요 이미지입니다.

    1. 왜 Linux Namespace를 이해해야 하나요

    쉽게 말해 Linux Namespace는 커널(Kernel)이 프로세스에게 보여주는 세상을 따로 나누는 기능이거든요. 같은 서버 위에서 돌아가더라도 A 프로세스는 자기 PID 목록만 보고, B 프로세스는 자기 네트워크 인터페이스만 보게 만들 수 있습니다. 이게 컨테이너 기술의 출발점입니다.

    여기서 중요한 포인트! 가상머신(Virtual Machine)은 커널까지 통째로 분리하는 방식이고, Namespace는 같은 커널을 공유하면서 보이는 범위만 나누는 방식입니다. 그래서 더 가볍고 빠릅니다. 대신 보안 경계(Security Boundary)로 과신하면 안 됩니다. 저도 처음엔 “분리됐으니 완전히 안전하겠지”라고 생각했는데, 실제로 써보니 Namespace는 격리의 한 축일 뿐이고 cgroups, capabilities, seccomp 같은 요소랑 같이 봐야 하더라고요.

    2. Linux Namespace 핵심 개념 정리

    대표적인 Namespace는 아래처럼 이해하시면 됩니다.

    종류 영문 무엇을 격리하나 현실적인 사용 예
    PID Process ID Namespace 프로세스 번호와 프로세스 트리 컨테이너 내부에서 1번 프로세스만 보이게 구성
    NET Network Namespace 네트워크 인터페이스, 라우팅, 포트 컨테이너별 가상 NIC와 독립 라우팅
    MNT Mount Namespace 마운트 지점과 파일시스템 뷰 호스트와 다른 루트 파일시스템 제공
    UTS UNIX Timesharing System Namespace 호스트명, 도메인명 컨테이너별 hostname 분리
    IPC Inter-Process Communication Namespace 공유 메모리, 세마포어, 메시지 큐 프로세스 간 IPC 격리
    USER User Namespace UID/GID 매핑 컨테이너 root를 호스트 비특권 사용자로 매핑

    한 줄로 줄이면 이렇습니다. Linux Namespace는 프로세스가 보는 시스템 자원을 논리적으로 쪼개는 장치거든요. 컨테이너 런타임은 이걸 조합해서 “내 것처럼 보이지만 사실은 제한된 환경”을 만들어냅니다.

    3. 실제 적용 사례: 컨테이너 기술에서 어떻게 쓰이나요

    가장 흔한 사례는 역시 Docker나 containerd 같은 런타임입니다. 예를 들어 웹 애플리케이션 컨테이너 하나를 띄운다고 해보죠. 그 안의 애플리케이션은 자기 PID 공간만 보고, 자기 네트워크 인터페이스만 보고, 자기 루트 파일시스템만 봅니다. 사용자는 그냥 컨테이너가 하나 올라간 걸로 보지만, 내부적으로는 여러 Namespace가 같이 엮여 있죠.

    제가 홈랩에서 많이 해보는 패턴은 이렇습니다.

    1. 리버스 프록시(Reverse Proxy) 컨테이너는 외부와 붙게 둡니다.
    2. 백엔드 애플리케이션 컨테이너는 별도 네트워크 네임스페이스에 둡니다.
    3. 로그 수집기나 모니터링 에이전트는 필요한 마운트만 노출합니다.
    4. 가능하면 User Namespace까지 고려해서 호스트 권한을 줄입니다.

    이 방식이 왜 좋냐면, 장애 범위가 줄어듭니다. 어떤 애플리케이션이 오작동해서 내부 프로세스를 마구 생성하더라도, 적어도 다른 워크로드의 프로세스 공간까지 바로 오염시키지는 않거든요. 물론 이것만으로 충분하진 않지만, 운영 안정성에서 체감 차이가 꽤 큽니다.

    4. 실전 구현: unshare로 Namespace 직접 만들기

    이제 이론 말고 직접 보겠습니다. 저는 Namespace를 설명할 때 항상 <code>unshare부터 보여드립니다. 이걸 한 번 손으로 쳐보면 감이 확 옵니다. 아래 예시는 PID, UTS, Mount Namespace를 분리해서 새 쉘을 띄우는 방식입니다.

    sudo unshare --fork --pid --mount --uts /bin/bash

    이 상태에서 호스트명도 바꿔보겠습니다.

    hostname ns-lab
    hostname
    ps -ef

    여기서 ps -ef를 보면 호스트 전체 프로세스가 아니라 새 Namespace 기준의 프로세스만 보여집니다. 처음 보면 “어? 왜 이렇게 적지?” 싶거든요. 그게 정상입니다.

    마운트도 분리해보죠.

    mount -t proc proc /proc
    mount | grep proc

    Mount Namespace를 분리한 뒤 /proc를 다시 마운트하지 않으면 프로세스 정보가 기대와 다르게 보일 수 있습니다. 이 부분에서 많이 헷갈립니다. 저도 예전에 “PID Namespace가 안 먹었나?” 하고 한참 봤었는데, 알고 보니 /proc를 새로 안 붙였던 거였습니다.

    Linux Namespace 실습에서 PID와 hostname 분리를 확인하는 터미널 이미지

    실습 중간에 확인해야 하는 핵심 명령과 분리된 PID 공간이 보이는 터미널 예시입니다.

    4-1. 네트워크 Namespace 실습

    네트워크는 조금 더 재미있습니다. 별도 네임스페이스를 만들고 veth pair(가상 이더넷 쌍)로 연결하면 거의 미니 컨테이너 네트워크처럼 테스트할 수 있죠.

    sudo ip netns add ns1
    sudo ip link add veth-host type veth peer name veth-ns
    sudo ip link set veth-ns netns ns1
    sudo ip addr add 10.10.10.1/24 dev veth-host
    sudo ip link set veth-host up
    sudo ip netns exec ns1 ip addr add 10.10.10.2/24 dev veth-ns
    sudo ip netns exec ns1 ip link set lo up
    sudo ip netns exec ns1 ip link set veth-ns up
    sudo ip netns exec ns1 ping -c 3 10.10.10.1

    이 실습이 좋은 이유는 컨테이너 기술의 네트워크 격리 원리를 거의 그대로 보여주기 때문입니다. 브리지(Bridge), NAT, 포트 포워딩까지 붙이면 Docker 네트워크 구조를 훨씬 잘 이해하게 됩니다.

    4-2. 간단한 프로세스 격리 확인용 C 코드

    시스템 프로그래밍 관점에서 보면 clone() 계열 시스템 콜로 Namespace를 만드는 흐름을 이해하는 것도 중요합니다. 아래 코드는 개념 확인용으로 아주 단순화한 예시입니다.

    #define _GNU_SOURCE
    #include <sched.h>
    #include <sys/wait.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    #define STACK_SIZE 1024 * 1024
    
    static int child_func(void *arg) {
        sethostname("ns-child", 8);
        system("hostname; ps -ef");
        return 0;
    }
    
    int main() {
        char *stack = malloc(STACK_SIZE);
        if (!stack) return 1;
    
        pid_t pid = clone(child_func, stack + STACK_SIZE, CLONE_NEWUTS | CLONE_NEWPID | SIGCHLD, NULL);
        if (pid == -1) return 1;
    
        waitpid(pid, NULL, 0);
        free(stack);
        return 0;
    }

    실무에서 직접 이런 코드를 매번 짜진 않지만, 런타임이 내부적으로 어떤 일을 하는지 이해하는 데는 꽤 도움이 됩니다.

    5. 주의사항과 트러블슈팅: 여기서 많이 막힙니다

    실제로 써보니 Linux Namespace는 개념보다 디버깅이 더 중요하더라고요. 아래는 제가 자주 겪었던 문제들입니다.

    • ⚠️ /proc 재마운트 누락: PID Namespace를 만들었는데 프로세스가 이상하게 보이면 먼저 확인하세요.
    • ⚠️ loopback 미활성화: Network Namespace 안에서 lo를 올리지 않으면 localhost 통신이 어색하게 깨집니다.
    • ⚠️ 권한 문제: User Namespace를 섞으면 UID/GID 매핑 때문에 파일 접근이 예상과 다를 수 있습니다.
    • ⚠️ 네트워크 라우팅 누락: veth만 연결해놓고 라우팅이나 NAT를 안 잡으면 외부 통신이 안 됩니다.

    특히 네트워크 부분은 진짜 많이 삽질합니다. 저는 예전에 “분명 인터페이스는 올라왔는데 왜 패킷이 안 나가지?” 하고 tcpdump만 한참 봤거든요. 알고 보니 호스트 쪽 IP 포워딩(IP Forwarding)이 빠져 있었습니다. 그래서 아래처럼 확인하는 습관을 들였습니다.

    sysctl net.ipv4.ip_forward
    ip netns exec ns1 ip route
    ip addr show veth-host

    보안 측면에서도 한 가지 강조하고 싶습니다. Namespace는 강력하지만 만능은 아니거든요. 격리 기술이라고 해서 무조건 안전한 게 아니고, 커널 취약점이나 잘못된 capability 설정이 있으면 경계가 흐려질 수 있습니다. 그래서 현업에서는 보통 cgroups, seccomp, AppArmor 또는 SELinux 같은 보안 메커니즘과 함께 갑니다.

    Linux Namespace 기반 네트워크 격리와 veth 연결 구성도

    호스트와 네임스페이스가 veth로 연결되고 패킷이 흐르는 경로를 이해하기 위한 구성도입니다.

    6. 검증과 결과 확인: 분리됐는지 어떻게 보나

    설정만 해놓고 끝내면 안 됩니다. 반드시 검증해야 합니다. 저는 보통 아래 순서로 봅니다.

    1. 프로세스가 분리됐는지 ps, /proc로 확인합니다.
    2. 호스트명이 분리됐는지 hostname으로 확인합니다.
    3. 네트워크 인터페이스가 분리됐는지 ip addr로 확인합니다.
    4. 마운트 뷰가 다른지 mount 출력으로 비교합니다.
    5. 필요하면 네임스페이스 핸들을 lsns로 확인합니다.
    lsns
    sudo ip netns exec ns1 ip addr
    sudo ip netns exec ns1 hostname
    sudo ip netns exec ns1 ps -ef

    이렇게 보면 각 격리가 실제로 먹었는지 금방 드러납니다. lsns는 운영 중 문제 파악할 때 꽤 유용하더라고요. 어떤 프로세스가 어떤 Namespace에 속했는지 감을 잡는 데 도움이 되거든요.

    실무 관점의 결과를 정리하면 이렇습니다.

    검증 항목 성공 시 기대 결과 실패 시 의심 포인트
    PID 분리 내부 프로세스만 보임 /proc 재마운트 누락
    hostname 분리 Namespace 내부 이름만 변경됨 UTS 미분리
    네트워크 분리 별도 인터페이스/라우팅 표시 veth 연결, lo 활성화 누락
    마운트 분리 호스트와 다른 마운트 목록 Mount Namespace 미적용
    Linux Namespace 적용 결과를 검증하는 운영 확인 화면

    분리된 Namespace가 실제로 적용됐는지 확인하는 검증 결과 예시 이미지입니다.

    7. 실제 운영에서 어디에 써먹나

    혹시 이런 경험 있으신가요? 개발팀은 “컨테이너니까 독립적이다”라고 생각하는데, 운영팀은 “그래도 결국 같은 커널인데?”라는 불안이 남습니다. 둘 다 맞는 말이거든요. 그래서 Namespace를 이해하면 커뮤니케이션이 훨씬 쉬워집니다.

    제가 현장에서 보거나 직접 적용해본 패턴은 대체로 이렇습니다.

    • 멀티테넌트(Multi-tenant) 환경에서 워크로드 간 기본 격리
    • CI 러너나 빌드 작업의 프로세스/파일시스템 분리
    • 네트워크 실험 환경 구성과 장애 재현
    • 보안 테스트용 최소 권한 실행 환경 만들기

    특히 홈랩에서는 이게 정말 좋습니다. VM 여러 대 띄우기 부담스러울 때 Namespace 기반으로 작은 실험 환경을 빠르게 만들 수 있거든요. 물론 커널 공유라는 특성 때문에 VM을 완전히 대체하진 못하지만, 문제 재현과 구조 학습에는 진짜 편하더라고요.

    8. 정리와 다음 단계

    Linux Namespace를 이해하면 컨테이너가 갑자기 훨씬 덜 추상적으로 보입니다. 그냥 “신기한 배포 단위”가 아니라, PID Namespace, Network Namespace, Mount Namespace 같은 커널 기능의 조합으로 보이기 시작하거든요. 저도 처음엔 Docker 명령만 외웠는데, 바닥 기술을 알고 나니 장애 대응 속도가 확실히 빨라졌습니다. 드디어 됐다! 싶은 순간이 오더라고요.

    오늘 정리한 핵심만 다시 적어보면 이렇습니다.

    • Linux Namespace는 프로세스가 보는 시스템 자원을 분리합니다.
    • 컨테이너 기술은 여러 Namespace를 조합해 가벼운 실행 환경을 만듭니다.
    • 실전에서는 네트워크, 마운트, 권한 매핑에서 가장 많이 막힙니다.
    • 검증 명령을 반드시 함께 익혀야 운영에서 써먹을 수 있습니다.

    다음 단계로는 cgroups와 함께 보면 좋습니다. Namespace가 “보이는 범위”를 나눈다면, cgroups는 CPU와 메모리 같은 자원 사용량을 통제하거든요. 다음 글에서 다룰 예정입니다. 그리고 이전 글에서 컨테이너 런타임 구조를 정리했다면 같이 보시면 연결이 더 잘 됩니다.

    Linux Namespace 종류와 실제 적용 포인트를 정리한 요약 인포그래픽

    PID, NET, MNT 등 주요 Namespace와 운영 포인트를 빠르게 복습할 수 있는 요약 이미지입니다.

    9. 자주 묻는 질문

    Q1. Namespace만 쓰면 컨테이너를 직접 만든 셈인가요?

    완전히 그렇진 않습니다. Namespace는 핵심 구성요소지만, 실제 컨테이너 환경에는 cgroups, 루트 파일시스템, capability 제어, 보안 정책 등이 함께 필요하죠.

    Q2. Docker를 쓰는데도 Namespace를 따로 알아야 하나요?

    네, 운영이나 장애 대응을 생각하면 알아두는 게 좋습니다. 특히 네트워크 안 붙음, 파일 안 보임, 프로세스 이상 동작 같은 문제는 바닥 기술을 이해해야 빨리 풀린다고 봅니다.

    Q3. User Namespace는 꼭 써야 하나요?

    상황에 따라 다릅니다. 보안상 이점은 분명하지만, 권한 매핑과 파일 접근에서 복잡도가 올라갑니다. 운영 환경에서는 호환성과 보안 요구사항을 함께 봐야 합니다.