Kubernetes 大规模使用过的都说简单,没有用过清一色的都是使用复杂、概念晦涩难懂,因此即使是那些具有一定服务器端知识的人也可能会感到困惑。让我在这里尝试一些不同的东西。与其解释一个不熟悉的问题(如何在 Kubernetes 中运行 Web 服务?)和另一个(你只需要一个清单,三个 sidecar 和一堆 gobbledygook),我将尝试揭示 Kubernetes 技术发展趋势。如果您已经知道如何使用虚拟机运行服务,希望您会发现最终并没有太大区别。如果您对大规模运营服务完全不熟悉,那么跟随技术的发展可能会帮助您了解当代方法。像往常一样,这篇文章并不全面。相反,它试图总结我的个人经历以及计算机多年来虚拟化是如何形成的。
如何使用虚拟机部署服务早在 2010 年,当我刚刚开始我的软件工程师职业生涯时,使用虚拟机(或有时是裸机)部署应用程序非常普遍。你需要一个临时的 Linux 虚拟机,将 Nginx 或 Apache 反向代理放在它前面,然后在它旁边运行一堆守护进程和 cronjobs。这样的机器将代表服务的单个实例,打个比方,就类似于一个盒子,而服务本身将只是分布在网络上的一组命名的相同机器。根据您的业务规模,您可能只有几个、几十个、几百个甚至几千个盒子分布在为生产流量提供服务的多个盒子中。

通常,机器群的大小将定义配置(安装操作系统和软件包)、扩展(产生相同的盒子)、服务发现(将一组盒子隐藏在一个名称后面)和部署(运送新版本的代码)的方式到盒子)完成了。如果你是一个只有几个类似宠物的盒子的公司,您可能会发现自己很少半手动地配置新盒子。这通常意味着总线系数低(由于缺乏自动化)、安全状况差(由于缺乏定期补丁更新)以及可能更长的灾难恢复。从好的方面来说,管理成本会非常低,因为不需要扩展,您的部署会很简单(只需几个盒子来交付代码),而且服务发现会很简单(由于相当静态地址池)。
对于拥有大量盒子的公司来说,现实情况会有所不同。大量机器通常会导致更频繁地需要配置新盒子(更多的盒子意味着更多的破损)。你会投资自动化(投资回报率会很高),最终得到许多牛一样的盒子。作为不断重新创建盒子的副产品,您将增加总线因素并改善安全状况(将自动更新和安装补丁)。在它的反面,会存在低效的扩展(由于每日/每年的流量分布不均匀),过于复杂的部署(很难将代码快速交付到许多机器上),以及脆弱的服务发现(您是否尝试过大规模运行consul或zookeeper?)会导致更高的运营成本。
Amazon Elastic Compute Cloud (EC2) 等早期云产品允许更快地启动(和关闭)机器;使用packer制作并使用cloud-init自定义的机器镜像,使配置稍微容易一些;puppet和ansible等自动化工具支持应用基础架构更改并大规模交付新版本的软件。但是,仍有很大的改进空间。
Docker 容器解决了什么问题在过去,拥有不同的生产和开发环境是很常见的。这将导致应用程序可能在您安装的 Debian 机器上本地运行,但由于缺少依赖项而无法在生产中的 vanilla CentOS 上启动。相反,在本地安装应用程序的依赖项可能会遇到一些麻烦,但由于资源需求高,为每个服务运行预配置的虚拟机进行开发将是不可行的。即使在生产中,虚拟机的庞大也是一个问题。每个服务拥有一个虚拟机可能会导致低于最佳资源利用率和/或相当大的存储和计算开销,但是将多个服务放在一个盒子中可能会使它们发生资源抢占冲突。世界显然需要一个更轻量级的盒子。

这就是容器的用武之地。就像允许将裸机服务器分割成几台更小(更便宜)的机器的虚拟机一样,容器将一个 Linux 机器分割成数十个甚至数百个独立的环境。在一个容器中,您可能会觉得您拥有自己的虚拟机,以及您最喜欢的 Linux 发行版。好吧,至少乍一看。从外部看,容器只是在主机操作系统上运行并共享其内核的常规进程。打包应用程序及其所有依赖项(包括特定版本的操作系统用户空间和库)的能力,将其作为容器镜像发送,并在安装了 Docker(或类似工具)的任何位置的标准化执行环境中运行,极大地提高了工作负载的可重复性.
由于容器边界的轻量级实现,计算开销显著降低,允许单个生产服务器运行可能属于多个(微)服务的数十个不同容器。当然,这可能以降低安全性为代价。由于不可变和共享的镜像层,镜像存储和分发也变得更加高效。在某种程度上,容器也改变了供应的方式。使用(粗心编写的)Dockerfiles 和ko和Jib之类的(神奇的)工具,责任极大地转移到了开发人员身上,简化了生产 VM 的要求——从开发人员的角度来看,你只需要一个 Docker-(或更高版本的 OCI-)兼容应用程序的运行时,因此您不会再因为要求安装某个版本的 Linux 或系统包而惹恼您的运维朋友。
最重要的是,容器加速了运行服务的替代方式的开发。现在有 17 种方法可以在 AWS 上运行容器https://www.lastweekinaws.com/blog/the-17-ways-to-run-containers-on-aws/
,其中大部分是完全无服务器的,在足够简单的情况下,您可以使用 Lambda 或 Fargate 并从牛一样的盒子中受益!
容器被证明是一个非常方便的开发工具。构建容器镜像也比构建 VM 更简单、更快捷。再加上如何有效分离团队之间职责的老组织问题,导致典型企业的平均服务数量显著增加,每个服务的盒子数量也有类似的增加。Docker 普及的容器形式实际上具有很强的欺骗性。乍一看,每个服务实例都有一个便宜的专用 VM。但是,如果这样的实例需要sidecar(例如在您的 Web 应用程序前面运行的本地反向代理来终止 TLS 连接或加载秘密和/或预热缓存的守护程序),您会立即感觉到疼痛,这就是容器与虚拟机的本质区别。
Docker 容器被刻意设计为只包含一个应用程序。一个容器——一个 Nginx;一个容器 - 一个 Python Web 服务器;一个容器 - 一个守护进程。容器的生命周期将绑定到该应用程序的生命周期。并且特别不鼓励将像systemd这样的 init 进程作为顶级入口点运行。因此,要从本文开头的图表重新创建一个 VM-box,您需要拥有三个具有共享网络堆栈的协调容器-box(嗯,至少localhost需要相同)。要运行该服务的两个实例,您需要三个三个一组的六个容器!
从扩展的角度来看,这意味着我们需要一起扩展(和缩减)一些容器。部署也需要同步进行。新版本的 Web 应用程序容器可能会开始使用新的端口号,并与旧版本的反向代理容器不兼容。我们显然在这里错过了一个抽象,它与容器一样轻量级,但与原始 VM 盒子一样富有表现力。此外,容器本身也没有提供任何将盒子分组为服务的方法。但他们促成了箱子人数的增加!Docker 竞相用它的 Swarm 产品解决这些问题,但另一个系统赢了……
Kubernetes 解决了这一切……还是没有?Kubernetes 设计师显然没有发明新的运行容器的方法,而是决定重新创建良好的旧的基于 VM 的服务架构,但使用容器作为构建块。好吧,至少这是我的看法。但对我来说,作为以前有 VM 经验的人,一旦我了解了新术语并弄清楚了类似的概念,许多最初的 Kubernetes 想法就会开始看起来很熟悉。
Kubernetes Pod 是新的虚拟机让我们从 Pod 抽象开始。Pod 是您可以在 Kubernetes 中运行的最小的东西。最简单的 Pod 定义如下所示:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.20.1
ports:
- containerPort: 80
乍一看,上面的清单只是说明要运行什么镜像(以及如何命名)。但是请注意containers属性是一个列表!现在,回到那个nginx + web app例子,在 Kubernetes 中,您可以简单地将反向代理和应用程序本身放在一个盒子中,而不是为 Web 应用程序容器运行额外的 Pod:
apiVersion: v1
kind: Pod
metadata:
name: foo-instance-1
spec:
containers:
- name: nginx #
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?