List (Almost) Everything Inside a Namespace of a Kubernetes Cluster

One day, I was preparing to remove a no longer needed namespace of one Kubernetes cluster. Before I did that, I checked what’s inside again to be sure.

So I typed $ kubectl get all and see if I missed something. It turned out that several things were not listed in the output, like the ingresses I was expecting.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
NAME                                    READY   STATUS      RESTARTS   AGE
pod/someapp-api-558675c7cb-tzhfz        1/1     Running     0          16h
pod/someapp-cronjobs-1581948600-28wx8   0/1     Completed   0          16m
pod/someapp-cronjobs-1581949200-dfrnr   0/1     Completed   0          5m56s

NAME                   TYPE           CLUSTER-IP       EXTERNAL-IP        PORT(S)     AGE
service/someapp-api    ClusterIP      172.20.140.192   <none>             10020/TCP   61d
service/someapp-svc    ExternalName   <none>           some.fake.domain   <none>      61d

NAME                         READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/someapp-api  1/1     1            1           61d

NAME                                    DESIRED   CURRENT   READY   AGE
replicaset.apps/someapp-api-758675c7cb  1         1         1       4d9h
(...omitted)

We all know that some resources in Kubernetes are namespaced, which means these resources are put inside a certain scope (a namespace, or virtual cluster). For example, deployment, pod, role, and pvc are namespaced. Others are not, like namespace, pv, node, and clusterrole, etc.

Since $ kubectl get all doesn’t list everything, we need to combine another command $ kubectl api-resources to achieve that. This command will print all the supported API resoruces.

To get everything inside a namespace, we will use $ kubectl api-resources --namespaced=true:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
NAME                              SHORTNAMES   APIGROUP                       NAMESPACED   KIND
bindings                                                                      true         Binding
componentstatuses                 cs                                          false        ComponentStatus
configmaps                        cm                                          true         ConfigMap
endpoints                         ep                                          true         Endpoints
namespaces                        ns                                          false        Namespace
nodes                             no                                          false        Node
persistentvolumeclaims            pvc                                         true         PersistentVolumeClaim
persistentvolumes                 pv                                          false        PersistentVolume
pods                              po                                          true         Pod
(...omitted)
mutatingwebhookconfigurations                  admissionregistration.k8s.io   false        MutatingWebhookConfiguration
validatingwebhookconfigurations                admissionregistration.k8s.io   false        ValidatingWebhookConfiguration
customresourcedefinitions         crd,crds     apiextensions.k8s.io           false        CustomResourceDefinition
apiservices                                    apiregistration.k8s.io         false        APIService
controllerrevisions                            apps                           true         ControllerRevision
daemonsets                        ds           apps                           true         DaemonSet
deployments                       deploy       apps                           true         Deployment
replicasets                       rs           apps                           true         ReplicaSet
(...omitted)

That gave us what we need to pipe into $ kubectl get <api resource>, but still needs some extra works like cut -d ' ' -f 1.

It’s not that bad, just not elegant enough. Let’s see whether $ kubectl api-resources --help can help us:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Options:
      --api-group='': Limit to resources in the specified API group.
      --cached=false: Use the cached list of resources if available.
      --namespaced=true: If false, non-namespaced resources will be returned, otherwise returning namespaced resources
by default.
      --no-headers=false: When using the default or custom-column output format, don't print headers (default print
headers).
  -o, --output='': Output format. One of: wide|name.
      --sort-by='': If non-empty, sort nodes list using specified field. The field can be either 'name' or 'kind'.
      --verbs=[]: Limit to resources that support the specified verbs.

Looks like --output=name is what we need here. It’s really exciting to see command line options that perfectly meet the needs, feels like the developers think (or users make a feature request) way ahead of you.

Anyway, let’s try to put everything together:

1
2
3
4
5
6
7
$ kubectl api-resources --namespaced=true --output=name | xargs -n 1 kubectl get
Error from server (MethodNotAllowed): the server does not allow this method on the requested resource
NAME                 AGE
controller-manager   <unknown>
scheduler            <unknown>
etcd-0               <unknown>
(...omitted)

Oops, it seems there are errors, and we don’t’ know what’s the kind of API resources of each line.

Out of ideas, I had to put the kind and the name as headers for these objects. At least I can see there is indeed an ingress inside the namespace this time.

1
2
3
4
5
6
7
8
9
$ kubectl api-resources --namespaced=true --output=name | xargs -n 1 kubectl get -o custom-columns=KIND:.kind,NAME:.metadata.name
KIND   NAME
Error from server (MethodNotAllowed): the server does not allow this method on the requested resource
(...omitted)
KIND   NAME
Job    someapp-cronjobs-1581949800
KIND      NAME
Ingress   search
(...omitted)

However, it still won’t tell you what’s the resource you can’t get with $ kubectl get.

To make it more slightly understandable, I changed the command line a little bit:

1
2
3
4
5
6
7
8
$ kubectl api-resources --namespaced=true --output=name | xargs -n 1 -I 🤷‍♂️ sh -c "echo '***🤷‍♂️***:'; kubectl get 🤷‍♂️"

***bindings***:
Error from server (MethodNotAllowed): the server does not allow this method on the requested resource
***configmaps***:
NAME                       DATA   AGE
someapp-config             5      60d
(...omitted)

In the end, the solution is still not elegant enough. At least it works, though. It’s time to stop.

0%