- 提供完整的沙盒(隔离)操作系统环境
- 允许打包和隔离应用程序及其整个运行时环境
- 提供可移植的轻量级环境
- 帮助最大限度地提高数据中心的资源利用率
- 协助不同的开发、测试和生产部署工作流
容器定义
一个容器可以定义为一个单一的操作系统镜像,捆绑了一组隔离的应用程序及其依赖的资源,以便它们与主机分开运行。可能有多个这样的容器在同一台主机中运行。
容器可以分为两类:
-
操作系统级别 :整个操作系统在主机内的隔离空间中运行,与主机共享相同的内核。
-
应用程序级别 :应用程序或服务以及该应用程序所需的最少进程在主机内的隔离空间中运行。
容器不同于传统意义上的虚拟化技术,并再很多方面优于传统虚拟化 :
-
与传统虚拟机相比,容器是轻量级的。
-
与容器不同,虚拟机需要仿真层(软件或硬件),这会消耗更多资源并增加额外开销。
-
容器与底层主机共享资源,用户空间和进程隔离。
-
由于容器的轻量级特性,更多的容器可以每台主机不是每个虚拟机上运行的主机 。
-
与较慢的虚拟机启动过程相比,启动容器几乎是立即发生的。
-
容器是可移植的,无论底层主机操作系统如何,都可以使用所需的软件包可靠地重新生成系统环境。
图1-1说明了虚拟机、Linux 容器 (LXC) 或操作系统级容器以及应用程序级容器在主机操作系统中的组织方式的差异。
图 1-1。 比较虚拟机、LXC 或操作系统级容器和应用程序级容器容器历史 开发虚拟化 是为了充分利用可用的计算资源。虚拟化使多个虚拟机能够在单个主机上运行,用于具有自己隔离空间的不同目的。虚拟化使用虚拟机管理程序、位于主机操作系统和来宾或虚拟机操作系统之间的计算机软件实现了这种隔离的操作系统环境。正如介绍中提到的,容器化是虚拟化的下一个逻辑步骤,在操作系统级别和应用程序级别提供虚拟化。 容器技术已经以不同的形式存在了很长时间,但最近随着 Linux 内核中原生容器化支持的引入,它在 Linux 世界中得到了显着的普及。表1-1列出了一些早期的相关技术,它们使我们达到了当前的技术状态。 表 1-1。 容器技术时间表
| 年 | 技术 | 首次在操作系统中引入 |
|---|---|---|
| 1982年 | Chroot | 类 Unix 操作系统 |
| 2000年 | Jail | FreeBSD |
| 2000年 | Virtuozzo 容器 | Linux、Windows(Parallels Inc. 版本) |
| 2001年 | Linux VServer | Linux, 视窗 |
| 2004年 | Solaris 容器(zones ) | Sun Solaris,Open Solaris |
| 2005年 | OpenVZ | Linux(开源版 Virtuozzo) |
| 2008年 | LXC | Linux |
| 2013年 | Docker | Linux、FreeBSD、Windows |
启用容器的功能
容器依靠 Linux 内核中的以下功能在主机内获得一个包含或隔离的区域。该区域与虚拟机密切相关,但不需要管理程序。
-
控制组 (cgroups)
-
命名空间
-
文件系统或 rootfs
控制组 (Cgroups)
要理解 cgroups 的重要性,请考虑一个常见的场景:运行在系统上的进程在特定实例向系统请求某些资源,但不幸的是当前资源不可用,因此系统决定推迟进程,直到请求的资源满足可用的。当其他进程释放它们时,请求的资源可能变得可用。这会延迟流程执行,这在许多应用程序中可能是不可接受的。当恶意进程消耗了系统上的全部或大部分可用资源并且不允许其他进程执行时,就会发生这种资源不可用。
Google 在 2007 年的 cgroups 项目中提出了一种新的通用方法来解决资源控制问题。控制组允许基于进程组来控制和计算资源。主线 Linux 内核在 2008 年首次包含 cgroups 实现,这为 LXC 铺平了道路。
Cgroups 提供了一种将任务或进程集及其未来子项聚合到分层组中的机制。这些组可以根据需要配置为具有专门的行为。
列出 Cgroup
Cgroup列 在目录/sys/fs/cgroup的伪文件系统子系统 中,它提供了当前运行系统中可用或挂载的所有 cgroup 子系统的概览:stylesen@harshu:∼$ ls -alh /sys/fs/cgroup total 0 drwxr-xr-x 12 root root 320 Mar 24 20:40 . drwxr-xr-x 8 root root 0 Mar 24 20:40 .. dr-xr-xr-x 6 root root 0 Mar 24 20:40 blkio lrwxrwxrwx 1 root root 11 Mar 24 20:40 cpu -> cpu,cpuacct lrwxrwxrwx 1 root root 11 Mar 24 20:40 cpuacct -> cpu,cpuacct dr-xr-xr-x 6 root root 0 Mar 24 20:40 cpu,cpuacct dr-xr-xr-x 3 root root 0 Mar 24 20:40 cpuset dr-xr-xr-x 6 root root 0 Mar 24 20:40 devices dr-xr-xr-x 4 root root 0 Mar 24 20:40 freezer dr-xr-xr-x 7 root root 0 Mar 24 20:40 memory lrwxrwxrwx 1 root root 16 Mar 24 20:40 net_cls -> net_cls,net_prio dr-xr-xr-x 3 root root 0 Mar 24 20:40 net_cls,net_prio lrwxrwxrwx 1 root root 16 Mar 24 20:40 net_prio -> net_cls,net_prio dr-xr-xr-x 3 root root 0 Mar 24 20:40 perf_event dr-xr-xr-x 6 root root 0 Mar 24 20:40 pids dr-xr-xr-x 7 root root 0 Mar 24 20:40 systemd
内存子系统层次结构
我们来看一个 cgroup 的内存子系统层次结构的例子。它在以下位置可用: /sys/fs/cgroup/内存 内存子系统层次结构由以下文件组成:root@harshu:/sys/fs/cgroup/memory# ls cgroup.clone_children memory.memsw.failcnt cgroup.event_control memory.memsw.limit_in_bytes cgroup.procs memory.memsw.max_usage_in_bytes cgroup.sane_behavior memory.memsw.usage_in_bytes init.scope memory.move_charge_at_immigrate lxc memory.numa_stat memory.failcnt memory.oom_control memory.force_empty memory.pressure_level memory.kmem.failcnt memory.soft_limit_in_bytes memory.kmem.limit_in_bytes memory.stat memory.kmem.max_usage_in_bytes memory.swappiness memory.kmem.slabinfo memory.usage_in_bytes memory.kmem.tcp.failcnt memory.use_hierarchy memory.kmem.tcp.limit_in_bytes notify_on_release memory.kmem.tcp.max_usage_in_bytes release_agent memory.kmem.tcp.usage_in_bytes system.slice memory.kmem.usage_in_bytes tasks memory.limit_in_bytes user memory.max_usage_in_bytes user.slice root@harshu:/sys/fs/cgroup/memory#列出的每个文件都 包含有关为其创建的控制组的信息。例如,以字节为单位的最大内存使用量由以下命令给出(由于这是顶级层次结构,它列出了当前主机系统的默认设置): root@harshu:/sys/fs/cgroup/memory# cat memory.max_usage_in_bytes 15973715968 前面的值以字节为单位;它对应于大约 14.8GB 的内存,可供当前运行的系统使用。您可以在/sys/fs/cgroup 中创建自己的cgroup并控制每个子系统。
命名空间
在 2006 年举行的渥太华 Linux 研讨会上,Eric W. Bierderman 发表了他的论文“Multiple Instances of the Global Linux Namespaces”(可在https://www.kernel.org/doc/ols/2006/ols2006v1-pages-101- 112.pdf)。这篇论文提出向 Linux 内核添加十个命名空间。他对这些额外命名空间的灵感来自于 2002 年引入的用于挂载的现有文件系统命名空间。提议的命名空间如下:
-
文件系统挂载命名空间 (mnt)
-
UTS 命名空间
-
IPC 命名空间 (ipc)
-
网络命名空间 (net)
-
进程 ID 命名空间 (pid)
-
用户和组 ID 命名空间
-
安全模块和命名空间
-
安全密钥命名空间
-
设备命名空间
-
时间命名空间
命名空间提供了对全局系统资源的抽象,对于定义的命名空间内的进程来说,该资源将作为其自己的特定全局资源的独立实例出现。命名空间用于实现容器;它们提供了容器和主机系统之间所需的隔离。
随着时间的推移,Linux 内核中实现了不同的命名空间。在撰写本文时,Linux 内核中 实现了七个命名空间,列于表1-2 中。
表 1-2。
现有的Linux 命名空间
| 命名空间 | 持续的 | 隔离 |
|---|---|---|
| Cgroup | CLONE_NEWCGROUP | C组根目录 |
| IPC | CLONE_NEWIPC | System V IPC、POSIX 消息队列 |
| Network | CLONE_NEWNET | 网络设备、堆栈、端口等。 |
| Mount | CLONE_NEWNS | 挂载点 |
| PID | CLONE_NEWPID | 进程 ID |
| User | CLONE_NEWUSER | 用户和组 ID |
| UTS | CLONE_NEWUTS | 主机名和 NIS 域名 |
简单网络 命名空间
命名空间是通过将适当的克隆标志传递给clone()系统调用来创建的。有一个网络命名空间的命令行界面,可以用来说明一个简单的网络命名空间,如下: 笔记 创建网络命名空间需要 root 权限。1、创建一个名为stylesen-net的网络命名空间:
# ip netns add stylesen-net
2、要列出新创建的网络命名空间中存在的所有设备,请发出以下命令。此示例显示默认环回设备。
# ip netns exec stylesen-net ip link list 1: lo:mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
3、尝试 ping 回环设备:
# ip netns exec stylesen-net ping 127.0.0.1 connect: Network is unreachable4、 虽然环回设备可用,但尚未启动。启动回送设备并再次尝试 ping:
# ip netns exec stylesen-net ip link set dev lo up # ip netns exec stylesen-net ping 127.0.0.1PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data. 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.045 ms 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.059 ms 64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.097 ms 64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.084 ms 64 bytes from 127.0.0.1: icmp_seq=5 ttl=64 time=0.095 ms ^C --- 127.0.0.1 ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 4082ms rtt min/avg/max/mdev = 0.045/0.076/0.097/0.020 ms因此,我们可以创建 网络命名空间并向其中添加设备。可以创建任意数量的网络命名空间,然后可以在这些单独命名空间中可用的设备之间设置不同的网络配置。



