容器技术基本概念理解
开
1. 容器
1.1 定义
一种沙盒技术,
可以将应用运行在其中,与外界隔离
这个沙盒可以被方便地“转移”。
本质上,他就是一种特殊的进程。通过在创建容器进程的时候,指定了这个进程所需要启用的一组Namespace参数,进而让该容器进程只能看到当前Namespace所限定的资源、文件、设备、状态或者配置。--进程划分独立空间思想
一个正在运行的Linux容器,可以被一分为二地看待:
一组联合挂载在/var/lib/docker/aufs/mnt上的rootfs,这部分被称为“容器镜像”(Container Image),是容器的静态视图
一个由Namespace + Cgroups构成的隔离环境,这部分被称为“容器运行时”,是容器的动态视图
docker framwork.PNG
1.2 核心原理小结
在为待创建的用户进程
启动Linux Namespace配置
设置指定的Cgroups参数
切换进程的根目录(change root, 配合namespace mount)
切换进程的根目录的时,Docker项目会在最后一步优先使用pivot_root的系统调用,如果系统不支持,才会使用chroot。
2. 虚拟机
虚拟机在物理宿主机上存在一层Hypervisor的硬件虚拟化层,通过Hypervisor虚拟化出了CPU, 内存,I/O设备等,然后在这些虚拟设备上装了一个新的操作系统,即GuestOS,通过不同的操作系统,来实现同一个物理宿主机上的环境隔离。
容器和虚拟机的区别
# | 容器 | 虚拟机 |
---|---|---|
关键技术 | Docker Engine | Hypervisor,GuestOS |
实现原理 | Docker Engine通过在原有物理宿主机上的原操作系统,在起Docker进程的时候,通过指定各种namespace参数实现了不同Docker容器(进程)之间的进程隔离 | Hypervisor通过虚拟化出硬件设备,在硬件设备上安装若干个GuestOS,通过操作系统,实现不同操作系统内的进程互相不感知 |
本质 | 不同的Docker容器本质上是物理宿主机上的操作系统中运行的不同进程 | 不同的虚拟机本质上是Hypervisor虚拟化出来硬件上安装的不同的操作系统 |
优劣 | GuestOS会带来很大的性能消耗:1. 不做优化的场景,根据实验一个运行CentOS的KVM VM启动之后VM自身占用100~200M内存 2. VM内部用户对宿主机操作系统的调用必须经过Hypervisor这一层的拦截和处理,会对计算资源、网络和磁盘I/O的造成很大损耗 | 不需要虚拟化层导致“敏捷”“高性能”是容器相比与虚拟机的最大优势。但是正因为如此,Docker容器对应用进程隔离的不如通过Hypervisor的虚拟化工具进行的隔离要彻底。如1. 同一个宿主机上的不同Docker容器还是共享的同一个操作系统内核 2. Linux内核中,很多资源和对象是不能被NameSpace化的,比如时间,如果调用系统方法修改系统时间,那么所有Docker容器都可以感知到---定制化安全加固方案:通过Seccomp技术,对容器内部发起的系统调用进行过滤来进行安全加固,但是牺牲了一定的性能,且这种定制不具备普适性 |
因此,不能Docker engine放在和Hypervisor同样的地位,Docker Engine或任何容器管理工具都不对容器中的应用进程的隔离环境负责,而是由物理宿主机的操作系统本身直接负责的。Hypervisor是会虚拟出硬件设备,在这上面通过不同的GuestOS实现隔离的。而Docker Engine在这里扮演的角色,更多是的旁路式的辅助和管理工作。
那么如何在容器的隔离和性能之间做出平衡呢?
基于虚拟化和独立内核技术的容器
容器和VM的对比
3. Docker Engine是做什么的?
#TODO
4. 容器编排
容器编排.PNG
5. 集群管理
#TODO
6. 进程
6.1 定义
狭义定义:进程是正在运行的程序的实例(an instance of a computer program that is being executed)。
广义定义:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。
对进程来说,静态表现就是程序,未运行时存储在磁盘上;运行起来后,变成了计算机中数据和状态的总和,也是其动态表现。
容器技术的核心功能,是通过约束和修改进程的动态表现,从而为其制造出一个容器的边界。
7. Linux Cgroups(Linux Control Group)
7.1 解决问题
虽然Docker容器可以通过Namespace改变进程视图可见性,但是本质上容器这个进程及其内部的应用进程,都是统一归宿主机的操作系统管理,这就意味着,这个容器内部的进程和容器外部的宿主机的进程时处于平等竞争关系的。那么问题来了,这些资源占用怎么去隔离?---Cgroups
7.2 主要作用
限制一个进程族能够使用的资源上限,包括CPU,内存,磁盘,网络带宽等。此外还能够对进程进行优先级设置、审计、以及将进程挂起和恢复等操作。
详见《Linux Cgroups》
7.3 存在问题
容器中执行top指令,显示的信息是宿主机的CPU和内存数据,不是当前容器的数据。因为/proc下的存储的信息是作为top指令的主要数据来源,而/proc文件系统是感知不Cgroups限制的存在
8. Namespace技术
8.1 作用
修改进程视图的主要方法。说白了,容器正是通过在起容器进程的时候,增加namespace的配置参数,使得在该容器内部可见的进程与容器外部(物理机OS)上看到的进程“隔离”开来。但是,在物理宿主机看来这些被“隔离”的进程与其他进程并没有太大区别。
8.2 存在问题
namespace problem.PNG
这部分如何理解?
看容器本质就好了,容器项目通过起用户进程时候限定cgroups和namespace并切换root来起了一个“沙盒”里的应用进程,所以通过一个容器项目起来的一个应用进程就是一个容器。
9. RPC(Remote Procedure Call)
RPC.jpg
简单理解:rpc调用能够通过类似本地调用的方式实现在分布式架构中Service A调用起Service B的方法。
在上图中,以左边的Client端为例,Application就是rpc的调用方,Client Stub就是代理对象,也就是那个看起来像是Calculator(这个类是实际实现在右侧Application中的)的实现类,其实内部是通过rpc方式来进行远程调用的代理对象,至于Client Run-time Library,则是实现远程调用的工具包,比如jdk的Socket,最后通过底层网络实现实现数据的传输。
这个过程中最重要的就是序列化和反序列化了,因为数据传输的数据包必须是二进制的,你直接丢一个Java对象过去,人家可不认识,你必须把Java对象序列化为二进制格式,传给Server端,Server端接收到之后,再反序列化为Java对象。
10. 容器镜像(rootfs)
10.1 既然Docker容器是在物理宿主机上的进程,那么Docker镜像和物理宿主机的操作系统之间是什么关系?
可以简单这么理解
如果容器镜像os支持某硬件的驱动,但是宿主机os如果不支持该硬件驱动的话,也白搭
可以理解为镜像只是提供了一套镜像文件系统中的各种文件,而各种内核相关的模块或者特性支持,完全依赖于宿主机
也正是通过容器镜像,打包了整个操作系统的文件和目录(虽然没打包内核),也就意味着,应用以及他所运行所需要的全部依赖都被封装在了一起,而对于一个应用来说,操作系统本身才是他运行所需要的完整的依赖库。也正是因为这样,才有了容器的一个重要特性:一致性。
一致性
优雅地解决云端和本地服务环境不同造成在应用打包过程中使用PaaS最“痛苦”的步骤。
11. 操作系统
11.1 操作系统文件和操作系统内核的区别
为什么说容器通过mount namespace挂载不同版本的操作系统文件,但是不同的Docker还是使用的操作系统内核。(通俗理解就是不能通过容器技术在Windows宿主机上运行Linux容器,或者在低版本的Linux宿主机上运行高版本的Linux容器)
13. Volume机制
13.1 作用
是为了解决在通过rootfs机制(打包了操作系统所包含的文件、配置和目录)和mount 那么space建立起了一个同宿主机完全隔离的文件环境系统同时引入的两个问题:
宿主机上的文件系统,怎么让容器的进程访问到
总而言之,是在隔离开宿主机和容器的文件系统之后,怎么进行文件共享操作。
13.2 是什么
允许用户将宿主机上指定的目录或者文件,挂载到容器里面进行读取和修改操作。
注意mount namespace在根目录下挂载rootfs和Volume机制挂载的区别
rootfs挂载到根目录是docker仓库中打包的操作系统的文件系统
Volume机制是把物理机上的卷挂载到通过rootfs和mount namespace隔离开的容器卷上以达到容器和宿主机的文件共享目的
13.3 用法
// mount /home on host to /test in container filesystem $ docker run -v /home:/test
- 点赞
- 收藏
- 关注作者
评论(0)