云原生新手入门指南
Kubernetes 是做什么的?什么是 Docker?什么是容器编排?Kubernetes 是如何工作和扩展的?你可能还有很多其他的问题,本文将一一为你解答。
这篇文章适合初学者,尤其是那些工作忙碌,没有办法抽出太多时间来了解 Kubernetes 和云原生的开发者们,希望本文可以帮助你进入 Kubernetes 的世界。
那么什么是容器呢?
要讨论容器化首先要谈到虚拟机 (VM),顾名思义,虚拟机就是可以远程连接的虚拟服务器,比如 AWS 的 EC2 或阿里云的 ECS。
接下来,假如你要在虚拟机上运行一个网络应用 —— 包括一个 MySQL 数据库、一个 Vue 前端和一些 Java 库,在 Ubuntu 操作系统 (OS) 上运行。你不用熟悉其中的每一个技术 —— 你只要记住,一个应用程序由各种组件、服务和库组成,它们运行在操作系统上。
现在,将应用程序打包成一个虚拟机镜像,这个镜像中包括了 Ubuntu 操作系统。这使得虚拟机变得非常笨重 —— 通常有几个 G 的大小。
虚拟机镜像包含了整个操作系统及所有的库,对应用程序来说,这个镜像过于臃肿,其中大部分组件并没有被应用程序直接调用。如果你需要重新创建、备份或扩展这个应用程序,就需要复制整个环境(虚拟机镜像),在新环境中启动应用通常需要几十秒甚至几分钟时间。如果你想单独升级应用中的某个组件,比如说 Vue 应用,就需要重建整个虚拟机镜像。另外,如果你的两个应用依赖同一个底层镜像,升级底层镜像会同时影响这两个应用,而有时候,你只需要升级其中一个应用的依赖而已。这就是所谓的 “依赖陷阱”。
解决这个问题的办法就是容器。容器是继虚拟机之后更高层次的抽象,在这层抽象中,整个应用程序的每个组件被单独打包成一个个独立的单元,这个单元就是所谓的容器。通过这种方式,可以将代码和应用服务从底层架构中分离出来,实现了完全的可移植性(在任何操作系统或环境上运行应用的能力)。所以在上面的例子中,Ubuntu 操作系统就是一个单元(容器)。MySQL 数据库是另一个容器,Vue 环境和随之而来的库也是一个容器。
但是,MySQL 数据库是如何自己 “运行” 的?数据库本身肯定也要在操作系统上运行吧?没错!
更高层次的容器,比如 MySQL 容器,实际上会包含必要的库来与底层的操作系统容器通信和集成。所以你可以把容器看成是整个应用堆栈中的一层,每层都依赖于下层的单元。而这就类似于船舶或港口中集装箱的堆叠方式,每个容器的稳定性都依赖于下面的容器的支持。所以应用容器的核心是一个受控的执行环境。它们允许你从头开始定义整个环境,从操作系统开始,到你要使用的各个版本的库,再到你要添加的代码版本。
与容器相关的一个重要概念是微服务。将应用程序的各个组件拆分并打包成独立的服务,这样每个组件都可以很容易地被替换、升级、调试。上面的例子中,我们会为 Vue 前端创建一个微服务,为 MySQL 数据库创建另一个微服务,为 Java 中间件部分创建另一个微服务,以此类推。很明显,微服务与容器化是相辅相成的。
现在你已经对容器有一定了解了吧?Docker 是最常用的容器化工具,也是最流行的容器运行时。
Docker 开源于 2013 年。用于打包和创建容器,管理基于容器的应用。所有 Linux 发行版、Windows 和 macOS 都支持 Docker。
首先,简单介绍一下历史。Kubernetes 是 Google 基于其内部容器调度平台 Borg 的经验开发的。2014 年开源,并作为 CNCF(云原生计算基金会)的核心发起项目。
那么 Kubernetes 又跟容器是什么关系呢?让我们再回到上面的例子。假设我们的应用爆火,每天的注册用户越来越多。
现在,我们需要增加后端资源,使浏览我们网站的用户在浏览页面时加载时间不会过长或者超时。最简单的方式就是增加容器的数量,然后使用负载均衡器将传入的负载(以用户请求的形式)分配给容器。
这样做虽然行之有效,但也只能 在用户规模有限的情况下使用。当用户请求达到几十万或几百万时,这种方法也是不可扩展的。你需要管理几十个也许是几百个负载均衡器,这本身就是另一个令人头疼的问题。如果我们想对网站或应用进行任何升级,也会遇到问题,因为负载均衡不会考虑到应用升级的问题。我们需要单独配置每个负载均衡器,然后升级该均衡器所服务的容器。想象一下,当你有 20 个负载均衡器和每周 5 或 6 个小的更新时,你将不得不进行大量的手工劳动。
我们需要的是一种可以一次性将变更传递给所有受控容器的方法,同时也需要一种可以轻松地调度可用容器的方法,这个过程还必须要是自动化的,这正是 Kubernetes 所做的事情。
接下来,我们将探讨 Kubernetes 究竟是如何工作的,它的各种组件和服务,以及更多关于如何使用 Kubernetes 来编排、管理和监控容器化环境。为了简单起见,假设我们使用的是 Docker 容器,尽管如前所述,Kubernetes 除了支持 Docker 之外,还支持其他几种容器平台。
首先,最重要的是你需要认识到 Kubernetes 利用了 “期望状态” 原则。就是说,你定义了组件的期望状态,而 Kubernetes 要将它们始终调整到这个状态。
例如,你想让你的 Web 服务器始终运行在 4 个容器中,以达到负载均衡的目的,你的数据库复制到 3 个不同的容器中,以达到冗余的目的。这就是你想要的状态。如果这 7 个容器中的任何一个出现故障,Kubernetes 引擎会检测到这一点,并自动创建出一个新的容器,以确保维持所需的状态。
现在我们来定义一些 Kubernetes 的重要组件。
当你第一次设置 Kubernetes 时,你会创建一个集群。所有其他组件都是集群的一部分。你也可以创建多个虚拟集群,称为命名空间 (namespace),它们是同一个物理集群的一部分。这与你可以在同一物理服务器上创建多个虚拟机的方式非常相似。如果你不需要,也没有明确定义的命名空间,那么你的集群将在始终存在的默认命名空间中创建。
Kubernetes 运行在节点 (node) 上,节点是集群中的单个机器。如果你有自己的硬件,节点可能对应于物理机器,但更可能对应于在云中运行的虚拟机。节点是部署你的应用或服务的地方,是 Kubernetes 工作的地方。有 2 种类型的节点 ——master 节点和 worker 节点,所以说 Kubernetes 是主从结构的。
主节点是一个控制其他所有节点的特殊节点。一方面,它和集群中的任何其他节点一样,这意味着它只是另一台机器或虚拟机。另一方面,它运行着控制集群其他部分的软件。它向集群中的所有其他节点发送消息,将工作分配给它们,工作节点向主节点上的 API Server 汇报。
Master 节点本身也包含一个名为 API Server 的组件。这个 API 是节点与控制平面通信的唯一端点。API Server 至关重要,因为这是 worker 节点和 master 节点就 pod、deployment 和所有其他 Kubernetes API 对象的状态进行通信的点。
Woker 节点是 Kubernetes 中真正干活的节点。当你在应用中部署容器或 pod(稍后定义)时,其实是在将它们部署到 worker 节点上运行。Worker 节点托管和运行一个或多个容器的资源。
Kubernetes 中的逻辑而非物理的工作单位称为 pod。一个 pod 类似于 Docker 中的容器。记得我们在前面讲到,容器可以让你创建独立、隔离的工作单元,可以独立运行。但是要创建复杂的应用程序,比如 Web 服务器,你经常需要结合多个容器,然后在一个 pod 中一起运行和管理。这就是 pod 的设计目的 —— 一个 pod 允许你把多个容器,并指定它们如何组合在一起来创建应用程序。而这也进一步明确了 Docker 和 Kubernetes 之间的关系 —— 一个 Kubernetes pod 通常包含一个或多个 Docker 容器,所有的容器都作为一个单元来管理。
Kubernetes 中的 service 是一组逻辑上的 pod。把一个 service 看成是一个 pod 的逻辑分组,它提供了一个单一的 IP 地址和 DNS 名称,你可以通过它访问服务内的所有 pod。有了服务,就可以非常容易地设置和管理负载均衡,当你需要扩展 Kubernetes pod 时,这对你有很大的帮助,我们很快就会看到。
ReplicationController 或 ReplicaSet 是 Kubernetes 的另一个关键功能。它是负责实际管理 pod 生命周期的组件 —— 当收到指令时或 pod 离线或意外停止时启动 pod,也会在收到指示时杀死 pod,也许是因为用户负载减少。所以换句话说,ReplicationController 有助于实现我们所期望的指定运行的 pod 数量的状态。
kubectl 是一个命令行工具,用于与 Kubernetes 集群和其中的 pod 通信。使用它你可以查看集群的状态,列出集群中的所有 pod,进入 pod 中执行命令等。你还可以使用 YAML 文件定义资源对象,然后使用 kubectl 将其应用到集群中。
请记住,我们使用 Kubernetes 而不是直接使用 Docker 的原因之一,是因为 Kubernetes 能够自动扩展应用实例的数量以满足工作负载的需求。
自动缩放是通过集群设置来实现的,当服务需求增加时,增加节点数量,当需求减少时,则减少节点数量。但也要记住,节点是 “物理” 结构 —— 我们把 “物理” 放在引号里,因为要记住,很多时候,它们实际上是虚拟机。
无论如何,节点是物理机器的事实意味着我们的云平台必须允许 Kubernetes 引擎创建新机器。各种云提供商对 Kubernetes 支持基本都满足这一点。
我们再继续说一些概念,这次是和网络有关的。