Understanding Containers and Containerized Applications
- Kubernetes 主要管理在容器中运行的应用程序。
容器和虚拟机的区别
开销
- 容器不需要单独的资源池或任何其他操作系统级进程。运行在现有主机操作系统中的隔离进程,仅消耗应用程序消耗的资源。
- 虚拟机运行自己的一组系统进程,除了用户应用程序自己的进程消耗的资源之外,还需要额外的计算资源。
- 会将多个应用程序分组到每个虚拟机中。
- 为每个应用程序创建一个单独的容器。
启动时间
- 容器还可以更快地启动应用程序,因为只需要启动应用程序进程本身。
- 虚拟机需要启动其他系统级进程。
隔离
- 虚拟机
- 物理硬件资源拆分为每个虚拟机中的操作系统可以使用的较小的虚拟资源集。
- 运行的应用程序对虚拟机中的来宾操作系统内核进行系统调用。
- 内核在虚拟CPU上执行的机器指令通过虚拟机管理程序转发到主机的物理CPU。
- 每个虚拟机都有自己的linux内核和内存块。
- 容器
- 在主机作系统中运行的单个内核上进行系统调用。
- 这个内核是唯一在主机的CPU上执行指令的内核。
- CPU不需要像处理虚拟机那样处理任何类型的虚拟化。
- 容器使用相同的内核,且共享内存空间。
容器的隐患
- 一个容器中的应用程序可能会使用它来读取其他容器中应用程序的内存。
- 如果不限制容器可以使用的内存量,这可能会导致其他容器内存不足或导致其数据被交换到磁盘。
Docker
Docker是一个用于打包、分发和运行应用程序的平台。
-
镜像
- 容器镜像是将应用程序及其环境打包到其中的东西。如 zip 文件或压缩包。
- 它包含应用程序将使用的整个文件系统和其他元数据,例如执行镜像时要运行的可执行文件的路径、应用程序侦听的端口以及有关镜像的其他信息。
-
注册表
- 注册表是容器映像的存储库,用于在不同的人员和计算机之间交换映像。
- 构建映像后,您可以在同一台计算机上运行它,也可以将映像推送(上传)到注册表,然后将其拉取(下载)到另一台计算机。
- 某些注册表是公共的,允许任何人从中提取映像,而其他注册表是私有的,只有具有所需身份验证凭据的个人、组织或计算机才能访问。
-
容器
- 容器是从容器镜像实例化的。
- 正在运行的容器是在主机操作系统中运行的正常进程,但其环境与主机环境和其他进程的环境隔离。
- 容器的文件系统源自容器映像,但也可以将其他文件系统挂载到容器中。
- 容器通常受到资源限制,这意味着它只能访问和使用已分配给它的资源量,例如CPU和内存。
-
Docker操作流程
- 构建容器镜像。
- 通过注册表分发它。
- 从镜像创建正在运行的容器。
-
当您在容器中运行应用程序时,它会准确地看到您捆绑到容器映像中的文件系统内容,以及您挂载到容器中的任何其他文件系统。
-
无论应用程序是在笔记本电脑上还是在成熟的生产服务器上运行,即使生产服务器使用完全不同的 Linux 发行版,它都会看到相同的文件。
-
应用程序通常无法访问主机操作系统中的文件,因此服务器是否具有与开发计算机完全不同的已安装库集并不重要。
-
镜像层
- 容器镜像由通常小得多的层组成。这些层可以在多个镜像之间共享和重复使用。
- 层使镜像分发非常高效,但也有助于减少镜像的存储占用空间。
- 文件系统通过写时复制(CoW)机制隔离。
- 容器的文件系统由容器映像中的只读层和堆叠在顶部的附加读/写层组成。
- 当在容器 A 中运行的应用程序更改其中一个只读层中的文件时,整个文件将被复制到容器的读/写层中,并在那里更改文件内容。
- 由于每个容器都有自己的可写层,因此对共享文件的更改在任何其他容器中都不可见。
- 删除文件时,它只会在读/写图层中标记为已删除,但它仍然存在于下面的一个或多个图层中。
- 删除文件永远不会减小图像的大小。
-
限制
- 因为容器没有自己的内核。
- 如果容器化应用程序需要特定的内核版本,则它可能无法在每台计算机上运行。
- 如果计算机运行的是不同版本的Linux内核,或者未加载所需的内核模块,则该应用程序无法在其上运行。
docker cli
| 命令 | 简介 |
|---|---|
docker run |
运行容器 |
docker ps |
列出容器 |
docker inspect |
查看容器其他信息 |
docker build |
创建镜像 |
docker rm |
删除容器 |
docker stop |
停止容器 |
docker start |
启动容器 |
docker image |
列出镜像 |
docker history |
查看镜像历史 |
docker log |
查看容器日志 |
docker tag |
添加标签 |
docker push |
推送镜像 |
docker pull |
下载镜像 |
docker rmi |
删除镜像 |
docker image prune |
清除未使用的镜像 |
docker exec |
运行命令 |
docker login |
登录 |
命名空间
- Linux操作系统中可用的所有系统资源(例如文件系统、进程 ID、用户 ID、网络接口等)都位于所有进程查看和使用的同一个存储桶中。
- 内核允许创建称为命名空间的其他存储桶,并将资源移动到其中,以便将它们组织成更小的集合。
- 创建新进程时,可以指定它应使用的命名空间。该进程仅看到此命名空间中的资源,而不会看到其他命名空间中的资源。
类型
-
Mount namespace (mnt)
- 隔离挂载点(文件系统)。
-
Process ID namespace (pid)
- 隔离进程 ID。
-
Network namespace (net)
- 隔离网络设备、堆栈、端口等。
- 为进程提供一组专用的网络接口。
-
Inter-process communication namespace (ipc)
- 隔离进程之间的通信(这包括隔离消息队列、共享内存等)。
-
UNIX Time-sharing System (UTS)
- 隔离系统主机名和网络信息服务(NIS)域名。
- 为进程提供专用主机名。
-
User ID namespace (user)
- 隔离用户和组ID。
-
(Linux Control group)Cgroup namespace
- 隔离控制组根目录。
-
容器是一个分配了七个命名空间(每种类型一个)的进程。有些与其他进程共享,而另一些则不共享。这意味着进程之间的边界并不都在同一条线上。
Linux Control Group
- 隔离系统资源(CPU、内存、磁盘和网络带宽)。
- 使用cgroup时,一个进程或一组进程只能使用分配的CPU、内存和网络带宽。这样,进程就不会占用为其他进程保留的资源。
docker run --cpus="0.5" --memory="100m"
加强容器之间的隔离手段
- Linux capabilities
- 为容器提供所有权限的子集。
- 创建容器时,可以在容器中添加或删除(删除)Capabilities。每个Capability表示容器中进程可用的一组权限。
- seccomp(安全计算模式)
- 创建一个 JSON 文件来创建自定义 seccomp 配置文件,该文件列出了允许使用该配置文件的容器进行的系统调用。然后,在创建容器时将文件提供给 Docker。
- SELinux(安全增强型 Linux)
- 将标签附加到文件和系统资源以及用户和进程中。只有当涉及的所有使用者和对象的标签与一组策略匹配时,用户或进程才能访问文件或资源。
- AppArmor(应用铠甲)
- 一个内置于Linux内核的强制访问控制安全模块。
- 使用文件路径而不是标签,并且专注于进程而不是用户。
总结
- 容器是常规进程,但彼此隔离,与主机作系统中运行的其他进程隔离。
- 容器比虚拟机轻得多,但由于它们使用相同的 Linux 内核,因此它们不像虚拟机那样隔离。
- Docker 是第一个使容器流行的容器平台,也是 Kubernetes 支持的第一个容器运行时。现在,通过容器运行时接口 (CRI) 支持其他接口。
- 容器映像包含用户应用程序及其所有依赖项。它通过容器注册表分发,用于创建正在运行的容器。
- 可以使用单个 docker run 命令下载和执行容器。
- Docker 从 Dockerfile 构建映像,其中包含 Docker 应在构建过程中执行的命令。图像由可在多个图像之间共享的图层组成。每层只需传输和存储一次。
- 容器由称为namespace、Control group、capabilities、seccomp、AppArmor 和/或 SELinux 的 Linux 内核功能隔离。
- 命名空间确保容器只能看到主机上可用的部分资源,控制组限制它可以使用的资源量,而其他功能则加强了容器之间的隔离。
