云原生之路 | 1.快速了解容器(Container)及容器编排技术

85b6f72a8a618d41c3f87ec532d1cc3f.jpeg

8d9cf3e7a3e269f3f2bbd729b34db6b6.gif

各位亲爱的读者,现在公众号更改了推送规则,如果您需要第一时间看到我们推送的好内容。

一定要记得给公众号星标,经常点赞、在看、转发、分享和留下您的评论 !

原文链接:

云原生之路 | 1.快速了解容器(Container)及容器编排技术本章着眼于容器在云原生中的重要性,为了便于读者能快速从Docker到Kubernetes进行实践操作学习,在此之前我们需要了解一些关于容器技术、Docker、Containerd以及K8S等相关基础知识,为DevOps工作带来切实的好处。icon-default.png?t=N7T8https://mp.weixin.qq.com/s/EAii_f_wx_bvjImzb6Ht8g关注【公众号】回复【学习交流群】加入【SecDevOps】学习交流群!


文章目录:

26239642769104726777343836878088.png


前言简述:

2022年,原本是准备和同事一起完成出一本Kubernetes在企业落地实践的书的,但是由于老婆怀孕以及后来娃娃的出生需要照顾,从而错过了发版时间(工期赶不赢),后来一想是有点后悔,浪费了这一次宝贵机会,但是也无可奈何,出书对主题大纲、书籍目录、代码贴图、文章内容以及来源等格式都有严格的限制,所以说就是想赶上时间也是没办法的,不过在之前我已经完成了六章,如今生活一切都步入了正规,作者不详所以写和总结的文章吃灰,遂一一分享出来给大家一起学习,并且后续作者也会继续更新云原生在企业落地实践等相关文章,在【云原生落地实用指南】付费专栏之中持续更新,希望大家多多支持,关注转发!

作者主页:[ https://www.weiyigeek.top]  

博客:[ https://blog.weiyigeek.top ]

627b4856de2fa7d556cc423ebbb57007.png

8c57e5741cd747dd931994cec1da0c76.png

b69d9f72a9a1ebe98f72406069b4c946.png

ae76a24435696e393ae2d596f95a1b9b.jpeg

7918a40782946c8d6ce6547d9c149507.png


第1章 快速了解容器技术

本章着眼于容器在云原生中的重要性,为了便于读者能快速从Docker到Kubernetes进行实践操作学习,在此之前我们需要了解一些关于容器技术、Docker、Containerd以及Kubernetes等相关基础知识。

1.1容器基础知识

1.1.1什么是容器

What is a Container?

从中文字面意义上可解释为我们日常生活中盛物品的器具,如盒子、杯子、搪瓷盆、玻璃瓶等,而从英文字面中解析则可以将container这个单词有集装箱、容器的含义(主要偏集装箱意思),在运输行业使用物理容器来隔离不同的货物,以便通过轮船和火车运输,而其在不同的应用场景下又有着不相同的解释。

在软件开发技术使用容器在其内部包含其他组件的组件。例如小程序是一个容器,其他容器包括窗口、框架、对话框和面板等组件。

本书中容器表示是一个标准的软件可执行单元,将应用程序的代码与相关配置文件、库以及运行应用所需的依赖项捆绑在一起,实际上你可将它比作货物的集装箱。为应用程序提供标准化、可移植的打包。因此应用程序可以从一个计算环境快速可靠地运行到另一个计算环境,无论是在桌面、传统 IT 还是部署在云上。

为此,容器利用了一种操作系统 (OS) 虚拟化形式即LXC (Linux  Container)技术,在 Docker 0.9 版本中,Libcontainer 取代 LXC 成为默认的执行驱动。其中利用操作系统的功能(在 Linux 内核的支持下,即 namespace和 cgroups 机制)来隔离进程并控制数量这些进程可以访问的 CPU、内存和磁盘。容器是小巧、快速且可移植,因为与虚拟机不同,容器不需要在每个实例中都包含来宾操作系统,而是可以简单地利用主机操作系统的功能和资源。

几十年前,容器首次出现在2000年 FreeBSD Jails 和 AIX Workload Partitions 等版本中,以及在2001年LXC(Linux Container)技术的诞生,而实际上大多数现代开发或者运维人员都应该只记得 2013年是现代容器时代的开端,那时Docker容器技术通过 dotCloud 登上了舞台映入大众眼帘,又随着2014年6月Google发布了Kubernetes (简称:K8S)第一个版本来管理编排Docker容器。

1.1.2为什么要使用容器

Why use Containers?

假设您在现在正在开发一款新的应用,您使用的是一台笔记本电脑,而且您的开发环境具有特定的配置。其他开发人员身处的环境配置可能稍有不同。您正在开发的应用不止依赖于您当前的配置,还需要某些特定的库、依赖项和文件。与此同时,您的企业还拥有标准化的开发和生产环境,有着自己的配置和一系列支持文件。

此时您希望尽可能多在本地模拟这些环境,而不产生重新创建服务器环境的开销。因此,您要如何确保应用能够在这些环境中运行和通过质量检测,并且在部署过程中不出现令人头疼的问题,也无需重新编写代码和进行故障修复?

答案就是使用容器,以便我们为应用程序提供标准化、可移植的打包。

容器可以确保您的应用拥有必需的库、依赖项和文件,让您可以在生产环境中自如地迁移这些应用,无需担心会出现任何负面影响。实际上,您可以将容器镜像中的内容,视为 Linux 发行版(如Alpine Linux、Debian、CentOS)的一个安装实例,因为其中完整包含APK、APT或 RPM 软件包、配置文件等内容。但是安装容器镜像发行版,远比你安装新的操作系统及其依赖环境容易得多。这样就可以避免许多由环境引起的故障问题,并且可以在测试环境和生产环境中快速迁移部署应用、使得您的应用软件能快速的交付使用。

虽然这只是一个常见情况的示例,但在需要很高的可移植性、可配置性和隔离的情况下,我们可以利用 Linux 容器通过很多方式解决难题。Linux 容器的价值在于,它能加速开发并满足新出现的业务快速迭代的需求。在某些情形中(如通过 Apache Kafka 进行实时数据流处理),容器是不可或缺的,因为它们是提供应用所需的可扩展性的唯一途径。无论基础架构是在企业内部还是在云端,或者混合使用两者,容器都能满足您的需求。当然选择正确的容器平台也同样重要。

前面我们说了这么多容器(Container)好话,但是现在我们心中肯定有如下几个问题:容器就是虚拟化吗?如何区分容器与虚拟化?容器部署究竟与传统的虚拟化部署有何区别? 但在回答上面的问题前,我们需要简单了解虚拟化相关知识

虚拟化的工作原理,以及什么是虚拟机?

1)虚拟化 (virtualization) 是使用软件在计算机硬件上创建抽象层的过程,该抽象层允许将单个计算机的硬件元素划分为多个虚拟计算机。所使用的软件称为管理程序一个小层,使多个操作系统能够彼此并行运行,共享相同的物理计算资源。当在数据中心的物理计算机或服务器(也称为裸机服务器)上使用管理程序时 ,它允许物理计算机将其操作系统和应用程序与其硬件分离,然后它可以将自己分成几个独立的“虚拟机”。在企业中常用的虚拟化环境解决方案是VMware、Xen、开源的KVM以及华为的FusionCompute等。

虚拟化的分类说明

A.硬件虚拟化:真正意义上的基于它的技术不多见,少数网卡中的单根多IO虚拟化等技术;

B.软件虚拟化(Virtualization)

B.1应用虚拟化

B.2平台虚拟化:细分

B.2.1 完全虚拟化

B.2.2 硬件辅助虚拟化:利用硬件CPU辅助支持虚拟化技术Intel-VT和AND-V处理铭感指令来实现完全虚拟化的功能;

B.2.3 部分虚拟化:只对部分硬件资源进行虚拟化,客户端系统需要进行修改;

B.2.4 准虚拟化(Paravirtualization): 如Xen、KVM

B.2.5 操作系统级虚拟化:内核通过创建多个虚拟化的操作系统实例内核和库来隔离不同的进程,dokcer以及其他容器都在这个范畴之内;

2)虚拟机 (VM) 是一种用于构建虚拟化计算环境的技术。它们已经存在了很长一段时间,被认为是第一代云计算的基础。简单地说,虚拟机是对物理计算机的模拟。虚拟机使团队能够在一台计算机上运行多台机器、多个操作系统。VM 通过使用称为管理程序的轻量级软件层与物理计算机交互。管理程序可以将 VM 彼此分开,并在它们之间分配处理器、内存和存储。所以VM 也称为虚拟服务器、虚拟服务器实例和虚拟专用服务器。

峰回路转,我们又回到上面给出的三个问题中。

容器就是虚拟化吗?如何区分容器与虚拟化?

不完全如此,更确切的说法应该是:两者为互补关系。

我们用一种简单方式来思考一下:

l虚拟化使得您的操作系统(Windows 或 Linux)可同时在单个硬件系统上运行。

l容器则可共享同一个操作系统内核,将应用进程与系统其他部分隔离开。例如:ARM Linux 系统运行 ARM Linux 容器,x86 Linux 系统运行 x86 Linux 容器,x86 Windows 系统运行 x86 Windows 容器。Linux 容器具有极佳的可移植性,但前提是它们必须与底层系统兼容。

虚拟化会使用虚拟机监控程序模拟硬件,从而使多个操作系统能够并行运行。但这不如容器轻便。事实上在仅拥有容量有限的有限资源时,您需要能够可以进行密集部署的轻量级应用。而Linux 容器在本机操作系统上运行,与所有容器共享该操作系统,因此应用和服务能够保持轻巧,并行化快速运行。

Linux 容器是我们开发、部署和管理应用方式的又一次飞跃。Linux 容器镜像提供了可移植性和版本控制,确保能够在开发人员的笔记本电脑上运行的应用,同样也能在生产环境中正常运行。相较于虚拟机,Linux 容器在运行时所占用的资源更少,使用的是标准接口(启动、停止、环境变量等),并会与应用隔离开;此外,作为(包含多个容器)大型应用的一部分时更加易于管理,而且这些多容器应用可以跨多个云环境进行编排。

容器部署究竟与传统的虚拟化部署有何区别?

说到这里就不得不不说在运维部署时代变迁流程, 大致来说在部署应用程序的方式上主要经历了三个时代:

1)传统部署时代:早期企业直接将应用程序部署在物理机上。由于物理机上不能为应用程序定义资源使用边界,我们也就很难合理地分配计算资源。

2)虚拟化部署时代: 针对上述问题虚拟化技术应运而生。用户可以在单台物理机的CPU上运行多个虚拟机(Virtual Machine),然后在虚拟机中运行不同的业务应用。

3)容器化部署时代: 容器与虚拟机类似,但是降低了隔离层级,共享了操作系统。因此,容器可以认为是轻量级的。

三种部署方式部署在系统架构层的区别,如下图1-1所示。

d3b5d9cbd25667419a8d5ba2552e8fca.png

图 1-1 三种部署方式部署在系统架构层的区别

容器 VS 虚拟机部署相关特性对比,如下表1-1所示:

对比特性

容器化部署

虚拟机部署

启动速度

秒级

分钟级

磁盘用量

以MB为基础单位

以GB为基础单位

服务性能

接近宿主机

弱于宿主机

系统支持

单机实例支持上千容器

管理的复杂性一般几十个

应用隔离

用户空间中的独立进程

所有应用进行都在主机上非隔离进程

资源安全

安全隔离(Namespace和Cgroup)

完全隔离

表 1-1 容器 VS 虚拟机部署相关特性对比

容器化给我们运维开发带来那些好处?

容器因具有许多优势而变得流行起来, 那除开前面所讲解的优势,容器化到底为我们带来那些好处。

容器的主要优势,尤其是与 VM 相比,是提供了一个抽象级别,使其轻量级和可移植性。

ü轻量级: 容器共享机器操作系统内核,无需每个应用程序都需要一个完整的操作系统实例,并使容器文件小而容易占用资源。它们较小的尺寸,尤其是与虚拟机相比,意味着它们可以快速启动并更好地支持水平扩展的云原生应用程序。  

ü可移植性: 容器提供打包和保存运行所需应用程序的所有必要组件的标准化格式,这意味着软件可以编写一次,然后运行,无需跨笔记本电脑、云和本地计算环境重新配置。

ü支持现代开发和架构: 由于它们跨平台的部署可移植性/一致性和可快速伸缩的组合,容器非常适合现代开发和应用程序模式,例如 DevOps、无服务器和微服务,这些模式构建为常规代码以小而多的增量部署。

ü提高利用率:与之前的虚拟机一样,容器使开发人员和运营商能够提高物理机的 CPU 和内存利用率。容器更进一步的地方在于,因为它们还支持微服务架构,所以可以更精细地部署和扩展应用程序组件,这是一个有吸引力的替代方案,而不是因为单个组件在负载上挣扎而不得不扩展整个单体应用程序。

总而言之,容器在整个应用程序生命周期工作流中提供以下优点:隔离性、可移植性、灵活性、可伸缩性和可控制箱性,其中最重要的优点是可在开发和运维之间提供隔离和应用相同的运行环境。

1.1.3容器的发展前景

容器正变得越来越突出,可谓是风头正盛,容器技术从诞生之初到现在不断在进行迭代更新以及优化,它对传统的基于虚拟机的虚拟化技术带来了颠覆性的挑战,尤其是在云环境中其正在改变着基础设施服务(IaaS)平台和平台即服务(PaaS)平台的架构和使用,许多组织甚至考虑将容器作为 VM 的替代品,作为其应用程序和工作负载的通用计算平台。

特别是最近几年里广泛应用在Docker 容器、Podman、Kubernetes容器编排等我们熟知的云原生解决方案上,关于它的热议席卷虚拟化乃至整个云计算行业,业内各大厂商(包括红帽、亚马逊、IBM和VMware)都加入了容器行业。但是在最开始的几年间由于容器没有相应的标准,导致各大厂商间(各自为营-PS:都想自己当大哥)开发的相关容器应用软件无法互相操作。

但是在 2015 年 6 月Docker 和容器行业的其他领导者宣布Open Container Initiative ( OCI - 一个围绕容器创建开放标准的开源社区) [1-1] 成立打破了这一僵局,该OCI组织是建立围绕容器格式和运行时的开放式行业标准的明确目的的开放式的治理结构。目前包含两个规范:镜像规范(image-spec)[1-2]和运行时规范(runtime-spec)[1-3]。运行时规范概述了如何运行在磁盘上解压缩的“文件系统包”。OCI 实现将下载一个 OCI 映像,然后将该映像解压缩到 OCI 运行时文件系统包中。此时OCI Runtime Bundle 将由 OCI Runtime 运行。并且通过OCI 镜像、分发和运行时规范着三个主要的标准,来确保各种容器技术间的互操作性。当前Google、Microsoft、红帽、阿里云和 Docker 等公司都是开放容器计划(OCI)的成员,致力于实现容器技术的开放行业标准化。

b6b4ca6d29f651f345971d19d880e4b0.png

图 1-2 开放容器计划(OCI)的成员

容器的在未来主要应用发展的方向如下所示:

1)云原生应用程序: 云原生应用程序依赖容器来实现跨环境(包括公有云、私有云和混合云)的通用操作模型。由于容器开销低、密度高,因此可以将许多容器托管在同一虚拟机内,使其成为交付云原生应用程序的理想选择。

2)机器AI学习:机器学习将算法应用于数据,并根据数据中的模式进行预测。容器可以使机器学习应用程序自成一体,在任何环境中都易于缩放。

3)不断扩大的容器生态系统:随着容器作为一种流行的打包和运行应用程序的方式继续获得动力,旨在加强和扩展生产用例的工具和项目生态系统继续增长。除了 Kubernetes 之外容器生态系统中两个最受欢迎的项目是 Istio 和 Knative。

综上所述,随着不断扩大的容器生态系统以及云计算平台的公有云、私有云不断的发展,容器提供了一定程度的灵活性和可移植性,非常适合多云世界,并且容器化应用程序为团队提供了处理现代 IT 的许多软件环境所需的灵活性,同时容器也是自动化和 DevOps 管道的理想选择,包括持续集成和持续部署(CI/CD) 实施,已经广泛基础到我们所使用的软件及运维平台之中。随着越来越多的云厂商不断加入到OCI中,坚信容器的生态系统会迈上更高的阶梯。

名词解析:

LCX 技术: 即Linux Containers虚拟化技术曾作为Docker Engine的基础组件,它可以将个操作系统管理的资源划分到孤立的组,以便更好的在孤立的组之间平衡有冲突的资源使用需求。

Libcontainer: 它作为LCX技术的替代品, 其目标是成为与平台无关的工具,可基于不同内核为 Docker 上层提供必要的容器交互功能。

Namespace 机制:负责实现隔离一个独立的容器所必须具备的资源,其包含了UTS、USER、IPC、PID、NETWORK、MOUNT等子系统。

Cgroup机制: 负责实现对系统资源的分配与限制,其包含了Cpu、Memory、Devices、Swap等子系統。

参考来源:

[1-1] : https://opencontainers.org/

[1-2] : https://github.com/opencontainers/image-spec/

[1-3] : https://github.com/opencontainers/runtime-spec/

1.2 Docker——小小搬运工

1.2.1什么是docker

What is a Docker ?

Docker (ˈdɑ:kə(r)) 英文翻译是”搬运工“的意思,搬运我们常说的集装箱Container,而Container 里面装的是任意类型的App,用于将APP 自动部署为可在云或本地运行的便携式独立容器之中。它是一个基于Go语言开发实现的遵循Apache 2.0协议开源项目(它是仅次于OpenStack最受欢迎的云计算开源项目), 它实现轻量级的操作系统虚拟化解决方案。Docker 使您能够将应用程序与基础设施(Infrastructure)单独分割出来,形成更小的颗粒(容器),从而提高交付软件的速度。

Docker 最开始的目标是"Build,Ship and Run Any App,Anywhere",通过对应用组件的封装 (Packaging) -> 分发(Distribution) -> 部署 (Deployment) -> 运行 (Runtime)等生命周期进行管理,达到应用级别"一次封装,到处运行";

当前 Docker 口号是使用容器构建、共享和运行您的应用程序,即将软件打包成用于开发、迁移和部署的标准化单元,它打包了代码及其所有依赖项,构建为容器镜像,容器镜像在运行时成为容器,

例如:它可以独立运行一个Web应用,也可以是一套数据库服务,甚至是一个操作系统或编译器环境,并且您可以将其打包成为镜像,拉取分发到其他环境中进行快速的部署运行。

Docker 容器无处不在Linux、Windows、数据中心、云、无服务器等,容器化软件的运行环境将始终相同无论基础架构如何改变,在 Docker 容器的环境中镜像在Docker Engine上,可以运行多个应用且都是相互隔离的。如下图1-3所示。容器将软件与其环境隔离开来,并确保它能够一致地工作,尽管存在差异,例如在开发环境、测试环境和演示环境、以及线上环境之间。

20ee114eb528048489a8232b1ef6c065.png

图 1-3 Docker容器运行环境及多个容器应用运行之上

Docker 平台提供了在称为容器的松散隔离环境中打包和运行应用程序的能力。隔离和安全性允许您在给定主机上同时运行多个容器。容器是轻量级的,包含运行应用程序所需的一切,因此您无需依赖主机上当前安装的内容。您可以在工作时轻松共享容器,并确保与您共享的每个人都获得以相同方式工作的相同容器。

Docker 提供了相关工具和平台来管理容器的生命周期,使用容器开发您的应用程序及其支持组件,容器成为分发和测试应用程序的单元。准备就绪后,将应用程序作为容器或通K8S编排服务部署到生产环境中。无论您的生产环境是本地数据中心、云提供商还是两者的混合,都是完全一致的。

Docker历史与发展

l在2008年,Solomon Hykes 和Sebastien Pahl、Kamel Founadi共同创立了一家名为 DotCloud 的公司,目标是利用容器技术来创建他们称作是“大规模的创新工具”,任何人都可以使用的编程工具。

l在2010年,dotCloud获得创业孵化器Y Combinator的支持,并开始吸引各方投资,在法国之后的3年中dotCloud内部孵化出了一款名为Docker的产品。

l在2013 年 3 月 Docker 创始人 Solomon Hykes 在 PyCon 大会上的演讲中首次公开介绍 Docker 这一产品。在此次大会之后,Docker 开启了应用程序开发的一场革命——通过使软件容器大众化,Docker 的创新式镜像格式以及容器运行时迅速成为社区、客户和更广泛行业的实际标准和基石。dotCloud发布了 Docker 的首个版本,并将Docker源码进行开源。

随着Docker技术的开源,此项技术能够将Linux容器中的应用代码打包并轻松的在服务器之间迁移,Docker技术瞬时的风靡了全球,2013年底DotCloud Inc则更名为Docker Inc [1-4],并全力的主攻到Docker项目开发中。

l在2014年8月,Docker Inc宣布将用于PaaS业务服务的DotCloud软件出售给德国柏林的PaaS服务厂商CloudControl,自此以后,DotCloud正式的和Docker分道扬镳了。在同年12月举行的DockerConEU大会上,Docker Swarm 和Docker Machine同时面世。Docker Swarm是一个Docker集群管理工具,而Docker Machine是部署Docker主机的命令工具。

l在 2015 年 6 月,由Docker、IBM、微软、红帽及Google等厂商所组成的开放容器项目OCP联盟成立,该项目旨在建立软件容器的通用标准。OCP成立于Linux基金会之下,其使命是使用户和公司能够继续创新和开发基于容器的解决方案,并充满信心地保护其先前的开发工作,并且不会造成行业分散。

l2016年6月在DockerCon上,Docker宣布了Open Container Initiative的正式成立。OCI意在业界一起合作,开发一个开放的、标准的容器格式和runtime(注:OCI也属于Linux基金会的协作项目)。同时Docker 向开放容器计划 (OCI) 捐赠了现在称为 runC的容器镜像规范和运行时代码,以帮助随着容器生态系统的成长和成熟建立标准化。

l在 2017 年,是容器成为主流技术的一年,所以Docker 在Linux之外支持众多平台(Docker for Mac,Docker for Windows,Docker for AWS,GCP 等)。并且OCI标准制定后,Docker 将 containerd 独立拆分为一个单独的项目,使得 docker 将容器的管理功能移出 docker 的核心引擎并移入一个单独的守护进程(即 containerd),并将其捐赠给了云原生计算基金会 (CNCF)。

在Austin举办的 DockerCon 上开源Docker项目正式命名为 Moby 项目[1-5]。由于这次改名,GitHub 上的 docker/docker 库也被转移到了 moby/moby,并且拥有了项目自己的 Logo。于此同时,将Docker本身拆分为Docker-CE免费版和Docker-EE商业版。Docker-CE目前是docker公司维护的开源项目,是一个基于Moby项目的免费的容器产品。Docker-EE目前是docker公司维护的闭源项目,是docker公司的商业产品。至此Docker容器天下三分,其中Moby由社区维护,Docker-CE由Docker公司维护,Docker-EE是Docker公司闭源的商业产品[1-6]。

l在 2019年,容器市场基本趋于稳定,对于容器的编排进过几轮的激烈竞争,最后由Google的Kubernetes 完胜(其实从其Logo中能了解其雄图大志)。新的战斗已经由容器和编排的战场,逐渐迁移到应用领域。云原生CNCF将引领新的技术方向,微服务、ServcieMesh、Envoy、ServerLess等正在路上。

l在2020年12月,Kubernetes 最新发布的 1.20 版本中弃用未来对 Docker CRI 接口的Dockershim支持(K8S直接调用 containerd 去管理容器的话性能会提高许多),但 Docker 作为容器镜像构建工具的作用将不受影响,用其构建的容器镜像将一如既往地在集群中与所有容器运行时正常运转。其实我们并不用慌张,根据 Kubernetes 发布周期,最快也是计划在 Kubernetes 1.22 版本完全弃用 Docker 作为运行时的支持,在随后的两年里我们都可以快乐的使用Docker。

名词解析: 

Docker 容器镜像: 是一个轻量级、独立、可执行的软件包,其中包含运行应用程序所需的一切:代码、运行时、系统工具、系统库和设置。,

containerd : 是一个行业标准的容器运行时,它利用了 runC,并在创建时强调了简单性、健壮性和便携性。

参考来源

[1-4] : https://www.docker.com

[1-5] : https://mobyproject.org/

[1-6] : https://docs.docker.com/get-started/overview/

1.2.2为什么选择Docker

Why use Docker?

Docker作为容器标准和行业领先地位,将容器技术大众化,使容器技术成为主流,并解决了困扰数百万开发人员的“matrix from hell”问题,使用 Docker您可以像管理应用程序一样管理基础设施。今天开发应用程序需要的不仅仅是编写代码。每个生命周期阶段的工具之间的多种语言、框架、架构和不连续的接口造成了巨大的复杂性。Docker 简化并加速了您的工作流程,同时让开发人员可以自由地为每个项目选择工具、应用程序堆栈和部署环境进行创新。

通过利用 Docker 的快速交付、测试和部署代码应用,您可以显著的减少编写代码和在生产中运行代码之间的延迟,节约系统占用的资源,随时可以弹性收缩、便于应用的管理,其次是Docker 社区建立在协作、包容和进步的文化之上(社区比较完善便于资料查找),相信这上面的几个点都是选择Docker的理由吧。

Docker 究竟为我们带来那些优势?

1)敏捷地创建和部署应用程序: 比VM创建容器镜像更快更方便;

2)持续开发、集成和部署:通过快速、简便的回滚(由于映像不变性),提供可靠且频繁的容器映像生成和部署。

3)分离开发和运维的关注点: 降低了开发和运维的耦合度

4)可监控性: 操作系统级别的资源监控信息以及应用程序健康状态以及其他信号的监控信息

5)开发、测试、生产不同阶段的环境一致性: 一次build到处运行;

6)跨云服务商、跨操作系统发行版的可移植性: 在 Ubuntu、RHEL、CoreOS、本地、主要公共云和其他任何位置上运行。

7)以应用程序为中心的管理:问题的焦点则是在操作系统的逻辑资源上运行一个应用程序,而VM注重于在虚拟硬件上运行一个操作系统

8)松耦合、分布式、弹性、无约束的微服务:应用程序被切分成更小的、独立的微服务,并可以动态部署和管理,而不是一个部署在专属机器上的庞大的单片应用程序

9)资源隔离:确保应用程序性能不受干扰

10)资源利用:资源高效、高密度利用

Docker 应用场景:

l使用docker容器开发、测试、部署服务:自动化测试和持续集成、发布;

l在服务型环境中部署与扩展Webapp以及调整数据库或其他应用;

l统一、优化和加速本地开发和构建流程;创建隔离的运行环境,测试环境

l构建多用户的平台即服务(PaaS)基础设施

l提供软件即服务(SaaS)的应用程序

l高性能、超大规模的宿主机部署,web应用的自动化打包和发布

1.2.3组织架构

前面针对Docker 容器做了简单介绍与其优势进行了说明,本文将Docker架构进行剖析介绍,但是在介绍之前我们需要先了解一些基础概念。

基本概念:

镜像(Image):Docker 镜像(Image)就相当于是一个操作系统中root 文件系统,也可类似于虚拟机镜像。比如官方镜像 alpine 就包含了完整的一套最小系统的 root 文件系统。

容器(Container):Doker 容器(Container)类似于一个轻量级的沙箱,镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

仓库(Repository):仓库可看成一个代码版本控制中心,用来集中存放镜像文件的场所。

基础架构

从Docker 组织架构图,如图1-4中所示,我们可以看到Docker对使用者来讲是一个C/S模式(客户端-服务器)的架构,其后端是一个非常松耦合的架构,由许多可交换的部件(例如network、volumes、image)进行有机组合支撑Docker的运行。

Docker客户端与Docker Daemon进程对话,后者负责构建、运行和分发 Docker 容器的繁重工作。

Docker客户端和Docker Daemon进程可以在同一系统上运行,或者您可以将 Docker 客户端连接到远程 Docker 守护程序。

Docker客户端和Docker Daemon进程使用 REST API、UNIX 套接字或网络接口进行通信。

值得注意另一个 Docker 客户端是 Docker Compose,它允许您使用由一组容器组成的应用程序。

0ddfdb7b6dbd0f992517e6d996e190c3.png

图1- 4 Docker 组织架构图

如下图1-5所示,我们在客户端执行的Docker 命令会通过REST API传递到Docker Daemon中,如果此时您传递的是docker run 命令需要运行一个容器时,Dcoker Daemon 在接收到客户端指令后,它首先会验证本地是否存在该镜像,如不存在则会从远程仓库中pull不存在的镜像到本地,最后让该镜像运行起来成为应用容器进行对外服务工作了。

36ad1e65467d7c22b8d43e0dc14997f8.png

图 1-5 Dcoker 架构流程图

Docker 守护进程 ( dockerd) : 侦听 Docker API 请求并管理 Docker 对象,例如图像、容器、网络和卷。守护进程还可以与其他守护进程通信以管理 Docker 服务。

Docker 客户端 ( docker): 是许多Docker 用户与 Docker 交互的主要方式。当您使用诸如docker run、docker images此类的命令时,客户端会通过REST API将这些命令发送到Dockerd从而执行它们。该docker命令使用,注意Docker 客户端可以与多个守护进程通信。

Docker 仓库 (registry): 存储 Docker 镜像,例如Docker Hub 是一个任何人都可以使用的公共注册中心,Docker 默认配置为在 Docker Hub 上查找镜像,当然您也可运行自己的私有仓库。当您使用docker pull或docker run命令时,所需的映像将从您配置的仓库中提取。当您使用该docker push命令时,您的映像会被推送到您配置的仓库中。

Docker对象(Object): 当您使用 Docker 时,您是在创建和使用镜像、容器、网络、卷、插件和其他对象。

Docker 镜像(Image) : 它是用于创建一个Docker 容器指令的只读模板,通常镜像是基于其它基础镜像,按照自己额外的定义进行设置的,例如,您可以构建一个基于该ubuntu 镜像的镜像,安装 Apache Web 服务器和您的应用程序,以及使您的应用程序运行所需的配置详细信息。

Docker 容器(Container) : 容器是镜像运行的实例,您可以使用 Docker API 或 CLI 创建、启动、停止、移动或删除容器。您可以将容器连接到一个或多个网络,为其附加存储,甚至可以根据其当前状态创建新映像。

Docker Engine

Docker Engine (Docker 引擎)是用来运行和管理容器的核心软件。通常人们会简单地将其代指为 Docker 或 Docker 平台。如果了解或使用过 VMware ,那么可以将 Docker Engine理解为 ESXi 的角色。基于开放容器计划(OCI)相关标准的要求,Docker 引擎采用了模块化的设计原则,其组件是可替换的。

Docker Engine 引擎由如下主要的组件构成: Docker 客户端(Docker Client)、Docker 守护进程(Docker daemon)、containerd 以及 runC,由上述专用的工具协同工作,从而可以共同负责容器的创建和运行。

但是随着时间的推移,Docker daemon 的整体性带来了越来越多的问题。难于变更、运行越来越慢。这并非生态(或Docker公司)所期望的。Docker 公司意识到了这些问题,开始努力着手拆解这个大而全的 Docker daemon 进程,并将其模块化。当前这项拆解和重构 Docker 引擎的工作仍在进行中。不过所有容器执行和容器运行时的相关代码已经从 Docker Daemon 中移除,并重构为小而专的工具。

目前 Docker 引擎的架构示意图,如下图1-6所示图中有简要的描述。

7fd3d90e9730518c9d5ce1a055236a5e.png

图1-6 Docker 引擎的架构示意图

此处不对Containerd (实现容器的生命周期管理) 以及 containerd-shim (实现无 daemon 的容器) 与runC(实现容器的创建)进行展开讲解,在后续文章中会对其进行讲解,大概有个流程印象即可。

目前在Docker Engine 上运行的 Docker 容器有如下特点:

l标准: Docker 为容器创建了行业标准,因此它们可以在任何地方移植

l轻量级:容器共享机器的操作系统内核,因此每个应用程序不需要操作系统,从而提高服务器效率并降低服务器和许可成本

l安全:应用在容器中更安全,Docker 提供业界最强的默认隔离能力

1.2.4发展前景

根据Docker官网发布的数据[1-7],表明当前仍然有数以百万计的开发人员使用 Docker 来构建、共享和运行任何应用程序,而且 55% 的专业开发人员每天在工作中使用 Docker。在这些工作环境中,对软件供应链的外部攻击的增加正在加速开发人员对 Docker 可信内容的需求,包括 Docker 官方镜像和 Docker 验证发布者镜像。最后全球开发人员的快速增长——估计到 2030 年将达到 4500 万——推动我们实现可持续扩展,以便我们可以继续提供开发人员喜爱的创新、免费的 Docker 体验。

Docker容器技术出现已经超过6年了,这并不Docker容器技术生态系统已经发展到了尽头,相反的是容器及其周边的技术文化还有许多种方式可以保持发展。例如Docker 及其开源项目提供的技术,Moby 已被所有主要数据中心供应商和云提供商利用。这些提供商中的许多供应商都在利用 Docker 来提供其容器原生 IaaS 产品,此外领先的开源无服务器框架利用 Docker 容器技术。现在的Docker 容器无处不在,比如Linux、Windows、数据中心、云、无服务器等。

虽然K8S在1.20.x及之后宣布丢弃对Dockershim的支持,但对Docker来说这并不是致命的,Docker 社区不可能到放弃对 Kubernetes 兼容而放弃了整一个容器运行时市场(大蛋糕),所以最有可能的是 Docker 在新版本中支持 CRI 标准,从而继续作为容器运行时与 Kubernetes 共同发展。除此之外还可能从以下几个方面继续发展Docker容器技术。

1)更多更好的Windows容器

Docker成功推动了与 Microsoft 的合作,将 Docker 容器及其功能引入 Windows Server(有时称为Docker Windows 容器),有可能出现更多更好的Windows容器。尤其是在推出Windows新的服务器版本时,我预计微软在自己的操作系统是要持续支持原生容器以及加强对使用基于Windows集群的Kubernetes管理的支持。

2)更多的运行时

Docker是使容器成名的运行时,但是自从容器技术形成主流以来,也已经出现了许多其它的容器运行时,随着越来越多的组织为了满足特定的需求而推出自己的运行时,预计这个列表将会继续增长。尽管如此,我还是认为大多数工作负载将继续依赖于如今占主导地位的运行时,譬如Docker和Containerd、CRI-O、Kata-runtime。

3)容器安全商品化

对于国内做过等保的企业都知道,针对现在数字化经济安全是企业中重中之重,容不得一点马虎。所以除此之外还有其它出于种种原因,容器需要一种新的安全解决方法。截至目前,容器安全及其特有的挑战一直是IT安全人员讨论的焦点 ,更不用说一些公司了。要知道容器安全是件很特别的事情。但是如果容器需要扩展,则必须通过更广泛的安全流程来解决其安全需求。换句话说我们必须使用相同的系统和策略来保护我们用于一切的容器。要做到这样的效果容器安全必须商品化。未来我怀疑将不会再关注集装箱安全的特殊性,或者不再去寻求主要用于保护容器安全的安全平台上。相反的是,我们将容器集成到了其他的安全工作流程中去了。

为了更好了解的Docker的发展,我们可以从 GitHub 的docker/roadmap[1-8]中查看Docker 的最新的公共路线图情况。

参考连接:

[1-7] : https://www.docker.com/blog/updating-product-subscriptions

[1-8] : https://github.com/docker/roadmap

fb649f4872b485e132c56af83d44264f.jpeg

1.3 Containerd——容器运行时

1.3.1什么是Containerd

前世今生

自从在2013年Docker发布以来, Docker 公司在容器技术领域强势崛起一家独大。这让Google、RedHat、IBM等巨头们都产生了很大的危机感,因此他们想与 Docker 公司一起联合研发推进一个开源的容器运行时作为 Docker 技术的核心依赖,然而 Docker 公司很高冷的表示我不干!当巨头们听到这个反馈就非常不悦,因此通过一些手段对 Docker 公司软硬兼施,使其将 Libcontainer 捐给了开源社区也就是现在的 runC (Low level 容器运行时)。此外互联网科技巨头们又成立了 CNCF 去对抗 Docker 公司的一家独大,CNCF 成立的思路很明确,在容器领域干不过 Docker,那就搞容器上层的建设容器编排,此时Google将内部使用的Borg (15年的容器化基础架构) 系统采用Go语言进行重写成为Kubernetes开源项目,在2014年发布后迅速占领了容器编排的半壁江山。虽然 Docker 公司也尝试使用 Docker Swarm 去对抗 K8S但最后也以失败告终。

自此K8S慢慢成为云原生领域的标配,其生态系统也越做越大、越做越完善。随之而来是Docker 公司为了融入生态,捐献开源了 Docker 的基础核心依赖 containerd 。 在2019年2月28日containerd正式成为云原生计算基金会(Cloud Native Computing Foundation -CNCF) 的一个毕业项目, 紧随Kubernetes、Prometheus、Envoy和CoreDNS之后。并且自从 containerd 1.5后开始,Kubernetes容器运行时接口(CRI)的containerd插件已经合并到containerd中。

此外 K8S 为了能对接不同的容器运行时,也因为其中立性开发了一个运行时接口也就是CRI(Container Runtime Interface),现在我们熟知的Containerd、runC、cri-o等容器运行时都支持此CRI接口。但是由于当时确实没有啥 High Level 的 runtime,oci-o 虽然支持 CRI 接口但其功能太弱,那时的containerd 也尚未成熟,且当时其定位是嵌入到系统中,并非给终端用户使用; CoreOS rkt 也有自己的一套体系后来该项目也失败了。所以K8S只能暂时为了适配 Docker 搞了个 Dockershim 中转,将 CRI 转换为 Docker API。至此 K8S 和 Docker 进入了冷静期,双方都在各自优化自己,互不干扰。然而平静之下仍是暗潮汹涌,随着CNCF 社区一直在不断完善 containerd,其定位也发生了改变,由原来的系统嵌入组件,变成了今天的"工业标准容器运行时",并提供给终端用户使用。一直到2020年12月 K8S 宣布在v1.20版本放弃使用 DockerShim对Docker的操作,全面而改用 Containerd容器运行时直接操作容器。

其实K8S宣布废弃对dockershim容器运行时的支持, 一方面是因为商业因素, 而另一方面 K8S 已经提供了标准接口对接底层容器运行时,不再想单独维护一个类似于Dockershim的适配层去迎合Docker。

什么是Containerd?

Containerd是从Docker中分类出的容器运行时与runC一样被分解为Docke的高级运行时部分,它支持 OCI 的镜像标准、可以实现拉取和推送镜像、管理操作镜像负责容器的整个生命周期。

例如,当它需要运行一个容器时,它会将映像解压到一个OCI运行时包中,并将其发送给runC来运行它,Containerd还提供了一个API和客户端应用程序可以用来与之交互,containerd命令行客户端是ctr命令。

官方介绍: containerd可用作 Linux 和 Windows 的守护程序,它管理其主机系统的完整容器生命周期,从图像传输和存储到容器执行和监督,再到低级存储到网络附件等等。Container 主要特点是An industry-standard container runtime with an emphasis on simplicity, robustness and portability,中文翻译意思为业界标准的容器运行时,强调简单性、健壮性和可移植性。

那什么是CRI?

CRI是Kubernetes定义的一组gRPC服务。Kubelet作为客户端,基于gRPC框架,通过Socket和容器运行时通信。它包括两类服务:镜像服务(Image Service)和运行时服务(Runtime Service)。镜像服务提供下载、检查和删除镜像的远程程序调用。运行时服务包含用于管理容器生命周期,以及与容器交互的调用 ( exec / attach / port-forward ) 的远程程序调用。

那什么是dockershim?

描述: dockershim 是 Kubernetes 的一个组件,其作用是为了操作Docker。Docker是在2013年面世的,而Kubernetes是在2014年发布的,所以Docker刚开始并没有想到编排,也不会知道会出现Kubernetes这个庞然大物(它要是知道,也不会败的那么快)。但是Kubernetes在创建的时候就是以Docker作为容器运行时,很多操作逻辑都是针对的Docker,随着社区越来越健壮,为了兼容更多的容器运行时,才将Docker的相关逻辑独立出来组成了dockershim。

正因为这样,只要Kubernetes的任何变动或者Docker的任何变动,都必须维护Dockershim,这样才能保证足够的支持,但是通过dockershim操作Docker,其本质还是操作Docker的底层运行时Containerd,而且Containerd自身也是支持CRI(Container Runtime Interface)交互,所以正如前面所说kubernetes只是不想单独维护一个类似于Dockershim的适配层去迎合Docker运行时。

1.3.2为什么选择Containerd

Why Use Containerd?

在之前的工作中 containerd 一直都是薛定谔的存在,只闻其名但由于其还不成熟所以没啥用武之地,直到2020年12月 K8s 官方宣布要废弃 Docker 时,才把这家伙又拉回到大众视野里,现在的Containerd是CNCF的一个毕业项目,与kubernetes联系比较紧密在,其次Containerd也是Docker Engine的一个模块,其实我们早早的已经接触了它,相比较于其它的容器运行时我们更容易接受它,所以天时地利人和都选择Containerd,我们只是顺应容器编排时代发展的潮流。当然您也可以选择其它的容器运行时,它们也能工作于K8S中,因为它们都是基于OCI标准开发的,不同的是容器运行时拥有自己的侧重性和特点。

那kubernetes为啥会替换掉Dockershim呢?

主要原因主要在于其复杂性,由于需要通过Dockershim将指令传递给Docker,而Docker的多层封装和调用,导致其在可维护性上略逊一筹,增加了线上问题的定位难度 (貌似除了重启Docker,我们就毫无他法了),并且一旦Docker API有相应的改动或更新时,Dockershim也必须进行调整,所以在这样的原因下,K8S果断的丢弃Dockershim,直接向Containerd敞开怀抱,如下图1-6所示,我们对比了Dockershim、Containerd以及cri-o容器运行时的详细调用层级,可以看出 Containerd和cri-o的方案比起 Docker方案简洁很多, 因此我们更偏向于选用更加简单和纯粹的 containerd 和 cri-o 作为我们的容器运行时,但kubernetes 官方建议在1.20.x 之上的版本使用containerd作为容器运行时。

babdc11b6272f58ef8bf24c7bc689a93.png

图1-7 Dockershim、Containerd以及cri-o容器运行时在Kubelet调用对比

Containerd 有何特点?

lOCI Image Spec support (OCI图像规范支持)

lOCI Runtime Spec support (OCI运行时规范支持)

lImage push and pull support  (图像镜像推送和拉取的支持)

lContainer runtime and lifecycle support (容器运行时和生命周期支持)

lNetwork primitives for creation, modification, and deletion of interfaces  (用于创建、修改和删除接口的网络原语)

lManagement of network namespaces containers to join existing namespaces  (管理连接现有名称空间的网络名称空间容器)

lMulti-tenant supported with CAS storage for global images  (CAS存储支持用于全局映像的多租户)

专业术语

在介绍容器运行时相关概念及组件原理,梳理下我们常听到的 CRI、OCI、runC、containerd 等名词之间的关系。

lCRI (Container Runtime Interface) : 简称容器运行时接口,在Kubernetes 1.5版本中推出它是为了解决不同的容器运行时和Kubernetes的集成问题。实际上它只是kubernetes 定义的一组 gRPC 服务,Kubelet作为客户端基于gRPC 框架,通过 Socket 和不同的容器运行时通信。

lOCI(Open Container Initiative) : 简称开放容器计划,它是由Docker 公司与 CoreOS 和 Google 共同创建的,定义了创建容器的格式和运行时的开源行业标准,包括镜像规范(ImageSpecification)和运行时规范(RuntimeSpecification)

1)镜像规范: 镜像规范定义了OCI镜像的标准,high level 运行时将会下载一个OCI 镜像,并把它解压成OCI 运行时文件系统包(filesystem bundle),例如制定镜像格式、操作等

2)运行时规范: 描述了如何从OCI 运行时文件系统包运行容器程序,并且定义它的配置、运行环境和生命周期,如何为新容器设置命名空间(namepsaces)和控制组(cgroups),以及挂载根文件系统等等操作,都是在这里定义的。它的一个参考实现是runC(低层级运行时- Low-level Runtime) 除它以外也有很多其他的运行时遵循OCI标准,例如kata-runtime。

lfilesystem bundle文件系统束: 定义了一种将容器编码为文件系统束的格式,即以某种方式组织的一组文件,并包含所有符合要求的运行时对其执行所有标准操作的必要数据和元数据,即 config.json 与 根文件系统。

lDocker、Google 等开源了用于运行容器的工具和库 runC作为 OCI 的一种实现参考, 随后各种运行时和库也慢慢出现例如,rkt、containerd(今天的主角)、cri-o,然而这些工具所拥有的功能却不尽相同,有的只有运行容器(runc、lxc),而有的除此之外也可以对镜像进行管理(containerd、cri-o), 按照前面容器运行时进行分为两类, 容器运行时(Container Runtime): 运行于Docker或者Kubernetes集群的每个节点中, 负责容器的整个生命周期,包括构建、创建、运行、管理、删除等对容器的操作。其中Docker是目前应用最广的,随着容器云的发展,越来越多的容器运行时涌现。当前容器运行时分成了 low-level 和 high-level 两类,不同的容器运行时工具分类关系图,如图1-8所示。

1)low-level : 指的是仅关注运行容器的容器运行时,调用操作系统,使用 namespace 和 cgroup 实现资源隔离和限制

low-level runtime : 主要关注如何与操作系统资源交互和创建并运行容器,目前主流的有:

a.lmctfy -- Google的一个项目它是Borg使用的容器运行时。

b.runC-- 目前使用最广泛的容器运行时。它最初是作为Docker的一部分开发的,后来被提取出来作为一个单独的工具和库, 其实现了 OCI 规范包含config.json文件和容器的根文件系统。

c.rkt -- CoreOS开发的Docker/runc的一个流行替代方案,提供了其他 low-level runtimes (如runc)所提供的所有特性。

2)high-level :指包含了更多上层功能,例如 grpc调用,镜像存储管理等。

high-level runtime : 主要负责传输和管理容器镜像,解压镜像,并传递给low-level runtimes来运行容器。目前主流的有:

a.docker -- 老熟人完整的集装箱(Container)解决方案

b.containerd -- 本章主角

c.rkt -- 与Docker类似的容器引擎更加专注于解决安全、兼容、执行效率等方面的问题。

767339c7949d5fcfe4857cdaf1e774bb.png

图 1-8 容器运行时工具分类关系图

1.3.3组织架构

Containerd 的设计理念是成为业界标准的容器运行时,主要强调简单性、健壮性和可移植性,它管理着容器完整的生命周期,包括容器镜像的传输和存储、容器的执行和管理、存储和网络等。从下图1-9可以查看出Containerd 是一个大的插件系统,图中每一个虚线框其实就对应一个插件。

l底层系统支持 Linux 、Windows操作系统 和 支持 arm 和 x86 架构

l中间 containerd 包含 Backend、core、API 三层

1)Backend 层: Runtime plugin 提供了容器运行时的具体操作,为了支持不同的容器运行时 containerd 也提供了一系列的 containerd-shim

2)Core 层: 则是核心部分,提供了各种功能的服务,其中比较常用的是 Content service ,提供对镜像中可寻址内容的访问,所有不可变的内容都被存储在这里;Images Service 提供镜像相关的操作;Snapshot Plugin : 用来管理容器镜像的文件系统快照。镜像中的每一个 layer 都会被解压成文件系统快照,类似于 Docker 中的 graphdriver

3)API 层: 通过 GRPC 与客户端连接,例如提供了给 Prometheus 使用 API 来进行监控,给kubernetes提供了CRI接口,给containerd提供了服务处理程序。

l高层提供各种客户端和主流平台的接入,客户端包括 K8s 的 kubelet以及containerd 自己的命令行 ctr 等,平台包括Docker、RANCHER等 。

3140a1ee2a98a78e8da9ed4f4c505a9b.png

图1-9 Containerd架构图

1.3.4发展前景

自从2019 年Containerd正式成为 Cloud Native Computing Foundation(CNCF)的一个毕业项目以来,其周边生态

链逐渐发展完善。越来越多的云厂商和容器厂商采用Containerd,如阿里云、AWS、Cloud Foundry、Docker、Google、IBM、Rancher Labs 等支持推广生态系统最广泛采用的容器运行时[1-9]。对于 containerd 中的各种组件,应该定义扩展点,在这些扩展点中可以将实现交换为替代方案由于containerd 将使用runcOCI 作为执行层的默认运行时,所以只要符合 OCI 运行时规范的运行时可以轻松添加到 containerd。

特别在K8S 宣布在V1.24版本后某默认采用Containerd作为容器运行时来管理容器的生命周期,其主要目的是减少K8S容器运行时架构层的复杂性。至此Containerd 便从Docker 后台登上了前台,展现在人们眼前,便快速的席卷容器生态圈,当前Containerd 保持着显着的势头——展示了对基础容器技术的需求, 所以说Containerd 随着容器技术不断的发展,以及Kubernetes 容器编排平台的火热。

同样为了更好了解的containerd的发展,我们可以从 GitHub 中的containerd/containerd [1-10] 查看containerd的最新的公路线图情况。

参考链接

[1-9] : https://www.cncf.io/announcements/2019/02/28/cncf-announces-containerd-graduation/

[1-10] : https://github.com/containerd/containerd/milestones

1.4 Kubernetes——容器大管家

1.4.1什么是Kubernetes

近些年由于Cloud云原生(公有云、私有云)以及大数据、人工智能的发展,促进了企业从传统转型到数字信息化再到上云, 其中运维部署应用技术也从物理机转向虚拟化再转向了容器化,而又随着分布式架构应用的火热,以及对业务快速迭代的的需要,容器化部署方式给开发、运维带来许多便利,但同时也出现一些问题,例如当一个应用容器停机出现故障,怎样自动让另外一个容器去及时的替补,又当并发访问量变大的时候,怎么样做到横向扩展容器数量。

我们把这些容器管理的问题统称为容器编排问题,为了解决这些容器编排问题,开发者们研发了一系列容器编排的解决方案,所以便推动了如今的Kubernetes 容器编排系统,它实现了对容器资源的编排与控制。在本章节里作者尽量用最简单直白的语言来介绍Kubernetes这个庞然大物。

前世今生

让我们回顾一下 Kubernetes (后续简称K8S)的前世今生,在K8S发布前后也出现过其它众多容器编排解决方案,在此过程中K8S不断快速迭代加之CNCF 与K8S社区 [1-11]的逐渐完善,在2019年后容器编排领域竞争格局基本尘埃落定, K8S成为容器编排领域的事实标准(老大),同时它也成为了云原生的底层基础设施。

l在2013年,Apache Mesos成为Apache计划中的首要开发目标,它是由加州大学伯克利分校的AMPLab首先开发的一款开源群集管理软件(分布式的资源管理框架),能够将数据中心电脑系统中的CPU、存储器、存储设备以及其他运算资源,全部加以虚拟化,并进行管理,支持Hadoop、ElasticSearch、Spark、Storm 和Kafka等应用架构,在2019年8 月Twitter 宣布弃用MESOS投向Kubernetes 的怀抱。

l在2014年,Docker 发布自己的容器编排集群管理工具Docker Swarm ,它针对于 Docker 最薄弱的集群化、容器编排与服务构建,但是更新回滚的功能相比较于Kubernetes 较薄弱,在2019年阿里云宣布 Docker Swarm从云平台构建选项中剔除,同时Docker也放弃了Docker Swarm这标志着它即将退出容器编排的舞台。

l在2014年,Google 首次发布Kubernetes 容器化编排系统,它是基于 Borg 15年的容器化基础架构经验之上,采用GO语言进行重写凝聚了社区的最佳创意和实践,它是CNCF 毕业项目并在开源发布后迅速在各个企业占有一席之地。当时可能谁也没有想到4年后它成为容器化编排的实际标准,甚至得到全球各大科技巨头的支持,可以说Kubernetes是下一代分布式架构的王者,是容器编排领域的老大。

下图1-10所示,我们使用 google trends 对比在对于上述的容器编排工具 kubernetes 、 docker swarm、 mesos 三个关键词搜索热度(2019年9月数据)进行展示。

fad75a4af7b7be365424d465959313ad.png

图1-10 K8S、Docker swarm、Mesos 的Google搜索热度

What is a Kubernetes?

Kubernetes (简称K8S) 的名字起源于希腊语,其含义是舵手、领航员、向导,其logo即像一张渔网又像一个罗盘。其深层含义可能是,既然Docker把自己定位是驮着集装箱在大海遨游的鲸鱼,那么Kubernetes则是掌控大海从而捕获和指引这条鲸鱼按照其设定的路线巡游,从这里可以看出Google对其打造了新一代容器世界的伟大蓝图(雄图霸业)

Kubernetes 是一个用于自动化部署、扩展和管理容器化应用程序的开源系统,它将组成应用程序的容器组合成逻辑单元,以便于容器管理和服务发现,其功能与架构都遵循了"一切以服务为中心,一切围绕服务运转"以及微服务的架构,简化开发流程与运维的成本;。

简单的说,它就是容器集群管理系统,一个全新基于容器技术的分布式架构方案,实现生产级别的容器编排系统,其特点是可移植的、可扩展的,用于管理容器化的工作负载和服务,我们可使用声明式配置,它便可以依据配置信息自动地执行容器化应用程序的管理(自动化的容器部署、扩展和自动运维),实现了简化开发与运维操作流程。

什么是容器编排技术?

容器编排的技术定义是预定义流程的执行(先做A、再做B、然后做C)。与此相对应Kubernetes构建了一系列相互独立、可预排的控制过程,以持续不断地将系统从当前状态调整到声明的目标状态。比如: 如何从 A 达到 C,,并不重要集中化的控制也就不需要了, 就是这样的设计思想使得Kubernetes使用更简单、更强大、稳健、反脆弱和可扩展。

K8S能完成什么工作?

前面我们说过容器是打包和运行应用程序的好方式,但是免不了容器发生故障,在生产环境中您需要管理运行应用程序的容器并确保不会停机;

例如: 当一个容器故障停机,需要另外一个容器需要立刻启动以替补停机的容器。类似的这种对容器的管理动作由系统来执行会更好更快速(而放弃传统的手工方式)。

Kubernetes 针对此类问题提供了一个可弹性运行分布式系统的框架,可以使你非常健壮地运行分布式系统,它可以处理应用程序的伸缩、failover(故障转移)、部署模式等多种需求。同时Kubernets 也提供了完善的容器生态系统,涵盖了开发、自动化部署测试、运维监控、告警等各个环节;

K8S的特点及优势

l- 项目代码开源: 托管于CNCF拥有众多云厂商以及开发者,并且可以自由地部署在企业内部,私有云、混合云或公有云。

l- 完善的社区: 提供完整的帮助文档以及社区生态。

l- 多种方式安装部署: 您可以选择Kubeadm、二进制或者kubeplay部署。

l- 贴近操作系统,消耗资源小: 安装占用的系统资源相比较于虚拟机已经是非常节俭了。

l- 支持众多第三方插件: K8S是一个包容的管理平台,同时它拥有庞大的生态系统,利用各类插件来实现更强大的功能。

l- 灵活性、迁移便利: K8S的灵活性都能让你在应对复杂系统时得心应手,通过应用的资源清单将应用快速部署到其它集群之中。

l- 实现服务发现和负载均衡:通过DNS 名称或 IP 地址暴露容器的访问方式,并且可以在同组容器内分发负载以实现负载均衡;

l- 实现存储编排:可以自动挂载指定的存储系统,例如 本地存储、NFS(网络存储)、ISCSI(网络存储)、以及云存储 等

l- 实现自动发布和回滚: 描述已部署容器的所需状态并将以合适的速率调整容器的实际状态, 可以自动执行部署创建新容器、删除现有容器并将其所有资源采用到新容器;

l- 实现故障自愈: 重新启动发生故障、替换容器、kill杀死不满足自定义健康检查条件的容器 (在容器就绪之前,避免调用者发现该容器)

l- 实现密钥及配置管理: 可以存储和管理敏感信息(例如,密码、OAuth token、ssh密钥等), 您可以更新容器应用程序的密钥、配置等信息,而无需重新构建容器的镜像;

l- 实现角色权限分配管理: 我们可以为不同资源对象、名称空间分别指定访问者角色及权限,以达到安全访问隔离的效果。

Kubernetes适合那些人群学习研究?

项目经理、软件架构师、软件工程师、测试工程师、运维工程师以及其它网络技术爱好者;

作为一名新手如何学习Kubernetes?

由于Kubernetes 知识和生态体系太庞,所以对于初学者来说还是比较难以上手的,并且K8S版本迭代速度也比较快,所以可能你在学习Kubernetes由于其版本不同所支持或者丢弃特性有所不同,可能会编写在Kubernetes资源清单部署时会出现警告,但大致使用操作是没有多大变化的。

此时我们必须得参考Kubernetes官网[1-12]提供的帮助文档进行辅助学习,其次我们可以参考本书中的学习流程进行相应学习扩充。

1.4.2基础与核心架构

为了更好的了解与学习Kubernets基础核心架构,我们需借鉴Borg系统架构, 来对比K8S基础核心架构如何基于Borg系统进行演变,同时展示它们之间的异同性。

Borg 系统架构

Borg系统架构如图1-11所示,其主要由以下几个模块组成。

lBorgMaster : 集群大脑主要负责各组件请求的分发,为了防止其单节点故障, 高可用集群副本数据最好是 >= 3 奇数个节点;

lBorglet : 工作节点提供各类资源运行对应的容器, 并实时与Paxos进行联系监听,如果有请求取出(消费者)去执行该任务;

lPersistent Store : 简写 Paxos 它是Google的一个键值对数据库;

lScheduler : 调度器将任务调度的数据写入Persistent Store(Paxos)而不是直接与Borglet节点进行联系;

l客户端访问方式 : Borgcfg(Config File)、Command-line Tools、 Web Browsers;

1912a8f5f3c214acbd794ae4938fdd8d.png

图 1-11 Borg系统架构图

Kubernetes 系统架构

Kubernetes系统架构如图1-12所示,其主要由以下几个组件构成。

1)Kubernetes Master (Control Plane)

l控制平面组件(Control Plane Components) : 对集群做出全局决策(比如调度),以及检测和响应集群事件( 例如当不满足部署的 replicas 字段时启动新的 pod),它可以在可以在集群中的任何节点上运行。

lAPI 服务器(Kube-APIServer) : API 服务器是 Kubernetes 控制面的前端, 它是所有服务请求访问统一入口, 基于HTTP协议进行的Client/Server架构开发(由于HTTP协议本身支持多种请求方式和验证则没有必要采用TCP协议重写)

l本地控制器管理组件(Kube-Controller Manager) : 控制器进程的控制平面组件, 在控制器组件其内部包含多个控制器,并且每个控制器都是一个单独的进程,为了降低复杂性,它们都被编译到同一个可执行文件,并在一个进程中运行。控制器包括节点控制器(Node Controller) / 副本控制器维持副本期望数目(Replication Controller) / 端点控制器(Endpoints Controlle) / 服务帐户和令牌控制器 (Service Account & Token Controllers)

l云控制器管理组件(Cloud-Controller Manager ): 云控制器管理器是指嵌入特定云的控制逻辑的 控制平面组件。云控制器管理器使得你可以将你的集群连接到云提供商的 API 之上,并将与该云平台交互的组件同与你的集群交互的组件分离开来,它仅运行特定于云平台的控制回路。如果你在自己的环境中运行 Kubernetes,或者在本地计算机中运行学习环境,所部署的环境中不需要云控制器管理器。

l任务调度器组件(kube-scheduler) : 负责监视新创建的、未指定运行节点(node)的 Pods,选择节点让 Pod 在上面运行。调度决策考虑的因素包括单个 Pod 和 Pod 集合的资源需求、硬件/软件/策略约束、亲和性和反亲和性规范、数据位置、工作负载间的干扰和最后时限。

l键值数据库组件(etcd) : 它是兼具一致性和高可用性的键值数据库,可以作为保存 Kubernetes 所有集群数据的后台数据库(容器创建、容器状态信息、服务状态信息), 并协助分布式集群的正常运转。

2)Kubernetst Nodes (WorkLoad)

l容器操作组件(Kubelet): 在集群中每个节点(node)上运行的代理,其通过CRI 接口直接跟容器引擎(Docker)或者Containerd进行交互,保证容器(containers)都 运行在 Pod 中,实现容器的生命周期管理。注意它不会管理不是由K8S创建的容器

l网络代理组件(Kube-Proxy) : 它是集群中每个节点上运行的网络代理,维护节点上的网络规则,这些网络规则允许从集群内部或外部的网络会话与 Pod 进行网络通信,它也是实现 Kubernetes 服务(Service) 概念的一部分,例如实现负载均衡、流量转发、服务发现等功能。

l容器运行时(Container Runtime) : 容器运行环境是负责运行容器的软件,Kubernetes 支持多个容器运行环境: docker、 containerd、CRI-O 以及任何实现 Kubernetes CRI 容器运行环境接口。

3)Cloud Provider API : 云供应商提供的API接口,支持多种共有云、私有云、混合云模式

5081b0957edd55eeb43aba05ea4e8bd6.png

图 1-12 Kubernetes系统架构图

此时我们可由上面图1-11和图1-12可以看出,Kubernetes 架构与Borg架构相似度极高,K8S其主要核心API 组件类比于BorgMaster组件,而Node 类比于Borglet,其在K8S与Borg中同的是将数据存储组件从BorgMaster中分离出来并采用etcd兼具一致性和高可用性的键值数据库,极大的提高了集群的可用性、稳定性。

1.4.3专业术语解释

Infrastructure as a Service (IaaS- 基础设施及服务) :提供给消费者的服务是对所有计算基础设施的利用,包括处理CPU、内存、存储、网络和其它基本的计算资源,用户能够部署和运行任意软件,包括操作系统和应用程序。相关产品包括阿里云、腾讯云、百度云、京东云、Google Cloud、AWS Cloud

Platform as a Service (PaaS平台及服务) :提供给消费者的服务是把客户采用提供的开发语言和工具(例如Java,python, .Net等开发环境)开发的或收购的应用程序部署到供应商的云计算基础设施上去。相关产品包括新浪云(SAE) | Google Cloud 平台(GCP)

Software as a Service (SaaS软件即服务) :提供给客户的服务是bai运营商运行在云计算基础设施上的应用程序,用户可以在各种设备上通过客户端界面访问,如浏览器。相关产品包括Office 365(云办公) 、 腾讯文档。

K8S:Kubernetes,简称 K8s,是用 8 代替中间 8 个字符 “ubernete” 而成的缩写

Kubernetes 对象:在 Kubernetes 系统中Kubernetes 对象是持久化的实体,它可以使用这些实体去表示整个集群的状态。

Kubernetes 资源清单: Kubenetes 所有的资源对象的定义和描述采用Yaml或者Json的文件格式, 可将其比喻作剧本,即按照要求定义进行相应资源的执行操作。

对象规约(Spec): spec 描述你创建对象时所希望具有的特征如 期望状态(Desired State)。

对象状态(Status):status描述了对象的 当前状态(Current State),它是由 Kubernetes 系统和组件 设置并更新的

对象名称: 集群中的每一个对象都有一个名称 来标识在同类资源中的唯一性,比较常见的三种资源命名约束包括DNS子域名、DNS标签名、路径分段名称 。

UIDs:Kubernetes 系统生成的字符串唯一标识对象,在集群的整个生命周期中创建的每个对象都有一个不同的 uid,它旨在区分类似实体的历史事件。

名称空间(Namespace):在多个用户之间划分集群资源的一种方法(通过资源配额),一般企业中只是将其根据业务类型或者地域分类进行划分。

标签(Labels):是附加到 Kubernetes 对象(比如 Pods)上的键值对,以便让控制器进行高效的查询和监听操作。

标签选择器(selector):通过标签选择器Label Selector查询和筛选拥有某些Label的资源对象,而K8s通过类似于SQL的简单又通用的对象(where 条件)查询机制;用来选择对象和查找满足某些条件的对象集合。

注解(annotations):使用标签或注解将元数据附加到 Kubernetes 对象,使得客户端程序(例如工具和库)能够获取这些元数据信息。

工作负载:在 Kubernetes 上运行的应用程序,一般运行在Node节点上。

容器镜像:它是一个随时可以运行的软件包, 包含运行应用程序所需的一切:代码和它需要的所有运行时、应用程序和系统库,以及一些基本设置的默认值。

容器运行时:负责运行容器的软件以及容器声明周期的管理。

Pod:在 Kubernetes 中创建和管理的、最小的可部署的计算单元。

1.4.4 Docker和Containerd与Kubernetes的关系

在前面文章中我们讲述了Docker容器技术、Containerd 容器运行时,它们到底与Kubernetes有何种关系? 这将是本文讲述的重点。

如下图1-13所所示 dockershim(Docker)、containerd 和 cri-o 都是遵循CRI的容器运行时,我们称他们为高层级运行时(High-level Runtime)。

e44fbfb7168e903a5a71d518c6a69030.png

图 13.Docker和Containerd与Kubernetes的关系

由上图可知Kubelet 通过grpc使用DockerShim适配器+Docker实现了Containerd 容器运行时的功能,它们都是High-level Runtime类型。K8S为了通过Docker操作容器才使用Dockershim这个接口适配器(中间人),而实际上Docker底层实现部分也是使用Containerd来实现对容器声明周期进行管理。此处也表明了K8S为啥要抛弃Dockershim的原因,因为自家的CNCF已经拥有Containerd并且可以完美的替代Dockershim + Docker模式进行工作,所以K8S不想花费人力、物力、财力去迎合Docker。

1.4.5 Kubernetes应用场景浅谈

前面说到2019年底以Google开源Kubernetes容器集群管理平台,摘得容器编排王者头衔奠定其老大哥的形象,并随着这几年云原生、分布式微服务框架以及大数据的火热发展,越来越多的业务应用部署在Kubernetes集群中,可以看出Kubernetes的受欢迎程度是毋庸置疑的。

那在企业中虚拟化、云容器化正在逐步推进,同时随着开发和运维人员对Kubernetes的掌握与推广,业务迭代也跟贴近于容器运行环境,帮助着我们加速开发、测试、上线的效率。同时利用其自动化部署能力实现持续集成和交互(CI/CD)减少开发、运维人员手动操作的需要,在Kubernetes集群中我们可以快速进行异常重启、金丝雀发布、根据业务访问负载进行扩缩容,以及部署原先在物理主机部署的数据库集群,都能轻轻松松在kubernetes中快速构建运行,例如 Redis集群的部署、ElasticSearchs集群的部署,可以看出Kubernetes为企业节约成本和大量的时间,在这业务需要快速迭代的时代里,这是企业非常所需也是乐于见到。

同时在云厂商业务中也在广泛使用kubernetes这一项容器编排技术,衍生出了非常多的云产品,极大的推动了云原生的发展,使得部署在云上的业务变得越来越便于管理、稳定、安全。在云原生应用领域,容器平台厂商未来的竞争一定是生态的竞争,并不是某一个功能比别人做得好,就能赢得市场,需要从用户的使用角度出发,不断的从各方进行发展,其次通过开源能使其走的更快、更远。

参考连接:

[1-11]: https://kubernetes.io/

[1-12]: https://kubernetes.io/docs/home/

亲,文章就要看完了,不关注一下【全栈工程师修炼指南】吗?

新手问答

1.如何结合企业业务需求制定适当的容器方案?

首先我们需要根据企业的实际需求以及业务架构、以及运维安全管理等多个维度进行研判,顺应技术潮流进行对企业内部技术迭代,容器平台的建设也需要考虑场景、技术、系统对接、成本、人员技能等因素。我们可以在本地构建或采用云厂商提供的容器部署管理平台,针对这两者都有自己特点。其次如果你的应用比较单一的情况下建议直接采用Docker方案进行部署,但如果您的应用关联性强、并且是微服务架构的情况下,强烈推荐使用容器集群管理平台方案进行部署。

2.为何选择Kubernetes作为容器编排的解决方案?

容器技术发展迅速,相关开源社区以及各大厂商都在努力贡献,使得容器周边生态逐步完善。同时微服务框架的功能越来越完备,随着微服务架构思想不断普及,在不久的将来会有越来越多的新业务基于微服务架构的形式进行出现,而容器是微服务架构应用最理想的运行环境,导致容器平台的应用场景也是不断改善、更新和更越来越强大。Kubernetes作为容器集群管理平台的佼佼者,是我们对业务容器化管理的首要选择对象,它可以帮助我们快速部署、迭代、发布业务,并可以通过第三方插件进行日志采集和监控告警。

本章小结

本章主要讲解了四个部分,首先针对容器基础概述,容器技术有何特点,以及容器技术发展前景做了简单介绍,帮助读者们针对容器方面做了一个简单了解,其次以容器技术引出Docker容器技术基础概念,发展历程和组织架构,以及选择使用Docker为我们带来那些便利、好处。然后介绍了什么是Containerd容器运行时,以及其架构特点,知道了它的基本功能就是管理容器的生命周期,最后讲解了本书的主角Kubernetes容器集群管理平台基础概念,分析其组织架构特点,以及其功能特点,为我们开发、运维工作带来那些切实的好处。随着基础理论的学习可以帮助读者快速入门,并在随后的Docker与Kubernetes实战中体验到它们魅力,以及容器技术为云原生带来赋能。

本文至此完毕,更多技术文章,尽情等待下篇好文!

原文地址: https://blog.weiyigeek.top

如果此篇文章对你有帮助,请你将它分享给更多的人! 

a574a70c618cf61f2929fec5e615d71c.gif

2ac2277655b6d394f6e711c7932c2dc0.png 学习书籍推荐 往期发布文章 e43288bdf4a9774ceb636f38e4988e75.png

 专栏推荐  

欢迎长按(扫描)二维码 取更多渠道哟!

04207f71542fa9dd48f4819ddfae941d.gif

欢迎关注 【全栈工程师修炼指南】(^U^)ノ~YO

作者微信【weiyigeeker】,拉你一起学习交流进步吧!

3da4a3ac7a62596b9830065c3a56145f.jpeg 2a94536fc266c69e88dded3e1601cd2d.png

温馨提示:由于作者水平有限,本章错漏缺点在所难免,希望读者批评指正,若有问题或建议请在文章末尾留下您宝贵的经验知识,联系邮箱地址[master@weiyigeek.top]或关注公众号[全栈工程师修炼指南]留言。

点击【"阅读原文"】获取更多

若有帮助请【转发】并点个【在看 + 赞 】!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值