概述

业务是基于应用运转的,曾经每个服务器只能运行单一应用。为了解决这个问题,虚拟机技术出现了。每当业务部门需要增加应用的时候,IT部门会尝试在现有的有空闲性能的服务器上安装虚拟机并部署新的应用。

不过虚拟机最大的缺点就是依赖其专用的操作系统。OS会占用额外的CPU、RAM和存储,这些资源本可以用于运行更多的应用。每个OS都需要补丁和监控。另外在某些情况下,OS需要许可证才能运行。

容器模型其实跟虚拟机模型相似,其主要的区别在于,容器的运行不会独占操作系统。实际上,运行在相同宿主机上的容器是共享一个操作系统的,这样就能够节省大量的系统资源,如CPU、RAM以及存储。容器同时还能节省大量花费在许可证上的开销,以及为OS打补丁等运维成本。同时容器还具有启动快和便于迁移等优势。

但容器技术在发展之初很难应用于生产环境,Docker的出现让容器虚拟化技术开始被大众广泛使用。

安装

这里简单介绍一下在Linux系统上安装Docker的两种方式。

脚本安装

在Linux上使用wget获取安装脚本并执行:

$ wget -qO- https://get.docker.com/ | sh

yum安装

添加 Docker 安装源:

$ sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

安装最新版Docker:

$ sudo yum install docker-ce docker-ce-cli containerd.io

最好通过非root用户来使用Docker,这时需要添加非root用户到本地Docker Unix组当中:

$ sudo usermod -aG docker test

如果读者当前登录用户就是要添加到Docker组中的用户的话,则需要重新登录,组权限设置才会生效。

存储驱动的选择

每个Docker容器都有一个本地存储空间,用于保存层叠的镜像层以及挂载的容器文件系统。本地存储是通过存储驱动进行管理的,Docker在Linux底层支持几种不同的存储驱动的具体实现,每一种实现方式都采用不同方法实现了镜像层和写时复制。

在Linux上,Docker可选择的一些存储驱动包括AUFS(最原始也是最老的)、Overlay2(可能是未来的最佳选择)、Device Mapper、Btrfs和ZFS。

存储驱动的选择是节点级别的。这意味着每个Docker主机只能选择一种存储驱动,而不能为每个容器选择不同的存储驱动。在Linux上,读者可以通过修改/etc/docker/daemon.json文件来修改存储引擎配置,修改完成之后需要重启Docker才能够生效。下面的代码片段展示了如何将存储驱动设置为overlay2。

{
  "storage-driver": "overlay2"
}

如果读者修改了正在运行Docker主机的存储引擎类型,则现有的镜像和容器在重启之后将不可用,这是因为每种存储驱动在主机上存储镜像层的位置是不同的(通常在/var/lib/docker/ <storage-driver>/...目录下)。修改了存储驱动的类型,Docker就无法找到原有的镜像和容器了。切换到原来的存储驱动,之前的镜像和容器就可以继续使用了。

如果读者希望在切换存储引擎之后还能够继续使用之前的镜像和容器,需要将镜像保存为Docker格式,上传到某个镜像仓库,修改本地Docker存储引擎并重启,之后从镜像仓库将镜像拉取到本地,最后重启容器。

可以通过下面的命令来检查Docker当前的存储驱动类型。

$ docker system info

基本原理

Docker 是利用Linux的Namespace、Cgroups和联合文件系统三大机制来保证实现的,所以它的原理是使用Namespace做主机名、网络、PID 等资源的隔离,使用Cgroups对进程或者进程组做资源(例如:CPU、内存等)的限制,联合文件系统用于镜像构建和容器运行环境

Namespace

Namespace是Linux内核的一项功能,该功能对内核资源进行隔离,使得容器中的进程都可以在单独的命名空间中运行,并且只可以访问当前容器命名空间的资源。Namespace可以隔离进程ID、主机名、用户ID、文件名、网络访问和进程间通信等相关资源。

Docker主要用到以下五种命名空间:

  • pid namespace:用于隔离进程ID。
  • net namespace:隔离网络接口,在虚拟的net namespace内用户可以拥有自己独立的IP、路由、端口等。
  • mnt namespace:文件系统挂载点隔离。
  • ipc namespace:信号量,消息队列和共享内存的隔离。
  • uts namespace:主机名和域名的隔离。

Cgroups

Cgroups是一种Linux内核功能,可以限制和隔离进程的资源使用情况(CPU、内存、磁盘 I/O、网络等)。在容器的实现中,Cgroups通常用来限制容器的CPU和内存等资源的使用。

联合文件系统

联合文件系统,又叫 UnionFS,是一种通过创建文件层进程操作的文件系统,因此,联合文件系统非常轻快。Docker 使用联合文件系统为容器提供构建层,使得容器可以实现写时复制以及镜像的分层构建和存储。常用的联合文件系统有 AUFS、Overlay 和 Devicemapper 等。


与昊
225 声望636 粉丝

IT民工,主要从事web方向,喜欢研究技术和投资之道