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

简介: Docker 在当下很火,那么,当我们谈 Docker ,谈容器的时候,我们在谈什么?或者说,你对 Docker ,对容器了解吗?容器,到底是怎么一回事儿?

Linux 容器

这篇文章着重来讲一下 Linux 容器,为什么强调 Linux 容器,而不是 Docker ,是因为 Docker 是基于虚拟化技术来实现的,但是这篇文章涉及到 Linux 容器的核心实现方面,两者不同,所以着重强调一下。

容器其实是一种沙盒技术。顾名思义,沙盒就是能够像一个集装箱一样,把你的应用装起来。这样,应用与应用之间就有了边界而不会相互干扰;同时装在沙盒里面的应用,也可以很方便的被搬来搬去,这也是 PaaS 想要的最理想的状态。但是说起来容易,等到真正实现起来的时候,就会有难度。因为容器是运行在宿主机上面的,当它运行起来的时候,需要加载到内存中,需要 CPU 完成加法操作等等。也就是说,如果想要实现真正意义上的容器,就要解决容器和宿主机真正隔离这样的问题,但现实中这样的问题还没办法解决。

既然问题还没解决,那么我们所说的容器,是在说什么?容器的核心功能又什么?

容器核心功能

在上面已经说过,容器其实是一种沙盒技术,应用和应用之间有“边界”。所以容器的核心功能,就是通过约束和修改进程的动态表现,从而创造出一个"边界"。

这个官方语言可能会有点儿难懂,咱们换个说法。容器用英语来说就是 Container ,而 Container 的另一个意思是集装箱。提到集装箱的时候,你的脑海里第一反应是不是大船停靠在岸边,然后好多整齐划一的箱子可以运来运去。为什么这些集装箱可以很方便的运来运去呢?因为它们大小一致,而且是箱子,对吧?所以当我们使用 Container 来形容容器的时候,就是我们想要让容器达到一个可以打包,符合标准的状态。

基于以上,我觉得咱们可以达成一个共识,就是如果想要让容器帮助我们达到一个可以打包,符合标准的状态的话,首先要解决的是什么问题?就是将容器和容器之间隔离出来,这样我才能对这个容器统一做一个操作,对不对。对于 Docker 等大多数 Linux 容器来说,做到让容器和容器之间隔离,主要是两种技术:一种是看起来是隔离了的技术:Namespace 技术,它是用来修改进程视图的主要方法,也就是说每个 namespace 中的应用看到的是不同的 IP 地址、用户空间等;一种是用起来是隔离了的技术:Cgroups 技术,它是用来制造约束的主要手段,也就是说,我这台服务器总共有 8G 的内存,都给这一个应用的话,其他的应用怎么跑起来呢?所以 Cgroups 技术就是对容器来做一个限制。

Namespace

Namespace 就是命名空间的意思,如果编程使用的是,面向对象的程序设计语言,那对于这个词应该不是很陌生。一个团队在一起写代码,难免会有相同的类,此时编译就会冲突。如果每个功能都有自己的命名空间,那在不同的空间里面就算类名相同,也不会有啥冲突。写程序如此,在 Linux 上跑程序也是如此。当我们在一台 Linux 上跑多个进程时,进程有全局的进程 ID ,网络也有全局的路由表。如果多个进程使用不同的路由策略,可能会导致这些进程冲突,解决办法也很简单,将这些进程放在一个独立的 namespace 里面就可以了嘛。

说是这样说,但是有一点我希望你能明确知道,进程在静态状态下就是程序,它只是磁盘上的二进制文件罢了。只有当它运行起来时,才成为进程。所以,当我们开始运行程序时,操作系统都会为进程分配一个进程编号,这个编号就是进程的唯一标识。假设我们开始运行了一个程序,它的 PID=100 。也就是说这个程序是第 100 个进程,在它前面还有 99 个进程。而现在,如果我们通过 Docker 把这个程序运行在一个容器当中,那么 Docker 就会在第 100 个进程创建时,给它施一个"障眼法",让它永远看不到其他 99 个进程,这样这个程序就会误以为自己是第 1 个进程 这种机制,其实就是对被隔离应用的进程空间做了手脚,使得这些进程只能看到重新计算过的进程编号,比如上面的第 100 个进程,经过 Docker 的"障眼法"之后,误以为自己是第 1 个进程,但是实际上在宿主机的操作系统中,它还是原来的第 100 个进程。

容器限制( Cgroups )

Linux Cgroups 的全称是 Linux Control Group 。它最主要的作用,就是限制一个进程组能够使用的资源上限,包括 CPU ,内存,磁盘,网络带宽等。特别简单的一句话就是,你的电脑只有 8G 内存,你会允许一个进程占用你的内存到 7G 嘛?一般情况下应该是不会吧,那样的话,做其他事情不都卡的要死嘛,对不对。所以在 Linux 中,提供了一种技术,来控制进程组所能使用的资源。Cgroups 的有很多子系统,每一项子系统都有自己独有的资源限制能力,比如:

  • blkio :为块设备设定 I/O 限制,一般用于磁盘等设备;
  • cpuset :为进程分配单独的 CPU 核和对应的内存节点;
  • memory :为进程设定内存使用的限制;
  • cpu :使用调用程序为进程控制 CPU 的访问;Linux Cgroups 的设计还是比较易用的,它就是一个子系统目录加上一组资源限制文件的组合。对于 Docker 等 Linux 容器项目来说,它们只需要在每个子系统下面,为每个容器创建一个控制组(即创建一个新目录),然后在启动容器进程之后,把这个进程的 PID 填写到对应控制组的 tasks 文件中就可以了。至于在这些控制组下面的资源文件里填什么值,那就交给用户执行 docker run 时的参数来指定了。

经过以上分析,我们可以了解到,容器这个听起来玄而又玄的概念,实际上它就是操作系统上的一种特殊的进程而已。所以,容器本身并没有价值,有价值的是"容器编排"。当我们在谈容器的时候,其实我们在谈如何更好的去编排容器。这也是为什么当下 k8s 这么火的原因。

容器与虚拟机异同

看到这里,你会不会有疑问,容器和虚拟机之间有什么不同呢?你可能看到过下面这个图片:110.jpg

在这张图的左边,画出了虚拟机的工作原理,其中 Hypervisor 的软件是虚拟机主要部分,它通过硬件虚拟化功能,将主机的 cpu ,内存, I/O 设备等虚拟出来,在这些虚拟的硬件上,安装了一个新的操作系统,也就是图中的 GuestOS 。此时,用户的应用进程就可以运行在这个虚拟的机器中,它能看到的也就只有 GuestOS 的文件和目录,使用的也是这个机器里面的虚拟设备。这就是为什么虚拟机能够将不同的应用进程相互隔离,因为它们所在的系统本来就不是同一个系统。

这张图的右边则是容器,它只由应用程序本身和它的环境依赖(库和其他应用程序)两部分组成,并且是直接在宿主机上运行的。当你想要启动容器的时候,根本不需要启动整个操作系统,因为它本来就是在这个操作系统上的。而且,因为容器直接在宿主机上,所有容器都共享这个底层操作系统,没有另外新装操作系统,这就使得容器不管是在体积上,还是启动速度方面,都会更快,开销更小,也更加容易迁移。

还记得讲容器的时候,介绍的 Namespace 技术嘛,虚拟机是真实存在的,你可以直接在自己的电脑上创建一个,但是容器不一样,它没有一个真正的“容器”运行在宿主机里面, Docker 项目帮助用户启动的,还是原来的应用进程,只是在创建这些进程时,加上了 Namespace 参数罢了,但是对于宿主机来说,本质还是进程罢了。

参考:

1、极客时间:《深入剖析 Kubernetes》 2、《Kubernetes 进阶实战》


好了各位读者朋友们,以上就是本文的全部内容了。能看到这里的都是最优秀的程序员,二哥必须要伸出骄傲的大拇指为你点个赞👍。如果觉得不过瘾,还想看到更多,我再给大家推荐几篇。

HashMap 在多线程环境下操作可能会导致程序死循环

线程安全之synchronized关键字

灵魂拷问:Java的Comparable和Comparator是兄弟俩吗?

灵魂拷问:Java如何获取数组和字符串的长度?length还是length()?

日常操作来了!如果觉得这篇文章有点用的话,求在看、求转发,明人不说暗话,我喜欢这种被大家伙宠爱的感觉。

one more thing!如果大家想要在最短的时间内成为一名 Java 大神,可以扫描下方的二维码,加入我们的知识星球。我们下篇文章见!

相关文章
|
3月前
|
机器学习/深度学习 人工智能 自然语言处理
短剧出海配音技术演进:从拼接合成到零样本声音克隆
本文梳理TTS技术四代演进:从机械拼接、参数合成,到端到端神经网络,再到零样本声音克隆。聚焦短剧配音痛点——情感失真、节奏错位、音色错配,详解CosyVoice、ElevenLabs等方案如何实现细粒度情感控制、智能停顿与角色化音色匹配,推动AI从“朗读”迈向“演戏”。
|
6月前
|
存储 机器学习/深度学习 人工智能
别让大模型“失忆”:手把手教你用向量数据库打造它的专属知识库
本文深入浅出地讲解向量数据库原理与实践:用“语义身份证”比喻Embedding,以图书管理员类比关键词与语义搜索差异;手把手用Python+Faiss+BGE搭建中文语义检索系统,并详解RAG流程、效果评估与调优要点,助你为大模型装配真正懂业务的“外挂大脑”。
702 4
|
应用服务中间件 Linux 开发者
用的到linux-tomcat端口占用排查-Day5
通过本文的介绍,详细讲解了在CentOS 8系统上排查和解决Tomcat端口占用问题的方法。从使用 `netstat`、`lsof`和 `ss`命令检查端口占用情况,到使用 `ps`和 `top`命令查找和停止占用端口的进程,再到修改Tomcat端口配置,最后介绍了自动化脚本的方法。希望本文能帮助系统管理员和开发者有效地解决端口占用问题,确保Tomcat服务器的正常运行。
636 11
|
Linux 数据安全/隐私保护
Linux文件权限调整:chmod指令解析
在日常使用或系统管理中,对 `chmod`的熟练应用是提高工作效率和维持系统稳定性的关键。掌握如何给予或限制权限是每个Linux使用者都应该具备的技能。
758 17
|
Ubuntu Linux Shell
Linux系统中如何查看磁盘情况
【9月更文挑战第3天】在Linux系统中,有多种方式查看磁盘情况。可通过命令行工具`df`查看文件系统磁盘使用情况,选项`-h`以人类可读格式显示,`-T`显示文件系统类型;`du`命令显示目录或文件磁盘使用情况,`-h`以人类可读格式显示,`-s`仅显示总计;`fdisk -l`列出磁盘和分区信息。此外,图形界面的磁盘管理工具和文件管理器也可用于查看磁盘使用情况。这些方法有助于更好地管理磁盘空间。
1715 4
|
数据采集 人工智能 数据可视化
如何让AI写出高质量的数据分析报告?DataV-Note的评估体系揭秘
本文围绕DataV-Note智能分析创作平台的评估体系建设展开,旨在探索如何在AI技术快速发展的背景下,构建一套科学、可量化、多维度的数据分析报告评估体系。
535 10
|
存储 监控 安全
开发者的黄金时代:原生鸿蒙应用市场的全生命周期服务
2024年10月22日,华为发布了HarmonyOS NEXT,标志着鸿蒙生态进入商用发展阶段。原生鸿蒙应用市场全面焕新,不仅在UI设计、互动体验和隐私安全机制上进行了重塑,还为开发者和用户提供了从开发到分发的全生命周期服务。通过统一上架、多端分发、隐私合规保障等措施,原生鸿蒙应用市场助力开发者实现高效、安全的应用开发与分发,为全球数亿鸿蒙用户带来更流畅、更安全的使用体验。
|
C++
Leetcode第一题(两数之和)
这篇文章介绍了解决LeetCode第一题“两数之和”的两种方法:暴力法和哈希表法,并提供了相应的C++代码实现。
506 0
Leetcode第一题(两数之和)
|
IDE Java 程序员
安卓应用开发入门:打造你的第一个“Hello World”
【9月更文挑战第11天】在编程的世界里,每一个初学者的旅程都从一个简单的“Hello World”开始。本文将带领安卓开发的新手们,通过简单直观的方式,一步步构建出自己的第一个安卓应用。我们将探索安卓工作室(Android Studio)的安装、项目的创建,以及如何运行和调试你的应用。无论你是编程新手还是想扩展技能的老手,这篇文章都将为你打开一扇通往安卓世界的大门。
622 8
|
机器学习/深度学习 编解码 算法
常用的Python库介绍
Python作为一种功能强大的编程语言,拥有众多的第三方库和框架,这些库和框架覆盖了从数据处理、网络编程、Web开发到人工智能等多个领域。
493 15