一、先谈谈进程

在正式介绍Namespace之前,先介绍下进程,因为容器本质上是进程,但是在介绍进程之前,先理清下“程序”和“进程”的关系,这是IT从业人员在日常工作中经常碰到的两个词汇,举个通俗点的例子帮助大家理解,“程序”可以看成是一张机械图,图上的内容都是手工画上去的,相当于是计算机的输入,在机械图未正式设计出产品的时候,它是静态的,而当工程师按照机械图正式设计各个零部件、组合、啮合到最后产品成型的整个动态过程,可看成是一个进程,因此进程可认为是程序运行起来后的计算机执行环境的总和,是静态程序的具体实现。

二、容器的namespace

在上节中介绍了什么是进程,可通过ps命名查看当前宿主机正在运行的进程,如下图所示

[root@k8s-master James]# ps
PID TTY TIME CMD
pts/ :: su
pts/ :: bash
pts/ :: ps

容器本质上对于Linux操作系统来说,和上述进程一样,但是会在进程上加入了很多namespace来实现进程、挂载点、网络、用户信息之间的隔离,这样容器看上去就像一个沙箱,在沙箱内部只能看到和操作限定namespace下的系统资源,以PID namespace为例,我们先创建1个容器

[root@k8s-master James]# docker run -it -d busybox /bin/sh
01a0fd62d2110e54b0c3635b2897e7c18e6b78f026fa57b4214d7662dd3b38ba

[root@k8s-master James]# docker exec -it 01a0fd62d2110e54b0c3635b2897e7c18e6b78f026fa57b4214d7662dd3b38ba /bin/sh
/ # ps
PID USER TIME COMMAND
1 root 0:00 /bin/sh
6 root 0:00 /bin/sh
11 root 0:00 ps

这条命名的意思是我想启动一个容器执行/bin/bash命令,并分配一个伪终端的交互窗口和容器进行交互,docker run是创建和启动容器的意思,-it表示就是分配一个伪终端的输入和输出交互窗口,busybox是镜像,/bin/bash是操作程序。当创建成功后,输入ps可查看容器中正在运行的进程,可以看到有2个进程,PID代表进程的唯一编号,可以看到1号PID的操作程序为/bin/bash,之前谈到容器也是一种进程,回到宿主机查看下此容器的进程

[root@k8s-master James]# docker container top 01a0fd62d2110e54b0c3635b2897e7c18e6b78f026fa57b4214d7662dd3b38ba
UID PID PPID C STIME TTY TIME CMD
root : pts/ :: /bin/sh

其PID为24691了,此PID在容器中不存在,也就是说容器中只能看到自己程序执行后的进程,而看不到其他容器和宿主机上的进程,且容器里面的进程编号PID也做了障眼法般的处理,与宿主机上的PID不一致,而实现这个技术的就是PID namespace,而容器类似的还有NET、IPC、MNT、UTS、USER的namespace,其对应隔离的内容如下表所示:

namespace 隔离的内容
PID 进程
IPC 信号量、消息队列和共享内容
UTS   主机名、域名
NET 网络设备、网络栈、端口
MNT 文件系统
User 用户和用户组

网络相对比较复杂,我们再详细深入看下,从上表可以看出不同的网络命名空间可以隔离网络设备、网络栈、端口等,为了达到这个目标,LINUX系统就需要支持虚拟化网络协议栈的多个实例,且这些独立的协议栈可处于不同的网络命名空间来进行隔离,达到彼此无法进行通信隔离的效果,如果想要不同的网络命名空间设备进行通信,应如何操作呢?答案是:veth设备对,什么是veth设备对,你可以认为是一根管道,一端连接一个网络命名空间的协议栈,另外一端连接另外一个网络命名空间的协议栈来实现通信,那如何建立veth设备对呢?接下来一起操作下

在root用户下,先创建一个网络命名空间

[root@k8s-master zhanglei]# ip netns add net_test1
[root@k8s-master zhanglei]# ip netns list
net_test1

再创建一个设备对veth:

[root@k8s-master zhanglei]# ip link add veth0 type veth peer name veth1
[root@k8s-master zhanglei]# ip link show
: veth0@veth1: <BROADCAST,MULTICAST,M-DOWN> mtu qdisc noop state DOWN mode DEFAULT group default qlen

可以看到veth0和veth1的设备对已经生成,veth的设备支持在不同的网络命名空间进行转移,将veth0设备住转移到net_test1命名空间

[root@k8s-master zhanglei]# ip link set veth0 netns net_test1

此时在宿主机上ip link show,因不同的网络命名空间设备是隔离的,且veth0设备已经被移动到net_test1网络命名空间,因此将无法在宿主机网络命名空间再次找到veth0

[root@k8s-master zhanglei]# ip netns exec net_test1 ip link show
: lo: <LOOPBACK> mtu qdisc noop state DOWN mode DEFAULT group default qlen
link/loopback ::::: brd :::::
: tunl0@NONE: <NOARP> mtu qdisc noop state DOWN mode DEFAULT group default qlen
link/ipip 0.0.0.0 brd 0.0.0.0
: veth0@if59: <BROADCAST,MULTICAST> mtu qdisc noop state DOWN mode DEFAULT group default qlen
link/ether :c0::4d:: brd ff:ff:ff:ff:ff:ff link-netnsid

同时我们将另veth1设置到命名空间net_test2里面

[root@k8s-master zhanglei]# ip netns add net_test2
[root@k8s-master zhanglei]# ip netns show
net_test2
net_test1 (id: )
[root@k8s-master zhanglei]#  ip link set veth1 netns net_test2
[root@k8s-master zhanglei]# ip netns exec net_test2 ip link show
: lo: <LOOPBACK> mtu qdisc noop state DOWN mode DEFAULT group default qlen
link/loopback ::::: brd :::::
: tunl0@NONE: <NOARP> mtu qdisc noop state DOWN mode DEFAULT group default qlen
link/ipip 0.0.0.0 brd 0.0.0.0
: veth1@if60: <BROADCAST,MULTICAST> mtu qdisc noop state DOWN mode DEFAULT group default qlen
link/ether 7e::da:3a:: brd ff:ff:ff:ff:ff:ff link-netns net_test1

到这里,veth0和veth1这个设备对已经配置在不同的网络命名空间了,但是此时还不能通信,就像电线已经搭好,但是还未通电,谁来扮演通电的角色呢?答案就是:IP

[root@k8s-master zhanglei]# ip netns exec net_test1 ip addr add 10.1.1.1/ dev veth0
[root@k8s-master zhanglei]# ip netns exec net_test2 ip addr add 10.1.1.2/ dev veth1
[root@k8s-master zhanglei]# ip netns exec net_test1 ip link set dev veth0 up
[root@k8s-master zhanglei]# ip netns exec net_test2 ip link set dev veth1 up
[root@k8s-master zhanglei]# ip netns exec net_test1 ping 10.1.1.2
PING 10.1.1.2 (10.1.1.2) () bytes of data.
bytes from 10.1.1.2: icmp_seq= ttl= time=0.097 ms
bytes from 10.1.1.2: icmp_seq= ttl= time=0.061 ms
bytes from 10.1.1.2: icmp_seq= ttl= time=0.032 ms
bytes from 10.1.1.2: icmp_seq= ttl= time=0.024 ms

[root@k8s-master zhanglei]# ip netns exec net_test2 ping 10.1.1.1
PING 10.1.1.1 (10.1.1.1) 56(84) bytes of data.
64 bytes from 10.1.1.1: icmp_seq=1 ttl=64 time=0.030 ms
64 bytes from 10.1.1.1: icmp_seq=2 ttl=64 time=0.090 ms
64 bytes from 10.1.1.1: icmp_seq=3 ttl=64 time=0.032 ms
64 bytes from 10.1.1.1: icmp_seq=4 ttl=64 time=0.033 ms

[root@k8s-master zhanglei]# ip netns exec net_test2 ping 10.1.1.1
PING 10.1.1.1 (10.1.1.1) () bytes of data.
bytes from 10.1.1.1: icmp_seq= ttl= time=0.030 ms
bytes from 10.1.1.1: icmp_seq= ttl= time=0.090 ms
bytes from 10.1.1.1: icmp_seq= ttl= time=0.032 ms
bytes from 10.1.1.1: icmp_seq= ttl= time=0.033 ms

如上,给每个设备配备1个ip地址,配备成功后再启动设备,然后就可以进行相互的通信了,前面提到每个容器拥有自己单独的网络命名空间,而网络命名空间之间的通信是通过设备对,而上面演示的就是命名空间通过设备对进行通信的全过程,

事实上容器之间、容器与宿主机之间都是通过设备对的方式进行通信的,当然实际上容器网络命名空间的创建、设备对的创建、IP的分配并不是手动进行的,都是容器在创建的时候会自动完成,对用户来说是无感知的,这里是方便展示内部原理,采用的手动的形式。

三、总结

本文主要重点介绍了容器PID和NET 命名空间(namespace)的隔离原理,其他namespace的隔离原理类似,容器本质上一种特殊的进程,它虽然提供了隔离技术,但与虚拟机的隔离技术要区别开来,虚拟机是在宿主机上通过Hypervisor虚拟了一个独立的GuestOS,它的隔离是彻底的,虚拟机上的进程在宿主机上无法查看;而容器本质上是宿主机上的进程,它的隔离机制是通过在进程上加入不同的namespace参数来实现资源、文件、设备、状态,或者配置的隔离,两者隔离的本质是有差异的,你或许有个疑问,既然容器是宿主机上的一个进程,而不同的进程可以相互共享宿主机的内核,一旦一个容器的应用逃逸影入侵宿主机,是不是会有可能会影响宿主机或者其他容器应用呢,事实上,的确存在这样的安全隐患,由此看来,容器的隔离性并不像虚拟机般隔离的彻底。

【原创】探索容器底层知识之Namespace的更多相关文章

  1. centos7下安装docker(10容器底层--cgroup和namespace)

    cgroup和namespace是实现容器底层的重要技术 cgroup:实现资源限制 namespace:实现资源隔离 1.cgroup:control group Linux操作系统通过cgroup ...

  2. C++ 顺序容器基础知识总结

    0.前言 本文简单地总结了STL的顺序容器的知识点.文中并不涉及具体的实现技巧,对于细节的东西也没有提及.一来不同的标准库有着不同的实现,二来关于具体实现<STL源码剖析>已经展示得全面细 ...

  3. 写给Android App开发人员看的Android底层知识(1)

    这个系列的文章一共8篇,我酝酿了很多年,参考了很多资源,查看了很多源码,直到今天把它写出来,也是战战兢兢,生怕什么地方写错了,贻笑大方. (一)引言 早在我还是Android菜鸟的时候,有很多技术我都 ...

  4. 6.Docker容器底层实现了解与安全机制

    原文地址: 点击直达 0x00 底层实现 我们以 Docker 基础架构来探究Docke底层的核心技术,简单的包括: Linux 上的命名空间(Namespaces) 控制组(Control grou ...

  5. 写给Android App开发人员看的Android底层知识(5)

    (十)Service Service有两套流程,一套是启动流程,另一套是绑定流程.我们做App开发的同学都应该知道. 1)在新进程启动Service 我们先看Service启动过程,假设要启动的Ser ...

  6. JS底层知识理解之执行上下文篇

    JS底层知识理解之执行上下文篇 一.什么是执行上下文(Execution Context) 执行上下文可以理解为当前代码的执行环境,它会形成一个作用域. 二.JavaScript引擎会以什么方式去处理 ...

  7. Java底层知识学习:Bytecode and JMM

    最近在跟着耗子哥的程序员练级指南学习Java底层知识,结合<深入理解Java虚拟机>这本书在看,写笔记,看资料,成长中…… 目前看完了第二章JMM和各内存区OOM的情况 一篇图文并茂介绍字 ...

  8. 容器的进程与namespace、rootfs

    一:容器是什么 容器的本质是一种特殊的进程. 在linux容器中有三个重要的概念:Namespace.Cgroups.rootfs. Namespace做隔离,让进程只能看到Namespace中的世界 ...

  9. 极客时间-左耳听风-程序员攻略-Java底层知识

    Java 字节码相关 字节码编程,也就是动态修改或是动态生成 Java 字节码.Java 的字节码相当于汇编,其中的一些细节. Java Zone: Introduction to Java Byte ...

随机推荐

  1. PHP date_add() 函数

    ------------恢复内容开始------------ 实例 添加 40 天到 2013 年 3 月 15 日: <?php$date=date_create("2013-03- ...

  2. loj #6247. 九个太阳 k次单位根 神仙构造 FFT求和原理

    LINK:九个太阳 不可做系列. 构造比较神仙. 考虑FFT的求和原理有 \(\frac{1}{k}\sum_{j=0}^{k-1}(w_k^j)^n=[k|n]\) 带入这道题的式子. 有\(\su ...

  3. C/C++编程笔记:一张思维导图,带你总结C语言全部知识点!

    很多小伙伴想要好好地学习一下C语言的知识,但是又不知道怎么学,应该学哪一些C语言的知识,笔者在网上看到了这一张C语言的比较完善的C语言的学习路线图,有兴趣的小伙伴可以保存起来哈! C语言是面向过程的, ...

  4. 埋在MySQL数据库应用中的17个关键问题!

    作者:扎瓦陈序元 来源:https://blog.csdn.net/weixin_42882439 MySQL的使用非常普遍,跟MySQL有关的话题也非常多,如性能优化.高可用性.强一致性.安全.备份 ...

  5. python8.3多进程

    from multiprocessing import Processimport time def run1 (name,sex): print(name,sex,"执行进程1" ...

  6. 一篇文章教会你用Python爬取淘宝评论数据(写在记事本)

    [一.项目简介] 本文主要目标是采集淘宝的评价,找出客户所需要的功能.统计客户评价上面夸哪个功能多,比如防水,容量大,好看等等. 很多人学习python,不知道从何学起.很多人学习python,掌握了 ...

  7. 解决Android v4、v7包导入标红问题import android.support.v4.app.ActivityCompat;import android.support.v7.app

    如果有如下错误:import android.support.v4.app.ActivityCompat;import android.support.v7.app.AppCompatActivity ...

  8. AutoUpdater迁移到Github

    一. 摘要 最近一两年在做跨平台的解决方案,使应用程序能支持Android, iOS, Windows, MacOs. Linux等操作系统,在Android, iOS上可以使用Google Play ...

  9. Hyperledger Fabric 部署

    Hyperledger Fabric 部署 Hyperledger Fabric需要使用Docker.Go环境. Docker环境安装 Docker环境安装 直接查看这一篇,安装好之后将当前用户非ro ...

  10. Python 常用的操作文件代码

    1:统计list中相同的个数,并按大小排序. original_list = ['a', 'b', 'b', 'a', 'd', 'd', 'b', 'z', 'c', 'b', 'r', 's', ...