DEV Community

Cover image for Get a specific apiVersion manifest from k8s
Roman Geraskin
Roman Geraskin

Posted on • Originally published at rgeraskin.hashnode.dev

Get a specific apiVersion manifest from k8s

TL;DR

To get a manifest from k8s in any supported API version you can use an extended kubectl get notation like kubectl get deployments.v1beta1.extensions mydeploy -o yaml

Briefly and with examples

Everybody knows how to get a resource manifest from Kubernetes. But do you know that you can put a manifest with one apiVersion set and get the same resource manifest with another apiVersion back?

Imagine

  1. You have a deployment in a cluster, that uses api-version extensions/v1beta1 from a git repo.
  2. You've updated the cluster (1.15 => 1.16). Old deployment works fine, but you can't deploy nothing new with the old manifest because in k8s 1.16 api-version extensions/v1beta1 is absent.
  3. You have two options:
    1. Rewrite it manually or
    2. Get it from the cluster in updated spec format (apps/v1)

To get manifest from k8s you can:

below there is an example for v1.15, where extensions/v1beta1 is not removed yet

# from extensions
kubectl get deployments.extensions ext -o yaml
# from extensions, but for v1beta1
kubectl get deployments.v1beta1.extensions ext -o yaml
# from apps
kubectl get deployments.apps ext -o yaml
# from apps, but v1
kubectl get deployments.v1.apps ext -o yaml
Enter fullscreen mode Exit fullscreen mode

Notice that if you do just kubectl get deployments ext -o yaml, you will get a manifest from extensions/v1beta1 nevertheless you've even applied apps/v1 before. Details here.

Prove it

1) Start 1.15

   minikube start --kubernetes-version=v1.15.12
Enter fullscreen mode Exit fullscreen mode

2) Make 2 manifests for deployments with different versions. Note the absence of spec.selector in extensions/v1beta1

   apiVersion: apps/v1
   kind: Deployment
   metadata:
     creationTimestamp: null
     labels:
       run: apps
     name: apps
   spec:
     replicas: 1
     selector:
       matchLabels:
         run: apps
     template:
       metadata:
         creationTimestamp: null
         labels:
           run: apps
       spec:
         containers:
         - image: nginx
           name: apps
   ---
   apiVersion: extensions/v1beta1
   kind: Deployment
   metadata:
     labels:
       run: ext
     name: ext
   spec:
     replicas: 1
     template:
       metadata:
         creationTimestamp: null
         labels:
           run: ext
       spec:
         containers:
         - image: nginx
           name: ext
Enter fullscreen mode Exit fullscreen mode

3) Apply

   ❯ minikube kubectl -- apply -f .
   deployment.apps/apps created
   deployment.extensions/ext created
Enter fullscreen mode Exit fullscreen mode

4) Check that resources apps and ext are in extensions/v1beta1 and in apps/v1 too

  • The hard way - curl:
   ❯ minikube kubectl -- proxy
   Starting to serve on 127.0.0.1:8001
   ❯ curl -s 127.0.0.1:8001/apis/extensions/v1beta1/namespaces/default/deployments/apps | yq . --yaml-output
   kind: Deployment
   apiVersion: extensions/v1beta1
   # ...
   ❯ curl -s 127.0.0.1:8001/apis/extensions/v1beta1/namespaces/default/deployments/ext | yq . --yaml-output
   kind: Deployment
   apiVersion: extensions/v1beta1
   # ...
   ❯ curl -s 127.0.0.1:8001/apis/apps/v1/namespaces/default/deployments/apps | yq . --yaml-output
   kind: Deployment
   apiVersion: apps/v1
   # ...
   ❯ curl -s 127.0.0.1:8001/apis/apps/v1/namespaces/default/deployments/ext | yq . --yaml-output
   kind: Deployment
   apiVersion: apps/v1
   # ...
Enter fullscreen mode Exit fullscreen mode
  • Or kubectl:
   # from extensions
   kubectl get deployments.extensions ext -o yaml
   # from extensions, but v1beta1
   kubectl get deployments.v1beta1.extensions ext -o yaml
   # from apps
   kubectl get deployments.apps ext -o yaml
   # from apps, but v1
   kubectl get deployments.v1.apps ext -o yaml
Enter fullscreen mode Exit fullscreen mode

Bonus: kubectl explain

If you do kubectl explain deployment than (surprise!) you'll get a description for extensions/v1beta1. Because kubectl explain works the same way, just like kubectl get:

If you want a specific version, use an --api-version flag :

minikube kubectl -- explain deployment.spec --api-version apps/v1
minikube kubectl -- explain deployment.spec --api-version extensions/v1beta1
Enter fullscreen mode Exit fullscreen mode

Top comments (2)

Collapse
 
bcouetil profile image
Benoit COUETIL 💫

Welcome, and thank you for sharing !

That is a nice trick, I did not know about it.

What use case made you discover this ? Why would you not need the latest version ?

Collapse
 
rgeraskin profile image
Roman Geraskin

I don't remember, it was kind of incidental catch)

But you can still have some situations where this trick can be useful. E.g. you have some manifest deployed in a test cluster and you want to copy it to stage. And k8s version in test is newer than stage.