当前位置: 首页 > 科技观察

当我们谈容器的时候,我们在谈什么

时间:2023-03-18 00:09:45 科技观察

当我们谈论容器时,我们在谈论什么?,这是怎么回事?这篇关于Linux容器的文章重点介绍了Linux容器。之所以强调Linux容器而不是Docker,是因为Docker是基于虚拟化技术实现的,但本文涉及Linux容器。在核心实现上,两者是有区别的,所以我再强调一下。容器实际上是一种沙盒技术。顾名思义,沙箱能够像容器一样打包您的应用程序。这样应用之间就有了界限,互不干扰;同时,安装在沙盒中的应用也可以方便地移动,这正是PaaS想要的理想状态。但是说起来容易,真正实现起来就难了。因为容器运行在宿主机上,运行时需要加载到内存中,CPU需要完成加法等操作。也就是说,要想实现真正意义上的容器,就必须解决容器与宿主机之间真正隔离的问题,而现实中,这个问题是没有办法解决的。既然问题没有解决,那么当我们在谈容器的时候,我们在谈什么?容器的核心功能是什么?上面说了,容器其实就是一种沙盒技术。boundary”。因此,容器的核心作用就是通过约束和修改进程的动态性能,来创建一个“边界”。这个官方语言可能有点难理解,我们改一下。容器就是Container中的英文,Container的另一个意思是集装箱,说到集装箱,大家首先想到的是岸边是否停靠着一艘大船,然后可以运来很多统一的箱子,为什么这些containers可以方便的运输吗?因为它们都是一样的大小,而且都是箱子,对吧?所以当我们用Container来描述一个容器的时候,我们希望让这个容器成为一个可以打包的,符合标准的状态。基于以上,我认为我们可以达成一个共识,就是如果我们要让容器帮我们达到一个可以打包,符合标准的状态,首先要解决什么问题呢?就是把容器和容器隔离开来,这样我们才一次手术可以在这个容器上执行吧?对于Docker等大多数Linux容器来说,实现容器间隔离主要有两种技术:一种是看似隔离的技术:Namespace技术,主要是用来修改进程视图,也就是说每个容器中的应用程序namespace看不同的IP地址、用户空间等;一种是使用时隔离的技术:Cgroups技术,这是用来创建约束的主要手段,也就是说,我的服务器总共有8G内存。如果都是为了这个应用,其他应用怎么跑?所以Cgroups技术就是对容器进行限制。NamespaceNamespace是命名空间的意思。如果您使用面向对象的编程语言进行编程,您应该熟悉这个词。一个团队一起写代码的时候,难免会有同一个类,这时候编译就会发生冲突。如果每个函数都有自己的命名空间,那么即使不同空间的类名相同,也不会有冲突。编写程序也是如此,在Linux上运行程序也是如此。当我们在一台Linux上运行多个进程时,进程有一个全局的进程ID,网络也有一个全局的路由表。如果多个进程使用不同的路由策略,这些进程可能会发生冲突。解决方法也很简单,将这些进程放在一个单独的命名空间中即可。就是这样,但我希望你能清楚地明白,进程是一个静态的程序,它只是磁盘上的一个二进制文件。只有在运行时,它才成为进程。因此,当我们开始运行一个程序时,操作系统会为该进程分配一个进程号,这是该进程的唯一标识。假设我们开始运行一个PID=100的程序。也就是说这个程序是第100个进程,前面还有99个进程。而现在,如果我们通过Docker在一个容器中运行这个程序,那么Doc??ker会在第100个进程创建时给它“蒙上眼睛”,让它永远看不到其他99个进程,这样你就会误以为这个程序是你是第一个过程。这种机制实际上是对隔离应用进程空间的一种操纵,让这些进程只能看到重新计算的进程号,比如上面的第100个进程。经过Docker的“瞎眼法”,误以为是第一个进程,但实际上在宿主机操作系统中,还是原来的第100个进程。容器限制(Cgroups)LinuxCgroups的全称是LinuxControlGroup。它的主要作用是限制一个进程组可以使用的资源上限,包括CPU、内存、磁盘、网络带宽等。很简单的一句话就是,你的电脑只有8G内存,你会允许一个进程占用你的内存到7G?正常情况下,应该是不可能的。那样的话,你不会被困在做其他事情吗?错误的。所以在Linux中,提供了一种技术来控制进程组可以使用的资源。Cgroups中有很多子系统,每个子系统都有自己独特的资源限制能力,比如:blkio:为块设备设置I/O限制,一般用于磁盘等设备;cpuset:为进程CPU核和对应的内存节点分配单独的资源;memory:设置进程的内存使用限制;cpu:使用调用程序来控制进程对CPU的访问;LinuxCgroups的设计比较好用,它是一个子系统目录加上一个组资源限制文件的组合。对于Docker等Linux容器项目,他们只需要在每个子系统下为每个容器创建一个controlgroup(即新建目录),然后在启动容器进程后,将进程的PID填入对应的control即可该组的任务文件很好。至于这些控制组下的资源文件填什么值,留给用户在执行dockerrun时指定参数。经过上面的分析,我们就可以明白,容器,听上去神秘莫测,其实只是操作系统上的一个特殊进程。所以,容器本身没有价值,有价值的是“容器编排”。当我们谈论容器时,实际上是在谈论如何更好地安排容器。这就是为什么k8s现在如此受欢迎的原因。容器和虚拟机的异同看到这里,是不是对容器和虚拟机的区别产生了疑惑呢?你可能看过下面这张图:在图片的左边,画出了虚拟机的工作原理,hypervisor软件是虚拟机的主要部分。它使用硬件虚拟化功能来虚拟化主机的cpu、内存和I/O设备。在这些虚拟硬件上,安装了新的操作系统。就是图中的GuestOS。此时,用户的应用进程就可以在这个虚拟机中运行了,它只能看到GuestOS的文件和目录,它也使用了本机中的虚拟设备。这就是为什么虚拟机可以相互隔离不同的应用进程,因为它们所在的系统不是同一个系统。这张图右边是容器,它只由应用本身和它的环境依赖(库和其他应用)组成,直接运行在宿主机上。当你要启动一个容器时,不需要启动整个操作系统,因为它本来就在这个操作系统上。而且,由于容器直接在宿主机上,所有容器共享底层操作系统,没有额外的全新安装操作系统,这使得容器在体积和启动速度上更快,开销更少,更多高效的。易于迁移。还记得讲容器的时候介绍过的Namespace技术。虚拟机确实存在,你可以直接在你的电脑上创建一个,但容器是不同的。主机中没有运行真正的“容器”。Docker项目帮助用户启动的是原来的应用进程,只是在创建这些进程的时候,加入了Namespace参数,但是对于宿主来说,本质还是一个进程。