容器的基本操作和实现原理

容器是什么

镜像就是一个特殊的文件系统
它提供了容器中程序执行需要的所有文件。具体来说就是应用程序想要启动,需要三类文件:

  • 相关的程序可执行文件、库文件和配置文件

这三类文件都被容器打包好了
这样,在容器运行的时候就不再依赖宿主机上的文件操作系统类型和配置了

从用户使用的角度来看,容器和一台独立的机器或者虚拟机没有什么太大的区别
但是它和虚拟机相比,却没有各种复杂的硬件虚拟层,没有独立的Linux内核

容器的所有进程调度、内存访问、文件读写都是直接跑在宿主机的内核之上的。

如何实现的

两个术语

  1. Namespace
  2. Cgroups

这两项技术可以让程序在一个资源可控的独立(隔离)环境中运行,这个就是容器了。

Namespace

查看docker容器中的进程情况

1
2
3
4
5
$ docker exec <containerID> ps -ef
PID USER TIME COMMAND
1 root 0:00 nginx: master process nginx -g daemon off;
24 nginx 0:01 nginx: worker process
25 root 0:00 ps -ef

直接在宿主机执行ps -ef | grep nginx也可以看到这几个进程

1
2
3
4
5
$ ps -ef | grep nginx
root 818 760 0 Jan18 ? 00:00:00 nginx: master process nginx -g daemon off;
systemd+ 921 818 0 Jan18 ? 00:00:01 nginx: worker process
root 1305 1276 0 Jan18 ? 00:00:00 nginx: master process nginx -g daemon off;
root 1367 1305 0 Jan18 ? 00:00:00 nginx: worker process

1674991583875

Linux在创建容器的时候,就会创建一个PID Namespace,会单独对进程进行PID的编号(每个Namespace的PID编号都是从1开始的)。
在这个PID Namespace中是看不到其他Namespace里的进程的。

而在宿主机上的Host PID Namespace,它是其他Namespace的父Namespace,可以看到这台机器上的所有进程,不过进程编号不是Container PID Namespace里的编号了。

Namespace其实就是一种隔离机制,主要目的是隔离运行在同一个宿主机上的容器,让这些容器之间不能访问彼此的资源。

作用:

  1. 可以充分利用系统的资源,同一台宿主机上可以运行多个用户的容器
  2. 保证安全性,因为不同用户之间不能访问对方的资源

Namespace类型:

  • Cgroup
  • IPC
  • Network
  • Mount
  • PID
  • Time
  • User
  • UTS

1674992082859

Cgroups

Cgroups(Control Groups)
可以对指定的进程做各种计算机资源的限制,比如限制CPU的使用率、内存使用量、IO设备的流量等等。

Cgroups定义:

几种常用的Cgroups子系统:

  • cpu子系统,用来限制一个控制组(一组进程,可以理解为一个容器里面的所有进程)可使用的最大CPU
  • memory子系统,用来限制一个控制组最大的内存使用量
  • pids子系统,用来限制一个控制组里最多可以运行多少个进程
  • cpuset子系统,用来限制一个控制组里的进程可以在哪几个物理CPU上运行

Cgroups有v1和v2两个版本:
v1在Linux中很早就实现了,各种子系统比较独立,每个进程在各个Cgroups子系统中独立配置,可以属于不同的group

虽然这样比较灵活,但是会导致对同一进程的资源协调比较困难。虽然v1有缺陷,但是生产环境中大部分还是使用的v1。

总结

Namespace帮助容器来实现各种计算资源的隔离

Cgroups主要限制容器能够使用的资源量