Open callmeaxxe opened 1 year ago
package main
import (
"fmt"
"os"
)
// docker run image <CMD> <ARG>
// go run main.go run <CMD> <ARG>
// Step1: 명령어 종류에 따른 함수 실행. "run" 명령어 전달 시 run 함수 실행.
func main() {
switch os.Args[1] {
case "run":
run()
default:
os.Exit(1)
}
}
func run() {
fmt.Printf("Running: %v\n", os.Args[2:])
}
root@mobius-pub:~/projects/box# go run main.go run ls -l
Running: [ls -l]
package main
import (
"fmt"
"os"
"os/exec"
)
// docker run image <CMD> <ARG>
// go run main.go run <CMD> <ARG>
// Step2: 새로운 프로세스에서 명령어 실행 예) ls -l
func main() {
switch os.Args[1] {
case "run":
run()
default:
os.Exit(1)
}
}
func run() {
fmt.Printf("Running: %v\n", os.Args[2:])
cmd := exec.Command(os.Args[2], os.Args[3:]...)
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Run()
}
root@mobius-pub:~/projects/box# go run main.go run ls -l
Running: [ls -l]
total 12
-rw-r--r-- 1 root root 171 Sep 8 16:18 go.mod
-rw-r--r-- 1 root root 499 Sep 8 16:18 go.sum
-rw-r--r-- 1 root root 477 Sep 8 18:34 main.go
package main
import (
"fmt"
"os"
"os/exec"
"syscall"
)
// docker run image <CMD> <ARG>
// go run main.go run <CMD> <ARG>
// Step3: 새로운 UTS 설정 추가. Clone flag 추가 NEW UTS namespace. hostname 수동 변경 실습.
// 실습
// $ go run . run /bin/sh
// $ hostname box
func main() {
switch os.Args[1] {
case "run":
run()
default:
os.Exit(1)
}
}
func run() {
fmt.Printf("Running: %v\n", os.Args[2:])
cmd := exec.Command(os.Args[2], os.Args[3:]...)
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.SysProcAttr = &syscall.SysProcAttr{
Cloneflags: syscall.CLONE_NEWUTS,
}
must(cmd.Run())
}
// 에러 대응
func must(err error) {
if err != nil {
panic(err)
}
}
root@mobius-pub:~/projects/box# go run main.go run /bin/bash
Running: [/bin/bash]
root@mobius-pub:~/projects/box# hostname
mobius-pub
# hostname 변경
root@mobius-pub:~/projects/box# hostname container
root@mobius-pub:~/projects/box# hostname
container
# 다른 터미널에서는 hostname 이 기존 값으로 노출되는것 확인 (ns 분리되어)
package main
import (
"fmt"
"os"
"os/exec"
"syscall"
)
// docker run image <CMD> <ARG>
// go run main.go run <CMD> <ARG>
// Step4: 컨테이너 환경 시작시 호스트명을 container로 변경.
// $ go run . run /bin/sh
// $ hostname
func main() {
switch os.Args[1] {
case "run":
run()
case "child":
child()
default:
os.Exit(1)
}
}
func run() {
fmt.Printf("Running: %v\n", os.Args[2:])
// cmd := exec.Command(os.Args[2], os.Args[3:]...)
// 자기 자신을 하나 더 실행한 프로세스 내에서 child 를 실행
cmd := exec.Command("/proc/self/exe", append([]string{"child"}, os.Args[2:]...)...)
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.SysProcAttr = &syscall.SysProcAttr{
Cloneflags: syscall.CLONE_NEWUTS,
}
must(cmd.Run())
}
func child() {
fmt.Printf("Running child: %v\n", os.Args[2:])
// hostname 설정
syscall.Sethostname([]byte("container"))
cmd := exec.Command(os.Args[2], os.Args[3:]...)
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
must(cmd.Run())
}
func must(err error) {
if err != nil {
panic(err)
}
}
root@mobius-pub:~/projects/box# go run main.go run /bin/bash
Running: [/bin/bash]
Running child: [/bin/bash]
package main
import (
"fmt"
"os"
"os/exec"
"syscall"
)
// docker run image <CMD> <ARG>
// go run main.go run <CMD> <ARG>
// Step5: 컨테이너 환경에서 ps명령 실행 시 제한된 프로세스 정보만 조회. 루트 파일 시스템 변경.
// 실습으로 ps, cat /os-release 명령 실행.
func main() {
switch os.Args[1] {
case "run":
run()
case "child":
child()
default:
os.Exit(1)
}
}
func run() {
fmt.Printf("Running: %v as %d\n", os.Args[2:], os.Getpid())
cmd := exec.Command("/proc/self/exe", append([]string{"child"}, os.Args[2:]...)...)
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
// NEWPID : new PID ns, NEWNS : mount ns
cmd.SysProcAttr = &syscall.SysProcAttr{
Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWPID | syscall.CLONE_NEWNS,
}
must(cmd.Run())
}
func child() {
fmt.Printf("Running child: %v as %d\n", os.Args[2:], os.Getpid())
// hostname 설정
syscall.Sethostname([]byte("container"))
/* 루트 파일시스템 다운로드
# https://github.com/tianon/docker-brew-ubuntu-core/raw/88ba31584652db8b96a29849ea2809d99ce3cc31/focal/ubuntu-focal-oci-amd64-root.tar.gz
# mkdir /tmp/ubuntu
# tar zxf ubuntu-focal-oci-amd64-root.tar.gz -C /tmp/ubuntu
*/
// 루트 파일시스템 변경 (change root)
syscall.Chroot("/tmp/ubuntu")
syscall.Chdir("/")
// mount 옵션으로 proc fs mount
syscall.Mount("proc", "proc", "proc", 0, "")
// 함수 종료 전 실행을 위한 defer (unmount)
defer syscall.Unmount("proc", 0)
cmd := exec.Command(os.Args[2], os.Args[3:]...)
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
must(cmd.Run())
}
func must(err error) {
if err != nil {
panic(err)
}
}
root@mobius-pub:~/projects/box# go run main.go run /bin/bash
Running: [/bin/bash] as 639301
Running child: [/bin/bash] as 1
# proc fs 를 새로 마운트해줘야 함
root@container:~/projects/box# ps aux | head -5
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 167288 11264 ? Ss Sep04 0:15 /sbin/init
root 2 0.0 0.0 0 0 ? S Sep04 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? I< Sep04 0:00 [rcu_gp]
root 4 0.0 0.0 0 0 ? I< Sep04 0:00 [rcu_par_gp]
# proc fs 마운트를 위한 코드 추가된 결과 (잘 안됨..)
root@mobius-pub:~/projects/box# go run main.go run /bin/bash
Running: [/bin/bash] as 642316
Running child: [/bin/bash] as 1
groups: cannot find name for group ID 121
root@container:/# echo $$
6
:(){ :|:& };:
)func cg() {
// 리눅스 커널 cgroup 기능을 사용하기 위해 path 에 접근
cgroups := "/sys/fs/cgroup/"
pids := filepath.Join(cgroups, "pids")
// `linux_campus` control group 생성
os.Mkdir(filepath.Join(pids, "linux_campus"), 0755)
// PID max 값을 20개로 지정
must(ioutil.WriteFile(filepath.Join(pids, "linux_campus/pids.max"), []byte("20"), 0700))
must(ioutil.WriteFile(filepath.Join(pids, "linux_campus/notify_on_release"), []byte("1"), 0700))
// 자기 자신의 프로세스 정보 등록
must(ioutil.WriteFile(filepath.Join(pids, "linux_campus/cgroup.procs"), []byte(strconv.Itoa(os.Getpid())), 0700))
}
package main
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strconv"
"syscall"
)
// docker run image <CMD> <ARG>
// go run main.go run <CMD> <ARG>
// Step1: cgroup을 사용하여 컨테이너 내 process 갯수 제한.
// 실습
// $ go run . run /bin/sh
// $ :(){ :|:& };:
func main() {
switch os.Args[1] {
case "run":
run()
case "child":
child()
default:
os.Exit(1)
}
}
func run() {
fmt.Printf("Running: %v as %d\n", os.Args[2:], os.Getpid())
cmd := exec.Command("/proc/self/exe", append([]string{"child"}, os.Args[2:]...)...)
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.SysProcAttr = &syscall.SysProcAttr{
Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWPID | syscall.CLONE_NEWNS,
}
cmd.Run()
}
func child() {
fmt.Printf("Running child: %v as %d\n", os.Args[2:], os.Getpid())
cg()
syscall.Sethostname([]byte("container"))
syscall.Chroot("/tmp/ubuntu")
syscall.Chdir("/")
syscall.Mount("proc", "proc", "proc", 0, "")
defer syscall.Unmount("proc", 0)
cmd := exec.Command(os.Args[2], os.Args[3:]...)
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
must(cmd.Run())
}
func cg() {
cgroups := "/sys/fs/cgroup/"
pids := filepath.Join(cgroups, "pids")
os.Mkdir(filepath.Join(pids, "linux_campus"), 0755)
must(ioutil.WriteFile(filepath.Join(pids, "linux_campus/pids.max"), []byte("20"), 0700))
must(ioutil.WriteFile(filepath.Join(pids, "linux_campus/notify_on_release"), []byte("1"), 0700))
must(ioutil.WriteFile(filepath.Join(pids, "linux_campus/cgroup.procs"), []byte(strconv.Itoa(os.Getpid())), 0700))
}
func must(err error) {
if err != nil {
panic(err)
}
}
root@mobius-pub:~# cd /sys/fs/cgroup/
root@mobius-pub:/sys/fs/cgroup# ls
blkio cpu cpuacct cpu,cpuacct cpuset devices freezer hugetlb memory net_cls net_cls,net_prio net_prio perf_event pids rdma systemd unified
root@mobius-pub:/sys/fs/cgroup# cd pids/
root@mobius-pub:/sys/fs/cgroup/pids# ls
cgroup.clone_children cgroup.procs cgroup.sane_behavior linux_campus notify_on_release release_agent system.slice tasks user.slice
root@mobius-pub:/sys/fs/cgroup/pids# cd linux_campus/
root@mobius-pub:/sys/fs/cgroup/pids/linux_campus# ls
cgroup.clone_children cgroup.procs notify_on_release pids.current pids.events pids.max tasks
root@mobius-pub:/sys/fs/cgroup/pids/linux_campus# cat pids.max
20
root@mobius-pub:/sys/fs/cgroup/pids/linux_campus# cat tasks
4673
4675
4676
4677
4678
4679
root@mobius-pub:/sys/fs/cgroup/pids/linux_campus# cat pids.current
20
root@mobius-pub:/sys/fs/cgroup/pids/linux_campus#
5. (실습) 나만의 컨테이너 생성 - 소개