【kubebuilder 学习之初学】编写官方样例 Cronjob Controller

参考

小结

# yaml 改动有关或重新生成,如 crd、webhook 等 yaml
$ make manifests
# 部署 crd
$ make install
# 卸载 crd
$ make uninstall
# controller 调试,在终端可看到 controller 日志
$ make run

# 生成镜像,此处为默认名称,详见 Dockerfile 中 IMG 环境变量
$ make docker-build 
# 自定义生成镜像名称
$ make docker-build IMG=dfy-cronjob-operator:v2
# 部署 controller 和 webhook 到集群中
$ make deploy
# 卸载 controller 和 webhook
$ make undeploy

# 查看 make deploy 会部署哪些内容
$ kustomize build config/default
  • 调试过程
# 1. 部署 crd
$ make manifests install
# 2. 运行 controller
$ make run
# 3. 创建示例,需要提前手动填充 config/samples/batch_v1_cronjob.yaml 对应的 crd 字段内容
 kubectl apply -f config/samples/batch_v1_cronjob.yaml

1 | 创建 CRD

# we'll use a domain of tutorial.kubebuilder.io,
# so all API groups will be <group>.tutorial.kubebuilder.io.
# 1. 执行 domain 域名,避免与其他域的同名 CRD 冲突
$ kubebuilder init --domain tutorial.kubebuilder.io
# 2. 在该域内生成 CronJob CRD,也可以称之为,创建一个 API
$ kubebuilder create api --group batch --version v1 --kind CronJob
# 3. 生成 crd 定义 yaml
$ make manifests
# 4. 部署 crd:将 crd 这种类型告知给 k8s 集群,也就是执行 crd 定义yaml
$ make install

# 5. 若 cronjob 结构定义有改动,需要重新生成和部署 crd, 就是执行上面 3 和 4 步,简化如下
$ make manifest install

domain 有什么作用

# 可以看到 cronjob,k8s 原生也有
# 我们创建的 cronjob 和 k8s 原生 cronjob,都设置 group 为 batch, version 为 v1
# 若未指定 domain,将造成冲突
kubectl api-resources | grep cronjob
cronjobs                          cj           batch/v1                               true         CronJob
cronjobs                          cj2          batch.tutorial.kubebuilder.io/v1       true         CronJob

2 | 设计 CRD 结构定义

// api/v1/cronjob_types.go

// +kubebuilder:object:root=true               标记这是一个根对象,这个类型直接对应于一个 Kubernetes API 资源,而不是嵌套在其他资源中的子资源。
// +kubebuilder:resource:shortName=cj2				 执行该类型的缩写为 cj2
// +kubebuilder:subresource:status             为该类型生成个 status 子资源

// 用户自定义 crd
// CronJob is the Schema for the cronjobs API
type CronJob struct {
Root Object Definitions
    metav1.TypeMeta   `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`

    Spec   CronJobSpec   `json:"spec,omitempty"`
    Status CronJobStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true
// 自动生成,用于承接一堆 CRD 实例,可以理解为数组,用于存储多个 CRD 实例
// CronJobList contains a list of CronJob
type CronJobList struct {
    metav1.TypeMeta `json:",inline"`
    metav1.ListMeta `json:"metadata,omitempty"`
    Items           []CronJob `json:"items"`
}

// 用户自定义,对应 crd 的 spec 字段
// CronJobSpec defines the desired state of CronJob
type CronJobSpec struct {
    // +kubebuilder:validation:MinLength=0

    // The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron.
    Schedule string `json:"schedule"`

    // +kubebuilder:validation:Minimum=0

    // Optional deadline in seconds for starting the job if it misses scheduled
    // time for any reason.  Missed jobs executions will be counted as failed ones.
    // +optional
    StartingDeadlineSeconds *int64 `json:"startingDeadlineSeconds,omitempty"`

    // Specifies how to treat concurrent executions of a Job.
    // Valid values are:
    // - "Allow" (default): allows CronJobs to run concurrently;
    // - "Forbid": forbids concurrent runs, skipping next run if previous run hasn't finished yet;
    // - "Replace": cancels currently running job and replaces it with a new one
    // +optional
    ConcurrencyPolicy ConcurrencyPolicy `json:"concurrencyPolicy,omitempty"`

    // This flag tells the controller to suspend subsequent executions, it does
    // not apply to already started executions.  Defaults to false.
    // +optional
    Suspend *bool `json:"suspend,omitempty"`

    // Specifies the job that will be created when executing a CronJob.
    JobTemplate batchv1beta1.JobTemplateSpec `json:"jobTemplate"`

    // +kubebuilder:validation:Minimum=0

    // The number of successful finished jobs to retain.
    // This is a pointer to distinguish between explicit zero and not specified.
    // +optional
    SuccessfulJobsHistoryLimit *int32 `json:"successfulJobsHistoryLimit,omitempty"`

    // +kubebuilder:validation:Minimum=0

    // The number of failed finished jobs to retain.
    // This is a pointer to distinguish between explicit zero and not specified.
    // +optional
    FailedJobsHistoryLimit *int32 `json:"failedJobsHistoryLimit,omitempty"`
}

// 用户自定义,对应 status 子资源
// 在 controller reconcile 中自定义更新逻辑,通过 if err := r.Status().Update(ctx, &cronJob); err != nil { 更新 status 子资源
// CronJobStatus defines the observed state of CronJob
type CronJobStatus struct {
    // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
    // Important: Run "make" to regenerate code after modifying this file

    // A list of pointers to currently running jobs.
    // +optional
    Active []corev1.ObjectReference `json:"active,omitempty"`

    // Information when was the last time the job was successfully scheduled.
    // +optional
    LastScheduleTime *metav1.Time `json:"lastScheduleTime,omitempty"`
}


// kubebuilder 自动生成的,将 Kinds 注册到 API group 中。这使我们可以将此 API group 中的 Kind 添加到任何 Scheme 中。
func init() {
    SchemeBuilder.Register(&CronJob{}, &CronJobList{})
}

详解 status 子资源
  • https://kubernetes.io/zh-cn/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#subresources

当你在自定义资源(Custom Resource)中使用 // +kubebuilder:subresource:status 标记时,kubebuilder 会在生成的 CRD YAML 文件中包含一个 status 子资源。这意味着 Kubernetes 会为该自定义资源管理 status 子资源,允许你通过专门的 API 来更新资源的状态。

具体作用如下:

  1. 启用 status 子资源: 标记告诉 Kubernetes 这个自定义资源有一个 status 子资源,这个子资源可以通过 Kubernetes API 单独访问和更新。
  2. API 分离: 允许状态和规格(spec)分离,通过不同的 API 端点分别更新。规格可以通过 /spec 更新,而状态可以通过 /status 更新。
  3. 状态更新: 状态更新通常由控制器执行。控制器会定期检查资源的状态并更新 status 字段,以反映资源的当前状态或操作结果。
  4. 权限控制: 在使用 status 子资源时,可以对 statusspec 操作分别设置 RBAC 权限。这样可以确保只有具有适当权限的实体才能修改资源状态。

3 | 编写 controller

//  controllers/cronjob_controller.go

// kubebuilder 为我们搭建了一个基本的 reconciler 结构体。 
// 几乎每个 reconciler 都需要记录日志,并且需要能够获取对象,因此这个结构体是开箱即用的。
// CronJobReconciler reconciles a CronJob object
// 可自定义添加字段,用于记录或控制,如 Log 字段
type CronJobReconciler struct {
    client.Client
    Log    logr.Logger
    Scheme *runtime.Scheme
}

// 编写 controller 的控制逻辑、调谐逻辑
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
}
  • controller 的初始化,在项目根目录 main.go 中
	if err = (&controllers.CronJobReconciler{
		Client: mgr.GetClient(),
		Scheme: mgr.GetScheme(),
		// 未赋值此 Log 字段时,Log 对应一个 logr.Logger 零值(结构体内的所有字段都为 零值)
		Log: ctrl.Log.WithName("controllers").WithName("CronJob"),
	}).SetupWithManager(mgr); err != nil {
		setupLog.Error(err, "unable to create controller", "controller", "CronJob")
		os.Exit(1)
	}

关注 job 资源

  • 由于 cronjob 需要操作并关注 job 资源,所以需要权限和关注
    • 权限,通过 kubebuilder 注释实现
    • 关注,通过 owns ,job 资源变化也会出发 cronjob 的调谐逻辑
//  controllers/cronjob_controller.go

// 1. 足够的权限,操作 job 资源
//+kubebuilder:rbac:groups=batch.tutorial.kubebuilder.io,resources=cronjobs,verbs=get;list;watch;create;update;patch;delete  自动生成
//+kubebuilder:rbac:groups=batch.tutorial.kubebuilder.io,resources=cronjobs/status,verbs=get;update;patch  自动生成
//+kubebuilder:rbac:groups=batch.tutorial.kubebuilder.io,resources=cronjobs/finalizers,verbs=update 自动生成
//+kubebuilder:rbac:groups=batch,resources=jobs,verbs=get;list;watch;create;update;patch;delete   手动添加
//+kubebuilder:rbac:groups=batch,resources=jobs/status,verbs=get  手动添加

func (r *CronJobReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
	... ...
}


// 2. 关注 cronjob 掌管的 job 资源变化,触发调谐逻辑
// - 其他知识:创建一个 Indexer
var (
    // Indexer 名称
    jobOwnerKey = ".metadata.controller"
    apiGVStr    = batch.GroupVersion.String()
)

func (r *CronJobReconciler) SetupWithManager(mgr ctrl.Manager) error {

    // 创建一个名为 .metadata.controller 的 Indexer
    if err := mgr.GetFieldIndexer().IndexField(&kbatch.Job{}, jobOwnerKey, func(rawObj runtime.Object) []string {
        // grab the job object, extract the owner...
        job := rawObj.(*kbatch.Job)
        owner := metav1.GetControllerOf(job)
        if owner == nil {
            return nil
        }
        // ...make sure it's a CronJob...
        if owner.APIVersion != apiGVStr || owner.Kind != "CronJob" {
            return nil
        }

        // ...and if so, return it
        return []string{owner.Name}
    }); err != nil {
        return err
    }

    // 关注 cronjob 创建的 job 实例,job 的变化会触发 cronjob 的 reconcile 调谐逻辑
    return ctrl.NewControllerManagedBy(mgr).
        For(&batch.CronJob{}).
        Owns(&kbatch.Job{}).
        Complete(r)
}

Owns 字段的作用

在 Kubernetes 中,Owns 字段用于指定控制器应该监视的资源类型,这些资源是由该控制器管理的主要资源拥有的。具体来说,当一个控制器声明它“拥有”某些资源时,它表示控制器不仅要监视和管理其主要资源,还要监视这些主要资源所创建或拥有的其他资源。

示例代码

在你的示例代码中:

//  controllers/cronjob_controller.go
return ctrl.NewControllerManagedBy(mgr).
    For(&batchv1.CronJob{}).
    Owns(&kbatchv1.Job{}).
    Complete(r)
详细解释
  1. For(&batchv1.CronJob{}):
    • 这行代码指定控制器的主要资源类型是 CronJob
    • 控制器将监视和管理 CronJob 资源,当 CronJob 资源发生变化时,它将调用 Reconcile 方法。
  2. Owns(&kbatchv1.Job{}):
    • 这行代码指定控制器还应监视 Job 资源,这些 Job 资源是由 CronJob 资源创建或拥有的。
    • Job 资源发生变化(例如创建、更新或删除)时,控制器也会调用 Reconcile 方法。
    • 这确保了 CronJob 控制器可以响应其拥有的 Job 资源的变化,从而确保 CronJobJob 之间的一致性和正确性。
作用

Owns 的作用包括以下几个方面:

  1. 资源关系管理
    • 确保控制器不仅监视主要资源(如 CronJob),还监视这些资源创建或拥有的子资源(如 Job)。
    • 当子资源状态改变时,控制器可以及时响应和处理。
  2. 自动调用 Reconcile
    • 当控制器拥有的子资源发生变化时,Kubernetes 会通知控制器,并自动调用 Reconcile 方法。
    • 这有助于保持主要资源和子资源之间的一致性。例如,当一个 Job 完成或失败时,CronJob 控制器可以根据需要更新 CronJob 的状态。
  3. 简化控制器逻辑
    • 通过 Owns 字段,控制器开发者可以简化控制器逻辑,因为 Kubernetes 会自动处理子资源的事件通知。
    • 开发者只需在 Reconcile 方法中处理这些事件即可。
结论

在 Kubernetes 中,Owns 字段是控制器的一种声明,用于指定控制器除了监视主要资源外,还要监视由这些主要资源拥有的其他资源。当这些拥有的资源发生变化时,Kubernetes 会自动调用控制器的 Reconcile 方法,从而确保资源之间的一致性和正确性。

4 | 编写 webhook

使用 kubebuilder create webhook 命令可以为指定的 Kubernetes 资源创建 Webhook,帮助进行默认值设置和程序化验证。让我们详细解释这个命令及其参数的作用。

命令和参数

kubebuilder create webhook --group batch --version v1 --kind CronJob --defaulting --programmatic-validation

作用

该命令会为指定的 CronJob 资源创建 Webhook,用于处理默认值设置和程序化验证。

参数解释

  1. --group batch
    • 指定资源所属的 API 组为 batch
    • CronJob 资源会被创建在 batch API 组下。
  2. --version v1
    • 指定资源的 API 版本为 v1
    • CronJob 资源使用的版本是 v1
  3. --kind CronJob
    • 指定资源的类型(或种类)为 CronJob
    • 这个命令将会为 CronJob 资源创建 Webhook。
  4. --defaulting
    • 创建一个 Mutating Webhook,用于在创建或更新 CronJob 资源时设置默认值。
    • 当用户创建或更新 CronJob 资源但没有提供某些字段的值时,这个 Webhook 会自动填充默认值。
  5. --programmatic-validation
    • 创建一个 Validating Webhook,用于在创建或更新 CronJob 资源时进行程序化验证。
    • 这个 Webhook 会检查传入的 CronJob 资源的字段值是否符合特定的业务逻辑或规则,如果不符合,则拒绝该操作。

生成的内容

运行上述命令后,Kubebuilder 会在项目中生成必要的代码和配置文件,包括:

  1. Webhook 配置
    • api/v1/cronjob_webhook.go 文件中,会生成默认值设置和验证逻辑的框架代码。
  2. Webhook 代码
    • Default 方法:用于设置 CronJob 资源的默认值。
    • ValidateCreateValidateUpdateValidateDelete 方法:用于在创建、更新和删除 CronJob 资源时进行验证。
  3. Webhook 配置文件
    • config/webhook 目录下生成相应的 YAML 文件,用于配置 Webhook 服务。
    • 包括 MutatingWebhookConfiguration 和 ValidatingWebhookConfiguration 的配置文件,这些配置文件会被应用到 Kubernetes 集群中,以注册 Webhook 服务。

示例代码

api/v1/cronjob_webhook.go 文件可能包含以下示例代码:

// +kubebuilder:webhook:path=/mutate-batch-v1-cronjob,mutating=true,failurePolicy=fail,groups=batch,resources=cronjobs,verbs=create;update,versions=v1,name=mcronjob.kb.io

// +kubebuilder:webhook:path=/validate-batch-v1-cronjob,mutating=false,failurePolicy=fail,groups=batch,resources=cronjobs,verbs=create;update;delete,versions=v1,name=vcronjob.kb.io
// 可以理解为 Mutating Webhook 填充默认值,需要手动编写对应逻辑
func (r *CronJob) Default() {
    cronjoblog.Info("default", "name", r.Name)
    // 设置默认值的逻辑
}

// 可以理解为 Validating Webhook,可以理解为在资源创建、更新、删除时,执行的验证逻辑,需要手动编写
func (r *CronJob) ValidateCreate() error {
    cronjoblog.Info("validate create", "name", r.Name)
    // 创建时的验证逻辑
    return nil
}

func (r *CronJob) ValidateUpdate(old runtime.Object) error {
    cronjoblog.Info("validate update", "name", r.Name)
    // 更新时的验证逻辑
    return nil
}

func (r *CronJob) ValidateDelete() error {
    cronjoblog.Info("validate delete", "name", r.Name)
    // 删除时的验证逻辑
    return nil
}

结论

通过运行 kubebuilder create webhook 命令并指定相应参数,可以为 CronJob 资源创建默认值设置和程序化验证的 Webhook。这些 Webhook 可以帮助自动填充默认值并确保资源的合法性,提升资源管理的自动化和可靠性。

5 | 部署 webhook

  • 需要注意的是

    • 上面编写的 webhook 没有建议的验证命令,如 make run 验证并调试 controller
    • webhook 需要和 controller 一起部署到集群中后,才能验证
    • 而又来个问题,webhook 需要证书
  • 所以为了便捷调试 controller,我们增加了一个 webhook 开关,来控制 webhook 是否开启

    • // 在 main 函数中增加此段逻辑
       if os.Getenv("ENABLE_WEBHOOKS") != "false" {
      		if err = (&batchv1.CronJob{}).SetupWebhookWithManager(mgr); err != nil {
      			setupLog.Error(err, "unable to create webhook", "webhook", "Captain")
      			os.Exit(1)
      		}
      	}
      
    • 进行 controller 调试

    • # 不开启 webhook 
      $ make run ENABLE_WEBHOOKS=false
      # 开启 webhook 会报错,缺少证书
      $ make run ENABLE_WEBHOOKS=true
      

5.1 安装cert-manager

  • 为什么需要给webhook提供证书

    • API Server 通过 HTTPS POST 访问 Webhook Server, 因此 Webhook Server 必须要监听在 https 协议上
    • 因此我们需要给webhook提供证书
  • kubebuilder官方也 建议使用 cert-manager 为 webhook 服务器提供证书

  • 安装cert-manager

    kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.4/cert-manager.yaml	
    
  • 查看安装结果

    [root@localhost cert-manager]# kubectl get pod -n cert-manager
    NAME                                       READY   STATUS    RESTARTS   AGE
    cert-manager-7fb948f468-r5dj2              1/1     Running   0          142m
    cert-manager-cainjector-75c5fc965c-shtx6   1/1     Running   0          142m
    cert-manager-webhook-757c9d4bb7-vhgt7      1/1     Running   0          142m
    
    [root@localhost cert-manager]# kubectl get ValidatingWebhookConfiguration
    NAME                   WEBHOOKS   AGE
    cert-manager-webhook   1          143m
    
    [root@localhost cert-manager]# kubectl get MutatingWebhookConfiguration
    NAME                   WEBHOOKS   AGE
    cert-manager-webhook   1          143m
    

5.2 修改配置文件

让我们的webhook,使用cert-manager提供的证书,还需要修改项目中的几个配置文件

不同的 kubebuilder 版本修改的可能不一致,但逻辑都是间 cert manager 相关注释解开即可

  • 修改 config/default/kustomization.yaml,将关于WEBHOOK、CERTMANAGER 的 都取消注释即可

    # Adds namespace to all resources.
    namespace: cronjob-operator-system
    
    # Value of this field is prepended to the
    # names of all resources, e.g. a deployment named
    # "wordpress" becomes "alices-wordpress".
    # Note that it should also match with the prefix (text before '-') of the namespace
    # field above.
    namePrefix: cronjob-operator-
    
    # Labels to add to all resources and selectors.
    #labels:
    #- includeSelectors: true
    #  pairs:
    #    someName: someValue
    
    resources:
    - ../crd
    - ../rbac
    - ../manager
    # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
    # crd/kustomization.yaml
    - ../webhook
    # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required.
    - ../certmanager
    # [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'.
    - ../prometheus
    
    patches:
    # Protect the /metrics endpoint by putting it behind auth.
    # If you want your controller-manager to expose the /metrics
    # endpoint w/o any authn/z, please comment the following line.
    - path: manager_auth_proxy_patch.yaml
    
    # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
    # crd/kustomization.yaml
    - path: manager_webhook_patch.yaml
    
    # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'.
    # Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks.
    # 'CERTMANAGER' needs to be enabled to use ca injection
    - path: webhookcainjection_patch.yaml
    
    # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix.
    # Uncomment the following replacements to add the cert-manager CA injection annotations
    replacements:
     - source: # Add cert-manager annotation to ValidatingWebhookConfiguration, MutatingWebhookConfiguration and CRDs
         kind: Certificate
         group: cert-manager.io
         version: v1
         name: serving-cert # this name should match the one in certificate.yaml
         fieldPath: .metadata.namespace # namespace of the certificate CR
       targets:
         - select:
             kind: ValidatingWebhookConfiguration
           fieldPaths:
             - .metadata.annotations.[cert-manager.io/inject-ca-from]
           options:
             delimiter: '/'
             index: 0
             create: true
         - select:
             kind: MutatingWebhookConfiguration
           fieldPaths:
             - .metadata.annotations.[cert-manager.io/inject-ca-from]
           options:
             delimiter: '/'
             index: 0
             create: true
         - select:
             kind: CustomResourceDefinition
           fieldPaths:
             - .metadata.annotations.[cert-manager.io/inject-ca-from]
           options:
             delimiter: '/'
             index: 0
             create: true
     - source:
         kind: Certificate
         group: cert-manager.io
         version: v1
         name: serving-cert # this name should match the one in certificate.yaml
         fieldPath: .metadata.name
       targets:
         - select:
             kind: ValidatingWebhookConfiguration
           fieldPaths:
             - .metadata.annotations.[cert-manager.io/inject-ca-from]
           options:
             delimiter: '/'
             index: 1
             create: true
         - select:
             kind: MutatingWebhookConfiguration
           fieldPaths:
             - .metadata.annotations.[cert-manager.io/inject-ca-from]
           options:
             delimiter: '/'
             index: 1
             create: true
         - select:
             kind: CustomResourceDefinition
           fieldPaths:
             - .metadata.annotations.[cert-manager.io/inject-ca-from]
           options:
             delimiter: '/'
             index: 1
             create: true
     - source: # Add cert-manager annotation to the webhook Service
         kind: Service
         version: v1
         name: webhook-service
         fieldPath: .metadata.name # namespace of the service
       targets:
         - select:
             kind: Certificate
             group: cert-manager.io
             version: v1
           fieldPaths:
             - .spec.dnsNames.0
             - .spec.dnsNames.1
           options:
             delimiter: '.'
             index: 0
             create: true
     - source:
         kind: Service
         version: v1
         name: webhook-service
         fieldPath: .metadata.namespace # namespace of the service
       targets:
         - select:
             kind: Certificate
             group: cert-manager.io
             version: v1
           fieldPaths:
             - .spec.dnsNames.0
             - .spec.dnsNames.1
           options:
             delimiter: '.'
             index: 1
             create: true
    
  • 修改 config/crd/kustomization.yaml,为每个 CRD 启用 CA 注入

    # This kustomization.yaml is not intended to be run by itself,
    # since it depends on service name and namespace that are out of this kustomize package.
    # It should be run by config/default
    resources:
    - bases/batch.graham924.com_cronjobs.yaml
    #+kubebuilder:scaffold:crdkustomizeresource
    
    patches:
    # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix.
    # patches here are for enabling the conversion webhook for each CRD
    - path: patches/webhook_in_cronjobs.yaml
    #+kubebuilder:scaffold:crdkustomizewebhookpatch
    
    # [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix.
    # patches here are for enabling the CA injection for each CRD
    - path: patches/cainjection_in_cronjobs.yaml
    #+kubebuilder:scaffold:crdkustomizecainjectionpatch
    
    # [WEBHOOK] To enable webhook, uncomment the following section
    # the following config is for teaching kustomize how to do kustomization for CRDs.
    
    configurations:
    - kustomizeconfig.yaml
    

5.3 开启webhook环境变量开关

export ENABLE_WEBHOOKS=true

5.4 打包镜像并上传仓库

# 打包镜像并上传到仓库
make docker-build docker-push IMG=dfy-cronjob-operator:v2

# 此处打包镜像,但不上传到仓库,因为是本地调试
# IMG 是指定镜像名称,若不指定,其会使用 Makefile 中默认的 IMG 变量名称
make docker-build IMG=dfy-cronjob-operator:v2

# 采用的是 kind 集群
# 查看当前使用的 kind 集群名称
kubectl config current-context
# 将镜像导入到 kind 集群
kind load docker-image dfy-cronjob-operator:v2 --name k8s-cluster-ingress
# 执行部署
make deploy IMG=dfy-cronjob-operator:v2
无法运行排错
  • 查看部署的 deployment 镜像拉取策略是否为 IfNotPresent 策略

  • 若不为,可修改镜像 pull 策略。 在 /config/manager/manager.yaml 配置文件中, 添加 imagePullPolicy 策略。 由于本地开发, 并不准备上传到云上, 所以设置为 IfNotPresent

    •     spec:
            securityContext:
              runAsNonRoot: true
            containers:
            - command:
              - /manager
              args:
              - --leader-elect
              image: controller:latest
              name: manager
      
              ## 由于不上传到镜像仓库, 所以这里以本地编译的版本为准
              imagePullPolicy: IfNotPresent
      
      

5.5 部署和验证

make deploy IMG=dfy-cronjob-operator:v2
kubectl create -f config/samples/batch_v1_cronjob.yaml
  • 可以修改 config/samples/batch_v1_cronjob.yaml,为schedule写一个错误的cron表达式,看是否会创建成功。
    • 期望情况是创建的时候就会报错cron验证失败
  • 20
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值