Delete Kubernetes namespace only if it's empty? - kubernetes

I am using Helm to deploy multiple "components" of my application into a single namespace and using Jenkins to trigger create and destroy jobs. It doesn't seem that I can use Helm to delete the namespace thus I am looking to just use a Kubernetes command.
However, It seems that if I use kubectl delete namespace it will forcefully destroy the namespace and all its resources.
I'd like to destroy the namespace only if it is empty. Is there a command to do this?

I'd like destroy the namespace only if it is empty. Is there a command
to do this?
No there is not command to do that. This behavior is by design.
I would suggest a different approach. You should have all your deployment yamls in version control system for all of the components including namespace. When you want to create use kubectl create -f deployment.yaml and when you want to delete use kubectl delete -f deployment.yaml

See Remove Empty Namespaces Operator, it can do exactly what you want.
Why? Because it's not so easy to iterate over resources in the namespace to decide if it's empty or not. After all, there are "default resources" like default service account and probably other stuff from you tooling/operators.
So these resources should be excluded from iteration. Bash scripting becomes too complicated this way. And one day I decided to implement it with Python.

You can run kubectl get all --namespace YOUR_NAMESPACE and then depends on output call delete namespace

try this, better iterate over kube-api resources and this will give every resource list inside the namespace.
kubectl api-resources --verbs=list --namespaced -o name \
| xargs -n 1 kubectl get --show-kind --ignore-not-found -l <label>=<value> -n
<namespace>
or another approch
kubectl api-resources --verbs=list --namespaced -o name | `
%{ kubectl get $_ --show-kind --ignore-not-found -l <label>=<value> -n
<namespace> }

There's not a simple command to check a namespace before delete, it requires some kubectl scripting or a kube API client.
From the github issue discussing get alls limitations liggit provides an example and adding some jq processing you can get a (slow) command that errors unless it successfully finds all resource types are empty (no items):
set -o pipefail
kubectl api-resources --verbs=list --namespaced -o name \
| xargs -n 1 kubectl get --ignore-not-found -n YOUR_NAMESPACE -o json \
| jq '.items[] | .kind + "/" + .metadata.name | error'

just use folloing to delete all empty namespaces
kubectl get ns --no-headers -o custom-columns=":metadata.name" | xargs -I{} kubectl get all -n {} 2>&1 | grep "No" | cut -d " " -f 5 | xargs -I{} kubectl delete namespace {}
you can list empty namespaces by this
kubectl get ns --no-headers -o custom-columns=":metadata.name" | xargs -I{} kubectl get all -n {} 2>&1 | grep "No" | cut -d " " -f 5

Related

How to delete multiple namespaces with label option

I have generated a bunch of namespaces like below and now i want to delete only these name spaces without deleting kube-system namespaces,i tried with grep but no success
kubectl delete namespaces | grep "gatling*"
error: resource(s) were provided, but no name, label selector, or --all flag specified
Multiple namespaces
First get the names of the namespaces you want to delete:
kubectl get namespaces --no-headers=true -o custom-columns=:metadata.name | grep gatling
With -o custom-columns=:metadata.name we output only the names of the services. The output is piped to grep, which filters them by looking for gatling.
Then run the delete command for each line with xargs:
kubectl get namespaces --no-headers=true -o custom-columns=:metadata.name | grep gatling | xargs kubectl delete namespace

Kubernetes POD delete with Pattern Match or Wildcard

When I am using below it deletes the running POD after matching the pattern from commandline:
kubectl get pods -n bi-dev --no-headers=true | awk '/group-react/{print $1}' | xargs kubectl delete -n bi-dev pod
However when I am using this command as an alias in .bash_profile it doesn't execute .
This is how I defined it :
alias kdpgroup="kubectl get pods -n bi-dev --no-headers=true | awk '/group-react/{print $1}'| kubectl delete -n bi-dev pod"
when execute this as below I get below error in commandline:
~ $ kdpgroup
error: resource(s) were provided, but no name, label selector, or --all flag specified
When I define this in .bash_profile I get this :
~ $ . ./.bash_profile
-bash: alias: }| xargs kubectl delete -n bi-dev pod: not found
~ $
Am I missing something to delete POD using Pattern Match or with Wilcard ?
thanks
Am I missing something to delete POD using Pattern Match or with Wilcard?
When using Kubernetes it is more common to use labels and selectors. E.g. if you deployed an application, you usually set a label on the pods e.g. app=my-app and you can then get the pods with e.g. kubectl get pods -l app=my-app.
Using this aproach, it is easier to delete the pods you are interested in, with e.g.
kubectl delete pods -l app=my-app
or with namespaces
kubectl delete pods -l app=my-app -n default
See more on Kubernetes Labels and Selectors
Set-based selector
I have some pod's running in the name of "superset-react" and "superset-graphql" and I want to search my wildcard superset and delete both of them in one command
I suggest that those pods has labels app=something-react and app=something-graphql. If you want to classify those apps, e.g. if your "superset" varies, you could add a label app-type=react and app-type=graphql to all those type of apps.
Then you can delete pods for both app types with this command:
kubectl delete pods -l 'app-type in (react, graphql)'
As the question asks, this is about using a wild card. Let me give examples on using wild cards to delete pods.
Delete Pods which contain the word "application"
Replace <namespace> with the namespace you want to delete pods from.
kubectl get pods -n <namespace> --no-headers=true | awk '/application/{print $1}'| xargs kubectl delete -n <namespace> pod
This will give a response like the following. It will print out the deleted pods.
pod "sre-application-7fb4f5bff9-8crgx" deleted
pod "sre-application-7fb4f5bff9-ftzfd" deleted
pod "sre-application-7fb4f5bff9-rrkt2" deleted
Delete Pods which contain "application" or "service"
Replace <namespace> with the namespace you want to delete pods from.
kubectl get pods -n <namespace> --no-headers=true | awk '/application|service/{print $1}'| xargs kubectl delete -n <namespace> pod
This will give a response like the following. It will print out the deleted pods.
pod "sre-application-7fb4f5bff9-8crgx" deleted
pod "sre-application-7fb4f5bff9-ftzfd" deleted
pod "sre-service-7fb4f5bff9-rrkt2" deleted
You just need to escape the '$1' variable in the awk command:
alias kdpgroup="kubectl get pods -n bi-dev --no-headers=true | awk '/group-react/{print \$1}'| xargs kubectl delete -n bi-dev pod"
I know that escape is boring, and if you want to avoid it you can use as a function in you .bash_profile:
kdpgroup() {
kubectl get pods -n default --no-headers=true | awk '{print $1}' | xargs kubectl delete pod -n default
}
A robust way with variables, based on #keetSugathadasa answer:
ns="optional-namespace"
regex="pattern"
kubectl get pods ${ns:+ -n $ns} --no-headers | awk /${regex}/'{print $1}' \
| xargs kubectl delete ${ns:+ -n $ns} pod
using grep you can filter the keyword like this and delete matching pod name like this
kubectl get pods --no-headers=true | awk '{print $1}' | grep keyword | xargs kubectl delete pod

Listing all resources in a namespace

I would like to see all resources in a namespace.
Doing kubectl get all will, despite of the name, not list things like services and ingresses.
If I know the the type I can explicitly ask for that particular type, but it seems there is also no command for listing all possible types. (Especially kubectl get does for example not list custom types).
Any idea how to show all resources before for example deleting that namespace?
Based on this comment , the supported way to list all resources is to iterate through all the api versions listed by kubectl api-resources:
kubectl api-resources enumerates the resource types available in your cluster.
this means you can combine it with kubectl get to actually list every instance of every resource type in a namespace:
kubectl api-resources --verbs=list --namespaced -o name \
| xargs -n 1 kubectl get --show-kind --ignore-not-found -l <label>=<value> -n <namespace>
This may not get all resources but it may be what someone is looking for
kubectl get all,cm,secret,ing -A
This seems to get most of the resources, prefixed with the type.
At least, it gets:
pod
service
daemonset
deployment
replicaset
statefulset
job
configmap
secret
ingress
This doesn't get custom resources but does get services.
Else this does something similar:
for i in `kubectl api-resources | awk '{print $1}'`; do kubectl get $i; done
Running v1.13
I ended up needing this same functionality due to failed Helm deployments that left remnants in a specific namespace. Here's a function you can put in your bash profile:
function kubectlgetall {
for i in $(kubectl api-resources --verbs=list --namespaced -o name | grep -v "events.events.k8s.io" | grep -v "events" | sort | uniq); do
echo "Resource:" $i
if [ -z "$1" ]
then
kubectl get --ignore-not-found ${i}
else
kubectl -n ${1} get --ignore-not-found ${i}
fi
done
}
Usage: kubectlgetall <namespace>
Example: get all resources from the kafka namespace:
kubectlgetall kafka
Complete solution
kubectl -n <NAMESPACE> get $(kubectl api-resources --namespaced=true --no-headers -o name | egrep -v 'events|nodes' | paste -s -d, - ) --no-headers
Answer of rcorre is correct but for N resources it make N requests to cluster (so for a lot of resources this approach is very slow). Moreover, not found resources (that have not instances) are very slow for getting with kubectl get.
There is a better way to make a request for multiple resources:
kubectl get pods,svc,secrets
instead of
kubectl get pods
kubectl get svc
kubectl get secrets
So the answer is:
#!/usr/bin/env bash
# get all names and concatenate them with comma
NAMES="$(kubectl api-resources \
--namespaced \
--verbs list \
-o name \
| tr '\n' ,)"
# ${NAMES:0:-1} -- because of `tr` command added trailing comma
# --show-kind is optional
kubectl get "${NAMES:0:-1}" --show-kind
or
#!/usr/bin/env bash
# get all names
NAMES=( $(kubectl api-resources \
--namespaced \
--verbs list \
-o name) )
# Now join names into single string delimited with comma
# Note *, not #
IFS=,
NAMES="${NAMES[*]}"
unset IFS
# --show-kind is enabled implicitly
kubectl get "$NAMES"
If you are using kubectl krew plug-in, I will suggest using get-all.
It can get almost 90% of resources. Including configmap, secret, endpoints, istio, etc...
A Powershell implementation of rcorre's answer would look like
kubectl api-resources --verbs=list --namespaced -o name | `
%{ kubectl get $_ --show-kind --ignore-not-found -l <label>=<value> -n <namespace> }
All kubernetes objects are stored in etcd.
All objects are stored in ETCD v3 the following way:
/registry/<object_type>/<namespace>/<name>
I suggest just to take the list of all resources of some namespace from etcd v3 directly:
ETCDCTL_API=3 etcdctl --endpoints=<etcd_ip>:2379 get / --prefix --keys-only | grep -E "^/\w+/\w+/<namespace>/+"
Just covering some basics:
Resources can be fetched using the kubectl get command.
Resources can be filtered by namespace using the -n [NAMESPACE] or --namespace [NAMESPACE] flags.
I will use the -A (same as --all-namespaces) flag in the following examples for brevity.
Some of the other answers show how to list available resource types:
kubectl api-resources --verbs=list -o name
With this in mind, we can get all resources, leveraging xargs and sed:
kubectl get "all,$(kubectl api-resources --verbs=list -o name | xargs | sed 's/ /,/g')" -A
An alternative to xargs is to use tr:
kubectl get "$(kubectl api-resources --verbs=list -o name | tr '\n' ',')all" -A
I think this could be se simplest way to print out all the resource name in a kubernetes cluster:
#!/bin/bash
for resource in [$(kubectl api-resources -o name | tr "\n" " ")]
do
kubectl get $resource --all-namespaces -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}'
done
to specify the namespace you just need to modify the line in the loop setting --namespace=<your-namespace> and remove --all-namespaces
Here's a PowerShell version of what other's have said
function getall {
# https://stackoverflow.com/questions/47691479/listing-all-resources-in-a-namespace
[CmdletBinding()]
param(
$namespace
)
$types=kubectl api-resources --verbs=list --namespaced -o name
kubectl get $($types -join ",") -n $namespace --show-kind
}
It's not a 100% solution, but for me works the following
kgetall='kubectl get namespace,replicaset,secret,nodes,job,daemonset,statefulset,ingress,configmap,pv,pvc,service,deployment,pod --all-namespaces'
and just call
kgetall
But obviously I expected that behavior from
kubectl get all --all-namespaces
in the first place.
Following this solution, in fish shell it looks like below.
Add the following function to your ~/.config/fish/config.fish
function kall
kubectl -n $argv get (string join ',' (kubectl api-resources --namespaced --verbs list -o name))
end
the easy way for me to retrieve all the contents of the namespace was
kubectl get all -n

How do I extract multiple values from kubectl with jsonpath

I've found jsonpath examples for testing multiple values but not extracting multiple values.
I want to get image and name from kubectl get pods.
this gets me name
kubectl get pods -o=jsonpath='{.items[*].spec.containers[*].name}' | xargs -n 1
this gets me image
kubectl get pods -o=jsonpath='{.items[*].spec.containers[*].image}' | xargs -n 1
but
kubectl get pods -o=jsonpath='{.items[*].spec.containers[*].[name,image}' | xargs -n 2
complains invalid array index image - is there a syntax for getting a list of node-adjacent values?
Use below command to get name and image:
kubectl get pods -Ao jsonpath='{range .items[*]}{#.metadata.name}{" "}{#.spec.template.spec.containers[].image}{"\n"}{end}'
It will give output like below:
name image
Useful command, I had to modify it a little to make it work (failed with -a flag). Also, I added a filter to app label and one more field to get: namespace, pod name, image
kubectl get pods --all-namespaces -o jsonpath='{range .items[*]}{#.metadata.namespace}{"\t"}{#.metadata.name}{"\t"}{#.spec.containers[*].image}{"\n"}{end}' -l app=nginx
Thanks! I had to change a little bit, but this worked for me:
#!/bin/bash
releases=$(kubectl get deployment -A --output=jsonpath='{range .items[*]}{#.metadata.namespace}{"|"}{#.metadata.name}{"\n"}{end}')
for release in $releases; do
namespace=$( echo $release | cut -d "|" -f 1)
deployment=$( echo $release | cut -d "|" -f 2)
kubectl rollout restart deployments -n "${namespace}" "${deployment}"
done

kubernetes list all running pods name

I looking for the option to list all pods name
How to do without awk (or cut). Now i'm using this command
kubectl get --no-headers=true pods -o name | awk -F "/" '{print $2}'
Personally I prefer this method because it relies only on kubectl, is not very verbose and we don't get the pod/ prefix in the output:
kubectl get pods --no-headers -o custom-columns=":metadata.name"
You can use the go templating option built into kubectl to format the output to just show the names for each pod:
kubectl get pods --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}'
Get Names of pods using -o=name Refer this cheatsheet for more.
kubectl get pods -o=name
Example output:
pod/kube-xyz-53kg5
pod/kube-xyz-jh7d2
pod/kube-xyz-subt9
To remove trailing pod/ you can use standard bash sed command
kubectl get pods -o=name | sed "s/^.\{4\}//"
Example output:
kube-xyz-53kg5
kube-pqr-jh7d2
kube-abc-s2bt9
To get podname with particular string, standard linux grep command
kubectl get pods -o=name | grep kube-pqr | sed "s/^.\{4\}//"
Example output:
kube-pqr-jh7d2
With this name, you can do things, like adding alias to get shell to running container:
alias bashkubepqr='kubectl exec -it $(kubectl get pods -o=name | grep kube-pqr | sed "s/^.\{4\}//") bash'
You can use custom-columns in output option to get the name and --no-headers option
kubectl get --no-headers=true pods -l app=external-dns -o custom-columns=:metadata.name
You can use -o=name to display only pod names. For example to list proxy pods you can use:
kubectl get pods -o=name --all-namespaces | grep kube-proxy
The result is:
pod/kube-proxy-95rlj
pod/kube-proxy-bm77b
pod/kube-proxy-clc25
There is also this solution:
kubectl get pods -o jsonpath={..metadata.name}
Here is another way to do it:
kubectl get pods -o=name --field-selector=status.phase=Running
The --field-selector=status.phase=Running is needed as the question mention all the running pod names. If the all in the question is for all the namespaces, just add the --all-namespaces option.
Note that this command is very convenient when one want a quick way to access something from the running pod(s), such as logs :
kubectl logs -f $(kubectl get pods -o=name --field-selector=status.phase=Running)
Get all running pods in the namespace
kubectl get pods --field-selector=status.phase=Running --no-headers -o custom-columns=":metadata.name"
From viewing, finding resources.
You could also specify namespace with -n <namespace name>.
jsonpath alternative
kubectl get po -o jsonpath="{range .items[*]}{#.metadata.name}{end}" -l app=nginx-ingress,component=controller
see also:
more examples of kubectl output options
If you want to extract specific container's pod name then
A simple command can do all the hard work
kubectl get pods --template '{{range .items}}{{.metadata.name}}{{end}}' --selector=app=<CONTAINER-NAME>
Just replace <CONTAINER-NAME> with your service container-name
Well, In our case we have kept pods inside different namespace, here to identify the specific pod or list of pods we ran following command-
Approach 1:
To get the list of namespaces
kubectl get ns -A
To get all the pods inside one namespaces kubectl get pods -n <namespace>
Approach 2:
Use this command-
kubectl get pods --all-namespaces
kubectl exec -it $(kubectl get pods | grep mess | awk '{print $1}') /bin/bash
kubectl get po --all-namespaces | awk '{if ($4 != "Running") system ("kubectl -n " $1 " delete pods " $2 " --grace-period=0 " " --force ")}'