Fari

什么是容器

之前一直把容器理解成虚拟机,容器内的用户是独立的,与宿主机无关的,容器内的进程也是完全和宿主机隔离的。今天才知道这基本上是错误的,这是被vmware这类虚拟机形成思维定势了。

使用vmware创建一个虚拟机就好像在现实世界中,使用计算机完全模拟出来一个虚拟世界,这个虚拟世界的环境和真实世界一模一样,只不过它是用计算机模拟的。这个虚拟世界中出现任何问题都不会对现实世界造成影响,虚拟世界的人口膨胀到人挤人了,现实世界该咋样还咋样。

但是容器不同,容器使用的是命名空间的技术,就是贴标签,所有的人都是真实存在的,他们共享同一片土地。但是给他们穿上了不同的衣服,红色衣服的人只能看到穿红色衣服的人,绿色的只能看到绿色衣服的人,总之就是只能看到同标签的人。那么,如果哪天穿红色衣服的人发生了人口膨胀,那势必穿绿色衣服人的生存空间也会受到影响——即使他们互相看不到对方。

这就意味着,你在容器中运行一个MySQL进程,实际上在宿主机是真的有一个MySQL进程在运行的

可以这样理解,当你创建一个容器后,它会先创建一堆文件,例如/usr、/opt等等,这些文件也是真的在宿主机存在的,只不过它们会分配一个命名空间(标签),例如实际创建的/usr目录可能是 xxx:/usr,而所有带有xxx的文件或者进程,也都只能看到带有xxx的文件或进程。

但是从宿主机的角度来看,不管带有什么标签,一个进程就是一个进程,文件就是文件。这就是为什么明明是在虚拟机中运行的MySQL,却能在宿主机上通过top看到(可能pid显示不同)。也就是说,如果你在容器中启动了两个进程,你在宿主机中kill掉其中一个,那另一个进程仍然是在容器中正常运行的。

另一个非常重要的概念就是用户映射了,既然容器中的进程和文件都是实实在在在宿主机上的,那么如果我在容器中创建了一个文件或者启动一个进程,那这个文件或进程是属于哪个用户的呢?

实际上容器中的用户和宿主机的某个用户本质上是同一个用户,它们之间通过用户映射关系进行绑定。例如在宿主机下我有一个用户hunt,当我用该用户创建了一个容器时,容器运行时(docker、containerd等)会在容器中创建创建一个用户(比如root),并将root映射到宿主机上的hunt,它们其实本质上就是同一个用户在不同的命名空间下的映射,不同命名空间下拥有的权限也不同。所以此时我在容器中以root身份启动了一个MySQL服务,而在宿主机中看到的其实是hunt启动的一个MySQL服务。那如果我手动在容器中创建一个用户,然后用这个用户启动一个进程,宿主机看到的是什么呢?这就得看容器运行时的具体实现了,可能使用启动容器运行时的账户,可能使用一个匿名账户等等。

Tags: