Kubernetes: Error from server when edit Deployment [duplicate] - kubernetes

I have defined a Deployment for my app:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: myapp-deployment
spec:
replicas: 2
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: 172.20.34.206:5000/myapp_img:2.0
ports:
- containerPort: 8080
Now, if I want update my app's image 2.0 to 3.0, I do this:
$ kubectl edit deployment/myapp-deployment
vim is open. I change the image version from 2.0 to 3.0 and save.
How can it be automated? Is there a way to do it just running a command? Something like:
$ kubectl edit deployment/myapp-deployment --image=172.20.34.206:5000/myapp:img:3.0
I thought using Kubernetes API REST but I don't understand the documentation.

You could do it via the REST API using the PATCH verb. However, an easier way is to use kubectl patch. The following command updates your app's tag:
kubectl patch deployment myapp-deployment -p \
'{"spec":{"template":{"spec":{"containers":[{"name":"myapp","image":"172.20.34.206:5000/myapp:img:3.0"}]}}}}'
According to the documentation, YAML format should be accepted as well. See Kubernetes issue #458 though (and in particular this comment) which may hint at a problem.

There is a set image command which may be useful in simple cases
Update existing container image(s) of resources.
Possible resources include (case insensitive):
pod (po), replicationcontroller (rc), deployment (deploy), daemonset (ds), job, replicaset (rs)
kubectl set image (-f FILENAME | TYPE NAME) CONTAINER_NAME_1=CONTAINER_IMAGE_1 ... CONTAINER_NAME_N=CONTAINER_IMAGE_N
http://kubernetes.io/docs/user-guide/kubectl/kubectl_set_image/
$ kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
deployment "nginx-deployment" image updated
http://kubernetes.io/docs/user-guide/deployments/

(I would have posted this as a comment if I had enough reputation)
Yes, as per http://kubernetes.io/docs/user-guide/kubectl/kubectl_patch/ both JSON and YAML formats are accepted.
But I see that all the examples there are using JSON format.
Filed https://github.com/kubernetes/kubernetes.github.io/issues/458 to add a YAML format example.

I have recently built a tool to automate deployment updates when new images are available, it works with Kubernetes and Helm:
https://github.com/rusenask/keel
You only have to label your deployments with Keel policy like keel.sh/policy=major to enable major version updates, more info in the readme. Works similarly with Helm, no additional CLI/UI required.

Related

How do I update a deployment via YAML with rollback support?

I am trying to update a deployment via the YAML file, similar to this question. I have the following yaml file...
apiVersion: apps/v1
kind: Deployment
metadata:
name: simple-server-deployment
labels:
app: simple-server
spec:
replicas: 3
selector:
matchLabels:
app: simple-server
template:
metadata:
labels:
app: simple-server
spec:
containers:
- name: simple-server
image: nginx
ports:
- name: http
containerPort: 80
I tried changing the code by changing replicas: 3 to replicas: 1. Next I redeployed like kubectl apply -f simple-deployment.yml and I get deployment.apps/simple-server-deployment configured. However, when I run kubectl rollout history deployment/simple-server-deployment I only see 1 entry...
REVISION CHANGE-CAUSE
1 <none>
How do I do the same thing while increasing the revision so it is possible to rollback?
I know this can be done without the YAML but this is just an example case. In the real world I will have far more changes and need to use the YAML.
You can use --record flag so in your case the command will look like:
kubectl apply -f simple-deployment.yml --record
However, a few notes.
First, --record flag is deprecated - you will see following message when you will run kubectl apply with the --record flag:
Flag --record has been deprecated, --record will be removed in the future
However, there is no replacement for this flag yet, but keep in mind that in the future there probably will be.
Second thing, not every change will be recorded (even with --record flag) - I tested your example from the main question and there is no new revision. Why? It's because::
#deech this is expected behavior. The Deployment only create a new revision (i.e. another Replica Set) when you update its pod template. Scaling it won't create another revision.
Considering the two above, you need to think (and probably test) if the --record flag is suitable for you. Maybe it's better to use some version control system like git, but as I said, it depends on your requirements.
Change of replicas does not create new history record. You can add --record to you apply command and check the annotation later to see what was the last spec applied.

kubectl rollout restart deployment <deployment-name> doesn't get the latest image

Why does kubectl rollout restart <deployment-name> doesn't get my latest image? I had rebuild my image but it seems that kubernetes doesn't update my deployment with the latest image.
tl;dr
I just wanted to add an answer here regarding the failure of kubectl rollout restart deployment [my-deployment-name]. My problem was that I changed the image name, without running kubectl apply -f [my-deployment-filename>.yaml first.
Long Answer
So my earlier image name is microservices/posts which is in my local and looked like this.
# This is a file named `posts-depl.yaml`
apiVersion: apps/v1
kind: Deployment
metadata:
name: posts-depl
spec:
replicas: 1
selector:
matchLabels:
app: posts
template:
metadata:
labels:
app: posts
spec:
containers:
- name: posts
image: microservices/posts
However, since I need to push it to Docker Hub, I rebuild the image with a new name of [my docker hub username]/microservices_posts then I pushed. Then I updated the posts-depl.yaml to look like this.
# Still same file `posts-depl.yaml` but updated
apiVersion: apps/v1
kind: Deployment
metadata:
name: posts-depl
spec:
replicas: 1
selector:
matchLabels:
app: posts
template:
metadata:
labels:
app: posts
spec:
containers:
- name: posts
image: [my docker hub username]/microservices_posts # Notice that I only change this part
Apparently, when I ran kubectl rollout restart deployment posts-depl, it didn't update. Then I finally decided to go to StackOverflow. I just thought I had a wrong mistake or probably meet up with kubernetes bug or something.
But turns out I had to run kubectl apply -f <your deployment filename>.yaml again. Then it's running fine.
Just sharing, might change someone's life. ;)
So for a review here..
It seems that my past deployment which is posts-depl is cached with the image name of my earlier image which is microservices/posts, and since I build a new image named [my docker hub username]/microservices_posts it doesn't acknowledge that. So when I run kubectl rollout restart deployment <deployment name>. What it does instead was looking for the microservices/posts image which is on my local! But since it was not updated, it doesn't do a thing!
Hence, what I should be doing was re-running kubectl apply -f <my deployment filename>.yaml again which already has been updated with the new image name as [my docker hub username]/microservices_posts!
Then, I live happily ever after.
Hope that helps and may you live happily ever after too.

Kubectl apply does not update pods or deployments

I'm using a CI to update my kubernetes cluster whenever there's an update to an image. Whenever the image is pushed and has the latest tag it kubectl apply's the existing deployment but nothing gets updated.
this is what runs
$ kubectl apply --record --filename /tmp/deployment.yaml
My goal is when the apply is ran that a rolling deployment gets executed.
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: api
spec:
replicas: 1
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: us.gcr.io/joule-eed41/api:latest
imagePullPolicy: Always
ports:
- containerPort: 1337
args:
- /bin/sh
- -c
- echo running api;npm start
env:
- name: NAMESPACE
valueFrom:
configMapKeyRef:
name: config
key: NAMESPACE
As others suggested, have a specific tag.
Set new image using following command
kubectl set image deployment/deployment_name deployment_name=image_name:image_tag
In your case it would be
kubectl set image deployment/api api=us.gcr.io/joule-eed41/api:0.1
As #ksholla20 mentionedm using kubectl set image is a good option for many (most?) cases.
But if you can't change the image tag consider using:
1 ) kubectl rollout restart deployment/<name>
(reference).
2 ) kubectl patch deployment <name> -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"version\":\"$CURRENT_BUILD_HASH_OR_DATE\"}}}}}}" (reference)
(*) Notice that the patch command allow you to change specific properties in the deployment (or any other object chosen) like the label selector and the pod label or other properties like the value of the NAMESPACE environment variable in your example.
I've run into the same problem and none of the solutions posted so far will help. The solution is easy, but not easy to see or predict. The applied yaml will generate both a deployment and a replicaset the first time it's run. Unfortunately, applying changes to the manifest likely only replaces the replicaset, while the deployment will remain unchanged. This is a problem because some changes need to happen at the deployment level, but the old deployment hangs around. To have best results, delete the deployment and ensure all previous deployments and replicasets are deleted. Then apply the updated manifest.

Single Container Pod yaml

Forgive my ignorance but I can't seem to find a way of using a yaml file to deploy a single container pod (read: kind: Pod). It appears the only way to do it is to use a deployment yaml file (read: kind: Deployment) with a replica of 1.
Is there really no way?
Why I ask is because it would be nice to put everything in source control, including the one off's like databases.
It would be awesome if there was a site with all the available options you can use in a yaml file (like vagrant's vagrantfile). There isn't one, right?
Thanks!
You should be able to find pod yaml files easily. For example, the documentation has an example of a Pod being created.
apiVersion: v1
kind: Pod
metadata:
name: hello-world
spec: # specification of the pod's contents
restartPolicy: Never
containers:
- name: hello
image: "ubuntu:14.04"
command: ["/bin/echo", "hello", "world"]
One thing to note is that if a deployment or a replicaset created a resource on your behalf, there is no reason why you couldn't do the same.
kubectl get pod <pod-name> -o yaml should give you the YAML spec of a created pod.
There is Kubernetes charts, which serves as a repository for configuration surrounding complex applications, using the helm package manager. This would serve you well for deploying more complex applications.
Never mind, figured it out. It's possible. You just use the multi-container yaml file (example found here: https://kubernetes.io/docs/user-guide/pods/multi-container/) but only specify one container.
I'd tried it before but had inadvertently mistyped the yaml formatting.
Thanks rubber ducky!

How can I edit a Deployment without modify the file manually?

I have defined a Deployment for my app:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: myapp-deployment
spec:
replicas: 2
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: 172.20.34.206:5000/myapp_img:2.0
ports:
- containerPort: 8080
Now, if I want update my app's image 2.0 to 3.0, I do this:
$ kubectl edit deployment/myapp-deployment
vim is open. I change the image version from 2.0 to 3.0 and save.
How can it be automated? Is there a way to do it just running a command? Something like:
$ kubectl edit deployment/myapp-deployment --image=172.20.34.206:5000/myapp:img:3.0
I thought using Kubernetes API REST but I don't understand the documentation.
You could do it via the REST API using the PATCH verb. However, an easier way is to use kubectl patch. The following command updates your app's tag:
kubectl patch deployment myapp-deployment -p \
'{"spec":{"template":{"spec":{"containers":[{"name":"myapp","image":"172.20.34.206:5000/myapp:img:3.0"}]}}}}'
According to the documentation, YAML format should be accepted as well. See Kubernetes issue #458 though (and in particular this comment) which may hint at a problem.
There is a set image command which may be useful in simple cases
Update existing container image(s) of resources.
Possible resources include (case insensitive):
pod (po), replicationcontroller (rc), deployment (deploy), daemonset (ds), job, replicaset (rs)
kubectl set image (-f FILENAME | TYPE NAME) CONTAINER_NAME_1=CONTAINER_IMAGE_1 ... CONTAINER_NAME_N=CONTAINER_IMAGE_N
http://kubernetes.io/docs/user-guide/kubectl/kubectl_set_image/
$ kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
deployment "nginx-deployment" image updated
http://kubernetes.io/docs/user-guide/deployments/
(I would have posted this as a comment if I had enough reputation)
Yes, as per http://kubernetes.io/docs/user-guide/kubectl/kubectl_patch/ both JSON and YAML formats are accepted.
But I see that all the examples there are using JSON format.
Filed https://github.com/kubernetes/kubernetes.github.io/issues/458 to add a YAML format example.
I have recently built a tool to automate deployment updates when new images are available, it works with Kubernetes and Helm:
https://github.com/rusenask/keel
You only have to label your deployments with Keel policy like keel.sh/policy=major to enable major version updates, more info in the readme. Works similarly with Helm, no additional CLI/UI required.