Kubernetes 核心组件(二)
0 参考资料
课程:《云原生训练营》
书籍:《Kubernetes源码剖析》
1 Kubernetes 核心数据结构
1.1 Group、Version、Resource核心数据结构
Kubernetes将资源再次分组和版本化,形成Group(资源组)、Version(资源版本)、Resource(资源)。Group、Version、Resource核心数据结构如图所示:
- Group :被称为资源组,在Kubernetes API Server中也可称其为APIGroup。
- Version :被称为资源版本,在Kubernetes API Server中也可称其为APIVersions。
- Resource :被称为资源,在Kubernetes API Server中也可称其为APIResource。
- Kind :资源种类,描述Resource的种类,与Resource为同一级别。
Kubernetes系统支持多个Group,每个Group支持多个Version,每个Version支持多个Resource,其中部分资源同时会拥有自己的子资源(即SubResource)。例如,Deployment资源拥有Status子资源。
1.2 kubernetes内置资源
- kubectl api-versions :列出当前Kubernetes系统支持的资源组和资源版本,其表现形式为
<group>/<version>
。 - kubectl api-resources :列出当前Kubernetes系统支持的Resource资源列表。
2 client-go
2.1 Client客户端对象
client-go支持4种Client客户端对象与Kubernetes API Server交互的方式,Client交互对象如图所示。
- RESTClient是最基础的客户端。RESTClient对HTTP Request进行了封装,实现了RESTful风格的API。ClientSet、DynamicClient及DiscoveryClient客户端都是基于RESTClient实现的。
- ClientSet在RESTClient的基础上封装了对Resource和Version的管理方法。每一个Resource可以理解为一个客户端,而ClientSet则是多个客户端的集合,每一个Resource和Version都以函数的方式暴露给开发者。ClientSet只能够处理Kubernetes内置资源,它是通过client-gen代码生成器自动生成的。
- DynamicClient与ClientSet最大的不同之处是,ClientSet仅能访问Kubernetes自带的资源(即Client集合内的资源),不能直接访问CRD自定义资源。DynamicClient能够处理Kubernetes中的所有资源对象,包括Kubernetes内置资源与CRD自定义资源。
- DiscoveryClient发现客户端,用于发现kube-apiserver所支持的资源组、资源版本、资源信息(即Group、Versions、Resources)。
以上4种客户端:RESTClient、ClientSet、DynamicClient、DiscoveryClient都可以通过kubeconfig配置信息连接到指定的Kubernetes API Server,后面将详解它们的实现。
2.1.1 kubeconfig配置管理
kubeconfig用于管理访问kube-apiserver的配置信息,同时也支持访问多kube-apiserver的配置管理,可以在不同的环境下管理不同的kube-apiserver集群配置,不同的业务线也可以拥有不同的集群。Kubernetes的其他组件都使用kubeconfig配置信息来连接kube-apiserver组件,例如当kubectl访问kube-apiserver时,会默认加载kubeconfig配置信息。
kubeconfig中存储了集群、用户、命名空间和身份验证等信息,在默认的情况下,kubeconfig存放在$HOME/.kube/config路径下。Kubeconfig配置信息如下:
- kubeconfig配置信息通常包含3个部分,分别介绍如下。
- clusters :定义Kubernetes集群信息,例如kube-apiserver的服务地址及集群的证书信息等。
- users :定义Kubernetes集群用户身份验证的客户端凭据,例如client-certificate、client-key、token及username/password等。
- contexts :定义Kubernetes集群用户信息和命名空间等,用于将请求发送到指定的集群。
client-go会读取kubeconfig配置信息并生成config对象,用于与kube-apiserver通信,代码示例如下:
1 | func main() { |
2.1.2 RESTClient 客户端
RESTClient是最基础的客户端。其他的ClientSet、DynamicClient及DiscoveryClient都是基于RESTClient实现的。RESTClient对HTTP Request进行了封装,实现了RESTful风格的API。它具有很高的灵活性,数据不依赖于方法和资源,因此RESTClient能够处理多种类型的调用,返回不同的数据格式。
2.2 Informer 机制
Informer 机制架构设计:
Informer架构设计中,有多个核心组件,分别介绍如下:
2.2.1 Reflector
Reflector用于监控(Watch)指定的Kubernetes资源,当监控的资源发生变化时,触发相应的变更事件,例如Added(资源添加)事件、Updated(资源更新)事件、Deleted(资源删除)事件,并将其资源对象存放到本地缓存DeltaFIFO中。
2.2.2 DeltaFIFO
DeltaFIFO可以分开理解,FIFO是一个先进先出的队列,它拥有队列操作的基本方法,例如Add、Update、Delete、List、Pop、Close等,而Delta是一个资源对象存储,它可以保存资源对象的操作类型,例如Added(添加)操作类型、Updated(更新)操作类型、Deleted(删除)操作类型、Sync(同步)操作类型等。
DeltaFIFO本质上是一个先进先出的队列,有数据的生产者和消费者,其中生产者是Reflector调用的Add方法,消费者是Controller调用的Pop方法。下面分析DeltaFIFO的核心功能:生产者方法、消费者方法及Resync机制。
2.2.3 Indexer
Indexer是client-go用来存储资源对象并自带索引功能的本地存储,Reflector从DeltaFIFO中将消费出来的资源对象存储至Indexer。Indexer与Etcd集群中的数据完全保持一致。client-go可以很方便地从本地存储中读取相应的资源对象数据,而无须每次从远程Etcd集群中读取,以减轻Kubernetes API Server和Etcd集群的压力。
Indexer数据结构说明如下:
- Indexers :存储索引器,key为索引器名称,value为索引器的实现函数。
- IndexFunc :索引器函数,定义为接收一个资源对象,返回检索结果列表
- Indices :存储缓存器,key为缓存器名称(在Indexer Example代码示例中,缓存器命名与索引器命名相对应),value为缓存数据。Index :存储缓存数据,其结构为K/V。
2.3 WorkQueue
WorkQueue称为工作队列,Kubernetes的WorkQueue队列与普通FIFO(先进先出,First-In,First-Out)队列相比,实现略显复杂,它的主要功能在于标记和去重,并支持如下特性。
- 有序 :按照添加顺序处理元素(item)。
- 去重 :相同元素在同一时间不会被重复处理,例如一个元素在处理之前被添加了多次,它只会被处理一次。
- 并发性 :多生产者和多消费者。
- 标记机制 :支持标记功能,标记一个元素是否被处理,也允许元素在处理时重新排队。
- 通知机制 :ShutDown方法通过信号量通知队列不再接收新的元素,并通知metricgoroutine退出。
- 延迟 :支持延迟队列,延迟一段时间后再将元素存入队列。
- 限速 :支持限速队列,元素存入队列时进行速率限制。限制一个元素被重新排队(Reenqueued)的次数。
- Metric :支持metric监控指标,可用于Prometheus监控。WorkQueue支持3种队列,并提供了3种接口,不同队列实现可应对不同的使用场景,分别介绍如下。
- Interface :FIFO队列接口,先进先出队列,并支持去重机制。
- DelayingInterface :延迟队列接口,基于Interface接口封装,延迟一段时间后再将元素存入队列。
- RateLimitingInterface :限速队列接口,基于DelayingInterface接口封装,支持元素存入队列时进行速率限制。
有状态应用-Operator
基于 CRD 的开发过程
- 借助Kubernetes RBAC 和 authentication 机制来保证该扩展资源的 security、access control、authentication 和 multitenancy。
- 将扩展资源的数据存储到 Kubernetes 的 etcd 集群
- 借助 Kubernetes 提供的 controller 模式开发框架,实现新的 controller,并借助 APIServer 监听 etcd 集群 关于该资源的状态,并定义状态变化的处理逻辑
基于CRD的开发,可以让开发人员扩展添加新功能,更新现有的功能,并且可以自动执行一些管理任务,这些自定义的控制器就像 Kubernetes 原生的组件一样,Operator 直接使用 Kubernetes API 进行开发,就可以根据这些控制器内部编写的自定义规则来监控集群、更改 Pods/Services、对正在运行的应用进行扩缩容。
控制器模式:
控制器代码示例:
安装 kubebuilder
下载链接:https://github.com/kubernetes-sigs/kubebuilder/releases
1 | mv <your_download_binary> /usr/local/bin/kubebuilder |
开发自定义 HTTPClient 资源
创建项目
1 | mkdir httpclient |
查看项目:cat PROJECT
:
1 | # Code generated by tool. DO NOT EDIT. |
定义 HTTPClient 资源
创建 API、resource、controller:
1 | kubebuilder create api --group apps --version v1beta1 --kind HTTPClient |
到现在为止,已经定义 HTTPClient 资源,可以进行修改。
修改 httpclient_types.go
修改 api/v1beta1/httpclient_types.go
填充 HTTPClient 资源类型的 字段。
1 | // HTTPClientSpec defines the desired state of HTTPClient |
修改 httpclient_controller.go
定义控制器业务逻辑:
1 | func (r *HTTPClientReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { |
生成 CRD
在创建项目时,已经自动生成了一个Makefile,可以执行 make help
看下:
1 |
|
manifests 和 generate 是针对开发使用,可以自动生成一些逻辑。可直接执行 make build
包含了以上步骤。
1 | make build |
生成的镜像那个如下:
下边 介绍下 make deploy
的具体执行逻辑:
1 | .PHONY: deploy |
- 进入 config/manager 目录,此目录下存放了 kustomize 的配置文件,kustomize 是一个用于 自定义 Kubernetes 配置的工具,有点像 Helm
- 使用Kustomize的
edit set image
命令来更新controller
镜像的引用。 $(KUSTOMIZE) build config/default
:使用Kustomize的build
命令来生成最终的Kubernetes资源配置文件- 将Kustomize的输出传入
kubectl apply -f -
命令,完成控制器在 kubernetes 集群中的部署
部署定义的资源
在 config/samples
下的 apps_v1beta1_httpclient.yaml
如下:
1 | apiVersion: apps.baihl.io/v1beta1 |