![一文带你理解14个K8S必备基础概念](https://static001.infoq.cn/resource/image/a3/9a/a352b43512a37c6c4c0644cb29cf1e9a.jpg)
在微服务、云计算和无服务架构时代,理解 Kubernetes 并且知道如何使用它是十分有用的。然而,官方的 Kubernetes 文档对于刚开始接触云计算的用户来说有些难以理解。在本文中,我们将了解在 Kubernetes 中的重要概念。在之后的系列文章中,我们还将了解如何写配置文件、使用 Helm 作为软件包管理器、创建一个云基础架构、使用 Kubernetes 轻松编排服务并且创建一个 CI/CD 流水线来自动化整个工作流。有了这些信息,你可以启动任意种类的项目,并且创建一个强大的基础架构。
首先,我们知道使用容器有多种好处,从部署速度的提升到大规模一致性交付等。即使如此,容器也并非一切问题的解决之道,因为使用容器会带来一定的开销,比如维护一个容器编排层。所以,你需要在项目开始的时候分析成本/效益。
现在,让我们开启 Kubernetes 世界之旅吧!
Kubernetes 硬件结构
节点
节点是 Kubernetes 中的 worker 机器,可以是任何具有 CPU 和 RAM 的设备。例如,智能手表、智能手机或者笔记本,甚至是树莓派都可以成为一个节点。当我们使用云时,节点就是一个虚拟机(VM)。所以,简单来说,节点是单一设备的抽象概念。这种抽象的好处是,我们不需要知道底层的硬件结构。我们只使用节点,这样一来,我们的基础设施就独立于平台。
![](https://static001.geekbang.org/infoq/16/16dbdcef75bc8a329aecb6b681706f45.jpeg)
集群
一个集群是一组节点。当你将程序部署到集群上时,它会自动将工作分配到各个节点。如果需要更多的资源(简单来讲,我们需要更多钱),那么集群中将会加入新的节点并且将会自动重新分配工作。
我们在集群上运行我们的代码,但我们不需要关心具体在哪个节点上运行了哪部分的代码。工作的分配是自动的。
![](https://static001.geekbang.org/infoq/d6/d6a6f5ec95d3517f23b5b48bdbd45044.jpeg)
持久卷(persistent volumes)
因为我们的代码可以从一个节点转移到另一个节点(例如,某个节点没有足够的内存,那么工作将会被重新调度到另一个拥有充足内存的节点上),所以在节点上保存数据容易丢失。如果我们想要永久保存我们的数据,我们应该使用持久卷。持久卷有点类似外部的硬盘,你可以将它插入并在上面保存你的数据。
Google 开发的 Kubernetes 是一个无状态应用程序的平台,其持久性数据存储在其他地方。当这一项目发展成熟之后,许多企业想要在有状态应用程序中使用它,所以开发人员需要添加持久卷管理。如同早期的虚拟化技术,数据库 server 通常情况下并不是首要迁移到新架构上去的 server。这是因为数据库是许多应用程序的核心,并且可能包含很多重要信息,所以本地数据库系统在虚拟机或物理机中通常规模很大。
所以,问题是,我们应该什么时候开始使用持久卷?要回答这个问题,首先,我们应该理解数据库应用的不同类型。
我们将数据管理解决方案分为以下两类:
垂直伸缩——包括传统的 RDMS 解决方案,例如 MySQL、PostgreSQL 以及 SQL Server
水平伸缩——包括“NoSQL”解决方案,例如 ElasticSearch 或基于 Hadoop 的解决方案
垂直伸缩解决方案(如 MySQL、PostgreSQL 以及 Microsoft SQL)不应该应用在容器内。这些数据库平台要求高 I/O、共享磁盘以及 block 存储等,并且无法处理集群内的节点丢失,但这一情况常常会发生在基于容器的生态系统内。
对于水平伸缩应用程序(如 Elastic、Cassanda、Kafka 等)可以使用容器。他们能够承受数据库集群内的节点丢失以及数据库应用可以自行恢复均衡。
通常情况下,你应该容器化分布式数据库,从而利用冗余的存储技术并且能够处理数据库集群内的节点丢失(ElasticSearch 是一个很好的例子)。
Kubernetes 软件组件
容器
现代软件开发的目标之一是保证各类应用程序在相同的主机或集群上可以彼此隔离。虚拟机是解决该问题的一个方案。但虚拟机需要他们自己的操作系统,所以他们的规模通常是千兆字节。
容器则恰恰相反,它可以隔离应用程序的执行环境但共享底层操作系统。所以,容器就像一个盒子,我们可以在其中保存一切运行应用程序所需要的:代码、运行时、系统工具、系统仓库、设置等。它们通常仅需要几兆字节即可运行,远远少于虚拟机所需资源,并且可以立即启动。
Pods
Pod 是一组容器。在 Kubernetes 中,最小的单位是 Pod。一个 pod 可以包含多个容器,但通常情况下我们在每个 pod 中仅使用一个容器,因为在 Kubernetes 中最小复制单位是 pod。如果我们想要为每个容器单独扩容,我们添加一个容器到 Pod 中即可。
![](https://static001.geekbang.org/infoq/96/96167f024a7bfc0606d526440baaaa3e.jpeg)
Deployments
Deployment 的最初功能是为 pod 和 ReplicaSet(相同 Pod 在其中会被复制很多次)提供声明式更新。使用 deployment,我们可以指定有多少相同 pod 的副本应该随时运行。Deployment 类似于 pod 的管理器,它可以自动启动所需数量的 pod、监控 pod 并在出现故障时重新创建 Pod。Deployment 极其有用,因为你不需要单独创建和管理每个 pod。
我们通常为无状态应用程序使用 deployment。然而,你可以通过给他附加一个持久卷来残存 deployment 的状态并使其变得有状态。
Stateful Sets
StatefulSet 是 Kubernetes 中的一个新概念并且它是用于管理有状态应用的资源。它管理 deployment 和一组 pod 的扩展,并且确保这些 pod 的顺序以及独特性。它与 deployment 类似,唯一的区别是 deployment 创建一组任意名称的 pod,并且 pod 的顺序对它来说并不重要,而 StatefulSet 创建的 pod 都有独一无二的名称以及顺序。所以,如果你想为名为 example 的 pod 创建 3 个副本,那么 StatefulSet 将会创建为:example-0、example-1、example-2。因此,这一创建方式最重要的好处就是你可以通过 pod 的名称就了解大致的情况。
DaemonSets
DaemonSet 可以确保 pod 运行在集群的所有节点上。如果从集群中添加/移除了一个节点,DaemonSet 会自动添加/删除该 pod。这对于监控以及日志十分重要,因为你可以监控每个节点并且不需要手动监控集群。
Services
Deployment 负责保持一组 Pod 处于运行状态,那么 Service 负责为一组 Pod 启动网络访问。Services 可以跨集群提供标准化的特性:负载均衡、应用间的服务发现以及零宕机应用程序 deployment。每个服务都有独一无二的 IP 地址以及 DNS 主机名称。可以为需要使用服务的应用程序手动配置相应的 IP 地址或主机名称,然后流量将会被负载均衡到正确的 pod。在外部流量的部分,我们会了解到更多的服务类型以及我们如何在内部服务和外部世界间进行通信。
![](https://static001.geekbang.org/infoq/f7/f7a0a532d779236736113f84c6f04ad9.jpeg)
ConfigMaps
如果你想部署到多个环境中,如 staging、开发环境和生产环境,bake 配置到应用程序中并不是一个好的操作,因为环境之间存在差异性。理想状况下,你会希望每个部署环境对应不同的配置。于是,ConfigMap 应运而生。ConfigMaps 可以让你从镜像中解耦配置工件以保持容器化应用程序的便携性。
外部流量
既然你已经了解运行在集群中的服务,那么你如何获取外部流量到你的集群中呢?有三种服务类型可以处理外部流量:ClusterIP、NodePort 以及 LoadBalancer。还有第 4 种解决方案:再添加一个抽象层,称为 Ingress Controller。
ClusterIP
ClusterIP 是 Kubernetes 中默认的服务类型,它可以让你在集群内部与其他服务进行通信。虽然 ClusterIP 不是为外部访问而设计的,但只要使用代理进行了一些改动,外部流量就可以访问我们的服务。不要在生产环境中采用这一解决方案,但可以用其来进行调试。声明为 ClusterIP 的服务不应该可以从外部直接可见。
NodePort
正如我们在本文第一部分中所看到的那样,pod 正在节点上运行。节点可以是各种不同的设备,如笔记本电脑或虚拟机(但在云端运行时)。每个节点有一个固定的 IP 地址。通过将一个服务声明为 NodePort,服务将会暴露节点 IP 地址,以便你可以从外部访问它。你可以在生产环境中使用 NodePort,但对于拥有许多服务的大型应用程序来说,手动管理所有不同的 IP 地址十分麻烦。
![](https://static001.geekbang.org/infoq/37/372c9cb16d02ef6541c9fc7146d2b046.jpeg)
LoadBalancer
声明一个 LoadBalancer 类型的服务,就可以使用云提供商的 LoadBalancer 向外部公开。外部 load balancer 如何将流量路由到服务 Pod 取决于集群提供程序。有了这个解决方案,你不必管理集群中每个节点的所有 IP 地址,但你将为每个服务配备一个 load balancer。缺点是,每个服务都有一个单独的 load balancer,你将按照 load balancer 实例付费。
![](https://static001.geekbang.org/infoq/a2/a2dfb578d2665b52b6e253f3915a1f2a.jpeg)
这一解决方案适用于生产环境,但它有些昂贵。接下来,我们来看看稍微便宜一些的解决方案。
Ingress
Ingress 不是一个服务,而是一个 API 对象,它可以管理外部对集群服务的访问。它作为反向代理和单一入口点(entry point)进入你的集群,将请求路由到不同的服务。我通常使用 NGINX Ingress Controller,它承担了反向代理,同时也作为 SSL 发挥作用。暴露 ingress 的最佳生产方案是使用一个 load balancer。
借助这一解决方案,你可以使用单个 load balancer 暴露任意数量的服务,所以你可以让费用保持在最低水平。
![](https://static001.geekbang.org/infoq/04/04e82c4c64a59bd5f187924a8aebb41c.jpeg)
总结
在本文中,我们了解了 Kubernetes 中的基本概念及其硬件架构。我们还讨论了不同的软件组件,如 Pod、Deployment、StatefulSets 以及 Services,并且了解了服务与外部世界之间如何进行通信。希望可以帮助你再次梳理 Kubernetes 里错综复杂的组件架构。
本文转载自:RancherLabs(ID:RancherLabs)
原文链接:一文带你理解14个K8S必备基础概念
评论 1 条评论