美文网首页Kubernetes
Kubernetes Operator开发之 一、Opeator

Kubernetes Operator开发之 一、Opeator

作者: 黎明你好 | 来源:发表于2020-03-02 14:57 被阅读0次

    Operator SDK User Guide

    Operator capability level

    每种operator类型需要不同的能力。对于你的operator为项目选择什么类型时,了解每个项目类型的特性和限制是很重要的。

    Phase I Phase II Phase III Phase IV Phase V
    基本安装 无缝升级 完整生命周期 深入理解 自动驾驶
    自动化应用程序配置和配置管理 支持补丁和小版本升级 应用程序生命周期,存储(备份,故障恢复) metrics、alert、log处理和工作负载分析 水平/横向扩展,自动配置调优,异常检测,调度调优
    Helm Helm
    Ansible Ansible Ansible Ansible Ansible
    GO GO GO GO GO

    kubebuilder vs operator-sdk

    kubebuilder和operator-sdk支持的Go项目之间没有太大的区别。两者都使用controller-tools和controller-runtime,并且都支持基本相似的go包结构。

    他们的不同点:

    • Operator SDK支持Ansible和Helm operator,这样很容易编写operator而不需要go,如果你对Ansible和Helm比较熟悉。
    • Operator SDK集成了Operator生命周期管理(OLM),这是Operator Framework的关键组件,对于2个集群操作很重要,比如管理员在线升级你的operator。
    • Operator SDK包含一个scorecard subcommand,帮助你了解operator是否遵循最佳实践。
    • Operator SDK包含一个e2e测试框架,它简化了针对实际集群测试操作符的工作。
    • Kubebuilder包含一个envtest包,允许operator开发人员使用独立的etcd和apiserver运行简单的测试。
    • Kubebuilder搭建了一个Makefile来帮助用户完成operator的任务(构建、测试、运行、代码生成等);Operator SDK目前使用内置的子命令。每种方法都有优缺点。SDK团队将来可能会迁移到基于makefile的方法。
    • Kubebuilder使用Kustomize构建部署清单;Operator SDK使用带有占位符的静态文件。
    • Kubebuilder最近改进了对许可和CRD转换webhook的支持,但还没有将其加入到SDK中。

    Create a new project

    operator-sdk new memcached-operator
    
    

    SDK还支持使用Ansible或Helm开发操作员。Helm使用指南。

    Operator project layout

    File/Folder s Purpose
    cmd 包含文件manager/main.go。operator的main程序。他将实例化一个新的manager,注册所有pkg/apis/...下的自定义资源定义和启动所有在pkg/controllers/...下的controller。
    pkg/apis 包含自定义资源(CRD)API的树目录。用户可以展开编辑pkg/apis/<group>/<version>/<kind>_types.go文件,为每种资源类型定义API,并将这些包导入它们的控制器中,以监视这些资源类型。
    pkg/controller 此pkg包含控制器实现。用户可以展开编辑pkg/controller/<kind>/<kind>_controller.go文件。定义控制器的协调逻辑来处理指定kind的资源类型。
    build 包含Dockerfile编译辑脚本,用于编译operator。
    deploy 包含用于注册CRD、设置RBAC和将operator部署为Deployment的各种YAML清单。
    go.mod go.sum 描述该操作符的外部依赖项的Go mod清单。
    vendor golang vendor目录,包含满足此项目中Go import 的外部依赖项目的本地副本。Go modules 管理vendor目录。除非使用—vendor标志初始化项目,或者go mod vendor在项目根目录中运行,否则此目录将不存在。

    我们主要是开发pkg下api和controller。

    Manager

    main程序为operator里的cmd/manager/main.go, 用于初始化并运行Manager。

    Manager将为pkg/api /…下所有自定义资源自动注册schema,和运行pkg/controller/…下的所有controller。

    Manager可以限制namespace所有控制器要监视的资源:

    mgr, err := manager.New(cfg, manager.Options{Namespace: namespace})
    

    默认情况下这将是operator运行的namespace。如果需要查看所有的namespace,请将namespace设置为空:

    mgr, err := manager.New(cfg, manager.Options{Namespace: ""})
    

    也可以使用 MultiNamespacedCacheBuilder 查看一组特定的namespace:

    var namespaces []string // List of Namespaces
    // Create a new Cmd to provide shared dependencies and start components
    mgr, err := manager.New(cfg, manager.Options{
       NewCache: cache.MultiNamespacedCacheBuilder(namespaces),
       MapperProvider:     restmapper.NewDynamicRESTMapper,
       MetricsBindAddress: fmt.Sprintf("%s:%d", metricsHost, metricsPort),
    })
    

    默认情况main程序将设置namager的namespace使用在deploy/operator.yaml定义的WATCH_NAMESPACE

    Add a new Custom Resource Definition

    增加一个名称为Memcached的Custom Resource Definition(CRD) API ,APIVersion cache.example.com/v1alpha1 和 Kind Memcached。

    operator-sdk add api --api-version=cache.limingnihao.com/v1alpha1 --kind=Memcached
    

    Define the spce and status

    修改Memcached Custom Resource(CR)的spec和status在文件pkg/apis/cache/v1alpha1/memcached_types.go:

    type MemcachedSpec struct {
        // Size is the size of the memcached deployment
        Size int32 `json:"size"`
    }
    type MemcachedStatus struct {
        // Nodes are the names of the memcached pods
        Nodes []string `json:"nodes"`
    }
    

    在修改*_types.go文件之后,运行下面命令更新和生成代码:

    $ operator-sdk generate k8s
    INFO[0000] Running deepcopy code-generation for Custom Resource group versions: [cache:[v1alpha1], ] 
    INFO[0008] Code-generation complete.  
    

    Updating CRD mainfests

    现在MemcachedSpecMemcachedStatus 有一些 fields 和 possibly annotations, 必须更新API's group 和 kind 与 CRD一致. 所以需要运行下面命令:

    $ operator-sdk generate crds
    INFO[0000] Running CRD generator.                       
    INFO[0000] CRD generation complete.         
    

    storage version

    创建 CustomResourceDefinition 时,会在 CustomResourceDefinition spec.versions 列表设置适当的稳定级和版本号。例如v1beta1表示第一个版本尚未稳定。所有自定义资源对象将首先存储在这个版本.

    所以你项目的CRD必须精确地指定一个storage version.

    如果转换涉及结构变更,并且需要自定义逻辑,转换应该使用 webhook。如果没有结构变更, 则使用 None 默认转换策略,不同版本时只有apiVersion字段有变更。

    使用+kubebuilder:storageversion来marker指示API服务器应该使用的存储数据的GVK。该marker应该位于Memcached类型之上的注释中。
    (没明白什么意思)

    OpenAPI validation

    当清单生成时,OpenAPIv3 schema被添加到spec.validation块中的CRD清单中。这个验证块允许Kubernetes在创建或更新Memcached Custom Resource时验证它的属性。

    Markers (annotations) 可用于验证您的API配置。这些markers将始终具有+kubebuilder:validation前缀。例如,可以通过添加以下标记来添加enum类型规范:

    // +kubebuilder:validation:Enum=Lion;Wolf;Dragon
    type Alias string
    

    CRD generationmarker文档讨论了markers在代码中的是用。完整的OpenAPIv3 validation markers请参考这里

    运行下面命令,更新CRDdeploy/crds/cache.example.com_memcacheds_crd.yaml.

    operator-sdk generate crds
    

    一个生成YAML的例子如下:

    spec:
      validation:
        openAPIV3Schema:
          properties:
            spec:
              properties:
                size:
                  format: int32
                  type: integer
    

    要了解有关Custom Resource Definitions中的OpenAPI v3.0验证模式的更多信息,请参阅Kubernetes文档

    Add a new Contrller

    添加一个新的Controller到项目,将监视和协调Memcached资源:

    $ operator-sdk add controller --api-version=cache.limingnihao.com/v1alpha1 --kind=Memcached
    

    这将在pkg/controller/memcached/...下搭建一个新的Controller实现。
    这个例子将生成文件pkg/controller/memcached/memcached_controller.gomemcached_controller.go是具体实现。

    示例中的Controller将为所有的Memcached CR执行以下逻辑:

    • 创建一个memcached Deployment如果不存在。
    • 确保这些Deployment数量和Memcached CR spec定义的相同。
    • 使用带有memcached pods名字的状态更新Memcached CR状态。

    接下来的两个小节将解释Controller如何监视资源以及如何触发协调循环。

    Resources watched by the Controller

    查看pkg/controller/memcached/memcached_controller.go的Controller实现,如何监听资源。

    第一个监视对象是作为主要资源的Memcached类型。对于每个添加/更新/删除事件,会给那个Memcached对象发送一个调和Request(a namespace/name key):

    // Watch for changes to primary resource Memcached
    err = c.Watch(&source.Kind{Type: &cachev1alpha1.Memcached{}}, &handler.EnqueueRequestForObject{})
    if err != nil {
        return err
    }
    

    下面是对Deployments的监事,但是event handler将每个event映射到Deplyments所有者的Request。本例子中,Memcached对象是Deployment的创建者,这将允许controller将Deployments作为辅助资源监视。

    // Watch for changes to secondary resource Pods and requeue the owner Memcached
    err = c.Watch(&source.Kind{Type: &corev1.Pod{}}, &handler.EnqueueRequestForOwner{
        IsController: true,
        OwnerType:    &cachev1alpha1.Memcached{},
    })
    if err != nil {
        return err
    }
    

    Controller configurations

    在初始化controller和生命watch参数时,有很多的配置。更多配置细节请参考controller godocs

    • 通过MaxConcurrentReconciles选项设置控制器的最大并发协调数。默认为1。
    _, err := controller.New("memcached-controller", mgr, controller.Options{
       MaxConcurrentReconciles: 2,
       ...
    })
    
    • 使用predicates过滤监视事件。
    • 选择EventHandelr的类型,可以将reconcile loop更改监听事件为reconcile request。对于operator更复杂的primary和secondary资源关系,可以使用EnqueueRequestsFromMapFunc handler,可以将监听事件转换为任务的reconcile request。EnqueueRequestForObject队列的一个请求包含事件源对象的Name和Namespace。

    Reconcile loop

    每个Controller都有一个Reconciler对象和一个实现了reconcile循环的reconcile()方法。reconcile loop通过Request argument查看主资源对象的Namespace/Name key,Memcached,从缓存:

    // Reconcile读取Memcached对象的集群状态,并根据读取的状态和Memcached. spec中的内容进行更改
    // 如果返回error为非空或Result.Requeue为true,控制器将再次请求处理Request,否则在完成后将从队列中删除。
    func (r *ReconcileMemcached) Reconcile(request reconcile.Request) (reconcile.Result, error) {
      // Lookup the Memcached instance for this reconcile request
      memcached := &cachev1alpha1.Memcached{}
      err := r.client.Get(context.TODO(), request.NamespacedName, memcached)
      ...
    }
    

    根据返回值,Result和error,Request将重新请求,然后再次触发Reconcile loop:

    // Reconcile successful - don't requeue
    return reconcile.Result{}, nil
    
    // Reconcile failed due to error - requeue
    return reconcile.Result{}, err
    
    // Requeue for any reason other than error
    return reconcile.Result{Requeue: true}, nil
    

    你还可以设置Result.RequeueAfter,设置在一些时间之后重新请求Request。

    import "time"
    
    // Reconcile for any reason than error after 5 seconds
    return reconcile.Result{RequeueAfter: time.Second*5}, nil
    

    Note: 返回带RequeueAfter的Result,是定期调整CR的方法。

    For a guide on Reconcilers, Clients, and interacting with resource Events, see the Client API doc.

    Build and run the operator

    在运行operator之前,CRD必须在 Kubernetes apiserver注册:

    $ kubectl create -f deploy/crds/cache.limingnihao.com_memcacheds_crd.yaml
    

    然后有两种方法,运行operator:

    • 作为Kubernetes集群内部的Deployment。
    • 集群外部的一个Go程序。

    1. Run as a Deployment inside the cluster

    Note:operator-sdk buikd调用docker build,或者是buildah bud。如果使用buildah则跳过operator-sdk build的跳过下面的说明。如果使用docker确保docker守护进程正在运行,并且可以在没有sudo的情况下运行docker客户机。您可以通过运行docker version来检查,

    Note:存在vendor/目录,运行

    $ go mod vendor
    

    构建memcached-operator image发布和注册:

    $ operator-sdk build quay.io/$USERNAME/memcached-operator:v0.0.1
    $ docker login quay.io
    $ docker push quay.io/$USERNAME/memcached-operator:v0.0.1
    
    # Update the operator manifest to use the built image name (if you are performing these steps on OSX, see note below)
    $ sed -i "s|REPLACE_IMAGE|quay.io/$USERNAME/app-operator|g" deploy/operator.yaml
    # On OSX use:
    $ sed -i "" "s|REPLACE_IMAGE|quay.io/$USERNAME/app-operator|g" deploy/operator.yaml
    
    或者只发布到本地
    $ operator-sdk build memcached-operator:v0.0.1
    

    Deployment清单在deploy/operator.yaml中生成。请确认更新deployment imageREPLACE_IMAGE,因为默认只是个占位符。

    containers:
      - name: memcached-operator
        # Replace this with the built image name
        image: REPLACE_IMAGE
        imagePullPolicy: IfNotPresent
    

    安装RBAC和发布memcached-operator:

    kubectl create -f deploy/service_account.yaml
    kubectl create -f deploy/role.yaml
    kubectl create -f deploy/role_binding.yaml
    kubectl create -f deploy/operator.yaml
    kubectl create -f deploy/crds/cache.limingnihao.com_v1alpha1_memcached_cr.yaml
    

    2.Run locally outside the cluster

    此方法在开发周期中是首选的,以便更快地部署和测试。

    在环境变量中设置operator的名称:

    export OPERATOR_NAME=memcached-operator
    

    使用$HOME/.kube/config中的默认Kubernetes配置文件在本地运行该operator:

    $ operator-sdk run --local --namespace=default
    2018/09/30 23:10:11 Go Version: go1.10.2
    2018/09/30 23:10:11 Go OS/Arch: darwin/amd64
    2018/09/30 23:10:11 operator-sdk Version: 0.0.6+git
    2018/09/30 23:10:12 Registering Components.
    2018/09/30 23:10:12 Starting the Cmd.
    

    Create a Memcached CR

    创建示例Memcached的CR使用deploy/crds/cache.example.com_v1alpha1_memcached_cr.yaml`生成:

    $ cat deploy/crds/cache.limingnihao.com_v1alpha1_memcached_cr.yaml
    apiVersion: "cache.example.com/v1alpha1"
    kind: "Memcached"
    metadata:
      name: "example-memcached"
    spec:
      size: 3
    
    $ kubectl apply -f deploy/crds/cache.limingnihao.com_v1alpha1_memcached_cr.yaml
    

    确保memcache -operator为CR创建部署:

    $ kubectl get deployment
    NAME                     DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    memcached-operator       1         1         1            1           2m
    example-memcached        3         3         3            3           1m
    

    检查pod和CR状态,确认memcached pods的状态变化:

    Update the size

    在memcached CR 将spec.size字段从3改成4:

    apiVersion: "cache.example.com/v1alpha1"
    kind: "Memcached"
    metadata:
      name: "example-memcached"
    spec:
      size: 4
    
    $ kubectl apply -f deploy/crds/cache.example.com_v1alpha1_memcached_cr.yaml
    

    确认operator的deployment数量发生改变:

    kubectl get deployment
    

    cleanup

    清除所有resources:

    kubectl delete -f deploy/crds/cache.limingnihao.com_v1alpha1_memcached_cr.yaml
    kubectl delete -f deploy/operator.yaml
    kubectl delete -f deploy/role_binding.yaml
    kubectl delete -f deploy/role.yaml
    kubectl delete -f deploy/service_account.yaml
    

    Advanced Topics

    Manage CR status conditions

    相关文章

      网友评论

        本文标题:Kubernetes Operator开发之 一、Opeator

        本文链接:https://www.haomeiwen.com/subject/rcfvkhtx.html