Operator初探

概念介绍

Posted by Gavin on December 13, 2019

解把飞花蒙日月

不知天地有清霜

operator 使用

功能

简言之,operator就是自定义资源对象的自定义controller,将应用的安装、配置、配置更新、升级、回滚、故障处理、备份等运维活动全部封装到代码中。在没有引入operator之前,应用被视为k8s基本对象如pod、deployments、configmaps等的集合,运维粒度也停留在k8s资源对象层面,这使得部署和维护一个复杂的应用是很麻烦的,纵使有诸如Helm之类的包管理工具,也只是简化了安装、发布应用的流程,维护的行为依旧复杂,operator就是为了解决运维困难而诞生的。引入operator之后,便可将应用视为单个对象(CR)像k8s原生组件一样进行操作。 一个 Operator 指的是一个面向特定应用的控制器,这一控制器对 Kubernetes API 进行了扩展,使用 Kubernetes 用户的行为方式,创建、配置和管理复杂的有状态应用的实例。他构建在基础的 Kubernetes 资源和控制器概念的基础上,但是包含了具体应用领域的运维知识,实现了日常任务的自动化。

核心概念

operator本质上是自定义controller,用于实时比较k8s集群上运行的自定义对象的状态是否与用户期望的状态一致,以及不一致时该采取何种操作逻辑使之达到一致。

  • controller和基本组件
  • operator和自定义组件
  • 逻辑框架(伪代码)
for {
	actualState := GetResourceActualState(rsvc)
	expectState := GetResourceExpectState(rsvc)
	if actualState == expectState {
		// do nothing
	} else {
		Reconcile(rsvc)
	}
}

时间线

  • Custom Resource & Custom Resource Definition 对于k8s api的拓展,向其中加入新对象
	#CRD
	
	apiVersion: apiextensions.k8s.io/v1beta1
	kind: CustomResourceDefinition
	metadata:
  	# 名称必须符合下面的格式:<plural>.<group>
 	name: crontabs.stable.example.com
	spec:
  	# REST API使用的组名称:/apis/<group>/<version>
  	group: stable.example.com
  	# REST API使用的版本号:/apis/<group>/<version>
  	version: v1
  	# Namespaced或Cluster
 	scope: Namespaced
  	names:
    	# URL中使用的复数名称: /apis/<group>/<version>/<plural>
    	plural: crontabs
    	# CLI中使用的单数名称
    	singular: crontab
    	# CamelCased格式的单数类型。在清单文件中使用
    	kind: CronTab
    	# CLI中使用的资源简称
    	shortNames:
   	- ct

	#CR	
	
	apiVersion: "stable.example.com/v1"
	kind: CronTab
	metadata:
 	 name: my-new-cron-object
	spec:
  	cronSpec: "* * * * /5"
  	image: my-awesome-cron-image

单纯设置了自定义资源,并没有什么用,只有跟自定义控制器结合起来,才能将资源对象中的声明式API翻译成用户所期望的状态,自定义控制器可以用来管理任何资源类型,但是一般是跟自定义资源结合使用

  • Custom Controller(Operator)
└── pkg
    ├── apis
    │   └── bolingcavalry
    │       ├── register.go
    │       └── v1
    │           ├── doc.go
    │           ├── register.go
    │           ├── types.go
    │           └── zz_generated.deepcopy.go
    └── client
        ├── clientset
        │   └── versioned
        │       ├── clientset.go
        │       ├── doc.go
        │       ├── fake
        │       │   ├── clientset_generated.go
        │       │   ├── doc.go
        │       │   └── register.go
        │       ├── scheme
        │       │   ├── doc.go
        │       │   └── register.go
        │       └── typed
        │           └── bolingcavalry
        │               └── v1
        │                   ├── bolingcavalry_client.go
        │                   ├── doc.go
        │                   ├── fake
        │                   │   ├── doc.go
        │                   │   ├── fake_bolingcavalry_client.go
        │                   │   └── fake_student.go
        │                   ├── generated_expansion.go
        │                   └── student.go
        ├── informers
        │   └── externalversions
        │       ├── bolingcavalry
        │       │   ├── interface.go
        │       │   └── v1
        │       │       ├── interface.go
        │       │       └── student.go
        │       ├── factory.go
        │       ├── generic.go
        │       └── internalinterfaces
        │           └── factory_interfaces.go
        └── listers
            └── bolingcavalry
                └── v1
                    ├── expansion_generated.go
                    └── student.go

用户需要完全实现从 Kubernetes Client 的创建开始,到监听 Kubernetes API Server 的请求,再到请求的队列化,以及后面的业务逻辑一整套的逻辑。

  • Operator-framework & Kubebuilder & others 从头编写一个controller(operator)太复杂,需要对k8s底层api有非常程度的理解,还需要多年运维经验,对小白来说非常不友好。因此需要简化其实现过程,因此出现了这两个开源项目。他们本质上就是帮助用户预先完成一些operator共用的逻辑部分,形成一个可通用的operator脚手架代码框架,让用户的关注点放回operator的业务逻辑编写。还有其他的一些不太知名的工具:shell-operator、meta-controller

与Helm对比

Operator Helm
自定义Controller 包管理工具
实时监控CR状态,自动化运维 简化k8s应用安装、部署,分发和复用应用模板(资源模板化)
动态 静态
关注CR(自定义资源对象) 关注chart(一系列资源,描述一组相关的集群资源)
需要自己定义资源、编写运维逻辑 需要组织yaml文件,一般无需自己写逻辑

Kubebuilder

概念

一个用于在Go中快速构建和发布Kubernetes API的SDK,它建立在用于构建核心Kubernetes API的规范技术之上,以提供简化的抽象来减少开发工作

kubebuilder install and usage

  • download and install godep
git clone https://github.com/tools/godep.git

mkdir -p ${GOPATH}/src/github.com/tools/
mv godep ${GOPATH}/src/github.com/tools/godep
cd ${GOPATH}/src/github.com/tools/godep

go install ./
  • download and install kustomize
wget https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv3.4.0/kustomize_v3.4.0_linux_amd64.tar.gz
tar -zxvf kustomize_v3.4.0_linux_amd64.tar.gz
mv kustomize /usr/local/bin/
  • download and install kubebuilder
wget https://github.com/kubernetes-sigs/kubebuilder/releases/download/v2.2.0/kubebuilder_2.2.0_linux_amd64.tar.gz
tar -zxvf kubebuilder_2.2.0_linux_amd64.tar.gz
mv kubebuilder /usr/local/bin
  • usage

    • create a project
      mkdir $GOPATH/src/example
    
      cd $GOPATH/src/example
    
      kubebuilder init --domain my.domain
    
    • create an api
      kubebuilder create api --group webapp --version v1 --kind Guestbook
    
    • CR(xxx_types.go)
      // GuestbookSpec defines the desired state of Guestbook
      type GuestbookSpec struct {
          // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
          // Important: Run "make" to regenerate code after modifying this file
    	
          // Quantity of instances
          // +kubebuilder:validation:Minimum=1
          // +kubebuilder:validation:Maximum=10
          Size int32 `json:"size"`
    	
          // Name of the ConfigMap for GuestbookSpec's configuration
          // +kubebuilder:validation:MaxLength=15
          // +kubebuilder:validation:MinLength=1
          ConfigMapName string `json:"configMapName"`
    	
          // +kubebuilder:validation:Enum=Phone,Address,Name
          Type string `json:"alias,omitempty"`
      }
    	
      // GuestbookStatus defines the observed state of Guestbook
      type GuestbookStatus struct {
          // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
          // Important: Run "make" to regenerate code after modifying this file
    	
          // PodName of the active Guestbook node.
          Active string `json:"active"`
    	
          // PodNames of the standby Guestbook nodes.
          Standby []string `json:"standby"`
      }
    	
      type Guestbook struct {
          metav1.TypeMeta   `json:",inline"`
          metav1.ObjectMeta `json:"metadata,omitempty"`
    	
          Spec   GuestbookSpec   `json:"spec,omitempty"`
          Status GuestbookStatus `json:"status,omitempty"`
      }
    	
    
    • Controller(xxx_controller.go)
      func (r *CronJobReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
          _ = context.Background()
          _ = r.Log.WithValues("cronjob", req.NamespacedName)
    	
          // your logic here
    	
          return ctrl.Result{}, nil
      }
    

Operator Framework

概念

Operator Framework 同样也是 CoreOS 开源的一个用于快速开发 Operator 的工具包,该框架包含两个主要的部分:

  • Operator SDK: 无需了解复杂的 Kubernetes API 特性,即可让你根据你自己的专业知识构建一个 Operator 应用。
  • Operator Lifecycle Manager OLM: 帮助你安装、更新和管理跨集群的运行中的所有 Operator(以及他们的相关服务)

operator sdk install and usage

  • workflow

    • 使用 SDK 创建一个新的 Operator 项目
    • 通过添加自定义资源(CRD)定义新的资源 API
    • 指定使用 SDK API 来 watch 的资源
    • 定义 Operator 的协调(reconcile)逻辑
    • 使用 Operator SDK 构建并生成 Operator 部署清单文件
  • install go

wget https://studygolang.com/dl/golang/go1.13.5.linux-amd64.tar.gz
tar -zxvf go1.13.5.linux-amd64.tar.gz
mv go /usr/local/

#添加环境变量
export PATH=$PATH:/usr/local/go/bin
  • install godep
git clone https://github.com/tools/godep.git

mkdir -p ${GOPATH}/src/github.com/tools/
mv godep ${GOPATH}/src/github.com/tools/godep
cd ${GOPATH}/src/github.com/tools/godep

go install ./

现状

目前operator极大拓展了k8s原生api的能力,使得应用的自动化运维成为可能,社区也很热情,由于operator本质上也是应用,因此大量社区成员将自己的专业知识融入其中,开发了很多operator,可以直接使用,但是目前大多还都不成熟,不推荐生产环境使用这些operator,还是需要自己的团队按需开发。目前operator的仓库:https://operatorhub.io/