在Operator开发之kubebuilder实战(一)的最后提到了Demo和Pod删除的问题:
首先,DemoController需要监听Pod资源的变化,kubebuilder提供了两种监听额外资源的变化的机制,一种是简单粗暴的Watchs
:
func (r *DemoReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&batchv1.Demo{}).
Watches(&corev1.Pod{}, &handler.EnqueueRequestForObject{}).
Complete(r)
}
这种方式就可以直接ListAndWatch Pod资源,这种方式的问题是,可以接收到所有命名空间的Pod的变化
,但是,在我们的场景中,希望只监听Demo负责创建的Pod。
另一种就是Owns
:
func (r *DemoReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&batchv1.Demo{}).
Owns(&corev1.Pod{}).
Complete(r)
}
这种方式就只会监听Demo负责创建的Pod,不过使用这种方式还需要在创建Pod时增加ownerReferences属性,这种方式就跟ReplicaSet类似:当ReplicaSet在创建Pod时,会将自身的信息写入到Pod的ownerReferences字段,当Pod变化时,会根据Pod找到关联的ReplicaSet,然后向ReplicaSet推送Pod变更。这种方式可以让DemoController接收必要的消息,而不需要实现过滤逻辑。
创建Pod时在metadata部分加入ownerReferences:
pod := &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Labels: make(map[string]string),
Annotations: make(map[string]string),
Name: name,
Namespace: req.Namespace,
OwnerReferences: []metav1.OwnerReference{
{
APIVersion: demo.APIVersion,
Kind: demo.Kind,
Name: demo.Name,
UID: demo.UID,
Controller: pointer.Bool(true), // 为true表示该资源是控制器
},
},
},
Spec: *demo.Spec.Template.Spec.DeepCopy(),
}
通过这两个改动的结合就可以达到效果:
需要注意的是:
SetupWithManager
里面监听的是Pod,但是调谐函数收到的是Pod关联的Demo的变更,而不像有些文章写的在这里还需要判断收到的变更是Demo还是Pod关于级联删除
:当删除一个资源时,该如何删除这个资源管理的资源。当使用kubectl delete
删除资源时,有个级联删除的选项--cascade
,该选项有三个值:
foregroundDeletion
,给Pod设置deletionTimestamp,然后去删除Pod,当清理操作完成时,再移除finalizers属性并删除Pod这就解释了为什么给Pod加上ownerReferences属性就可以在删除Demo时自动删除Pod。
资源删除过程中还需要提到两个属性:BlockOwnerDeletion
和Finalizers
:
Webhook是一种可以在请求过程中将请求发送给另一个web服务进行处理的机制,例如,GitLab中的Webhook,当向GitLabe仓库提交代码时,GitLab会产生一些事件,可以让GitLab将这些事件发送给我们的Web程序处理,从而可以实现流程的自动化。与GitLabe中的Webhook类似,k8s中的Webhook也是可以在apiserver处理请求时,将请求发送给其他的web服务处理,区别是,k8s中的Webhook不仅可以收到请求,还能够拦截和拒绝请求。
k8s apiserver在收到请求后,需要对请求进行准入控制,也就是判断请求是否合法,这里面有两种特殊的准入控制可以让开发人员增加自己的准入规则:
在这里我们创建Webhook,且带有变更准入和验证准入的功能:
创建Webhook:
// 创建默认和验证的webhook
kubebuilder create webhook --group batch --version v1 --kind Demo --defaulting --programmatic-validation
上述命令分别在api/v1和config增加了以下文件:
代码逻辑位于demo_webhook.go,其中Default()里面可以对未提供值的字段设置默认值,ValidateCreate()是对创建资源时进行验证,ValidateUpdate()是对更新资源时进行验证,ValidateDelete()是对删除资源时进行验证。
func (r *Demo) Default() {
demolog.Info("default", "name", r.Name)
// 设置replicas的默认值
if r.Spec.Replicas == nil {
r.Spec.Replicas = new(int64)
*r.Spec.Replicas = 1
}
}
func (r *Demo) ValidateCreate() (admission.Warnings, error) {
demolog.Info("validate create", "name", r.Name)
// 创建资源时对replicas的范围进行判断
if *r.Spec.Replicas < 1 || *r.Spec.Replicas > 10 {
return admission.Warnings{"replicas must greater than 1 and less than 11"}, errors.New("replicas must greater than 1 and less than 11")
}
return nil, nil
}
这里解决了当前资源和子资源的删除问题,并说明了级联删除,并简单讲解了Webhook的开发。