개발일기/Docker

3. UTS 네임스페이스로 호스트명 분리하기

ignuy 2025. 5. 29.

Go로 "컨테이너스러운" 프로세스를 만들어보자.

 

지난 포스팅에서는 프로세스의 분리와 PID 격리에 대해서 다루었다. 이번 시간엔 컨테이너 안에서만 별도의 호스트명(hostname)을 갖도록 프로세스를 제어해보자. 실제 도커처럼 hostname 명령으로 컨테이너 안의 이름을 바꿔도 호스트 OS에는 영향이 없도록 만드는 게 이번 시간의 목적이다.

이를 위해서 UTS 네임스페이스를 사용한다.

 

🔍 UTS 네임스페이스란?

UNIX Timesharing System의 약자인 UTS는 아래 두가지 항목을 격리시키는 역할을 한다.

 

  • hostname (예: conatinerM)
  • domainname (보통 잘 안 씀)

UTS는 hostname과 domainname을 네임스페이스 단위로 분리해주는 기능으로면 sethostname()을 호출해도 내 컨테이너 안에서만 변경되고, 호스트나 다른 컨테이너에는 영향을 주지 않는다.

* 컨테이너 안: hostname = containerM
* 호스트 시스템: 여전히 기존의 호스트명 유지

🌐 왜 중요한가?

1. 컨테이너 정체성 분리

  • 각 컨테이너는 자신만의 hostname 을 가지므로, 외부와 완전히 "독립적인" 컴퓨터처럼 보이게 된다.

2. 운영 도구와 로그 구분에 유리

  • 시스템 로그, 프롬프트(PS1), 호스트 기반 애플리케이션에서 호스트명이 자주 사용된다.
  • 여러 컨테이너에서 같은 프로그램을 실행할 때 hostname으로 식별이 쉽다.

3. 다른 네임스페이스(예: PID, NET 등)와 조합 시 더 유용

  • UTS 네임스페이스는 단독으로는 단순하지만, 다른 네임스페이스와 결합되면 완전한 격리된 실행 환경이 된다.

📂 코드 수정하기

지난 포스팅까지 run() 함수 안에서 PID 네임스페이스 격리를 위해서 Cloneflags를 사용 중이었다. 여기에 UTS 네임스페이스 설정을 추가해주자.

✅ run() 수정 전

cmd.SysProcAttr = &syscall.SysProcAttr{
	Cloneflags: syscall.CLONE_NEWPID,
}

✅ run() 수정 후 (UTS 설정 추가)

cmd.SysProcAttr = &syscall.SysProcAttr{
	Cloneflags: syscall.CLONE_NEWPID |
		syscall.CLONE_NEWUTS,
}

child()에서 호스트명 설정

UTS 네임스페이스는 자식 프로세스에서만 유효하므로, child() 함수 안에서 syscall.Sethostname()으로 직접 호스트명을 바꾸어야 한다.

func child() {
	fmt.Printf("Running child process PID %d\n", syscall.Getpid())

	must(syscall.Sethostname([]byte("containerM")), "set hostname")

	cmd := exec.Command(os.Args[2], os.Args[3:]...)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	must(cmd.Run())
}

🧪 실험

빌드와 실행 방법은 전 포스팅과 동일하다.

컨테이너 안에서 호스트 이름을 확인해보자.

컨테이너 내부에서 <hostname XXX> 명령어로 호스트네임을 바꿔도 컨테이너 외부에서의 터미널에서 출력되는 호스트 이름은 변하지 않는다.

 

🔎 왜 자식 프로세스 안에서만 sethostname()을 호출해야 할까?

UTS 네임스페이스는 CLONE_NEWUTS로 생성된 자식 프로세스의 네임스페이스 내부에서만 유효하다. 부모 프로세스에서는 여전히 호스트의 네임스페이스에 속해 있으므로, sethostname()을 호출하면 전체 시스템 호스트명이 바뀔 수 있으니 주의하자.
반드시 hostname을 자식 안에서만 설정해야 한다.

📌 요약

항목 설명
UTS 네임스페이스 hostname, domainname을 격리함
CLONE_NEWUTS 자식 프로세스에서 별도 네임스페이스 생성
syscall.Sethostname() 자식 프로세스 안에서만 호출해야 안전
실험 결과 외부와 무관하게 내부에서만 호스트명 변경됨

 

🔜 다음 이야기

다음 파트에서는 Mount 네임스페이스를 활용해, 컨테이너 안에서 루트 파일시스템을 분리해 볼 것이다. 이제 점점 컨테이너의 겉모습뿐 아니라 내부까지 격리된 구조를 갖추게 될 것이다.

댓글