Kubernetes概念及核心对象

想学习更多相关知识请看博主的个人博客地址:https://blog.huli.com/ https://blog.huli.com/
1.kubernetes快速入门 Kubernetes 集群将所有节点上的资源都整合到一个大的虚拟资源池里,以代替一个个单独的服务器,而后开放诸如 CPU、内存和 I/O 这些基本资源用于运行其基本单元 —— Pod 资源对象。Pod 的容器中运行着隔离的任务单元,它们以 Pod 为原子单位,并根据其资源需求聪虚拟资源池中为其动态分配资源。若可以将整个集群类比为一台传统的服务器,那么 Kubernetes(Master)就好比是操作系统内核,其主要职责在于抽象资源并调度任务,而 Pod 资源对象就是那些运行于用户空间中的进程。于是,传统意义上的向单节点或集群直接部署、配置应用的模型日渐式微,取而代之的是向 Kubernetes 的 API Server 提交运行 Pod 对象。
API Server 是负责接受并相应客户端提交任务的接口,用户可使用诸如 CLI 工具(如 kubectl)、UI 工具(如 Dashboard)或程序代码(客户端开发库)发起请求,其中,kubectl 是最为常用的交互式命令行工具。快速了解 kubernetes 的办法之一就是部署一个测试集群,并尝试测试使用他的各项基本功能。本章在简单介绍核心资源对象后将尝试使用 kubectl 创建 Deployment 和 Service 资源部署并暴露一个 Web 应用,以便读者快速了解如何在 Kubernetes 系统上运行应用程序的核心任务。
2.1 Kubernetes 的核心对象 2.1.1 Pod 资源对象 Pod 资源对象是一种集合了一到多个应用容器、存储资源、专用IP及支撑容器运行的其他选项的逻辑组件,如下图所示。换言之,Pod 代表着 Kubernetes 的部署单元及原子运行单元,即一个应用程序的单一运行实例,它通常由共享资源且关系紧密的一个或多个应用容器组成。
Kubernetes概念及核心对象
文章图片

Kubernetes 的网络模型要求其各 Pod 对象的 IP 地址位于同一网络平面内(同一 IP 网段),各 Pod 之间可使用其 IP 地址直接进行通信,无论他们运行于集群内的哪个工作节点之上,这些 Pod 对象都像是运行于同一局域网中的多个主机。
读者可以将每个 Pod 对象想象成一个逻辑主机,它类似于现实世界中的物理主机或VM(Virtual Machine),运行于同一个 Pod 对象中的多个进程也类似于物理机或 VM 上独立运行的进程。不过,Pod 对象中的各进程均运行于彼此隔离的容器中,并于各容器间共享两种关键资源:网络和存储卷。

  • 网络(networking):每个 Pod 对象都会被分配一个集群内专用的 IP 地址,也称为 Pod IP,同一 Pod 内部的所有容器共享 Pod 对象的 Network 和 UTS 名称空间,其中包括主机名、IP 地址和端口等。因此,这些容器间的通信就可以基于本地回环接口 lo 进行,而与 Pod 外的其他组件的通信则需要使用 Service 资源对象的 ClusterIP 及其相应的端口完成。
  • 存储卷(volume): 用户可以为 Pod 对象配置一组“存储卷”资源,这些资源可以共享给其内部的所有容器使用,从而完成容器间数据的共享。存储卷还可以确保在容器终止后被重启,甚至是被删除后也能确保数据不会丢失,从而保证了生命周期内的 Pod 对象数据的持久化存储。
一个 Pod 对象代表某个应用程序的一个特定实例,如果需要扩展应用程序,则意味着为此应用程序同时创建多个 Pod 实例,每个实例均代表应用程序的一个运行的“副本”(replica)。这些副本化的 Pod 对象的创建和管理通常由一组称之为“控制器”(Controller)的对象实现,例如,Deployment 控制器对象。
创建 Pod 时,还可以使用 Pod Preset 对象为 Pod 注入特定的信息,如 ConfigMap、Secret、存储卷、卷挂载和环境变量等。有了 Pod Preset 对象,Pod 模版的创建者就无须为每个模版显示提供所有信息,因此,也就无须事先了解需要配置的每个应用的细节即可完成模版定义。这些内容将在后面的章节中予以介绍。
基于期望的目标状态和各节点的资源可用性,Master 会将 Pod 对象调度至某选定的工作节点运行,工作节点于指向的镜像仓库(image registry)下载镜像,并于本地的容器运行时环境中启动容器。Master 会将整个集群的状态保存与 etcd 中,并通过 API Server 共享给集群的各个组件及客户端。
2.1.2 Controller Kubernetes 集群的设计中,Pod 是有生命周期的对象。用户通过手工创建或由 Controller(控制器)直接创建的 Pod 对象会被“调度器”(Scheduler)调度至集群中的某工作节点运行,待到容器应用进程运行结束之后正常终止,随后就会被删除。另外,节点资源耗尽或故障也会导致 Pod 对象被回收。
但 Pod 对象本身并不具有“自愈”功能,若是因为工作节点甚至是调度器自身导致了运行失败,那么它将会被删除;同样,资源耗尽或节点故障导致的回收操作也会删除相关的 Pod 对象。在设计上,Kubernetes 使用“控制器”实现对一次性的(用后即弃)Pod 对象的管理操作, 例如,要确保部署的应用程序的 Pod 副本数量严格反应用户期望的数目,以及基于 Pod 模版来重建 Pod 对象等,从而实现 Pod 对象的扩缩容、滚动更新和自愈能力等。例如,某节点发生故障时,相关的控制器会将此节点上运行的 Pod 对象重新调度到其他节点上进行重建。
控制器本身也是一种资源类型,它有着多种实现,其中与工作负载相关的实现 Reqlication Controller、Deployment、StatefulSet、DeamonSet 和 Jobs 等,也可统称它们为 Pod 控制器。如下图中的 Doployment 就是这类控制器的代表实现,是目前最常用的管理无状态应用的 Pod 控制器。
Pod 控制器的定义通常由期望的副本数量、Pod 模版和标签选择器(Label Selector)组成。Pod 控制器会根据标签选择器对 Pod 对象的标签进行匹配检查,所有满足选择条件的 Pod 对象都将受控于当前控制器并计入其副本总数,并确保此数目能够精确反映期望的副本数。
需要注意的是,在实际的应用场景中,在接受到请求流量负载显著低于或接近于已有 Pod 副本的整体承载能力时,用户需要手动修改 Pod 控制器中的期望副本数量以实现应用规模的扩容或缩容。不过,若集群中部署了 HeapSter 或 Prometheus 一类的资源指标监控附件时,用户还可以使用“HorizontalPodAutoscaler”(HPA) 计算出合适的 Pod 副本数量,并自动修改 Pod 控制器中期望的副本数以实现应用规模的动态伸缩,提高集群资源利用率,如下图所示。
Kubernetes 集群中的每个节点都运行着 cAdvisor 以收集容器及节点 CPU、内存及磁盘资源的利用率指标数据,这些统计数据由 Heapster 聚合后可通过 API Server 访问。HorizontalPodAutoscaler 基于这些统计数据监控容器健康状态并做出扩展决策。
Kubernetes概念及核心对象
文章图片

Kubernetes概念及核心对象
文章图片

2.1.3 Service 尽管 Pod 对象可以拥有 IP 地址,但此地址无法确保在 Pod 对象重启或被重建后保持不变,这会为集群中的 Pod 应用间依赖关系的维护带来麻烦:前端 Pod 应用(依赖方)无法基于固定地址持续跟踪后端 Pod 应用(被依赖方)。于是,Service 资源被用于在被访问的 Pod 对象中添加一个有着固定 IP 地址的中间层,客户端向此地址发起访问请求后由相关的 Service 资源调度并代理至后端的 Pod 对象。
换言之,Service 是“微服务”的一种实现,事实上它是一种抽象:通过规则定义出由多个 Pod 对象组合而成的逻辑集合,并附带访问这组 Pod 对象的策略。Service 对象挑选,关联 Pod 对象的方式和 Pod 控制器一样,都是要基于 Label Selector 进行定义,其示意图如下图所示。
【Kubernetes概念及核心对象】![Service 对象功能示意图][1]
Service IP 是一种虚拟 IP,也称为 Cluster IP,它专用于集群内通信,通常使用专用的地址段,如 “10.96.0.0/12” 网络,各 Service 对象的 IP 地址在此范围内由系统动态分配。
集群内的 Pod 对象可直接请求此类的 Cluster IP,例如,上图中来自 pod client 的访问请求即可以 Service 的 Cluster IP 作为目标地址,但集群网络属于私有网络地址,它们仅在集群内部可达。将集群外部的访问流量引入集群内部的常用方法是通过节点网络进行,实现方法是通过工作节点的 IP 地址和某端口(NodePort)接入请求并将其代理至相应的 Service 对象的 Cluster IP 上的服务端口,而后由 Service 对象的 Cluster IP 上的服务端口,而后由 Service 对象将请求代理至后端的 Pod 对象的 Pod IP 及应用程序监听的端口。因此,诸如上图中 External Clients 这种来自集群外部的客户端无法直接请求此 Service 提供的服务,而是需要事先经由某一个工作节点(如 Node Y)的 IP 地址进行,这类请求需要两次转发才能到达目标 Pod 对象,因此在通信效率上必然存在负面影响。
事实上,NodePort 会部署于集群中的每一个节点,这就意味着,集群外部的客户端通过任何一个工作节点的 IP 地址来访问定义好的 NodePort 都可以到达相应的 Service 对象。此种场景中,如果存在集群外部的一个负载均衡器,即可将用户请求负载均衡至集群中的部分或者所有节点。这是一种称为 “LoadBalancer” 类型的 Service,它通常是由 Cloud Provider 自动创建并提供的软件负载均衡器,不过,也可以是由管理员手工配置的诸如 F5 Big-IP 一类的硬件设备。
简单来说,Service 主要由三种常用类型:第一种是仅用与集群内部通信的 ClusterIP 类型:第二种是接入集群外部请求的 NodePort 类型,它工作于每个节点的主机 IP 之上;第三种是 LoadBalacer 类型,它可以把外部请求负载均衡至多个 Node 的主机IP的 NodePort 之上。此三种类型中,每一种都以前一种为基础才能实现,而且第三种类型中的 LoadBalacer 需要协同集群外部的组建才能实现,并且此外部组建并不接受 Kubernetes 的管理。
Kubernetes概念及核心对象
文章图片

2.1.4 部署应用程序的主体过程 Docker 容器技术使得部署应用程序从传统的安装、配置、启动应用程序的方式转为于容器引擎上基于镜像创建和运行容器,而 Kubernetes 又使得创建和运行容器的操作不必再关注其位置,并在一定程度上赋予了它动态扩缩容及自愈的能力,从而让用户从主机、系统及应用程序的维护工作中解脱出来。
用到某应用程序时,用户只需要向 API Server 请求创建一个 Pod 控制器,由控制器根据镜像等信息向 API Server 请求创建出一定数量的 Pod 对象,并由 Master 之上的调度器指派至选定的工作节点以运行容器化应用。此外,用户一般还需要创建一个具体的 Service 对象以便为这些 Pod 对象建立起一个固定的访问入口,从而使得其客户端能够通过其服务名称或 ClusterIP 进行访问,如下图所示:
Kubernetes概念及核心对象
文章图片

API Server 的常用客户端程序是 Kubernetes 系统自带的命令行工具 kubectl,它通过一众子命令用于实现集群及相关资源对象的管理操作,并支持直接命令式、命令式配置清单及声明式配置清单等三种操作方式,特性丰富且功能强大。而需作为集群附件额外部署的 Dashboard 则提供了基于 Web 界面的图形客户端,它是一个通用目的的管理工具,与 Kubernetes 紧密集成,支持多级别用户授权,能在一定程度上替代 kubectl 的大多数操作。
本章后面的篇幅将介绍在部署完成的 Kubernetes 集群环境众如何快速部署如图所示的示例应用程序,并简单说明如何完成对容器化应用的访问,以及如何进行应用规模的动态伸缩,并借此让读者了解 kubectl 命令的基本功能和用法。
3.Kubernetes应用管理模型 下图展示了Kubernetes的应用管理模型:
Kubernetes概念及核心对象
文章图片

Pod是Kubernetes中的最小调度资源。Pod中会包含一组容器,它们一起工作,并且对外提供一个(或者一组)功能。对于这组容器而言它们共享相同的网络和存储资源,因此它们之间可以直接通过本地网络(127.0.0.1)进行访问。当Pod被创建时,调度器(kube-schedule)会从集群中找到满足条件的节点运行它。
如果部署应用程序时,需要启动多个实例(副本),则需要使用到控制器(Controller)。用户可以在Controller定义Pod的调度规则、运行的副本数量以及升级策略等等信息,当某些Pod发生故障之后,Controller会尝试自动修复,直到Pod的运行状态满足Controller中定义的预期状态为止。Kubernetes中提供了多种Controller的实现,包括:Deployment(无状态应用)、StatefulSet(有状态应用)、Daemonset(守护模式)等,以支持不同类型应用的部署和调度模式。
通过Controller和Pod我们定义了应用程序是如何运行的,接下来需要解决如何使用这些部署在Kubernetes集群中的应用。Kubernetes将这一问题划分为两个问题域,第一,集群内的应用如何通信。第二,外部的用户如何访问部署在集群内的应用?
对于第一个问题,在Kubernetes中通过定义Service(服务)来解决。Service在Kubernetes集群内扮演了服务发现和负载均衡的作用。在Kubernetes下部署的Pod实例都会包含一组描述自身信息的label,而创建Service,可以声明一个Selector(标签选择器)。Service通过Selector,找到匹配标签规则的Pod实例,并将对Service的请求转发到代理的Pod中。Service创建完成后,集群内的应用就可以通过使用Service的名称作为DNS域名进行相互访问。
而对于第二个问题,Kubernetes中定义了单独的资源Ingress(入口)。Ingress是一个工作在7层的负载均衡器,其负责代理外部进入集群内的请求,并将流量转发到对应的服务中。
最后,对于同一个Kubernetes集群其可能被多个组织使用,为了隔离这些不同组织创建的应用程序,Kubernetes定义了Namespace(命名空间)对资源进行隔离。
4. Kubernetes架构模型 为了能够更好的理解Kubernetes下的监控体系,我们需要了解Kubernetes的基本架构,如下所示,是Kubernetes的架构示意图:
Kubernetes概念及核心对象
文章图片

Kubernetes的核心组件主要由两部分组成:Master组件和Node组件,其中Matser组件提供了集群层面的管理功能,它们负责响应用户请求并且对集群资源进行统一的调度和管理。Node组件会运行在集群的所有节点上,它们负责管理和维护节点中运行的Pod,为Kubernetes集群提供运行时环境。
Master组件主要包括:
  • kube-apiserver:负责对外暴露Kubernetes API;
  • etcd:用于存储Kubernetes集群的所有数据;
  • kube-scheduler: 负责为新创建的Pod选择可供其运行的节点;
  • kube-controller-manager: 包含Node Controller,Deployment Controller,Endpoint Controller等等,通过与apiserver交互使相应的资源达到预期状态。
Node组件主要包括:
  • kubelet:负责维护和管理节点上Pod的运行状态;
  • kube-proxy:负责维护主机上的网络规则以及转发。
  • Container Runtime:如Docker,rkt,runc等提供容器运行时环境。

    推荐阅读