一文彻底搞懂 Container

简介: 设想一下,在我们的日常项目开发过程中,存在一个应用服务,其使用一些基础库函数并具有某些依赖项。如果我们在不支持这些依赖项的环境平台上运行此应用程序,那么,我们可能会遇到意外错误。随着 DevOps 及云原生理念的注入,我们希望我们所开发的应用程序能够可以跨多个操作系统及平台正常运行。


    设想一下,在我们的日常项目开发过程中,存在一个应用服务,其使用一些基础库函数并具有某些依赖项。如果我们在不支持这些依赖项的环境平台上运行此应用程序,那么,我们可能会遇到意外错误。随着 DevOps 及云原生理念的注入,我们希望我们所开发的应用程序能够可以跨多个操作系统及平台正常运行。

    为了解决这个问题,基于传统方式,我们可以在虚拟机上运行应用程序。这样做的问题是,为了运行应用程序而启动整个操作系统会产生开销,并且操作系统的许多组件将不会被使用,容易浪费资源。因此,我们急需要寻求一种折中的解决方案以平衡资源使用率与跨平台特性,Container 技术,便是一种解决方案。

什么是 Container ?

    Container 是一种打包软件的方式,因为它不依赖于环境。应用程序的所有代码、库和依赖配置项都打包到容器中。与虚拟机不同,容器不是创建一个完整的虚拟操作系统,而是允许应用程序使用与它们正在运行的系统相同的 Linux 内核,并且只需要应用程序与尚未在主机上运行的东西一起交付。现在我们没有启动整个操作系统,而且我们拥有独立于机器的代码包。故此,我们可以认为:Container 是一个包含要执行的程序及其所有依赖项(例如代码、运行时、系统库等)的软件包。如下为基于 Kubernetes 平台下 Container 所在的位置。

OCI 概念解析  

    在解析 Container 之前,我们先了解一下 OCI 概念。OCI 全称为“Open Container Initiative” ,是一个开放的治理结构,于 2015 年 6 月 22 日由 Docker、CoreOS 和其他容器行业的领导者推出,旨在制定围绕容器格式和运行时创建开放行业标准。除此之外,开放容器计划 (OCI) 是一个轻量级的项目,在 Linux 基金会的支持下成立,其明确目的是围绕容器格式和运行时创建开放的行业标准。 

    OCI 目前包含两个规范:运行时规范(runtime-spec)和镜像规范(image-spec)。运行时规范概述了如何运行在磁盘上解压缩的“文件系统包”。在高层次上,OCI 实现将下载一个 OCI 映像,然后将该镜像解压到一个 OCI 运行时文件系统包中。此时,OCI Runtime Bundle 将由 OCI Runtime 运行。整个工作流程应该支持用户对 Docker 和 rkt 等容器引擎所期望的 UX:主要是无需额外参数即可运行镜像的能力。

    换句话来讲,OCI 是为操作系统进程和应用程序容器的标准制定一系列规范。

    每个 OCI 运行时规范,具体内容如下所示:

  • 容器是运行进程的隔离和受限的盒子
  • 容器将应用程序及其所有依赖项(包括操作系统库)打包在一起
  • 容器是为了可移植性——任何兼容的运行时都可以运行标准容器
  • 容器可以使用 Linux、Windows 和其他操作系统来实现
  • 虚拟机也可以用作标准容器

    其实,从本质上而言,通常往往有多种实现方法可以用来创建容器,尤其是在 Linux 操作系统上。除了目前广泛使用的 Docker 实现之外,我们可能还听说过 LXC、systemd-nspawn,甚至 OpenVZ。在 2015 年,Docker 已经相当受欢迎,再加上 Kubernetes 的正式问世,使得在此期间催生了其他竞争项目实现了自己的容器引擎,如 rkt 和 lmctfy。显然,OCI 的建立是为了标准化做容器的方式。事实上,它使 Docker 的容器实现成为一个标准的实现,但也包含了一些非 Docker 部分。接下来,我们来看一下 Container 的体系架构示意图,如下所示:

Container 体系架构示意图

    基于前面章节所述以及结合 Container 体系架构示意图,我们可以看到,仅从 Container 角度,其主要包括以下核心要素:

    1、应用程序,基于不同语言所编写的业务代码,例如,Java 、Go 、Python 以及其他开发语言等。

    2、运行进程,主要涉及容器运行过程中所提供的依赖环境资源信息,例如,守护进程等等。

    3、依赖组件,此处为应用程序运行所依赖的相关配置项及库函数,例如,代码所调用的第三方组件以及其运行过程中所需要依赖的操作系统底层库函数等。

    但若从其所处的关联环境角度解读,其同时也涉及“运行时”和“环境”等方面。基于 OCI 规范,Container 被定义为是一种用于执行具有可配置隔离和资源限制的进程的环境。那么,既然具备“隔离”和“资源限制”等机制,那么意味着 Container 可以以自描述和可移植的格式封装软件组件及其所有依赖项,以便兼容任何的运行时从而使得运行过程中无需额外的依赖项,无关乎其底层机器和容器的内容。

    除此之外,依据 OCI 规范所定义,基于 Container ,我们可以实现如下操作:

    1、使用标准的容器工具来进行创建、启动及停止。

    2、使用标准文件系统工具进行复制和快照建立。

    3、使用标准网络工具实现文件的下载和上传。

    4、OCI 运行时应该支持的容器操作涉及创建、启动、终止、删除和查询等多种事件状态。

    基于容器,在日常的软件项目开发过程中,开发人员能够将应用程序及其所有必需的部分内容打包,并将其作为一个标准的、轻量级的、安全的及整体的包交付出去。基于此种场景,在一定程度上能够让 DevOps 团队高枕无忧,因为他们知道他们正在构建和支持的应用程序将在任何环境中正常运行——无论是虚拟机、裸机还是云平台。毕竟,容器从根本上消除了单体应用程序固有的“在特定的环境上工作”的问题。

VM VS Container

    在解析虚拟机与 Container 之前,我们先了解下 Linux Container 体系相关概念。除了 Container 的操作和生命周期之外,OCI Runtime Spec 还指定了 Container 的配置和执行环境。

    根据 OCI 运行时规范,要创建 Container,需要为运行时提供所谓的文件系统包,该包由一个强制性的 config.json 文件和一个包含未来容器根文件系统的可选文件夹组成。 

“题外话:bundle 通常是通过解压容器镜像获得的,但镜像不是运行时规范的一部分。相反,它们受专用 OCI 镜像规范的约束。”

    config.json 包含对容器实施标准操作(创建、启动、查询状态、终止和删除)所需的数据。但是当我们谈到 config.json 文件的实际结构时,事情开始变得非常有趣。配置由公共部分和特定于平台的部分组成。公共部分包括 ociVersion、包中的根文件系统路径、根之外的附加挂载、要在容器中启动的进程、用户和主机名。嗯...但是著名的命名空间和 Cgroup 在哪里?

    在撰写本文时,OCI 运行时规范为以下平台定义了容器:Linux、Solaris、Windows、z/OS 及其他常用平台。

config.json 参考示意图

    我们都知道,目前最广泛使用的 OCI 运行时应该是 runc 和 crun。不出所料,两者都实现了 Linux 容器。但正如我们刚刚看到的,OCI 运行时规范提到了 Windows、Solaris 和其他容器。对我们来说更有趣的是,它定义了 VM 容器。

    容器不是要取代虚拟机作为相同执行环境抽象的更轻量级的实现吗?

    无论怎样,让我们仔细了解下 VM 容器。显然,它们不受 Linux 命名空间和 Cgroup 的支持。 相反,特定于虚拟机的容器配置提到了管理程序、内核和 VM 镜像。 因此,隔离是通过虚拟化一些硬件(管理程序)然后在其上启动成熟的操作系统(内核 + 镜像)来实现的。由此产生的环境便是我们所认知的黑匣子,即一个容器。我们来看一下 Linux Container 与 VM 基础架构,具体如下图所示:

    不过我们需要注意的是,OCI Runtime Spec 中所提到的 VM 镜像与用于创建包的传统容器镜像无任何相关联性,捆绑根文件的系统单独挂载到 VM 容器中。

    总而言之,要在计算机上可靠且可重复地部署软件,我们需要一个类似“盒子”的装置来存放应用程序的代码。此盒子应包含整个系统,以便开发人员完全了解他们要交付的内容,而无需关注盒子所包含环境的相关具体信息及依赖组件,毕竟。此盒子也不应该受到虚拟机性能成本的影响。最后,也是非常至关重要的一点:此盒子必须有一个通用型标准接口,无论里面存储什么应用程序,它都不应因环境的变化而发生变动。

    基于上述所讲,容器不仅仅是稍微孤立和受限的 Linux 进程。相反,它们是标准化的执行环境,可提高工作负载的可移植性。Linux 容器是当今最普遍的容器形式,但对更安全的容器的需求正在增长。OCI 运行时规范定义了 VM 支持的容器,而 Kata 项目使它们成为现实。所以,此刻是探索容器世界的激动人心的最佳时间~

    针对 Kubernetes Container 的其他方面内容特性,大家可阅读之前的文章,具体链接为:Kubernetes Container 解析。以上为本文基于底层原理对 Container 的相关简要解析,若文章中所述有问题,欢迎大家随时沟通、指导及交流。


# 参考资料

  https://opencontainers.org

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
安全 Linux Docker
容器安全拾遗 - Rootless Container初探
Docker和Kubernetes已经成为企业IT架构的基础设施,安全容器运行时越来越被关注。近期Docker 19.03中发布了一个重要的特性 “Rootless Container”,在提升容器的安全隔离性和可管理性方面前进了一大步。
7170 1
|
6月前
|
前端开发 UED
label的作用是什么?是怎么用的?
label的作用是什么?是怎么用的?
58 0
|
5月前
|
Kubernetes 监控 网络协议
k8s教程(service篇)-概念和原理(下)
k8s教程(service篇)-概念和原理(下)
82 0
k8s教程(service篇)-概念和原理(下)
|
5月前
|
Kubernetes 负载均衡 Linux
k8s教程(service篇)-概念和原理(上)
k8s教程(service篇)-概念和原理(上)
70 0
|
5月前
|
Kubernetes 负载均衡 网络协议
k8s教程(service篇)-概念和原理(中)
k8s教程(service篇)-概念和原理
78 0
|
10月前
|
Kubernetes API 微服务
一文搞懂 Container 运行原理
当我们开始学习 Kubernetes 时,我们并不完全清楚每个 Pod 是如何分配 IP 地址以及微服务容器化后是如何正常工作。或许,我们可能或多或少了解各个组件的概念以及它们是如何独立工作。但是,在特定的环境下可能不清楚这些组件是如何关联起来。
102 0
|
10月前
|
Kubernetes Devops Linux
一文搞懂 Minikube 底层原理
随着容器技术的井喷式发展及落地,通常情况下,我们将 Kubernetes 描述为“将 Linux 容器集群作为单个系统进行管理,以加速开发并简化维护”。与此同时,企业应用服务进行容器化改造时避免不了学习和使用 Kubernetes 。然而能够在环境中完整部署一整套多节点的 Kubernetes 集群,对于刚接触这块体系的 Devops 人员来说确实有一定的难度... ...
206 0
一文搞懂 Minikube 底层原理
|
11月前
|
存储 算法 C++
【C++知识点】STL 容器总结)(一)
【C++知识点】STL 容器总结(一)
96 0
|
11月前
|
前端开发 编译器 C++
【C++知识点】STL 容器总结(二)
【C++知识点】STL 容器总结(二)
102 0
|
存储 Linux API
关于docker的基础知识一共有哪些?底层原理是什么?
关于docker的基础知识一共有哪些?底层原理是什么?