【玩转client-go】管理 Kubernetes 中资源删除:Finalizer 和 DeletionTimestamp

目录

背景

用法

实现

总结


背景

在 Kubernetes 中,控制器负责管理资源对象以确保它们始终处于所需的状态。当需要删除资源对象时,Finalizer 和 DeletionTimestamp 是两个重要的字段,它们可以帮助控制器安全地管理资源对象的删除。

Finalizer 是一种机制,用于在删除资源对象之前执行某些操作。例如,在删除资源对象之前进行清理操作。Finalizer 列表是通过在资源对象的 metadata.finalizers 字段中指定的一组字符串来实现的。当资源对象被标记为要删除时,Kubernetes 会在 Finalizer 列表中添加 Finalizers。一旦所有 Finalizers 都执行完毕,Kubernetes 就会删除该对象。

DeletionTimestamp 是一个时间戳,用于标记资源对象的删除时间。当资源对象被标记为要删除时,Kubernetes 会在 DeletionTimestamp 字段中设置一个时间戳。一旦资源对象被标记为要删除,就无法再对它进行修改或更新。

扫描二维码关注公众号,回复: 15405528 查看本文章

用法

Finalizer 和 DeletionTimestamp 是紧密相关的。当资源对象被标记为要删除时,Kubernetes 会在 DeletionTimestamp 字段中设置一个时间戳,并在 Finalizer 列表中添加 Finalizers。一旦所有 Finalizers 都执行完毕,Kubernetes 就会删除该对象,并将 DeletionTimestamp 字段设置为 null。

实现

下面是一个示例 Deployment 资源对象的 Finalizer 和 DeletionTimestamp 的用法:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  finalizers:
  - my-finalizer
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest

在上面的示例中,Deployment 资源对象的 Finalizer 列表包含一个名为 my-finalizer 的 Finalizer。当删除 Deployment 资源对象时,Finalizer my-finalizer 将会执行某些清理操作,例如删除关联的 ConfigMap 资源对象。

const (
	myFinalizerName = "my-finalizer"
)

myFinalizerName 是在示例代码中定义的一个字符串常量,用于表示添加到 Deployment 资源对象的 Finalizer 的名称。你可以根据自己的需求设置 Finalizer 的名称,只需确保在添加和删除 Finalizer 时使用相同的名称即可。在示例代码中,Finalizer 的名称是 my-finalizer

下面是一个示例 Controller 的 reconcile 过程,演示了 Finalizer 和 DeletionTimestamp 的用法:

func (c *Controller) reconcile(ctx context.Context, deployment *appsv1.Deployment) error {
	// Check if the object is being deleted
	if !deployment.ObjectMeta.DeletionTimestamp.IsZero() {
		// The object is being deleted
		if containsString(deployment.ObjectMeta.Finalizers, myFinalizerName) {
			// Run finalization logic
			if err := c.finalizeDeployment(ctx, deployment); err != nil {
				return err
			}
			// Remove the finalizer
			deployment.ObjectMeta.Finalizers = removeString(deployment.ObjectMeta.Finalizers, myFinalizerName)
			if _, err := c.kubeClient.AppsV1().Deployments(deployment.Namespace).Update(ctx, deployment, metav1.UpdateOptions{}); err != nil {
				return err
			}
		}
		return nil
	}

	// The object is not being deleted
	if !containsString(deployment.ObjectMeta.Finalizers, myFinalizerName) {
		// Add finalizer
		deployment.ObjectMeta.Finalizers = append(deployment.ObjectMeta.Finalizers, myFinalizerName)
		if _, err := c.kubeClient.AppsV1().Deployments(deployment.Namespace).Update(ctx, deployment, metav1.UpdateOptions{}); err != nil {
			return err
		}
	}

	// Handle normal reconcile logic here
	// ...
}

func (c *Controller) finalizeDeployment(ctx context.Context, deployment *appsv1.Deployment) error {
	// Perform finalization logic, such as deleting related ConfigMaps
	// ...
	return nil
}

func containsString(strs []string, str string) bool {
	for _, s := range strs {
		if s == str {
			return true
		}
	}
	return false
}

func removeString(strs []string, str string) []string {
	newStrs := []string{}
	for _, s := range strs {
		if s != str {
			newStrs = append(newStrs, s)
		}
	}
	return newStrs
}


在上面的示例中,当 Deployment 资源对象被标记为要删除时,reconcile 函数会检查 Deployment 资源对象的 Finalizer 列表中是否包含 my-finalizer Finalizer。如果包含,则运行 finalizeDeployment 函数中的清理逻辑。完成清理逻辑后,将从 Finalizer 列表中删除 my-finalizer Finalizer。最后,使用 Kubernetes API 更新 Deployment 资源对象,以确保 Finalizer 列表正确更新。

如果 Deployment 资源对象被标记为要删除,但 Finalizer 列表中没有包含 my-finalizer Finalizer,reconcile 函数会将 my-finalizer Finalizer 添加到 Finalizer 列表中,以确保清理逻辑被正确执行。

总结

Finalizer 和 DeletionTimestamp 是 Kubernetes 中管理资源删除的重要机制。控制器可以使用 Finalizer 和 DeletionTimestamp 安全地管理资源对象的删除,并在必要时执行某些清理操作。在处理资源对象时,务必考虑 Finalizer 和 DeletionTimestamp 的作用,并确保正确使用它们,以避免意外删除资源对象。
 

猜你喜欢

转载自blog.csdn.net/kingu_crimson/article/details/129928445