TL;DR
To get a manifest from k8s in any supported API version you can use an extended
kubectl get
notation likekubectl 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
- You have a
deployment
in a cluster, that usesapi-version extensions/v1beta1
from a git repo. - 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. - You have two options:
- Rewrite it manually or
- 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
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
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
3) Apply
❯ minikube kubectl -- apply -f .
deployment.apps/apps created
deployment.extensions/ext created
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
# ...
- 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
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
Top comments (2)
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 ?
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.