Docker安全之: 核心机制

1、docker进阶

1.1 操作系统依赖

作为一种容器虚拟化技术,Docker深度应用了操作系统的多项底层支持技术。

Docker容器的实现原理就是通过Namespace命名空间实现进程隔离、UnionFilesystem联合文件系统实现文件系统隔离、ControlGroups控制组实现资源隔离。

Linux操作系统的命令空间(Namesspace)控制组(Control Group)联合文件系统(Union File System)和Linux网络虚拟化支持

2.1.1 名称空间: Namespace

名称空间类型: CLONE_NEWCGROUPCLONE_NEWIPCCLONE_NEWNETCLONE_NEWNSCLONE_NEWPIDCLONE_NEWUSERCLONE_NEWUTS

  • 进程的命名空间:Linux通过命名空间管理进程号,对于同一个进程(即同一个task_struct),在不同的命名空间中,看到的进程号不相同,每个进程命名空间有一套自己的进程号管理方法。进程命名空间是一个父子关系的结构,子空间中的进程对父空间是可见的。新fork出的进程在父命名空间和子命名空间将分别有一个进程号来对应。
  • 网络命名空间:如果有了PID命名空间,那么每个命名空间中的进程就可以相互隔离,但是网络端口还是共享本地系统的端口。通过网络命名空间,可以实现网络隔离。网络命名空间为进程提供了一个完全独立的网络协议栈视图,包括网络设备接口、IPv4和IPv6协议栈、IP路由表、防火墙规则、sockets等,这样每个容器的网络就能隔离开来。Docker采用虚拟网络设备的方式,将不同命名空间的网络设备连接到一起。默认情况下,容器中的虚拟网卡将同本地主机上的docker0网桥连接到一起。
  • IPC命名空间:容器中进程交互还是采用了Linux常见的进程间交互方法(Interprocess Communication)IPC,包括信号量、消息队列和共享内存等。PID Namespace和IPC Namespace可以组合起来一起使用,同一个IPC命名空间内的进程可以彼此可见,允许进行交互,不同空间的进程则无法交互。
  • 挂载命名空间: 类似于chroot,将一个进程放到一个特定的目录执行。挂载命名空间允许不同命名空间的进程看到的文件结构不同,这样每个命名空间中进程所看到的文件目录彼此被隔离。
  • UTS命令空间; UST(UNIX Time-sharing System)命名空间允许独立的主机名和域名,
    从而可以虚拟出一个独立主机名和网络空间环境,就跟网络上一台独立的主机一样。
  • 用户命名空间: 每个容器可以有不同的用户和组ID,也就是说可以在容器内使用特定的内部用户执行程序,而非本地系统上存在的用户。每个容器内部都可以有root账号,但跟宿主机不在一个命名空间。
    通过使用隔离的用户命名空间可以提高安全性,避免容器内进程获取到额外的权限。

2.1.2 控制组: CGroups

Control Groups(简称 CGroups)就是能够隔离宿主机器上的物理资源,例如 CPU、内存、磁盘 I/O 和网络带宽。每一个 CGroup 都是一组被相同的标准和参数限制的进程,不同的 CGroup 之间是有层级关系的,也就是说它们之间可以从父类继承一些用于限制资源使用的标准和参数。

在 CGroup 中,所有的任务就是一个系统的一个进程,而 CGroup 就是一组按照某种标准划分的进程,在 CGroup 这种机制中,所有的资源控制都是以 CGroup 作为单位实现的,每一个进程都可以随时加入一个 CGroup 也可以随时退出一个 CGroup。

CGroup 的使用也确实解决了我们限制子容器资源占用的问题,系统管理员能够为多个容器合理的分配资源并且不会出现多个容器互相抢占资源的问题。

2.1.3 联合文件系统:UnionFS

联合文件系统(UnionFS)是一种轻量级的高性能分层文件系统,它支持将文件系统中的修改信息作为一次提交,
并层层叠加,同时可以将不同目录挂载到同一个虚拟文件系统下,应用看到的是挂载的最终结果。

联合文件系统是实现Docker镜像的技术基础。Docker镜像可以通过分层来进行继承。

Docker目前支持的联合文件系统种类包括:AUFS、OverlayFS、btrfs、vfs、zfs和Device Mapper等。

2.1.4 inux网络虚拟化

Docker的本地网络实现其实就是利用了Linux上的网络命令空间虚拟网络设备(特别是veth)。

Docker虽然通过名称空间将网络等资源与主机资源做了隔离,但是docker中的服务离不开网络的支撑。Docker容器内的服务是如何在隔离情况下正常访问互联网的。

Docker0网卡:

iptable转发:Docker 通过 Linux 的命名空间实现了网络的隔离,又通过 iptables 进行数据包转发,让 Docker 容器能够优雅地为宿主机器或者其他容器提供服务。

libnetwork 中最重要的概念,容器网络模型由以下的几个主要组件组成,分别是 Sandbox、Endpoint 和 Network:

2.1.5 docker、Containerd、runc

Docker Daemon: 和一般的CS架构系统一样,守护进程负责和Docker client交互,并管理Docker镜像、容器。

  • 在Docker1.8之前,Docker守护进程启动的命令为:docker -d,这个阶段,守护进程看上去只是Docker client的一个选项。

  • Docker1.8开始,启动命令就变成了:docker daemon,这个阶段,守护进程看上去是docker命令的一个模块。

  • Docker1.11开始,守护进程启动命令变成了:dockerd,此时已经和Docker client分离独立成一个二进制程序了。

Containerd:Containerd向上为Docker Daemon提供了RPC接口,使得Dokcer Daemon屏蔽下面的结构变化,确保原有接口向下兼容。
向下通过containerd-shim结合runC,使得引擎可以独立升级,避免之前Docker Daemon升级会导致所有容器不可用的问题。

Containerd主要职责是镜像管理(镜像、元信息等)、容器执行(调用组件执行)。

img

RunC: runC是Docker按照开放容器格式标准(OCF,Open containerd Format)制定的一种具体实现。runC是从Docker的libcontainer中迁移而来的,实现了容器启动停止、资源隔离等功能。Docker默认提供了docker-runc实现,事实上,通过containerd的封装,可以在Docker Daemon启动的时候指定runC的实现。

即runc用来创建和运行容器,containerd作为常驻进程用来管理容器。

2.2 Docker核心机制

基本架构

Docker 是一个客户端-服务器(C/S)架构程序。Docker 客户端只需要向 Docker 服务器或者守护进程发出请求,服务器或者守护进程将完成所有工作并返回结果。Docker 提供了一个命令行工具 Docker 以及一整套 RESTful API。你可以在同一台宿主机上运行 Docker 守护进程和客户端,也可以从本地的 Docker 客户端连接运行在另一台宿主机上的远程 Docker 守护进程

img

2.3 Docker三剑客

img

https://zhuanlan.zhihu.com/p/361130561

https://zhuanlan.zhihu.com/p/257954941

https://www.jianshu.com/p/4a1f712185c4

https://www.huweihuang.com/article/runtime/runtime/

https://blog.csdn.net/wujianyongw4/article/details/71632293

https://zhuanlan.zhihu.com/p/470432554

posted @ 2022-11-13 18:18  丘山996  阅读(50)  评论(0)    收藏  举报