暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Docker 底层揭秘(二) - Linux Namespace 之 UTS

wangyanglinux 宝典 2021-01-31
854

Namespace UTS 级别说明及其利用 Go 调用接口的实验演示


0


环境说明



操作系统:Ubuntu 14.04


内核版本:3.13.0-24-generic


Go 语言版本:go version go1.7.1 linux/amd64


1


UTS Namespace 说明


UTS Namespace主要用来隔离 nodename 和 domainname 两个系统标识。在 UTS Namespace 里面,每个 Namespace 允许有自己的 hostname

下面使用 Go 来做一个 UTS Namespace 的例子,对于 Namespace 这种 Linux 系统调用来说,使用 C 肯定是最好调用的方式。但是对于 Docker 来说  Go 是其开发语言,所以接下来我们使用 Go 来演示


2


代码


package main


import (
// Go 语言内置的 log 包实现了简单的日志服务
"log"
// os 包提供了不依赖平台的操作系统函数接口
"os"
// exec 包执行外部命令,它将 os.StartProcess 进行包装使得它更容易映射到 stdin 和 stdout,并且利用pipe连接 i/o
"os/exec"
// syscall 包包含一个指向底层操作系统原语的接口
"syscall"
)


func main() {
// 指定被 fork 出来的新进程内的初始化命令,默认使用 sh 来执行
cmd := exec.Command("sh")


//
cmd.SysProcAttr = &syscall.SysProcAttr{
// 使用 CLONE_NEWUTS 这个标识区创建一个 UTS Namespace,GO 已经帮我们封装了对 clone() 函数的调用,这段代码执行后就会进入到一个 sh 运行环境中
Cloneflags: syscall.CLONE_NEWUTS,
}


// Stdin指定进程的标准输入,如为nil,进程会从空设备读取(os.DevNull)
cmd.Stdin = os.Stdin
// Stdout和Stderr指定进程的标准输出和标准错误输出
cmd.Stdout= os.Stdout
// Stdout和Stderr指定进程的标准输出和标准错误输出
cmd.Stderr = os.Stderr


/* Run执行c包含的命令,并阻塞直到完成。如果命令成功执行,stdin、stdout、stderr的转交没有问题,并且返回状态码为0,方法的返回值为nil(执行Run函数的返回状态,正确执行Run函数,并不代表正确执行了命令);如果函数没有执行或者执行失败,会返回*ExitError类型的错误;否则返回的error可能是表示I/O问题。即:该命令只会执行且阻塞到执行结束,如果执行函数有错则返回报错信息,没错则返回nil,并不会返回执行结果
*/
if err := cmd.Run(); err != nil {
// 打印输出内容,退出应用程序,defer 函数不会执行
log.Fatal(err)
}

    // 终止程序,退出码 -1
os.Exit(-1)
}



3


演示说明


ubuntu 父空间中执行的进程树

代码运行后子名称空间中运行的 pid

查看代码进程与子 shell 所处于的 NS UTS 的不同

通过上图我们可以看到,它们确实已经分离在了不同的 UTS Namespace 中,由于 UTS Namespace 对 hostname 做了隔离所以我们修改 hostname 也不会影响外部主机

实验过程描述:先在子名称空间中(左图) 修改了主机名为 wangyang,之后执行主机名查看为 wangyang。然后在 父名称空间中(右图)修改了主机名为 svcloudt.com ,之后执行主机名查看为 svcloudt.com,之后在子名称空间中(左图)查看主机名依然为 wangyang。由此,可以证明外部的 hostname 并没有被内部的修改所影响





下期预告:Docker 底层揭秘(三) - Linux Namespace 之 IPC


END





文章转载自wangyanglinux 宝典,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论