Kubernetes现已成为在私有云、公共云和混合云环境中大规模部署容器化应用程序的事实上的标准。最大的公共云平台AWS、Google Cloud、Azure、IBM Cloud和Oracle Cloud现在都为 Kubernetes 提供托管服务。几年前,RedHat 用 Kubernetes 完全取代了 OpenShift 实施,并与 Kubernetes 社区合作实施下一代容器平台。在 Kubernetes 流行后不久,Mesosphere 将 Kubernetes 的关键功能(例如容器分组、覆盖网络、第 4 层路由、机密等)融入到其容器平台 DC/OS 中。DC/OS 还将Kubernetes 与 Marathon 一起集成为容器编排器。Pivotal 最近推出了基于 Kubernetes 的Pivotal 容器服务 (PKS),用于在 Pivotal Cloud Foundry 上部署第三方服务,截至目前,还有许多其他组织和技术提供商正在快速适应它。
Kubernetes 始于 2014 年,拥有十多年在 Google与 Google 内部容器集群管理器 Borg 和 Omega 一起运行生产工作负载的经验。在我看来,它使得微服务、无服务器功能、服务网格和事件驱动应用程序等新兴软件架构模式的适应变得更加容易,并为整个云原生生态系统铺平了道路。最重要的是,其与云无关的设计使容器化应用程序可以在任何平台上运行,而无需对应用程序代码进行任何更改。如今,大型企业部署可以使用 Kubernetes 生态系统,而任何中小型企业从长远来看也可以节省大量的基础设施和维护成本。在本文中,我将解释 Kubernetes 的高层架构、其应用程序部署模型、服务发现和负载均衡、内部/外部路由分离、持久卷的使用、在节点上部署守护进程、部署有状态分布式系统、运行后台作业、部署数据库、配置管理、凭据管理、推出更新、自动缩放和包管理。
库伯内特斯架构
图 1:Kubernetes 架构
这个无可挑剔的集群管理器所采取的基本设计决策之一是它能够部署在虚拟机上运行的现有应用程序,而无需对应用程序代码进行任何更改。从高层来看,任何在虚拟机上运行的应用程序都可以通过简单地容器化其组件来部署在 Kubernetes 上。这是通过其核心功能实现的:容器分组、容器编排、覆盖网络、基于第 4 层虚拟 IP 的路由系统的容器到容器路由、服务发现、支持运行守护程序、部署有状态应用程序组件,最重要的是,能够扩展容器编排器以支持复杂的编排需求。
2023 年 Kubernetes 在企业中的前景
我们的报告包括对新兴 Kubernetes 趋势及其核心用途的研究,以及有关 K8s 安全性、Kubernetes 的 AI/ML、FinOps 和成本管理等的文章。
在非常高的层面上,Kubernetes 提供了一组动态可扩展的主机来使用容器运行工作负载,并使用一组称为 master 的管理主机来提供用于管理整个容器基础设施的 API。工作负载可能包括长时间运行的服务、批处理作业和容器主机特定的守护进程。所有容器主机都使用覆盖网络连接在一起,以提供容器到容器的路由。部署在 Kubernetes 上的应用程序可以在集群网络中动态发现,并且可以使用传统的负载均衡器公开到外部网络。集群管理器的状态存储在高度分布式的键/值存储中,该存储在主实例中运行。
Kubernetes 调度程序将始终确保每个应用程序组件都经过健康检查,提供高可用性,当副本数量设置为多个时,每个实例都会调度到多个主机中,如果其中一台主机不可用,则所有容器都将被调度。在该主机中运行的任务将被调度到任何剩余主机中。Kubernetes 提供的一项令人着迷的功能是两级自动缩放。首先,它提供了使用名为 Horizontal Pod Autoscaler 的资源自动缩放容器的能力,该资源可以监视资源消耗并相应地缩放所需的容器数量。其次,它可以根据资源需求通过添加和删除主机来扩展容器集群本身。此外,随着集群联合功能的引入,它甚至可以使用单个 API 端点管理可能跨越多个数据中心的 Kubernetes 集群集合。
这只是 Kubernetes 提供的开箱即用功能的一瞥。在接下来的几节中,我们将介绍其核心功能,并解释如何设计要立即部署在其上的软件应用程序。
应用部署模型
图 2:Kubernetes 应用程序部署模型
上图展示了 Kubernetes 上的高级应用程序部署模型。它使用名为ReplicaSet的资源来编排容器。ReplicaSet 可以被视为基于 YAML 或 JSON 的元数据文件,它定义了创建和复制所需的容器映像、端口、副本数量、激活健康检查、活动健康检查、环境变量、卷挂载以及安全规则。管理容器。容器始终在 Kubernetes 上创建为称为Pod 的组,Pod 是 Kubernetes 元数据定义或资源。每个 Pod 都允许使用 Linux 命名空间、cgroup 和其他内核功能在容器之间共享文件系统、网络接口和操作系统用户。可以 由另一个称为部署ReplicaSets 的高级资源进行管理,用于提供推出更新和处理回滚的功能。
通过执行简单的 CLI 命令,可以使用部署定义将容器化应用程序部署在 Kubernetes 上,如下所示:
1
kubectl run <应用程序名称> --image = <容器映像> --port = <端口号>
执行上述 CLI 命令后,它将使用给定的容器映像创建部署定义、副本集和 pod;使用应用程序名称添加选择器标签。根据当前的设计,由此创建的每个 pod 将有两个容器,一个用于给定的应用程序组件,另一个称为暂停,用于连接网络接口。
服务发现和负载平衡
图 3:Kubernetes 服务发现和负载均衡模型
Kubernetes 的主要功能之一是其使用 SkyDNS 和基于第 4 层虚拟 IP 的路由系统提供的服务发现和内部路由模型。这些功能为使用服务的应用程序请求提供内部路由。通过副本集创建的一组 Pod 可以使用集群网络内的服务进行负载平衡。服务使用选择器标签连接到 Pod。每个服务都将被分配一个唯一的 IP 地址、一个从其名称派生的主机名,并以循环方式在 Pod 之间路由请求。这些服务甚至将为可能需要会话关联的应用程序提供基于 IP 哈希的路由机制。服务可以定义端口的集合,并且为给定服务定义的属性将以相同的方式应用于所有端口。因此,在仅给定端口需要会话关联性而所有其他端口都需要使用基于循环的路由的情况下,可能需要使用多个服务。
服务内部如何运作
图片标题
Kubernetes 服务是使用名为 kube-proxy 的组件来实现的。每个节点中运行一个 kube-proxy 实例,并提供三种代理模式:Userspace、iptables 和 IPVS。当前默认是 iptables。
在第一种代理模式(用户空间)中,kube-proxy 本身将充当代理服务器,并将 iptable 规则接受的请求委托给后端 pod。在这种模式下,kube-proxy 将在用户空间中运行,并向消息流添加额外的跃点。在 iptables 中,kube-proxy 将创建一组 iptable 规则,用于将来自客户端的传入请求直接转发到网络层后端 pod 的端口,而无需在中间添加额外的跃点。这种代理模式比第一种模式要快得多,因为它是在内核空间运行,并且中间没有添加额外的代理服务器。
第三种代理模式是在 Kubernetes v1.8 中添加的,它与第二种代理模式非常相似,它利用基于IPVS的虚拟服务器来路由请求,而不使用 iptable 规则。IPVS是基于Netfilter的Linux内核中提供的传输层负载均衡功能,提供了一系列负载均衡算法。使用 IPVS 而不是 iptables 的主要原因是使用 iptables 时同步代理规则的性能开销。当创建数千个服务时,更新 iptable 规则需要相当长的时间,而 IPVS 则需要几毫秒。此外,IPVS 使用哈希表通过 iptables 的顺序扫描查找代理规则。关于IPVS代理模式介绍的更多信息可以参见华为在KubeCon 2017上所做的“ Scaling Kubernetes to Support 50,000 Services ”演讲。
内部/外部路由分离
图 5:Kubernetes 内部/外部路由分离
Kubernetes 服务可以通过两种主要方式暴露到外部网络。第一种是通过在节点上公开将流量转发到服务端口的动态端口来使用节点端口。第二种是使用通过入口控制器配置的负载均衡器,该控制器可以通过连接到同一覆盖网络将请求委托给服务。入口控制器是一个后台进程,可以在侦听Kubernetes API 的容器中运行,根据给定的一组入口动态配置和重新加载给定的负载均衡器。入口使用服务基于主机名和上下文路径定义路由规则。
一旦使用命令将应用程序部署在 Kubernetes 上kubectl run,就可以通过负载均衡器将其暴露给外部网络,如下所示:
1
kubectl 公开部署 <应用程序名称> --type = LoadBalancer --name = <服务名称>
上面的命令将创建一个负载均衡器类型的服务,并使用创建 Pod 时创建的相同选择器标签将其映射到 Pod。因此,根据 Kubernetes 集群的配置方式,将在底层基础设施上创建负载均衡器服务,以便通过该服务或直接路由给定 Pod 的请求。
持久卷的使用
图片标题
需要在文件系统上持久保存数据的应用程序可以使用卷将存储设备安装到临时容器,类似于卷与虚拟机的使用方式。Kubernetes 通过引入称为持久卷声明 (PVC) 的中间资源,将物理存储设备与容器松散耦合,正确设计了这一概念。PVC 定义磁盘大小、磁盘类型(ReadWriteOnce、ReadOnlyMany、ReadWriteMany),并将存储设备动态链接到针对 Pod 定义的卷。绑定过程可以使用 PV 以静态方式完成,也可以使用持久存储提供程序动态完成。在这两种方法中,卷将一对一链接到 PV,并且根据配置,即使 Pod 终止,也将保留给定的数据。根据使用的磁盘类型,多个 Pod 将能够连接到同一磁盘并进行读/写。
支持ReadWriteOnce的磁盘只能连接到单个 pod,并且无法同时在多个 pod 之间共享。但是,支持ReadOnlyMany的磁盘将能够以只读模式同时在多个 Pod 之间共享。相比之下,顾名思义,支持ReadWriteMany的磁盘可以连接到多个 pod,以读写模式共享数据。Kubernetes 提供了一系列卷插件,用于支持公共云平台上可用的存储服务,例如 AWS EBS、GCE 持久磁盘、Azure File、Azure Disk 以及许多其他知名存储系统(例如 NFS、Glusterfs、Cinder 等)。
在节点上部署守护进程
图 7:在 Kubernetes 节点上部署守护进程
Kubernetes 提供了一个名为 DaemonSets 的资源,用于在每个 Kubernetes 节点中将 pod 的副本作为守护进程运行。DaemonSets 的一些用例如下:
集群存储守护进程(例如)glusterd,ceph部署在每个节点上以提供持久存储。
节点监控守护进程(例如Prometheus Node Exporter)在每个节点上运行,用于监控容器主机。
日志收集守护进程,例如fluentd或logstash在每个节点上运行,用于收集容器和 Kubernetes 组件日志。
在节点集合上运行的入口控制器 Pod,用于提供外部路由。
部署有状态分布式系统
图片标题
容器化应用程序最困难的任务之一是设计有状态分布式组件的部署架构的过程。无状态组件可以很容易地容器化,因为它们可能没有预定义的启动顺序、集群要求、点对点 TCP 连接、唯一的网络标识符、优雅的启动和终止要求等。诸如数据库、大数据分析系统、分布式密钥/价值存储和消息代理可能具有复杂的分布式架构,可能需要上述功能。Kubernetes 引入了 StatefulSets 资源来支持这种复杂的需求。
从高层次上看,StatefulSet 与 ReplicaSet 类似,只不过它提供了处理 Pod 启动顺序的能力,唯一标识每个 Pod 以保留其状态,同时提供以下特性:
稳定、唯一的网络标识符。
稳定、持久的存储。
有序、优雅的部署和扩展。
有序、优雅的删除和终止。
有序、自动滚动更新
稳定是指在 pod 重新调度过程中保留网络标识符和持久存储。唯一的网络标识符是通过使用无头服务提供的,如上图所示。Kubernetes 提供了 StatefulSet 的示例,用于以分布式方式部署Cassandra和Zookeeper 。
运行后台作业
除了 ReplicaSets 和 StatefulSets 之外,Kubernetes 还提供了两个额外的控制器用于在后台运行工作负载,称为Jobs和CronJobs。作业和 CronJobs 之间的区别在于,作业执行一次并终止,而 CronJobs 则按照给定的时间间隔定期执行,类似于标准 Linux cron 作业。
部署数据库
在容器平台上部署数据库以供生产使用比部署应用程序稍微困难一些,因为它们需要集群、点对点连接、复制、着色、管理备份等。如前所述,StatefulSet 是专门为支持此类复杂的而设计的。目前,在 Kubernetes 上运行PostgreSQL和MongoDB集群有几个选项。YouTube 的数据库集群系统Vitess现在是 CNCF 项目,将是在 Kubernetes 上大规模运行 MySQL 的绝佳选择。最好指出的是,这些选项仍处于非常早期的阶段,如果现有的生产级数据库系统可在给定的基础设施上使用,例如 AWS 上的 RDS、GCP 上的 Cloud SQL 或本地数据库集群,那么考虑到安装复杂性和维护开销,可能最好选择这些选项之一。
配置管理
容器通常使用环境变量来参数化其运行时配置。然而,典型的企业应用程序使用大量的配置文件来提供给定部署所需的静态配置。Kubernetes 提供了一种使用名为 ConfigMaps 的简单资源来管理此类配置文件的绝佳方法,而无需将它们捆绑到容器镜像中。可以使用以下 CLI 命令使用目录、文件或文字值创建 ConfigMap: