Deletion & Retention¶
This guide describes what happens when you delete a GitlabInstance and how to safely clean up the resources that the operator intentionally retains.
What the operator does on deletion¶
When a GitlabInstance enters the deletion flow (e.g. kubectl delete gli my-gitlab -n my-gitlab), the operator's finalizer (k8s.bnerd.com/gitlab-finalizer) runs before the object is removed:
- Deletes operator-owned Secrets — the Secrets listed in
status.secrets(e.g.{instance}-gitlab-registry-storage) are deleted. - Removes the finalizer — allowing the Kubernetes API to garbage-collect the
GitlabInstanceobject.
Resources owned by the GitlabInstance via Kubernetes owner references (the HelmRelease and HelmRepository) are deleted automatically by the API server after the finalizer completes.
What is NOT deleted¶
Managed backends are retained — this is intentional
Managed PerconaPGCluster, Redis CRs (Redis / RedisReplication / RedisSentinel), and ECK Elasticsearch clusters carry no owner reference to the GitlabInstance. They are never deleted by the operator on instance deletion.
This prevents accidental data loss if an instance CR is deleted by mistake. You must delete these resources manually after verifying the data is no longer needed.
| Resource | Deleted on instance deletion? | By whom |
|---|---|---|
GitlabInstance object |
Yes | Kubernetes API (after finalizer) |
HelmRelease |
Yes | Kubernetes GC (owner reference) |
HelmRepository |
Yes | Kubernetes GC (owner reference) |
Operator-owned Secrets (status.secrets) |
Yes | Operator finalizer |
| GitLab chart Secrets | Yes | Kubernetes GC (owned by HelmRelease) |
PerconaPGCluster (managed) |
No | Must be deleted manually |
| Redis CRs (managed) | No | Must be deleted manually |
ECK Elasticsearch (managed) |
No | Must be deleted manually |
| Secrets you provided (S3, license, SMTP, BYO creds) | No | Must be deleted manually |
Deleting a GitlabInstance¶
-
Pre-flight — confirm the instance is safe to delete: no active users, data-retention requirements met, backups verified if needed.
-
Delete the instance:
-
Monitor the finalizer:
-
Verify the HelmRelease is gone:
-
Verify GitLab pods are gone:
Cleaning up managed backends¶
After verifying that the GitLab data is no longer needed:
Delete managed PostgreSQL¶
# Find the PerconaPGCluster
kubectl get perconapgcluster -n my-gitlab
# Delete it (Percona will clean up PVCs)
kubectl delete perconapgcluster my-gitlab-pg -n my-gitlab
# Wait for Percona to finish (may take several minutes)
kubectl get perconapgcluster my-gitlab-pg -n my-gitlab
# Eventually: NotFound
Delete managed Redis¶
# Standalone
kubectl delete redis my-gitlab-redis -n my-gitlab
# HA (RedisReplication + RedisSentinel)
kubectl delete redisreplication my-gitlab-redis -n my-gitlab
kubectl delete redissentinel my-gitlab-redis -n my-gitlab
Delete managed Elasticsearch (EE)¶
Delete the namespace¶
Once all managed backend resources and their PVCs have been removed:
Wait for Percona finalizers before deleting the namespace
Deleting the namespace while PerconaPGCluster resources are still present may cause the namespace to stall in Terminating due to Percona's own finalizers. Always delete the PerconaPGCluster first and wait for it to fully terminate.
Namespace stuck in Terminating¶
If the namespace stalls:
# Check what is still present
kubectl get all,pvc,perconapgcluster,redis,redisreplication,redissentinel,elasticsearch \
-n my-gitlab
# Check for remaining finalizers
kubectl describe namespace my-gitlab | grep -iA3 finalizers
Most commonly, a managed backend CR is still terminating (waiting for Percona or ECK to clean up PVCs). Check the respective operator logs: