go test run 文件_七天用Go写个docker(第一天)

e6a1ae0d9d7386e2c17c4d1e07330f47.png

1. docker详解

很多人刚接触docker的时候就会感觉非常神奇,感觉这个技术非常新颖,其实并不然,docker使用到的技术都是之前已经存在过的,只不过旧酒换了新瓶罢了。简单来说docker本质其实是一个特殊的进程,这个进程特殊在它被NamespaceCgroup 技术做了装饰,Namespace将该进程与Linux系统进行隔离开来,让该进程处于一个虚拟的沙盒中,而Cgroup则对该进程做了一系列的资源限制,两者配合模拟出来一个沙盒环境。

2. Namespace

Linux对线程提供了六种隔离机制,分别为:uts pid user mount network ipc ,它们的作用如下:
  • uts: 用来隔离主机名
  • pid:用来隔离进程PID号的
  • user: 用来隔离用户的
  • mount:用来隔离各个进程看到的挂载点视图
  • network: 用来隔离网络
  • ipc:用来隔离System V IPC 和 POSIX message queues

3. 环境配置

因为我们是在Windows里面写代码,然后将代码编译好,放到Linux中执行,所以这里我们要更改下我们goland的环境,因为在不同的环境中,go导入的文件也是不同,如果我们的环境使用的Windows,那么使用 os/exec 包时,导入的将是 exec_windows.go,而如果我们的环境是Linux,那么将会导入exec_linux.go文件,因为只有Linux才会给创建进程时提供这个隔离参数,所以我们需要把环境改成Linux。

a9f579f8dd015fc1d1262f19e85e5760.png

4. Go实现进程隔离

4.1 隔离uts

package main

import (
	"log"
	"os"
	"os/exec"
	"syscall"
)
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)
	}
}

我们编译一下,放到Linux中测试一下,windows中编译需要先把GOOS改成Linux,然后再执行go build,编译脚本如下

SET CGO_ENABLED=0
SET GOOS=linux
SET GOARCH=amd64
go build main.go

0f0c19881c0518f5ed1e592b1f174d5e.png

933fae71c356f39bc87c10bd2919238d.png

main 放到Linux环境中运行,这里我用的是 Centos

4.2 测试能否隔离主机名

  1. 给main文件添加可执行权限
chmod +x main
  1. 查看当前主机名

9cc03d497109794054ea04f6d988b971.png
  1. 执行 main 文件
./main

8d422a8cc428867f260a6618aec2c1ad.png

4. 修改主机名

hostname -b 新主机名

24934b6dc6c8f24b3e2e21c6f071841c.png

再次查看主机名,我们看到已经将主机名修改为 test

119758f91a0fb9eb6a2c7d010f22f160.png

5. 退出 shell,再次查看主机名

5a0ee8722182c5274fe4334715b68291.png
这时我们发现,外部的主机名,并没有被改变,说明该进程成功的将自己的hostname与外部的hostname进行隔离了。这也证明我们使用 uts namespace成功了。

4.2 其他的隔离

我们想对此进程进行那种隔离,只需要在Cloneflags中添加参数即可
package main

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

func main() {
	cmd := exec.Command("sh")
	cmd.SysProcAttr = &syscall.SysProcAttr{
		// 隔离 uts,ipc,pid,mount,user,network
		Cloneflags: syscall.CLONE_NEWUTS |
			syscall.CLONE_NEWIPC |
			syscall.CLONE_NEWPID |
			syscall.CLONE_NEWNS |
			syscall.CLONE_NEWUSER |
			syscall.CLONE_NEWNET,
		// 设置容器的UID和GID
		UidMappings: []syscall.SysProcIDMap{
			{
				// 容器的UID
				ContainerID: 1,
				// 宿主机的UID
				HostID: 0,
				Size:   1,
			},
		},
		GidMappings: []syscall.SysProcIDMap{
			{
				// 容器的GID
				ContainerID: 1,
				// 宿主机的GID
				HostID: 0,
				Size:   1,
			},
		},
	}
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	if err := cmd.Run(); err != nil {
		log.Fatal(err)
	}
}

35285a1ba774a8bb1f4e69db60cfc4bf.gif

下期讲解Cgroup知识,扫描下方二维码关注我微信公众号,持续更新...

http://weixin.qq.com/r/djv-50vE9BaLrQ_E925k (二维码自动识别)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值