Docker 核心技术

Docker 核心技术

简介

  • 基于 Linux 内核的 CgroupNamespace,以及 Union FS 等技术,对进程进行封装隔离,属于操作系统层面的虚拟化技术,由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。
  • 最初实现是基于 LXC,从 0.7 以后开始去除 LXC,转而使用自行开发的 Libcontainer,从 1.11 开始,则 进一步演进为使用 runC 和 Containerd。
  • Docker 在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极大的简化了容 器的创建和维护,使得 Docker 技术比虚拟机技术更为轻便、快捷。

Docker 原理

Namespace

介绍

Linux Namespace 是一种 Linux Kernel 提供的资源隔离方案:

  • 系统可以为进程分配不同的 Namespace
  • 并保证不同的 Namespace 资源独立分配、进程彼此隔离,即不同的 Namespace 下的进程互不干扰

Linux 内核代码中 Namespace 的实现

image-20220309091132595

Linux 对 Namespace 操作方法

  • clone

    在创建新进程的系统调用时,可以通过 flags 参数指定需要新建的 Namespace 类型:

    int clone(int (*fn)(void *), void *child_stack, int flags, void *arg)

  • setns

    该系统调用可以让调用进程加入某个已经存在的 Namespace 中:

    Int setns(int fd, int nstype)

  • unshare

    该系统调用可以将调用进程移动到新的 Namespace 下:

    int unshare(int flags)

Namespace 的隔离性

Namespace 类型 隔离资源 Kernel 版本
IPC System V IPC 和 POSIX 消息队列 2.6.19
Network 网络设备、网络协议栈、网络端口等 2.6.29
PID 进程 2.6.14
Mount 挂载点 2.4.19
UTS 主机名和域名 2.6.19
USR 用户和用户组 3.8
Pid namespace
  • 不同用户的进程就是通过 Pid namespace 隔离开的
  • 这使得不同 namespace 中,可以拥有相同的 Pid
net namespace
  • 网络隔离,每个 net namespace 有独立的 network devices, IP addresses, IP routing tables, /proc/net 目录。
  • Docker 默认采用 veth 的方式将 container 中的虚拟网卡同 host 上的一个 docker bridge: docker0 连接 在一起。

docker-network-topology

ipc namespace
  • container 中进程交互还是采用 linux 常见的进程间交互方法(IPC), 包括常见的信号量、消息队列和共享内存。
  • container 的进程间交互实际上还是,同 Pid namespace 中的进程间交互,因此需要在 IPC 资源申请时加入 namespace 信息,每个 IPC 资源有一个唯一的 32 位 ID。
mnt namespace
  • mnt namespace 允许不同 namespace 的进程看到的文件结构不同,这样每个 namespace 中的进程所看 到的文件目录就被隔离开了。
uts namespace
  • UTS(“UNIX Time-sharing System”) namespace 允许每个 container 拥有独立的 hostname 和 domain name,使其在网络上可以被视作一个独立的节点而非 Host 上的一个进程。
user namespace
  • 每个 container 可以有不同的 user 和 group id, 也就是说可以在 container 内部用 container 内部的用户 执行程序而非 Host 上的用户。

namespace 常用操作

  • 查看当前系统的 namespace:

    lsns –t <type>

  • 查看某进程的 namespace:

    ls -la /proc/<pid>/ns/

  • 进入某 namespace 运行命令:

    nsenter -t <pid> -n ip addr

Cgroups

介绍

  • Cgroups (Control Groups)是 Linux 下用于对一个或一组进程进行资源控制和监控的机制;
  • 可以对诸如 CPU 使用时间、内存、磁盘 I/O 等进程所需的资源进行限制;
  • 不同资源的具体管理工作由相应的 Cgroup 子系统(Subsystem)来实现;
  • 针对不同类型的资源限制,只要将限制策略在不同的的子系统上进行关联即可;
  • Cgroups 在不同的系统资源管理子系统中以层级树(Hierarchy)的方式来组织管理:每个 Cgroup 都可以 包含其他的子 Cgroup,因此子 Cgroup 能使用的资源除了受本 Cgroup 配置的资源参数限制,还受到父 Cgroup 设置的资源限制

Linux 内核代码中 Cgroups 的实现

image-20220309094108402

Cgroup 可限制和度量的资源

资源 说明
blkio 这个子系统设置限制每个块设备的输入输出控制。例如:磁盘,光盘以及 USB 等等。
CPU 这个子系统使用调度程序为 cgroup 任务提供 CPU 的访问。
cpuacct 产生 cgroup 任务的 CPU 资源报告
cpuset 如果是多核心的 CPU,这个子系统会为 cgroup 任务分配单独的 CPU 和内存。
devices 允许或拒绝 cgroup 任务对设备的访问。
freezer 设置每个 cgroup 的内存限制以及产生内存资源报告。
memory 设置每个 cgroup 的内存限制以及产生内存资源报告。
net_cls 标记每个网络包以供 cgroup 方便使用。
ns 名称空间子系统。
pid 进程标识子系统。

CPU 子系统

image-20220309095449382

cpuacct 子系统

image-20220309095520509

Memory 子系统

image-20220309095556954

文件系统

介绍

  • 将不同目录挂载到同一个虚拟文件系统下的文件系统
  • 支持为每一个成员目录(类似Git Branch)设定 readonly、readwrite 和 whiteout-able 权限
  • 文件系统分层, 对 readonly 权限的 branch 可以逻辑上进行修改(增量地, 不影响 readonly 部分的)。
  • 通常 Union FS 有两个用途, 一方面可以将多个 disk 挂到同一个目录下, 另一个更常用的就是将一个 readonly 的 branch 和一个 writeable 的 branch 联合在一起。

docker 初始化时,是将 rootfs 以 readonly 方式加载并检查,再通过 union mount 的方式,将 readwrite 文件系统挂在到 rootfs 之上。且允许不断往上叠加,并将下层的 FS 设定为 readonly。

这样一组 readonly 和 writeable 的结构,构成了 docker container 的运行时。

写操作

docker 的镜像具有共享的特性(镜像是一层一层的,底层的 readonly 镜像对于多个容器而言是共享的)。

  • 写时复制
    • 一个镜像可以被多个容器使用,但是不需要在内存和磁盘上做多个拷贝。
    • 在需要对镜像提供的文件进行修改时,该文件会从镜像的文件系统被复制到容器的可写层的文件系统 进行修改,而镜像里面的文件不会改变。
    • 不同容器对文件的修改都相互独立、互不影响。
  • 用时分配
    • 按需分配空间,而非提前分配,即当一个文件被创建出来后,才会分配空间。

OverlayFS

image-20220309100645481

Docker 架构

image-20220309100720348

image-20220309101032907

docker 守护进程 是由 init 创建的,containerd 是由守护进程创建的;

但是 docker 容器进程由 docker shim(垫片,由 init 创建) 创建的,以避免 containerd 带挂一堆下面的进程;

docker 网络

默认模式

image-20220309101533972

posted @ 2022-03-09 10:19  Mrxuexi  阅读(311)  评论(0编辑  收藏  举报