Skip to content

feature: run a clean-up job when uninstalling #3339

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/e2e-init.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ jobs:
path: e2ereport.json
retention-days: 1

- name: helm uninstalls spiderpool and cleans spiderpool CRD
- name: uninstalls spiderpool
id: clean
if: ${{ inputs.run_e2e == 'true' }}
run: |
Expand Down
1 change: 1 addition & 0 deletions charts/spiderpool/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ helm install spiderpool spiderpool/spiderpool --wait --namespace kube-system \
| `spiderpoolController.tls.auto.certExpiration` | server cert expiration for auto method | `73000` |
| `spiderpoolController.tls.auto.extraIpAddresses` | extra IP addresses of server certificate for auto method | `[]` |
| `spiderpoolController.tls.auto.extraDnsNames` | extra DNS names of server cert for auto method | `[]` |
| `spiderpoolController.cleanup.enable` | clean up resources when helm uninstall | `true` |

### spiderpoolInit parameters

Expand Down
34 changes: 34 additions & 0 deletions charts/spiderpool/templates/deleteHook.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{{- if .Values.spiderpoolController.cleanup.enable }}
apiVersion: batch/v1
kind: Job
metadata:
name: {{ .Values.spiderpoolController.name | trunc 48 | trimSuffix "-" }}-hook-pre-delete
annotations:
"helm.sh/hook": pre-delete
"helm.sh/hook-delete-policy": hook-succeeded,hook-failed
spec:
template:
spec:
serviceAccountName: {{ .Values.spiderpoolController.name | trunc 63 | trimSuffix "-" }}
containers:
- name: pre-delete
image: {{ include "spiderpool.spiderpoolController.image" . | quote }}
command:
- {{ .Values.spiderpoolController.binName }}
- clean
- --validate
- {{ .Values.spiderpoolController.name | trunc 63 | trimSuffix "-" }}
- --mutating
- {{ .Values.spiderpoolController.name | trunc 63 | trimSuffix "-" }}
env:
- name: SPIDERPOOL_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: SPIDERPOOL_POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
restartPolicy: Never
backoffLimit: 2
{{- end }}
25 changes: 25 additions & 0 deletions charts/spiderpool/templates/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,31 @@ rules:
- get
- list
- watch
- apiGroups:
- admissionregistration.k8s.io
resources:
- mutatingwebhookconfigurations
- validatingwebhookconfigurations
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- apiextensions.k8s.io
resources:
- customresourcedefinitions
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- apps
resources:
Expand Down
4 changes: 4 additions & 0 deletions charts/spiderpool/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,10 @@ spiderpoolController:
## @param spiderpoolController.tls.auto.extraDnsNames extra DNS names of server cert for auto method
extraDnsNames: []

cleanup:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mention it in the document of uninstalling

## @param spiderpoolController.cleanup.enable clean up resources when helm uninstall
enable: true

## @section spiderpoolInit parameters
##
spiderpoolInit:
Expand Down
221 changes: 221 additions & 0 deletions cmd/spiderpool-controller/cmd/clean.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
// Copyright 2022 Authors of spidernet-io
// SPDX-License-Identifier: Apache-2.0

package cmd

import (
"context"
"os"

"github.com/hashicorp/go-multierror"
"github.com/spf13/cobra"
"github.com/spidernet-io/spiderpool/pkg/constant"
spiderpoolv2beta1 "github.com/spidernet-io/spiderpool/pkg/k8s/apis/spiderpool.spidernet.io/v2beta1"
webhook "k8s.io/api/admissionregistration/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
)

var cleanCmd = &cobra.Command{
Use: "clean",
Short: "Clean resources",
Long: "Clean resources with specified parameters.",
Run: func(cmd *cobra.Command, args []string) {

validate, err := cmd.Flags().GetString("validate")
if err != nil {
logger.Fatal(err.Error())
os.Exit(1)
}
mutating, err := cmd.Flags().GetString("mutating")
if err != nil {
logger.Fatal(err.Error())
os.Exit(1)
}
logger.Sugar().Infof("validate %s\nmutating %s\n", validate, mutating)

client, err := NewCoreClient()
if err != nil {
logger.Fatal(err.Error())
os.Exit(1)
}
err = client.clean(validate, mutating)
if err != nil {
logger.Fatal(err.Error())
os.Exit(1)
}
},
}

type CoreClient struct {
client.Client
}

func NewCoreClient() (*CoreClient, error) {
c, err := client.New(
ctrl.GetConfigOrDie(),
client.Options{Scheme: scheme},
)
if err != nil {
return nil, err
}

return &CoreClient{Client: c}, nil
}

func (c *CoreClient) clean(validate, mutating string) error {
var jobResult *multierror.Error
ctx := context.Background()
vObj := &webhook.ValidatingWebhookConfiguration{}
err := c.Get(ctx, client.ObjectKey{Name: validate}, vObj)
if err == nil {
err := c.Delete(ctx, vObj)
if err != nil {
logger.Sugar().Errorf("failed to delete ValidatingWebhookConfiguration: %v.", err)
jobResult = multierror.Append(jobResult, err)
}
logger.Sugar().Infof("succeeded to delete ValidatingWebhookConfiguration")
}

mObj := &webhook.MutatingWebhookConfiguration{}
err = c.Get(ctx, client.ObjectKey{Name: mutating}, mObj)
if err == nil {
err := c.Delete(ctx, mObj)
if err != nil {
logger.Sugar().Errorf("failed to delete MutatingWebhookConfiguration: %v.", err)
jobResult = multierror.Append(jobResult, err)
}
logger.Sugar().Infof("succeeded to delete MutatingWebhookConfiguration")
}

ipPoolList := new(spiderpoolv2beta1.SpiderIPPoolList)
err = c.List(ctx, ipPoolList)
if err == nil {
for _, item := range ipPoolList.Items {
item.Finalizers = make([]string, 0)
err := c.Update(ctx, &item)
if err != nil {
logger.Sugar().Errorf("failed to clean the finalizers of ippool: %v, %v", &item.Name, err)
jobResult = multierror.Append(jobResult, err)
continue
}
logger.Sugar().Infof("succeeded to clean the finalizers of ippool %v", &item.Name)

err = c.Delete(ctx, &item)
if err != nil {
logger.Sugar().Errorf("failed to delete ippool: %v, %v ", &item.Name, err)
jobResult = multierror.Append(jobResult, err)
continue
}
logger.Sugar().Infof("succeeded to delete ippool: %v", &item.Name)
}
}

subnetList := new(spiderpoolv2beta1.SpiderSubnetList)
err = c.List(ctx, subnetList)
if err == nil {
for _, item := range subnetList.Items {
err = c.Delete(ctx, &item)
if err != nil {
logger.Sugar().Errorf("failed to delete subnet: %v, %v ", &item.Name, err)
jobResult = multierror.Append(jobResult, err)
continue
}
logger.Sugar().Infof("succeeded to delete subnet: %v", &item.Name)
}
}

spiderEndpointList := new(spiderpoolv2beta1.SpiderEndpointList)
err = c.List(ctx, spiderEndpointList)
if err == nil {
for _, item := range spiderEndpointList.Items {
item.Finalizers = make([]string, 0)
err := c.Update(ctx, &item)
if err != nil {
logger.Sugar().Errorf("failed to clean the finalizers of spiderEndpoint: %v, %v ", &item.Name, err)
jobResult = multierror.Append(jobResult, err)
continue
}
logger.Sugar().Infof("succeeded to clean the finalizers of spiderEndpoint %v", &item.Name)

err = c.Delete(ctx, &item)
if err != nil {
logger.Sugar().Errorf("failed to delete spiderEndpoint: %v, %v ", &item.Name, err)
jobResult = multierror.Append(jobResult, err)
continue
}
logger.Sugar().Infof("succeeded to delete spiderEndpoint: %v", &item.Name)
}
}

reservedIPList := new(spiderpoolv2beta1.SpiderReservedIPList)
err = c.List(ctx, reservedIPList)
if err == nil {
for _, item := range reservedIPList.Items {
err = c.Delete(ctx, &item)
if err != nil {
logger.Sugar().Errorf("failed to delete spiderReservedIP: %v, %v ", &item.Name, err)
jobResult = multierror.Append(jobResult, err)
continue
}
logger.Sugar().Infof("succeeded to delete spiderReservedIP: %v", &item.Name)
}
}

spiderMultusConfigList := new(spiderpoolv2beta1.SpiderMultusConfigList)
err = c.List(ctx, spiderMultusConfigList)
if err == nil {
for _, item := range spiderMultusConfigList.Items {
err = c.Delete(ctx, &item)
if err != nil {
logger.Sugar().Errorf("failed to delete spiderMultusConfig: %v, %v ", &item.Name, err)
jobResult = multierror.Append(jobResult, err)
continue
}
logger.Sugar().Infof("succeeded to delete spiderMultusConfig: %v", &item.Name)
}
}

spiderCoordinatorList := new(spiderpoolv2beta1.SpiderCoordinatorList)
err = c.List(ctx, spiderCoordinatorList)
if err == nil {
for _, item := range spiderCoordinatorList.Items {
item.Finalizers = make([]string, 0)
err := c.Update(ctx, &item)
if err != nil {
logger.Sugar().Errorf("failed to clean the finalizers of spiderCoordinator: %v, %v ", &item.Name, err)
jobResult = multierror.Append(jobResult, err)
continue
}
logger.Sugar().Infof("succeeded to clean the finalizers of spiderCoordinator %v", &item.Name)

err = c.Delete(ctx, &item)
if err != nil {
logger.Sugar().Errorf("failed to delete spiderCoordinator: %v, %v ", &item.Name, err)
jobResult = multierror.Append(jobResult, err)
continue
}
logger.Sugar().Infof("succeeded to delete spiderCoordinator: %v", &item.Name)
}
}

// Delete all crds of spiderpool
customResourceDefinitionList := new(apiextensionsv1.CustomResourceDefinitionList)
err = c.List(ctx, customResourceDefinitionList)
if err == nil {
for _, item := range customResourceDefinitionList.Items {
if item.Spec.Group == constant.SpiderpoolAPIGroup {
err = c.Delete(ctx, &item)
if err != nil {
logger.Sugar().Errorf("failed to delete customResourceDefinitionList: %v, %v ", &item.Name, err)
jobResult = multierror.Append(jobResult, err)
continue
}
logger.Sugar().Infof("succeeded to delete customResourceDefinitionList: %v", &item.Name)
}
}
}

return jobResult.ErrorOrNil()
}
4 changes: 4 additions & 0 deletions cmd/spiderpool-controller/cmd/command_root.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ var rootCmd = &cobra.Command{
// Execute adds all child commands to the root command sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
cleanCmd.Flags().String("validate", "", "Specify validate parameter")
cleanCmd.Flags().String("mutating", "", "Specify mutating parameter")

rootCmd.AddCommand(cleanCmd)
if err := rootCmd.Execute(); err != nil {
logger.Fatal(err.Error())
}
Expand Down
1 change: 1 addition & 0 deletions docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ nav:
- VWware vSphere: usage/install/cloud/get-started-vmware.md
- OpenStack: usage/install/cloud/get-started-openstack.md
- Upgrading: usage/install/upgrade.md
- Uninstalling: usage/install/uninstall.md
- System requirements: usage/install/system-requirements.md
- Concepts:
- Architecture: concepts/arch.md
Expand Down
49 changes: 49 additions & 0 deletions docs/usage/install/uninstall-zh_CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# 卸载指南

[**English**](./uninstall.md) | **简体中文**

本卸载指南适用于在 Kubernetes 上运行的 Spiderpool。如果您有任何疑问,请随时通过 [Spiderpool Community](../../README-zh_CN.md#_6) 联系我们。

## 注意事项

- 在执行卸载之前,请阅读完整的卸载指南以了解所有必要的步骤。

## 卸载

了解正在运行应用,理解卸载 Spiderpool 可能对其他相关组件(如中间件) 产生的影响,请确保完全了解风险后,才开始执行卸载步骤。

1. 通过 `helm ls` 查询集群所安装的 Spiderpool

```bash
helm ls -A | grep -i spiderpool
```

2. 通过 `helm uninstall` 卸载 Spiderpool

```bash
helm uninstall <spiderpool-name> --namespace <spiderpool-namespace>
```

将 `<spiderpool-name>` 替换为要卸载的 Spiderpool 的名称,将 `<spiderpool-namespace>` 替换为 Spiderpool 所在的命名空间。

### v0.10.0 以上版本

在 v0.10.0 之后引入了自动清理 Spiderpool 资源的功能,它通过 `spiderpoolController.cleanup.enabled` 配置项来启用,该值默认为 `true`,您可以通过如下方式验证与 Spiderpool 相关的资源数量是否自动被清理。

```bash
kubectl get spidersubnets.spiderpool.spidernet.io -o name | wc -l
kubectl get spiderips.spiderpool.spidernet.io -o name | wc -l
kubectl get spiderippools.spiderpool.spidernet.io -o name | wc -l
kubectl get spiderreservedips.spiderpool.spidernet.io -o name | wc -l
kubectl get spiderendpoints.spiderpool.spidernet.io -o name | wc -l
kubectl get spidercoordinators.spiderpool.spidernet.io -o name | wc -l
```

### v0.10.0 以下版本

在低于 v0.10.0 的版本中,由于 Spiderpool 的某些 CR 资源中存在 [finalizers](https://kubernetes.io/docs/concepts/overview/working-with-objects/finalizers/) ,导致 `helm uninstall` 命令无法清理干净,您需要手动清理。可获取如下清理脚本来完成清理,以确保下次部署 Spiderpool 时不会出现意外错误。

```bash
wget https://raw.githubusercontent.com/spidernet-io/spiderpool/main/tools/scripts/cleanCRD.sh
chmod +x cleanCRD.sh && ./cleanCRD.sh
```
Loading
Loading