教程一览:Openkruise
doc :openkruise.io/zh/docs/use…
pkg/webhook/util/deletionprotection/
特性开关
// pkg/features/kruise_features.go
func SetDefaultFeatureGates() {
if !utilfeature.DefaultFeatureGate.Enabled(PodWebhook) {
_ = utilfeature.DefaultMutableFeatureGate.Set(fmt.Sprintf("%s=false", KruisePodReadinessGate))
_ = utilfeature.DefaultMutableFeatureGate.Set(fmt.Sprintf("%s=false", ResourcesDeletionProtection))
_ = utilfeature.DefaultMutableFeatureGate.Set(fmt.Sprintf("%s=false", PodUnavailableBudgetDeleteGate))
_ = utilfeature.DefaultMutableFeatureGate.Set(fmt.Sprintf("%s=false", PodUnavailableBudgetUpdateGate))
_ = utilfeature.DefaultMutableFeatureGate.Set(fmt.Sprintf("%s=false", WorkloadSpread))
}
if !utilfeature.DefaultFeatureGate.Enabled(KruiseDaemon) {
_ = utilfeature.DefaultMutableFeatureGate.Set(fmt.Sprintf("%s=false", PreDownloadImageForInPlaceUpdate))
_ = utilfeature.DefaultMutableFeatureGate.Set(fmt.Sprintf("%s=true", DaemonWatchingPod))
_ = utilfeature.DefaultMutableFeatureGate.Set(fmt.Sprintf("%s=true", InPlaceUpdateEnvFromMetadata))
}
}
删除条件
这个比较简单,和官网文档描述一致,我直接贴出来
func ValidateWorkloadDeletion(obj metav1.Object, replicas *int32) error {
if !utilfeature.DefaultFeatureGate.Enabled(features.ResourcesDeletionProtection) || obj == nil || obj.GetDeletionTimestamp() != nil {
return nil
}
switch val := obj.GetLabels()[policyv1alpha1.DeletionProtectionKey]; val {
case policyv1alpha1.DeletionProtectionTypeAlways:
return fmt.Errorf("forbidden by ResourcesProtectionDeletion for %s=%s", policyv1alpha1.DeletionProtectionKey, val)
case policyv1alpha1.DeletionProtectionTypeCascading:
if replicas != nil && *replicas > 0 {
return fmt.Errorf("forbidden by ResourcesProtectionDeletion for %s=%s and replicas %d>0", policyv1alpha1.DeletionProtectionKey, val, *replicas)
}
default:
}
return nil
}
func ValidateNamespaceDeletion(c client.Client, namespace *v1.Namespace) error {
if !utilfeature.DefaultFeatureGate.Enabled(features.ResourcesDeletionProtection) || namespace.DeletionTimestamp != nil {
return nil
}
switch val := namespace.Labels[policyv1alpha1.DeletionProtectionKey]; val {
case policyv1alpha1.DeletionProtectionTypeAlways:
return fmt.Errorf("forbidden by ResourcesProtectionDeletion for %s=%s", policyv1alpha1.DeletionProtectionKey, val)
case policyv1alpha1.DeletionProtectionTypeCascading:
pods := v1.PodList{}
if err := c.List(context.TODO(), &pods, client.InNamespace(namespace.Name)); err != nil {
return fmt.Errorf("forbidden by ResourcesProtectionDeletion for list pods error: %v", err)
}
var activeCount int
for i := range pods.Items {
pod := &pods.Items[i]
if kubecontroller.IsPodActive(pod) {
activeCount++
}
}
if activeCount > 0 {
return fmt.Errorf("forbidden by ResourcesProtectionDeletion for %s=%s and active pods %d>0", policyv1alpha1.DeletionProtectionKey, val, activeCount)
}
default:
}
return nil
}
func ValidateCRDDeletion(c client.Client, obj metav1.Object, gvk schema.GroupVersionKind) error {
if !utilfeature.DefaultFeatureGate.Enabled(features.ResourcesDeletionProtection) || obj.GetDeletionTimestamp() != nil {
return nil
}
switch val := obj.GetLabels()[policyv1alpha1.DeletionProtectionKey]; val {
case policyv1alpha1.DeletionProtectionTypeAlways:
return fmt.Errorf("forbidden by ResourcesProtectionDeletion for %s=%s", policyv1alpha1.DeletionProtectionKey, val)
case policyv1alpha1.DeletionProtectionTypeCascading:
objList := &unstructured.UnstructuredList{}
objList.SetAPIVersion(gvk.GroupVersion().String())
objList.SetKind(gvk.Kind)
if err := c.List(context.TODO(), objList, client.InNamespace(v1.NamespaceAll)); err != nil {
return fmt.Errorf("failed to list CRs of %v: %v", gvk, err)
}
var activeCount int
for i := range objList.Items {
if objList.Items[i].GetDeletionTimestamp() == nil {
activeCount++
}
}
if activeCount > 0 {
return fmt.Errorf("forbidden by ResourcesProtectionDeletion for %s=%s and active CRs %d>0", policyv1alpha1.DeletionProtectionKey, val, activeCount)
}
default:
}
return nil
}
删除时机
pkg/webhook/cloneset/validating
我们拿 cloneSet 举例,来看什么时候会走到函数 ValidateWorkloadDeletion
// 声明变量 cloneset_create_update_handler.go
var _ admission.Handler = &CloneSetCreateUpdateHandler{}
// 定义 HandlerMap webhook.go
var (
// HandlerMap contains admission webhook handlers
HandlerMap = map[string]admission.Handler{
"validate-apps-kruise-io-v1alpha1-cloneset": &CloneSetCreateUpdateHandler{},
}
)
// API server 会在资源变更的时候把请求发给 admission controller(属于
// API server ), 然后便会调用对应的 Handle 逻辑
|-admission.Handler.Handle()
|- ValidateWorkloadDeletion