Kubernetes Operator工作原理
  yUuqgAt7EwFk 2023年11月02日 35 0

Kubernetes Operator工作原理

一、云原生应用POD创建、配置及管理现状

1.1 POD核心能力

image.png 《POD核心能力》 POD常规操作包括CURMD(Create,Update,Reade,Monitor,Delete),与之关联的资源常规操作亦如此。为减少容器云平台POD维护工作量,提高工作效率,由此行业内提出了Kubernetes Operator模式的设计思想。Kubernetes Operator基于 Kubernetes 资源和控制器概念构建,且涵盖了特定领域或应用的知识,用于实现其所管理软件的整个生命周期的自动化。

1.2 Operator概念

Operator 概念由 CoreOS 的工程师于 2016 年提出并开发实现,作为一种在 Kubernetes 集群上构建和驱动每个应用程序的高级原生方式,这需要特定领域的知识。它通过与 Kubernetes API 的密切合作,扩展Kubernetes API,开发特定的应用程序控制器,它用来创建、配置和管理复杂的有状态应用,如数据库、缓存和监控系统。Operator提供了一种一致的方法来自动处理所有应用程序操作过程,无需任何人为之反应。换句话说,Operator 是一种打包、运行和管理 Kubernetes 应用程序的方式。 Kubernetes Operator 是通过连接主API并watch的一组进程,一般会watch有限的资源类型。当相关(所watch的)event触发的时候,operator做出响应并执行具体的动作。

1.3 CRD概念

最早是谷歌提出Third Party Resource的概念,希望开发者以插件化形式扩展 K8s API 对象模型,以增强整个k8s的生态。基于Third Party Resource这一概念,Kubernetes 社区在 1.7 版本中提出了CRD 的概念。 CRD(Custom Resource Definition)客户资源定义:在k8s中一切皆是资源,资源就是CRD,用户自定义的k8s资源,是一个类型 ,默认自带的CRD比如deployment pod service等。在yaml中kind名称就是CRD名称。 CR(Custom Resourse)客户资源:是实现CRD的具体实例。 Kubernetes应用访问层CRD资源扩展架构如下: image.png 《Kubernetes应用访问层扩展架构图》 kubernetes扩展点分为应用访问层和基础设施层: 应用访问层扩展点:webhook、operator、aggregator、容器探针、启停回调、kubectl插件。 基础设施层扩展点:调度器扩展、存储插件、网络插件、设备插件。

二、Operator设计思想

Operator是一种架构理念,它区别于常见的shell等运维脚本方案:Operator希望应用能够自己管理自己,而不是由运维人员写一堆脚本从外围来控制他们。 Operator 模型基于 Kubernetes 中的两个概念结合而成:自定义资源和自定义控制器。 Operator模型通过编写自定义API CRD资源类型,聚合集成到K8S API Server,扩展 Kubernetes API 以代表人类(运营工程师或站点可靠性工程师)创建、配置和管理复杂的应用程序,即:自动化其所管理软件的整个生命周期的工作。 Operator 是构建在 Kubernetes 之上的控制器,可以自动化和简化特定的复杂操作。在 Kubernetes 中运行有状态组件集群变得与 Operator 无缝连接,因为它们弥合了有状态组件和在 Kubernetes 中运行的无状态应用程序之间的差距。它们使用声明性配置格式更容易打包、部署和管理生产就绪的有状态组件集群。它们还有助于备份、扩展和恢复,并且可以在现有 Kubernetes 集群内的任何位置运行。

2.1 Operator基本原理

狭义上来说,Operator=CRD+自定义Controller,通过自定义的Controller监听CRD对象实例的增删改事件,然后执行相应的业务逻辑。 广义上来说,Operator=CRD+自定义Controller+WebHook,在前者的基础上,可以在CRD对象的生命周期里设置相关的事件回调(WebHook),回调程序一般为外部自定义的一个HTTP URL。

2.1.1 自定义资源定义(Custom Resource Definition)

在使用Operator之前,首先需要定义一个自定义资源(Custom Resource),用于描述特定类型的应用程序或服务。自定义资源是通过创建一个自定义资源定义(CRD)对象来定义的。CRD定义了自定义资源的结构和行为,类似于Kubernetes内置资源(如Pod、Deployment等)的定义。 自定义资源可以包含多个字段,用于描述应用程序或服务的各种属性和配置。通过使用自定义资源,可以将特定类型的应用程序或服务抽象为一个单独的资源对象,并在Kubernetes中进行统一管理。

2.1.2 控制器(Controller)

控制器是Operator的核心组件,具有特定逻辑的控制器,遵循Controller Loop(Controller动作的基础),负责监听和响应CRD对象的变化,以保持应用程序或系统的稳定。控制器会通过Kubernetes API Server订阅CRD对象的事件,并根据事件类型执行相应操作。 控制器可以通过多种方式实现,例如使用Kubernetes提供的Client-go库进行编程、使用Operator SDK开发工具包或kubebuilder开发工具包。无论采用何种方式,控制器都需要实现以下几个基本功能: •启动时注册对CRD对象事件的监听; •监听到CRD对象创建事件时执行创建逻辑; •监听到CRD对象更新事件时执行更新逻辑; •监听到CRD对象删除事件时执行删除逻辑; 控制器工作原理如下: image.png Operator会与K8s API Server紧密合作,持续跟踪集群中CR对象的状态或事件,事件类型包括Create、Update和Delete,若接收到任何信息,它会将集群当前状态调整到CR对象期望的状态。

2.1.3 自动化操作

Operator可以根据特定业务逻辑执行一系列自动化操作。例如,在创建CRD对象时,Operator可以根据配置信息创建相应的Kubernetes资源(如Pod、Service等)。在更新CRD对象时,Operator可以根据更新后的配置信息对相关资源进行相应调整。在删除CRD对象时,Operator可以清理相关资源并释放相关的存储空间。

2.2 Operator解决的问题

Kubernetes Operator项目是一种解决数据库、监控等复杂应用容器化问题的模式。通过自定义控制器和自动化操作,Operator能够实现对特定类型应用程序或服务的自动化管理和操作。Operator解决的问题: 1、复杂应用POD自动化操作CURMD(Create,Update,Reade,Monitor,Delete)。 2、拓展Kubernetes StatefulSet控制器能力。 StatefulSet无法解决有状态应用的所有问题,它只是一个抽象层,负责给每个Pod打上不同的ID,并支持每个Pod使用自己的PVC卷。但有状态应用的维护非常复杂,否则每个公司也不用有一个独立的DBA团队来负责管理数据库。从上文也能看出,通过StatefulSet实例的操作,也只能做到创建集群、删除集群、扩缩容等基础操作,但比如备份、恢复等数据库常用操作,则无法实现。

2.3 Operator 的优势和适用场景

使用Operator能够带来以下几个优势: 1、自动化管理:Operator能够根据特定的业务逻辑自动管理和操作应用程序或服务。通过将领域专业知识编码到Operator中,可以实现对复杂应用程序或服务的自动化管理。 2、增强Kubernetes API:通过自定义资源定义,Operator能够扩展Kubernetes API,使其能够更好地理解和管理特定类型的应用程序或服务。 3、适应多样化需求:Operator可以根据不同的需求进行扩展和定制。通过编写不同的控制器和操作逻辑,可以实现对各种类型的应用程序或服务的自动化管理。 Operator适用于以下场景: 1、复杂应用程序:对于复杂的、多组件的应用程序,使用Operator能够简化部署、配置和管理过程,并提高可靠性和稳定性。 2、数据库集群:对于数据库集群(如MySQL、PostgreSQL等),使用Operator能够简化集群部署、备份恢复、扩缩容等操作,并提供更好的高可用性和数据一致性保证。 3、消息队列系统:对于消息队列系统(如Kafka、RabbitMQ等),使用Operator能够简化集群部署、分区扩展、消息路由配置等操作,并提供更好的消息传输效率和可靠性。 4、大数据框架:对于大数据处理框架(如Spark、Flink等),使用Operator能够简化集群部署、任务调度、资源管理等操作,并提供更好的性能和可扩展性。

2.4 Kubernetes Operator项目实现方式

1、使用Client-go库:Kubernetes提供了Client-go库,用于与Kubernetes API Server进行交互。可以使用Client-go库编写自定义控制器,监听和响应CRD对象的变化。 2、使用Operator SDK:Operator SDK是一个开发工具包,用于简化Operator的开发过程。它提供了一系列的命令行工具和代码生成器,能够自动生成基本的Operator代码框架,并提供一些常用的开发模式和最佳实践。 3、使用Kubebuilder:Kubebuilder是另一个Operator开发工具包,类似于Operator SDK。它基于Kubernetes CRD和Controller-runtime库,提供了一套用于构建和测试Operator的API和工具。

2.5 常见Kubernetes Operator项目

Operator项目汇总:https://github.com/operator-framework/awesome-operators 1、ETCD-Operator: https://github.com/coreos/etcd-operator.git

2、Prometheus-Operator: https://github.com/prometheus-operator/prometheus-operator.git

3、Istio-Operator: https://istio.io/latest/docs/setup/install/operator/

4、tidb-Operator: https://github.com/pingcap/tidb-operator.git

5、Ingress-Operator: (1)、nginxinc nginx-ingress-helm-operator https://github.com/nginxinc/nginx-ingress-helm-operator (2)、openfaas ingress-operator https://github.com/openfaas/ingress-operator

6、redis: https://github.com/ucloud/redis-cluster-operator

7、MySQL-Operator:四款官方MySQL Operator (1)、Oracle MySQL Operator https://github.com/mysql/mysql-operator (2)、Percona MySQL Operator https://github.com/percona/percona-xtradb-cluster-operator (3)、Bitpoke MySQL Operator https://github.com/bitpoke/mysql-operator (4)、GrdsCloud MySQL Operator https://operatorhub.io/operator/mysql

8、PostgreSQL-Operator; (1)、CrunchyData postgres operator https://github.com/CrunchyData/postgres-operator (2)、zalando postgres operator https://github.com/zalando/postgres-operator

9、大数据平台-Operator; (1)、spark组件 https://github.com/GoogleCloudPlatform/spark-on-k8s-operator (2)、flink组件 https://downloads.apache.org/flink/flink-kubernetes-operator-1.6.0/ (3)、clickhouse组件 https://github.com/Altinity/clickhouse-operator

三、Kubernetes Operator 的工作流程

3.1 Go Operator 类型的工作流程

1、使用kubebuilder开发工具包命令行界面 (CLI) 创建新的Operator项目; 2、通过添加自定义资源定义 (CRD) 来定义新的资源 API; 3、定义控制器来监视和协调资源; 4、使用kubebuilder开发工具包和控制器运行时 API 为控制器编写协调逻辑; 5、使用kubebuilder开发工具包CLI 构建和生成算子部署清单。

工作流程分为以下几个步骤: 1、初始化Operator项目。 2、创建CRD定义并注册到Kubernetes集群:首先需要创建一个CRD定义,描述自定义资源的结构和行为。将CRD定义提交给Kubernetes API Server进行注册。 3、部署Operator:部署一个或多个Operator实例到Kubernetes集群中。每个Operator实例都是一个独立的控制器,负责监听和响应CRD对象的变化。 4、创建CRD对象实例:使用kubectl或其他方式创建一个CRD对象。该对象包含了应用程序或服务的配置信息。 5、监听事件:Operator控制器监听到CRD对象实例创建事件,并执行相应逻辑。例如,根据配置信息创建相应的Kubernetes资源(如Pod、Service等)。 6、更新CRD对象实例:如果需要更新CRD对象的配置信息,可以通过kubectl或其他方式进行更新。Operator控制器监听到更新事件,并执行相应逻辑进行调整。 7、删除CRD对象实例:如果不再需要某个应用程序或服务,可以删除对应的CRD对象实例。Operator控制器监听到删除事件,并执行相应逻辑进行清理和释放资源。

3.2 Ansible Operator 类型的工作流程

1、使用 SDK 命令行界面 (CLI) 创建新的Operator项目。 2、使用 ansible 剧本和角色为您的对象编写协调逻辑。 3、使用 SDK CLI 构建和生成算子部署清单。 4、(可选)使用 SDK CLI 添加其他 CRD 并重复步骤 2 和 3。

3.3 Helm Operator 类型的工作流程

1、使用 SDK 命令行界面 (CLI) 创建新的Operator项目。 2、创建一个新的(或添加您现有的)Helm 图表以供操作员的协调逻辑使用。 3、使用 SDK CLI 构建和生成算子部署清单。 4、(可选)使用 SDK CLI 添加其他 CRD 并重复步骤 2 和 3。

四、Kubernetes Operator 项目实战

K8s Operator是对K8s API的扩展,它提供了创建、配置和管理代表复杂应用程序和组件的自定义资源的能力。 本实验选择目前主流的开发框架kubebuilder创建Operator,框架优点是容易使用,文档容易阅读,开发周期短并且复杂性低,以下是kubebuilder的架构: image.png 《kubebuilder的概念和架构》 main.go:为项目的入口。 go.mod:为依赖版本清单。 Makefile:构建和部署文件。 PROJECT:用于搭建新组建的Kubebuilder元数据。 config/:该目录下为启动配置。 config/manager:集群pod启动相关的控制器yaml。 config/rbac:运行控制器所需的权限定义。

4.1实验环境

根据官网,运行环境要求: kubebuilder-v3: •go version v1.20.0+ •docker version 17.03+. •kubectl version v1.11.3+. •Access to a Kubernetes v1.11.3+ cluster.

kubebuilder-v2: •go version v1.13+. •docker version 17.03+. •kubectl version v1.11.3+. •Access to a Kubernetes v1.11.3+ cluster.

本项目实验环境: •kubebuilder 3.11.1 •Go 1.20.8 •Docker 20.10.23 •kubectl 1.26.9 •kubernetes 1.26.9

4.1.1 GO安装

1、Go 语言环境安装,下载对应的安装包,配置GOPATH、GOROOT、GOPROXY,以及GO111MODULE 设置为on #gov1.20.8 wget https://golang.google.cn/dl/go1.20.8.linux-amd64.tar.gz 2、解压 tar xvf go1.20.8.linux-amd64.tar.gz -C /usr/local/ 3、配置环境变量 vi /etc/profile export PATH="$PATH:/usr/local/git/bin"

export GOROOT=/usr/local/go

export PATH="$PATH:/usr/local/go/bin"

export GOPATH=/gopath

export PATH="$PATH:/gopath/bin"

4、加载生效 source /etc/profile 5、修改go资源代理路径 go env -w GO111MODULE=on go env -w GOPROXY=https://goproxy.cn,direct go env -w CGO_ENABLED="0" 6、验证版本 go version

#按需求配置编译打包目标程序格式。windows为go env -w GOOS="windows" GOARCH="amd64" go env -w GOOS="linux" GOARCH="amd64"

4.1.2 kubebuilder安装

一、安装kustomize 1、下载安装包 wget https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv5.1.1/kustomize_v5.1.1_linux_amd64.tar.gz 2、解压 tar -zxvf kustomize_v5.1.1_linux_amd64.tar.gz 3、安装,授权并移到/usr/local/bin/下 chmod +x ./kustomize && mv kustomize /usr/local/bin/ 4、验证版本 kustomize version 二、安装 kubebuilder 1、下载安装包 wget https://github.com/kubernetes-sigs/kubebuilder/releases/download/v3.11.1/kubebuilder_linux_amd64 2、修改名称 mv kubebuilder_linux_amd64 kubebuilder 3、安装,授权并移到/usr/local/bin/下 chmod +x kubebuilder && mv kubebuilder /usr/local/bin/ 4、验证版本 kubebuilder version

4.1.3 docker和k8s集群安装

docker和k8s集群安装指引参考资料: 1、详见51cto学堂《kubernetes原理精讲【基础原理+实践篇】》课程第一章第5课。 2、https://blog.51cto.com/u_15104320/7872755

4.2 otp-operator项目开发

otp-operator用于自定义资源类型appotp实例创建、配置和管理的控制器,它会根据AppOTP实例的Spec属性,创建、更新满足要求的Pod对象。 以下创建otp-operator项目的所有操作均在K8s master节点上的项目根目录下完成。 otp-operator项目源码地址:https://gitee.com/anning-liang/otp-operator.git

4.2.1 初始化项目

1、首先执行以下命令,添加Go环境变量,使用代理下载项目所需依赖包 go env -w GOPROXY=https://goproxy.cn 2、新建项目文件夹otp-operator mkdir otp-operator 3、执行初始化命令,下载开发依赖包controller-runtime,并生成otp-operator项目基本框架 kubebuilder init --domain learn.com --repo learn.com/appotp image.png 项目初始化完成后,目录结构如下: image.png 其中cmd/main.go文件是控制器启动文件,go.mod文件列出了开发需要的依赖包,Makefile则是对kubebuilder客户端命令的解析,通过该文件可以了解框架提供的可用命令。

4.2.2 创建API和CRD

执行命令,声明API(group和version)及自定义资源类型kind kubebuilder create api --group appotp --version v1 --kind AppOTP #--kind首字母必须大写 image.png 命令执行成功,在项目的api/v1目录下生成appotp_types.go,该文件用于声明自定义资源类型AppOTP,internal/controller目录下生成appotp_controller.go,该文件用于定义AppOTP控制器和方法。API及自定义资源类型kind创建完成后,项目目录结构如下: image.png

4.2.3 定义CRD和Controller

1、定义CRD 在appotp_types.go中声明CRD AppOTP。 文件中主要包含AppOTP,AppOTPSpec和AppOTPStatus结构体的声明。AppOTP包含了metadata, AppOTPSpec和AppOTPStatus类型属性,metatdata指AppOTP的元数据信息,包括name, namespace和annotations等,AppOTPSpec属性包含了Size,Image,Resources,Envs和Ports字段,它们共同定义了集群中AppOTP实例期望的状态,即一个实例对应一个根据spec实例描述的pod,若实例更新了,pod也会随着更新,若实例删除了,pod也会一起删除。以上状态的管理控制由AppOTP控制器完成。 AppOTPStatus属性包含集群对象的DeploymentStatus字段也可以自定义字段,它反应了 CR实例的当前状态,当CR的当前状态达到期望状态时,DeploymentStatus值为正常,否则为空或异常。 image.png 2、定义Controller 在appotp_controller.go中声明AppOTP控制器和方法。AppOTPReconciler定义了AppOTP控制器,其中包含了client.Client类型字段,通过组合继承的方式向控制器方法Reconcile提供客户端访问K8s API Server获取资源对象状态和操作某个特定资源对象的方法,帮助控制器完成controller loop的过程。 image.png AppOTPReconciler结构体下有Reconcile和SetupWithManager方法。 image.png Reconcile方法提供了控制器的业务逻辑,接收跟踪的CR对象事件或当前状态,并根据期望状态对当前状态进行调整,以达到期望状态。 image.png Controller管理器,负责创建并启动Controller,For方法定义了控制器跟踪CR对象事件,一旦有任何事件发生,将触发Reconcile方法对该事件进行响应和处理,这里发生事件的CR会被封装成ctrl.Request对象,作为参数传给Reconcile方法。 注:添加控制器访问集群pods和deployments权限,如上图红框内容。 除了对CR对象事件进行跟踪和处理外,我们还可以调用Watches(object client.Object, eventHandler handler.EventHandler)对某个特定类型的对象事件进行跟踪和响应 ,方法第一个参数定义了跟踪对象类型,比如Pod,第二个参数则是在触发控制方法前,对事件处理的方法,比如使用自定义入队函数EnqueueRequestsFromMapFunc对事件进行过滤并封装成ctrl.Request对象传给Reconcile方法。

4.2.4 更新Operator manifest

CRD和Controller代码编写完成后,执行命令更新Operator manifest,根据appotp_types.go中对CRD的描述,在config/crd/bases目录下根据修改的Type生成了CRD的yaml文件(生成CRD AppOTP标准的描述文件)。 1、执行命令前给controller-gen文件授权。 chmod +x bin/controller-gen 2、执行命令生成部署文件 make manifests image.png cd config/crd/bases cat appotp.learn.com_appotps.yaml image.png

4.2.5 安装CRD到集群

make install image.png 验证 kubectl get crds | grep appotp image.png

4.2.6 appotp-controller二进制部署

make run image.png 启动成功后,AppOTP控制器进入一个持续跟踪AppOTP对象事件并做出响应的工作状态。

4.2.7 appotp-controller容器部署

1、使用make构建和推送镜像 注: 构建镜像命令会启一个容器执行构建镜像操作,如果报无法下载依赖包,建议使用方式二构建和推送镜像。 make docker-build IMG=registry.yunlearn.org:5000/public/appotp-controller:1.0.0 make docker-push IMG=registry.yunlearn.org:5000/public/appotp-controller:1.0.0

2、构建和推送镜像方式二(推荐) #在宿主机编译打包程序 cd /root/otp-operator/ CGO_ENABLED=0 go build -a -o manager cmd/main.go

2.1、修改Dockerfile,注释掉编译打包相关指令,基础镜像改成alpine:3.15,修改后内容如下: vi Dockerfile FROM alpine:3.15 WORKDIR / COPY manager . USER 65532:65532 ENTRYPOINT ["/manager"]

2.2、构建appotp-controller控制器镜像并推送到仓库 docker build -t registry.yunlearn.org:5000/public/appotp-controller:1.0.0 . docker push registry.yunlearn.org:5000/public/appotp-controller:1.0.0

2.3、修改镜像地址(由于gcr.io镜像拉取失败,改成可拉取的镜像地址) vi ./config/default/manager_auth_proxy_patch.yaml 改前:image: gcr.io/kubebuilder/kube-rbac-proxy:v0.14.1 改后:image: quay.io/brancz/kube-rbac-proxy:v0.14.0

2.4、检查确认RBAC授权文件role.yaml,增加appotp-controller容器对pods和deployments访问权限。 #注:上文appotp_controller.go源码,如果添加了rbac相关配置,make manifests指令会自动生成相关授权内容。 #文末尾追加授权内容: vi ./config/rbac/role.yaml

  • apiGroups:
    • ""
    • "apps" resources:
    • appotp
    • pods
    • deployments
    • services verbs:
    • create
    • delete
    • get
    • list
    • patch
    • update
    • watch

2.5、容器部署appotp-controller make deploy IMG=registry.yunlearn.org:5000/public/appotp-controller:1.0.0 image.png #卸载命令 make undeploy

2.6、验证appotp-controller容器部署结果 kubectl get po -A | grep controller-manager image.png #日志显示,容器部署与二进制部署日志一致,均正常。

4.3 AppOTP Operator 控制流程

image.png 《AppOTP Operator控制流程图》

4.4 AppOTP Operator 创建CRD实例

4.4.1 创建CRD实例appotp-sample

1、准备部署文件/root/otp-operator/config/samples/appotp_v1_appotp.yaml 根据需求修改示例部署文件,本实验项目修改要求:按appotp_types.go源码AppOTPSpec属性参数要求修改。内容如下: image.png

2、创建appotp-sample cd /root/otp-operator/config/samples/ kubectl apply -f appotp_v1_appotp.yaml

3、控制器接收并处理appotp-sample创建事件 image.png

4.4.2 更新CRD实例appotp-sample

1、修改appotp_v1_appotp_1_23.yaml文件,将应用版本升到1.23.0 image.png

2、创建appotp-sample cd /root/otp-operator/config/samples/ kubectl apply -f appotp_v1_appotp_1_23.yaml

3、控制器接收并处理appotp-sample更新事件 image.png

五、参考文档

1、Kubebuilder文档: https://book.kubebuilder.io/quick-start 2、Go SDK文档: https://go.dev/dl

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
yUuqgAt7EwFk