设为首页 加入收藏

TOP

100 行 shell 写个 Docker(一)
2023-07-23 13:41:32 】 浏览:133
Tags:100 shell 写个 Docker

作者:vivo 互联网运维团队- Hou Dengfeng

本文主要介绍使用shell实现一个简易的Docker。

一、目的

在初接触Docker的时候,我们必须要了解的几个概念就是Cgroup、Namespace、RootFs,如果本身对虚拟化的发展没有深入的了解,那么很难对这几个概念有深入的理解,本文的目的就是通过在操作系统中以交互式的方式去理解,Cgroup/Namespace/Rootfs到底实现了什么,能做到哪些事情,然后通过shell这种直观的命令行方式把我们的理解组合起来,去模仿Docker实现一个缩减的版本。

二、技术拆解

2.1 Namespace

2.1.1 简介

Linux Namespace是Linux提供的一种内核级别环境隔离的方法。学习过Linux的同学应该对chroot命令比较熟悉(通过修改根目录把用户限制在一个特定目录下),chroot提供了一种简单的隔离模式:chroot内部的文件系统无法访问外部的内容。Linux Namespace在此基础上,提供了对UTS、IPC、mount、PID、network、User等的隔离机制。Namespace是对全局系统资源的一种封装隔离,使得处于不同namespace的进程拥有独立的全局系统资源,改变一个namespace中的系统资源只会影响当前namespace里的进程,对其他namespace中的进程没有影响。

Linux Namespace有如下种类:

图片

2.1.2 Namespace相关系统调用

amespace相关的系统调用有3个,分别是clone(),setns(),unshare()。

  • clone: 创建一个新的进程并把这个新进程放到新的namespace中

  • setns: 将当前进程加入到已有的namespace中

  • unshare: 使当前进程退出指定类型的namespace,并加入到新创建的namespace中

2.1.3 查看进程所属Namespace

上面的概念都比较抽象,我们来看看在Linux系统中怎么样去get namespace。

系统中的每个进程都有/proc/[pid]/ns/这样一个目录,里面包含了这个进程所属namespace的信息,里面每个文件的描述符都可以用来作为setns函数(2.1.2)的fd参数。

#查看当前bash进程关联的Namespace
# ls -l /proc/$$/ns
total 0
lrwxrwxrwx 1 root root 0 Jan 17 21:43 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 root root 0 Jan 17 21:43 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 root root 0 Jan 17 21:43 net -> net:[4026531956]
lrwxrwxrwx 1 root root 0 Jan 17 21:43 pid -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 Jan 17 21:43 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Jan 17 21:43 uts -> uts:[4026531838]
 
#这些 namespace 文件都是链接文件。链接文件的内容的格式为 xxx:[inode number]。
    其中的 xxx 为 namespace 的类型,inode number 则用来标识一个 namespace,我们也可以把它理解为 namespace 的 ID。
    如果两个进程的某个 namespace 文件指向同一个链接文件,说明其相关资源在同一个 namespace 中。以ipc:[4026531839]例,
    ipc是namespace的类型,4026531839是inode number,如果两个进程的ipc namespace的inode number一样,说明他们属于同一个namespace。
    这条规则对其他类型的namespace也同样适用。
 
#从上面的输出可以看出,对于每种类型的namespace,进程都会与一个namespace ID关联。
 
#当一个namespace中的所有进程都退出时,该namespace将会被销毁。在 /proc/[pid]/ns 里放置这些链接文件的作用就是,一旦这些链接文件被打开,
    只要打开的文件描述符(fd)存在,那么就算该 namespace 下的所有进程都结束了,但这个 namespace 也会一直存在,后续的进程还可以再加入进来。

2.1.4 相关命令及操作示例

本节会用UTS/IPC/NET 3个Namespace作为示例演示如何在linux系统中创建Namespace,并介绍相关命令。

2.1.4.1 IPC Namespace

IPC namespace用来隔离System V IPC objects和POSIX message queues。其中System V IPC objects包含消息列表Message queues、信号量Semaphore sets和共享内存Shared memory segments。为了展现区分IPC Namespace我们这里会使用到ipc相关命令:

#    nsenter: 加入指定进程的指定类型的namespace中,然后执行参数中指定的命令。
#       命令格式:nsenter [options] [program [arguments]]
#       示例:nsenter –t 27668 –u –I /bin/bash
#
#    unshare: 离开当前指定类型的namespace,创建且加入新的namesapce,然后执行参数中执行的命令。
#       命令格式:unshare [options] program [arguments]
#       示例:unshare --fork --pid --mount-proc readlink /proc/self
#
#    ipcmk:创建shared memory segments, message queues, 和semaphore arrays
#       参数-Q:创建message queues
#    ipcs:查看shared memory segments, message queues, 和semaphore arrays的相关信息
#      参数-a:显示全部可显示的信息
#      参数-q:显示活动的消息队列信息

下面将以消息队列为例,演示一下隔离效果,为了使演示更直观,我们在创建新的ipc namespace的时候,同时也创建新的uts namespace,然后为新的uts namespace设置新hostname,这样就能通过shell提示符一眼看出这是属于新的namespace的bash。示例中我们用两个shell来展示:

shell A

 

#查看当前shell的uts / ipc namespace number
 
# readlink /proc/$$/ns/uts /proc/$$/ns/ipc
uts:[4026531838]
ipc:[4026531839]
 
#查看当前主机名
# hostname
myCentos
 
#查看ipc message queues,默认情况下没有message queue
# ipcs -q
 
------ Message Queues --------
ke
首页 上一页 1 2 3 4 5 6 7 下一页 尾页 1/9/9
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇 常用的文件查看命令 下一篇Linux基础命令和项目部署

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目