从两个角度理解Kubernetes基本概念

想要理解Kubernetes集群首先要思考两个问题:它是由什么组成的、它是怎样工作的。而想要搞清楚这两个问题我们可以在两个不同的层面寻找答案。

从物理层面看

从直观的层面来看,Kubernetes将多个物理机或虚拟机汇集到一个集群中,这个集群是配置Kubernetes的所有组件、功能和工作负载的物理平台。集群中存在两种不同的节点:Master和Node,这两种节点在集群中有不同的定位和分工。除了这两个节点外,Kubernetes集群还需要一些实现集群基本功能的组件,这就是add-ons。而当这些必要的组件都有了的时候,只需要给它们连上网络,Kubernetes集群就组成了。

Master

Master节点是集群的网关和中枢,负责为用户和客户暴露API、跟踪其他服务节点的健康状态、以最优方式调度各节点的工作负载、编排其他组件的通信等任务。Master节点是用户和客户间与集群的核心联结,并负责Kubernetes系统的大多数集中管控。

Master主要应当包含以下几个组件:

API Server(kube-apiserver)

API Server负责输出RESTful风格的Kubernetes API,它是发往集群的所有REST操作命令的接入点,并负责接收、校验并响应所有的REST请求,结果状态被持久化存储于etcd中。因此,API Server是整个集群的网关。

Cluster State Store(etcd)

Cluster State Store意为集群状态存储,Kubernetes集群的所有状态信息都需要持久存储于存储系统etcd中,etcd是由CoreOS基于Raft协议开发的分布式键值存储,可用于服务发现、共享配置和一致性保障(比如数据库主节点选择,分布式锁等)。其实etcd是独立的服务组件,并不隶属于Kubernetes集群。

Kubernetes之所以选择etcd来存储集群状态,是因为其不仅能够提供键值存储,还具有监听(watch)机制,可以监听和推送变更。在Kubernetes集群中,当etcd中存储的键值发生变化时会通知API Server,并通过watch API向客户端输出。基于这种watch机制,Kubernetes集群的各组件实现了高效协同。

Controller Manager(kube-controller-manager)

Controller Manager意为控制器管理器,在Kubernetes中,集群级别的大多数功能都是由几个被称为控制器的进程远程执行实现的,这些控制器进程被集成于kube-controller-manager守护进程中,它们的主要功能大致可以分为生命周期功能和API业务逻辑两类,具体如下。

  • 生命周期功能:包括Namespace创建和生命周期、Event垃圾回收、Pod终止相关的垃圾回收、级联垃圾回收和Node垃圾回收等;
  • API业务逻辑:有关具体业务的实现,例如,由ReplicaSet实现的Pod扩展。

Scheduler(kube-scheduler)

当API Server确认Pod对象的创建请求之后,就需要由Scheduler根据集群内各节点的可用资源状态和要运行容器的资源需求做出调度决策。

Node

Node是Kubernetes集群中的工作节点,负责接收来自Master节点的指令并根据指令创建或销毁相应的Pod。 在用户部署应用时,Master会基于调度算法将应用指派到某个或某几个特定的Node上,在集群加入或移除Node时,Master也会按照需要重新编排被影响的Pod,因此,用户无需关心应用究竟在哪个Node上运行。

Node主要应当包含以下几个组件:

kubelet

kubelet是Node的核心代理程序,它以守护进程的形式存在于每一个Node上。kubelet的主要作用有两方面,一方面kubelet会在API Server上注册当前的Node,通过cAdvisor监控容器和节点的资源占用情况,并且定期向Master汇报节点资源使用情况;另一方面kubelet从API Server接收关于Pod对象的配置信息并确保Pod的实际状态与目标状态一致。

容器运行环境

每个Node都要具备一种容器运行环境,它负责下载镜像并运行容器。kubelet并不依赖某种特定的容器环境,而是作为插件载入配置好的容器环境中,目前,Kubernetes支持的容器运行环境有Docker、RKT、cri-o和Fraki,未来还可能会加入更多的容器环境。

kube-proxy

kube-proxy同样作为守护进程运行在每一个Node上,它能够按需为Service资源对象生成iptables或ipvs规则,从而捕获访问当前Service的ClusterIP的流量并将其转发至对应的后端Pod对象上。

add-ons

所谓add-ons就是Kubernetes集群依赖的核心组件,它们通常由第三方提供,托管运行于Kubernetes集群之上,为Kubernetes提供某种核心功能的补充。下面列出几个常见的add-ons。

CoreDNS

CoreDNS可以看作是早期的kubeDNS的升级产物,在Kubernetes 1.1.1版本正式成为Kubernetes集群默认的服务注册和服务发现的动态域名解析服务。它在Kubernetes集群中调度运行提供DNS服务的Pod,其它Pod可以使用这些DNS服务Pod来解决主机名相关问题。

Kubernetes Dashboard

Kubernetes集群的管理和使用可以基于Web的UI界面,而基础的Kubernetes集群并没有提供这类服务,这时就要依靠dashboard组件。

Heapster

Heapster是一个针对容器和节点的性能监控与分析系统,它可以收集并解析多种指标数据,如资源利用率、生命周期事件等。当然自从Kubernetes 1.1.2版本起,Heapster已经被Prometheus结合其他组件所代替。

Ingress Controller

我们知道Service的负载均衡作用是基于传输层实现的,而Ingress是在应用层实现的HTTP负载均衡机制。Ingress和Service的其中一点区别在于,Ingress资源并不能直接实现“流量穿透”,它仅是一组路由规则的集合,这些规则需要通过Ingress Controller来发挥作用。目前可用的Ingress Controller有Nginx、Traefik、Envoy和HAProxy等。

网络模型

Kubernetes集群网络模型至少包含三个网络:

节点网络

节点网络是各个主机节点和etcd等独立的服务组件所属的网络,其地址配置于主机的网络接口,用于各个节点的通信,例如Master与各Node之间的通信。节点网络不由Kubernetes集群管理,也不依赖Kubernetes集群的任何组件,管理员应当在Kubernetes集群构建之前就完成节点网络的规划和配置。

Pod网络

Pod网络是Kubernetes集群专门提供给Pod资源的网络,每个Pod都会有一个集群唯一的IP地址和其他一些网络参数,这个地址配置在Pod中容器的网络接口上,因此Pod网络是一个虚拟网络。

Pod网络的实现需要借助kubenet插件或CNI插件,管理员在构建Kubernetes集群时应当一同将Pod网络定义好,之后创建Pod时会自动完成各网络参数的动态配置。

Service网络

Service网络是专门提供给Service资源使用的网络,Kubernetes集群中的Service也需要配置自己的IP地址等网络参数,但是这个IP地址并不存在于任何主机或容器的网络接口之上,而是由kube-proxy配置成iptables或ipvs规则,然后将指向此IP地址的流量调度到其后端的Pod上,因此Service网络也是虚拟网络。

与Pod网络类似,Service网络也要在集群构建时指定,每个Service的具体地址会在其创建时自动配置。

从两个角度理解Kubernetes基本概念

从抽象层面看

在物理层面上我们已经把Kubernetes需要的所有东西都准备好了,那么这些节点、组件、网络又是如何工作的呢?Kubernetes为了保证其内部的应用运行、应用编排、服务暴露、应用恢复等业务逻辑,抽象出了许多资源类型,如Pod、Service、Controller等,这些资源抽象才是Kubernetes功能的实现者。

Pod

Kubernetes的底层是搭建在Docker等容器环境之上的,但是Kubernetes并不会直接调度docker去管理容器,而是通过Pod将任意数量紧密关联的容器封装在其内,所以Pod就是Kubernetes的最小调度单元。

同一Pod内的容器紧密关联,表现为:

  • 各容器共享IPC、Network和UTC的Namespace,可以通过本地回环节口lo直接通信;
  • 各容器共享文件系统,即可以共同使用数据;
  • 各容器在Mount、User和PID的Namespace上保持隔离。

从两个角度理解Kubernetes基本概念

Label

资源标签是将资源进行分类的标识符,它是一组键值对形式的数据。标签是为了方便用户对资源有一个辨识性的认识,并不会为Kubernetes集群提供某些直接的含义。一个资源可以拥有多个标签,一个标签也可以同时标记多个资源(当然标签的使用应当符合逻辑)。

从两个角度理解Kubernetes基本概念

Label Selector

标签选择器是一种根据标签来过滤符合条件的资源对象的机制,比如我们可以将所有拥有标签“role: backend”的Pod筛选出来并将其添加为某Service的端点。
从两个角度理解Kubernetes基本概念

这样我们就清楚了,用户应该使用标签来对资源对象进行分类,再使用标签选择器为这些筛选出来的资源对象赋予新的职责。

Name和Namespace

Name是集群中资源对象的标识符,而Namespace可以理解为一组资源和对象的抽象集合,也可以认为是一些Name的作用域,怎么理解这个概念呢,比如Pod、Service、ReplicaSet和Deployment等都属于某个Namespace,那么它们的Name就应当在所属Namespace唯一存在,而Node、PersistentVolumes等则不属于任何Namespace,因此它们的Name应当在整个集群范围内唯一。在实际使用中,Namespace一般用于租户或项目间的资源隔离。
从两个角度理解Kubernetes基本概念

Service

Service是建立在一组Pod之上的资源抽象,它通过标签选择器选定一组Pod,并为这组Pod定义一个统一的固定访问入口(一个Service网络中的IP地址),到达Service IP的访问请求会以负载均衡的形式调度至后端的各个Pod之上,因此Service本质上来说是一个四层的代理和负载均衡服务。

Volume

存储卷是独立于容器文件系统之外的存储空间,常用于扩展容器的存储空间并为其提供持久存储能力。Kubernetes集群上的存储卷大致可以分为临时卷、本地卷和网络卷。临时卷和本地卷都位于本地Node上,因此一旦Pod经历销毁重建被调度到其他Node这两种类型的存储卷就将失效,因此临时卷和本地卷一般被用于数据缓存,而需要持久化保持的数据都放在持久卷上。

PersistentVolume

PersistentVolume意为持久化存储卷,与Node一样属于集群资源。PersistentVolume (PV)和PersistentVolumeClaim (PVC)为Kubernetes提供了方便的持久化卷:PV提供网络存储资源,PVC请求存储资源并将其挂载到Pod中。

Controller

在Kubernetes中我们不需要手动创建Pod实例,而是通过更高一层的抽象定义来管理Pod,这种抽象的定义方式就是Controller。控制器是一种管理Pod生命周期的资源抽象,它们是Kubernetes集群上的一类对象,包括Deployment、ReplicaSet、StatefuleSet、DaemonSet和Job等。

Ingress

Kubernetes中的负载均衡主要有两种实现机制:

  • Service:实现Kubernetes集群内部的负载均衡,借助kube-proxy将对Service的请求负载均衡地调度到Pod上;
  • Ingress:实现Kubernetes集群外部的负载均衡。

不管是Service网络还是Pod网络,其IP都只在集群内部可见,从集群外部来的请求需要通过负载均衡转发到Service所在节点暴露的端口上,这一过程就是由Ingress实现的。Ingress给Service提供集群外部访问的URL、负载均衡、HTTP路由等资源,而为了配置这些Ingress资源,在Kubernetes集群内需要部署一个Ingress Controller,它监视Ingress和Service的变化,并根据规则配置负载均衡和访问入口。