目录
背景
在 kubernetes 中,控制器负责管理资源对象以确保它们始终处于所需的状态。当需要删除资源对象时,finalizer 和 deletiontimestamp 是两个重要的字段,它们可以帮助控制器安全地管理资源对象的删除。
finalizer 是一种机制,用于在删除资源对象之前执行某些操作。例如,在删除资源对象之前进行清理操作。finalizer 列表是通过在资源对象的 metadata.finalizers 字段中指定的一组字符串来实现的。当资源对象被标记为要删除时,kubernetes 会在 finalizer 列表中添加 finalizers。一旦所有 finalizers 都执行完毕,kubernetes 就会删除该对象。
deletiontimestamp 是一个时间戳,用于标记资源对象的删除时间。当资源对象被标记为要删除时,kubernetes 会在 deletiontimestamp 字段中设置一个时间戳。一旦资源对象被标记为要删除,就无法再对它进行修改或更新。
用法
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 的作用,并确保正确使用它们,以避免意外删除资源对象。
发表评论