LXC
容器的概念
•容器技术,也称为容器,是一种包装方法一个应用程序,使其可以运行,并与其他应用程序隔离过程。
•容器是一个标准的软件单元,用于打包代码及其所有依赖关系使应用程序从一个计算环境到另一个。
•将软件打包成标准单元,以便开发、装运和部署
Linux的容器
- Linux容器是一组与系统其他部分隔离的进程,从提供支持这些进程所需的所有文件的不同映像运行。
- FreeBSD jail, 2000
- Linux VServer, 2001
- CGroups
- Namespaces
- LXC
Linux命名空间
•名称空间将全局系统资源包装在一个抽象中,使名称空间内的进程似乎拥有自己的全局资源的独立实例。
•对全局资源的更改对作为命名空间成员的其他进程可见,但对其他进程不可见。
•名称空间的一个用途是实现容器。
命名空间API包括以下系统调用:
- 克隆(2):克隆(2)系统调用创建一个新进程。
- setns(2):setns(2)系统调用允许调用进程加入现有命名空间。
- 取消共享(2):取消共享(2)系统调用将调用进程移动到新的命名空间
主机虚拟化和容器
KVM和LXC
命名空间和容器
PID命名空间
Linux Namespaces and CGroups
•Namespaces
• Mount namespaces:挂载点
• UTS namespaces:主机名与域名
• IPC namespaces:信号量、消息队列和共享内存
• PID namespaces:进程号
• Network namespaces:网络设备、网络栈、端口等
• User namespaces:用户和组
•cgroups
• blkio:块设备IO
• cpu:CPU
• cpuacct:CPU资源使用报告
• cpuset:多处理器平台上的CPU集合
• devices:设备访问
• freezer:挂起或恢复任务
• memory:内存用量及报告
• perf_event:对cgroup中的任务进行统一性能测试
• net_cls:cgroup中的任务创建的数据报文的类别标识符
filesystem namespace
CGroups
什么是LXC
•lxc是linux内核包含特性的用户空间接口。
•当前的lxc使用以下内核特性来包含进程
•内核名称空间(ipc、uts、mount、pid、network和user)
•Apparmor和Selinux配置文件
• Seccomp policies
• Chroots (using pivot_root)
• Kernel capabilities
• CGroups (control group
•LXC容器通常被视为介于chroot和一个成熟的虚拟机。
•LXC的目标是创造一个尽可能接近标准的环境Linux安装,但不需要单独的内核。
•Linux容器已经成为一个关键的开源应用程序包以及交付技术,将轻量级应用程序隔离与基于图像的部署方法的灵活性。
•CentOS 7使用核心技术实现Linux容器,如用于资源管理的控制组(cgroup),用于进程隔离,selinux用于安全性,支持安全的多租户和降低安全漏洞的可能性
•LXC、容器、OpenVZ、systemd-nspawn、RUNC
- Linux 容器架构
Docker
runC
•OCF:开放容器格式
•runc是一个cli工具,用于根据oci规范生成和运行容器
•容器作为runc的子进程启动,可以嵌入到其他各种系统中,而无需运行守护进程
•runc建立在libcontainer之上,同样的容器技术为数百万的docker引擎安装提供动力
docker架构
•Docker守护进程(Docker daemon)
•Docker守护进程(Dockerd)监听Docker API请求并管理Docker对象,如图像、容器、网络和卷。
•Docker客户端(Docker client)
•Docker客户端(Docker)是许多Docker用户与之交互的主要方式。
•docker命令使用的是docker api。
•Docker注册表
•Docker注册表存储Docker图像。
•Docker Hub和Docker Cloud是任何人都可以注册使用,Docker默认在Docker Hub上查找镜像。
•你甚至可以运行自己的私有仓库
Docker对象
•使用Docker时,您正在创建和使用镜像,容器,网络、卷、插件和其他对象。
- 镜像
- 镜像是一个只读模板,包含创建Docker容器的说明。
- 通常,一个图像基于另一个图像,并有一些额外的定制。
- 你可以创建自己的镜像,也可以只使用其他人创建并在仓库中发布的图像。
- 容器
- 容器是基于镜像运行的实例。
- 您可以使用Docker API或CLI创建、运行、停止、移动或删除容器。
- 你可以将容器连接到一个或多个网络,将存储连接到它,甚至创建新的
- 你可以将容器连接到一个或多个网络,分配存储给它,甚至基于容器当前的状态重新制作一个镜像。
Docker Host and Registry
chroot
chroot是操作系统级的“虚拟机”,其功能是切换程序运行时的根目录,将程序限制在指定的根目录中,从而隔离应用程序。在chroot中运行的程序实际上使用的是真实系统的内核和资源,所以性能不会有损耗。
- 其好处主要有:
- 增强主机安全性
在chroot中的程序不会访问到真实的系统文件,如真实系统的passwd等文件,和Windows下的沙箱类似,尤其适合对高风险的应用,如web等 - 独立的程序运行环境
运行在chroot中的程序使用的是chroot中的资源,不会使用主机提供的库文件等。要想在程序能在chroot中运行,就要解决依赖关系,所以用chroot还可以把程序“绿色化”,配置好的chroot环境,打包好丢到其它服务器直接就可以运行。这一特性也方便了运维和开发。 - 限制资源访问
可以限制chroot环境中用户能使用的命令,例如:如果不想用户使用passwd命令,不要把passwd命令放到chroot环境中就行了。出与安全考虑运行在chroot中的程序建议给最小权限。
- 增强主机安全性
- 作用:
- 将特权分配给无特权的进程,例如 Web 服务或 DNS 服务。
- 建立测试环境。
- 不使程序或系统崩溃下,运行旧程序或 ABI 兼容的程序。
- 系统恢复。
- 重新安装引导装载程序,例如 Grub 或 Lilo。
- 密码找回,重置一个已丢失的密码等。
LinuX Container
lxc-create,template
lxc增强版docker
命名空间「Namespaces」
pid namespace
不同用户的进程就是通过 pid namespace 隔离开的,且不同 namespace 中可以有相同 PID。具有以下特征:
每个 namespace 中的 pid 是有自己的 pid=1 的进程(类似 /sbin/init 进程)
每个 namespace 中的进程只能影响自己的同一个 namespace 或子 namespace 中的进程
因为 /proc 包含正在运行的进程,因此在 container 中的 pseudo-filesystem 的 /proc 目录只能看到自己 namespace 中的进程
因为 namespace 允许嵌套,父 namespace 可以影响子 namespace 的进程,所以子 namespace 的进程可以在父 namespace 中看到,但是具有不同的 pid
参考文档:Introduction to Linux namespaces – Part 3: PID
mnt namespace
类似 chroot,将一个进程放到一个特定的目录执行。mnt namespace 允许不同 namespace 的进程看到的文件结构不同,这样每个 namespace 中的进程所看到的文件目录就被隔离开了。同 chroot 不同,每个 namespace 中的 container 在 /proc/mounts 的信息只包含所在 namespace 的 mount point。
net namespace
网络隔离是通过 net namespace 实现的, 每个 net namespace 有独立的 network devices, IP addresses, IP routing tables, /proc/net 目录。这样每个 container 的网络就能隔离开来。 docker 默认采用 veth 的方式将 container 中的虚拟网卡同 host 上的一个 docker bridge 连接在一起。
参考文档:Introduction to Linux namespaces – Part 5: NET
uts namespace
UTS ("UNIX Time-sharing System") namespace 允许每个 container 拥有独立的 hostname 和 domain name, 使其在网络上可以被视作一个独立的节点而非 Host 上的一个进程。
参考文档:Introduction to Linux namespaces – Part 1: UTS
ipc namespace
container 中进程交互还是采用 Linux 常见的进程间交互方法 (interprocess communication - IPC), 包括常见的信号量、消息队列和共享内存。然而同 VM 不同,container 的进程间交互实际上还是 host 上具有相同 pid namespace 中的进程间交互,因此需要在IPC资源申请时加入 namespace 信息 - 每个 IPC 资源有一个唯一的 32bit ID。
参考文档:Introduction to Linux namespaces – Part 2: IPC
user namespace
每个 container 可以有不同的 user 和 group id, 也就是说可以以 container 内部的用户在 container 内部执行程序而非 Host 上的用户。
有了以上 6 种 namespace 从进程、网络、IPC、文件系统、UTS 和用户角度的隔离,一个 container 就可以对外展现出一个独立计算机的能力,并且不同 container 从 OS 层面实现了隔离。 然而不同 namespace 之间资源还是相互竞争的,仍然需要类似 ulimit 来管理每个 container 所能使用的资源 - cgroup。
Docker 镜像
•Docker镜像含有启动容器所需要的文件系统及其内容,因此,其用
于创建并启动docker容器
•采用分层构建机制,最底层为bootfs,其之为rootfs • bootfs:用于系统引导的文件系统,包括bootloader和kernel,容器启动完成后会被卸载以节约内存资源;
• rootfs:位于bootfs之上,表现为docker容器的根文件系统;
• 传统模式中,系统启动之时,内核挂载rootfs时会首先将其挂载为“只读”模式,完整性自检完成后将其重新挂载为读写模式;
• docker中,rootfs由内核挂载为“只读”模式,而后通过“联合挂载 ”技术额外挂载一个“可写”层;
•位于下层的镜像称为父镜像(parent image),最底层的称为基础镜像(base
image)
•最上层为“可读写”层,其下的均为“只读”层
Aufs
• advanced multi-layered unification filesystem:高级多层统一文件系统
•用于为Linux文件系统实现“联合挂载”• aufs是之前的UnionFS的重新实现,2006年由Junjiro Okajima开发;
• Docker最初使用aufs作为容器文件系统层,它目前仍作为存储后端之一来支持;
• aufs的竞争产品是overlayfs,后者自从3.18版本开始被合并到Linux内核;
• docker的分层镜像,除了aufs,docker还支持btrfs, devicemapper和vfs等
• 在Ubuntu系统下,docker默认Ubuntu的 aufs;而在CentOS7上,用的是devicemappe
Devicemapper
•Device Mapper 是 Linux2.6 内核中支持逻辑卷管理的通用设备映射机制
,它为实现用于存储资源管理的块设备驱动提供了一个高度模块化的
内核架构
•在内核中它通过一个一个模块化的 target driver 插件实现对 IO 请求的过滤或者重新定向等工作,当前已经实现的 target driver 插件包括软raid、软加密、逻辑卷条带、多路径、镜像、快照等
•前一页图中 linear、mirror、snapshot、multipath 表示的就是这些 target driver
•在这诸多“插件”中,有一种叫Thin Provisioning Snapshot,Docker正是使用了Thin Provisioning的Snapshot的技术实现了类似auFS的分层镜像