Delete stale feature branches in your Kubernetes cluster.
An end user of the project is a Kubernetes cluster's administrator which is involved into Continuous Integration
process and looking for a solution of the problem of feature branches' that live in the cluster after its pull request
is already merged.
Feature branch (or deploy preview) means that a pull request is deployed as a separate instance of your application.
It allows preventing errors and bugs, responsible people can check a feature before it's merged to production.
One of the ways to create a feature branch in Kubernetes cluster is to use namespaces
to separate production deployment from any other. Production configurations may look similar to:
kind: Deployment
apiVersion: apps/v1
metadata:
namespace: github-back-end
...
Otherwise, feature branches always have a different namespace. Such as -pr- prefix or postfix in its name. The example
is illustrated below:
kind: Deployment
apiVersion: apps/v1
metadata:
namespace: github-back-end-pr-17
...
To summarize what described above, the project helps you to delete namespaces as a namespace equals to all resources
that belong to a feature branch in Kubernetes cluster.
More information about implementation of feature branches using namespaces is here and here.
To understand the motivation of the project, let's check common continuous integration for a pull request and its lifecycle:
master).One important thing is that good lifecycle will delete all existing feature branch resources for a particular commit before applying configurations for the new commit. It's needed to ensure that each commit's deployment is done from a clear state.
But after the branch is merged to the production branch, all feature branch's resources are still running in a cluster and occupy its resources. What are the ways to delete them? Check alternatives section.
These are the ways to delete feature branch's resources after its branch is merged to production branch. All of them are not ideal as well as this project. Each of you can choose any approach that mostly fits your case.
On each production branch build, detect which branch was merged last and delete.
Integrate a webhook to your continuous integration system (example).
infrastructure as code process). So, to create a webhook, you will need separate
scripts that process webhook's data
which will not be uploaded to the source code server and should be maintained in a user interface.Create own Cronjob resource in a Kubernetes cluster.
Cronjob resource, so you lose nothing while
reusing.Apply the latest release configurations with the command below, it will create the StaleFeatureBranch resource,
install the operator into stale-feature-branch-operator namespace, create a service account
and necessary RBAC roles.
$ kubectl apply -f \
https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/configs/production.yml
If you need any previous release, full list of versions is available here.
To delete stale feature branches, after applying installation instructions above, create a configuration file with
feature-branch.dmytrostriletskyi.com/v1 as apiVersion and StaleFeatureBranch as kind:
apiVersion: feature-branch.dmytrostriletskyi.com/v1
kind: StaleFeatureBranch
metadata:
name: stale-feature-branch
spec:
namespaceSubstring: -pr-
afterDaysWithoutDeploy: 3
Choose any metadata's name for the resource and dive into specifications:
namespaceSubstring is needed to get all feature branches' namespaces. For instance, the example above will grab
github-back-end-pr-17 and github-back-end-pr-33 if there are namespaces github-back-end, github-front-end,
github-back-end-pr-17, github-back-end-pr-33 in a cluster as the -pr- substring occurs there.afterDaysWithoutDeploy is needed to delete only old namespaces. If you set 3 days there, namespaces created
1 day or 2 days ago will not be deleted, but created 3 days, 1 hour or 4 days will be deleted.It processes feature branches' namespaces every 30 minutes by default. The last available parameter in specifications
is checkEveryMinutes. You can configure a frequency of the processes in minutes if the default value doesn't fit you.
Check guideline below if you want to know how it works under the hood.
This guideline shows how the deletion of stale feature branches works under the hood. You should not reproduce the
instructions below for production cluster as it's just a detailed example to understand the behavior of the operator.
For this chapter, testing Kubernetes cluster on your personal computer will be used.
Kubernetes cluster in a
virtual machine (or Docker) on your personal computer.Kubernetes
cluster.Start Kubernetes cluster on your personal computer with the following command:
$ minikube start --vm-driver=docker
minikube v1.11.0 on Darwin 10.15.5
Using the docker driver based on existing profile.
Starting control plane node minikube in cluster minikube.
After, choose your cluster as the main one for kubectl. It's needed for cases you work with many clusters from the
single computer:
$ kubectl config use-context minikube
Switched to context "minikube".
Applied configurations in the same way you apply it to a production cluster. But as it's production configurations, they will expect old namespaces present in your cluster. Our cluster is fresh, and no old resources are present there. As you do not have them, the operator allows you to specify the debug parameter. If the debug is enabled, all namespaces will be deleted without checking for an oldness:
Copy the production configurations to your personal computer:
$ curl https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/configs/production.yml > \
stale-feature-branch-production-configs.yml
If you need any previous release, full list of versions is available here.
Enable debug by changing the setting. For Linux it's:
$ sed -i 's|false|true|g' stale-feature-branch-production-configs.yml
For macOS it's:
$ sed -i "" 's|false|true|g' stale-feature-branch-production-configs.yml
Apply the changed production configurations:
$ kubectl apply -f stale-feature-branch-production-configs.yml
Fetch all resources in Kubernetes cluster, you will see StaleFeatureBranch resource is available to use:
$ kubectl api-resources | grep stalefeaturebranches
NAME SHORTNAMES APIGROUP NAMESPACED KIND
stalefeaturebranches sfb feature-branch.dmytrostriletskyi.com true StaleFeatureBranch
Fetch pods in stale-feature-branch-operator namespace, you will see an operator that listens for new StaleFeatureBranch
resources running there:
$ kubectl get pods --namespace stale-feature-branch-operator
NAME READY STATUS RESTARTS AGE
stale-feature-branch-operator-6bfbfd4df8-m7sch 1/1 Running 0 38s
Fetch the operator's logs to ensure it's running:
$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator
{"level":"info","ts":1592306900.8200202,"logger":"cmd","msg":"Operator Version: 0.0.1"}
...
{"level":"info","ts":1592306901.5672553,"logger":"controller-runtime.controller","msg":"Starting EventSource","controller":"stalefeaturebranch-controller","source":"kind source: /, Kind="}
{"level":"info","ts":1592306901.6680624,"logger":"controller-runtime.controller","msg":"Starting Controller","controller":"stalefeaturebranch-controller"}
{"level":"info","ts":1592306901.6681142,"logger":"controller-runtime.controller","msg":"Starting workers","controller":"stalefeaturebranch-controller","worker count":1}
Create ready-to-use fixtures that contain two namespaces project-pr-1 and project-pr-2 with many other resources
as well (deployment, service, secrets, etc.).:
$ kubectl apply \
-f https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/fixtures/first-feature-branch.yml \
-f https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/fixtures/second-feature-branch.yml
namespace/project-pr-1 created
deployment.apps/project-pr-1 created
service/project-pr-1 created
horizontalpodautoscaler.autoscaling/project-pr-1 created
secret/project-pr-1 created
configmap/project-pr-1 created
ingress.extensions/project-pr-1 created
namespace/project-pr-2 created
deployment.apps/project-pr-2 created
service/project-pr-2 created
horizontalpodautoscaler.autoscaling/project-pr-2 created
secret/project-pr-2 created
configmap/project-pr-2 created
ingress.extensions/project-pr-2 created
You can check their existence by the following command:
$ kubectl get namespace,pods,deployment,service,horizontalpodautoscaler,configmap,ingress -n project-pr-1 && \
kubectl get namespace,pods,deployment,service,horizontalpodautoscaler,configmap,ingress -n project-pr-2
...
NAME READY STATUS RESTARTS AGE
pod/project-pr-1-848d5fdff6-rpmzw 1/1 Running 0 67s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/project-pr-1 1/1 1 1 67s
...
As it's told above, when debug is enabled, all namespaces will be deleted without checking for an oldness. It means if
we create StaleFeatureBranch configurations, the namespaces will be deleted immediately. The fixture for
StaleFeatureBranch will check for namespaces that contain -pr- in their names once a minute.
$ kubectl apply -f \
https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/fixtures/stale-feature-branch.yml
After, check the logs of the operator, and you will that namespaces are deleted:
```bash {"level":"info","ts":1592322500.64014,"logger":"stale-feature-branch-controller","msg":"Stale feature branch is being processing.","namespaceSubstring":"-pr-","afterDaysWithoutDeploy":1,"checkEveryMinutes":1,"isDebug":"true"
$ claude mcp add stale-feature-branch-operator \
-- python -m otcore.mcp_server <graph>