Golang实现UTS隔离

隔离机制是实现Docker容器的重要技术,其中UTS Namespace隔离的是主机与域名,
Linux内核中的调用参数为CLONE_NEWUTS。我们都知道Docker是用Golang实现了
那么自然我们可以用Golang来实现UTS Namespace隔离
主机环境如下

➜  ~ uname -a
Linux ubuntu 4.4.0-131-generic #157-Ubuntu SMP Thu Jul 12 15:51:36 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

➜  ~ go version
go version go1.6.2 linux/amd64

Golang源码

package main

import (
    "os/exec"
    "syscall"
    "os"
    "log"
)

func main(){
    cmd := exec.Command("sh")
    cmd.SysProcAttr = &syscall.SysProcAttr{
        Cloneflags:syscall.CLONE_NEWUTS,
    }
    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    if err := cmd.Run();err !=nil{
        log.Fatal(err)
    }
}

编译运行产生进入到fork出来新的进程里面的shell交互环境
查看当前进程的PID及系统中进程之间的关系

# echo $$
1805

# pstree -pl
systemd(1)-+-accounts-daemon(868)-+-{gdbus}(889)
           |                      `-{gmain}(881)
           |-acpid(865)
           |-atd(836)
           |-cron(842)
           |-dbus-daemon(848)
           |-dhclient(962)
           |-iscsid(1061)
           |-iscsid(1062)
           |-login(1138)---zsh(1228)
           |-lvmetad(422)
           |-lxcfs(845)-+-{lxcfs}(856)
           |            `-{lxcfs}(857)
           |-mdadm(897)
           |-nginx(1082)---nginx(1084)
           |-polkitd(907)-+-{gdbus}(912)
           |              `-{gmain}(910)
           |-rsyslogd(831)-+-{in:imklog}(861)
           |               |-{in:imuxsock}(860)
           |               `-{rs:main Q:Reg}(862)
           |-snapd(873)-+-{snapd}(913)
           |            |-{snapd}(914)
           |            |-{snapd}(915)
           |            |-{snapd}(921)
           |            |-{snapd}(930)
           |            `-{snapd}(931)
           |-sshd(1077)---sshd(1260)---sshd(1291)---zsh(1292)---sudo(1790)---go(1791)-+-ns(1802)-+-sh(1805)---pstree(1806)
           |                                                                          |          |-{ns}(1803)
           |                                                                          |          `-{ns}(1804)
           |                                                                          |-{go}(1792)
           |                                                                          |-{go}(1793)
           |                                                                          |-{go}(1794)
           |                                                                          `-{go}(1798)
           |-systemd(1219)---(sd-pam)(1225)
           |-systemd-journal(361)
           |-systemd-logind(826)
           |-systemd-timesyn(679)---{sd-resolve) S 1 (689)
           `-systemd-udevd(436)

fork进程的shell环境查看
(/proc/$PID/ns/下每个文件对应一个namespace, 它是一个符号链接, 会指向一个仅kernel可见的被称为nsfs(namespace filesystem)的文件系统中的一个inode)

# readlink /proc/1805/ns/uts
uts:[4026532192]
# readlink /proc/1802/ns/uts
uts:[4026531838]

在主机上查看

➜  ~ sudo readlink /proc/1802/ns/uts
uts:[4026531838]
➜  ~ sudo readlink /proc/1805/ns/uts
uts:[4026532192]

在fork进程shell环境中查看并修改hostname

# hostname
ubuntu
# hostname -b bird
# hostname
bird

在主机上

➜  ~ hostname
ubuntu

可以看到,fork进程的hostname产生了变更,主机不受影响,同样,主机hostname也不会对fork进程产生影响,由此fork进程的hostname
与主机父进程的hostname成功实现了隔离。

参考

  • uts namespaces: Introduction
  • 自己动手写docker
  • namespaces

你可能感兴趣的:(Golang实现UTS隔离)