Context
현재 mini-container/main.go의 child()는 컨테이너 환경을 준비한 뒤 exec.Command(...).Run()으로 사용자 명령을 자식 프로세스로 실행한다.
cmd := exec.Command(os.Args[2], os.Args[3:]...)
...
must(cmd.Run())
이 구조에서는 컨테이너 안 PID 1이 사용자 명령이 아니라 /proc/self/exe child ... 프로세스가 된다. 예를 들어 /bin/sh 실행 시 컨테이너 내부에서는 다음처럼 보인다.
PID 1 /proc/self/exe child /bin/sh
PID 7 /bin/sh
child 프로세스가 PID 1로 남으려면 signal forwarding, zombie reaping, child exit code propagation 같은 init wrapper 책임을 가져야 한다. 하지만 현재 코드는 그 역할을 구현하지 않고 cmd.Run() 결과를 must(...)로 처리한다. 그래서 사용자 명령이 non-zero exit으로 끝나는 정상적인 상황도 parent 쪽에서 panic stack trace처럼 보일 수 있다.
이 단계에서는 tiny init을 구현하기보다, runc처럼 컨테이너 환경 설정을 마친 뒤 child 프로세스 자신을 사용자 명령으로 exec하는 방식이 더 단순하다.
Goal
child()가 rootfs, mount, hostname 설정을 마친 뒤 사용자 명령으로 exec되어, 컨테이너 내부 PID 1이 사용자가 요청한 프로세스가 되도록 한다.
또한 parent는 child의 종료 상태를 런타임 panic으로 출력하지 않고 가능한 한 그대로 프로세스 종료 코드로 반영한다.
Scope
mini-container/main.go의 child()에서 exec.Command(...).Run() 흐름을 제거한다.
- setup 완료 후
syscall.Exec(...)로 사용자 명령을 실행한다.
- parent의
cmd.Wait() 처리에서 non-zero exit을 panic으로 다루지 않도록 최소한으로 정리한다.
- signal forwarding/zombie reaping을 구현하는 tiny init 방식은 이 이슈에서 다루지 않는다.
- rootfs 경로, cgroup 이름, resource limit 설정값 config화는 이 이슈에서 다루지 않는다.
Acceptance Criteria
sudo ./mini-container run /bin/sh 실행 후 컨테이너 안 ps aux에서 /bin/sh가 PID 1로 보인다.
- 사용자 명령이 non-zero exit으로 끝나도 Go panic stack trace가 출력되지 않는다.
- parent process는 컨테이너 프로세스의 exit status를 가능한 한 동일하게 반환한다.
go test ./...가 통과한다.
Notes
선택지는 두 가지였다.
- runc식: setup process가 마지막에 사용자 명령으로
exec된다.
- tini식: setup process가 PID 1 wrapper로 남고 signal forwarding, zombie reaping, exit code propagation을 직접 구현한다.
현재 단계에서는 범위가 작은 runc식 전환을 선택한다.
Context
현재
mini-container/main.go의child()는 컨테이너 환경을 준비한 뒤exec.Command(...).Run()으로 사용자 명령을 자식 프로세스로 실행한다.이 구조에서는 컨테이너 안 PID 1이 사용자 명령이 아니라
/proc/self/exe child ...프로세스가 된다. 예를 들어/bin/sh실행 시 컨테이너 내부에서는 다음처럼 보인다.child프로세스가 PID 1로 남으려면 signal forwarding, zombie reaping, child exit code propagation 같은 init wrapper 책임을 가져야 한다. 하지만 현재 코드는 그 역할을 구현하지 않고cmd.Run()결과를must(...)로 처리한다. 그래서 사용자 명령이 non-zero exit으로 끝나는 정상적인 상황도 parent 쪽에서 panic stack trace처럼 보일 수 있다.이 단계에서는 tiny init을 구현하기보다, runc처럼 컨테이너 환경 설정을 마친 뒤
child프로세스 자신을 사용자 명령으로exec하는 방식이 더 단순하다.Goal
child()가 rootfs, mount, hostname 설정을 마친 뒤 사용자 명령으로exec되어, 컨테이너 내부 PID 1이 사용자가 요청한 프로세스가 되도록 한다.또한 parent는 child의 종료 상태를 런타임 panic으로 출력하지 않고 가능한 한 그대로 프로세스 종료 코드로 반영한다.
Scope
mini-container/main.go의child()에서exec.Command(...).Run()흐름을 제거한다.syscall.Exec(...)로 사용자 명령을 실행한다.cmd.Wait()처리에서 non-zero exit을 panic으로 다루지 않도록 최소한으로 정리한다.Acceptance Criteria
sudo ./mini-container run /bin/sh실행 후 컨테이너 안ps aux에서/bin/sh가 PID 1로 보인다.go test ./...가 통과한다.Notes
선택지는 두 가지였다.
exec된다.현재 단계에서는 범위가 작은 runc식 전환을 선택한다.