I have a devops pipeline divided in three steps:
kubectl apply -f configmap.yml
kubectl apply -f deployment.yml
kubectl rollout restart deployment/test-service
I think that when the configmap.yml changes the rollout restart step is useful. But when only the deployment.yml changes, I'm worried that the "extra" rollout restart step is not useful and should be avoided.
Should I execute rollout restart only when the configmap.yml changes or should I don't care about?
This isn't a direct answer, but it ended up being too long for a comment and I think it's relevant. If you were to apply your manifests using kustomize (aka kubectl apply -k), then you get the following behavior:
ConfigMaps are generated with a content-based hash appended to their name
Kustomize substitutes the generated name into your Deployment
This means the Deployment is only modified when the content of the ConfigMap changes, causing an implicit re-deploy of the pods managed by the Deployment.
This largely gets you the behavior you want, but it would require some changes to your deployment pipeline.
Best practice is to annotate the deployment's pod with the hash of the configmap. If the content of the configmap changes, the annotation changes and all pods will be rolling updated. If the configmap doesn't change, nothing will happen.
E.g. with helm:
annotations:
checksum/config: {{ include (print .Template.BasePath "/configmap.yaml") . | sha256sum }}
from grafana example.
If you're not using helm you can have a script create the hash in your pipeline.
By that the rollout restart step is not required anymore. Pods will restart always if the configmap and/or the deployment changes. Otherwise nothing happens.
Related
How do we update the imagePullPolicy alone for certain deployments using kubectl? The image tag has changed, however we don't require a restart. Need to update existing deployments with --image-pull-policy as IfNotPresent
Note: Don't have the complete YAML or JSON for the deployments, hence need to do it via kubectl
use
kubectl edit deployment <deployment_name> -n namespace
Then you will be able to edit imagePullPolicy
A pod can be created by Deployment or ReplicaSet or DaemonSet, if I am updating a pod's container specs, is it OK for me to simply modify the yaml file that created the pod? Would it be erroneous once I have done that?
Brief Question:
Is kubectl apply -f xxx.yml the silver bullet for all pod update?
...if I am updating a pod's container specs, is it OK for me to simply modify the yaml file that created the pod?
The fact that the pod spec is part of the controller spec (eg. deployment, daemonset), to update the container spec you naturally start with the controller spec. Also, a running pod is largely immutable, there isn't much you can change directly unless you do a replace - which is what the controller already doing.
you should not make changes to the pods directly, but update the spec.template.spec section of the deployment used to create the pods.
reason for this is that the deployment is the controller that manages the replicasets and therefore the pods that are created for your application. that means if you apply changes to the pods manifest directly, and something like a pod rescheduling/restart happens, the changes made to the pod will be lost because the replicaset will recreate the pod according to its own specification and not the specification of the last running pod.
you are safe to use kubectl apply to apply changes to existing resources but if you are unsure, you can always extract the current state of the deployment from kubernetes and pipe that output into a yaml file to create a backup:
kubectl get deploy/<name> --namespace <namespace> -o yaml > deploy.yaml
another option is to use the internal rollback mechanism of kubernetes to restore a previous revision of your deployment. see https://learnk8s.io/kubernetes-rollbacks for more infos on that.
When deciding on update strategy for a kubernetes application, there is an option to use Recreate strategy.
How would this be different from just uninstalling and installing the app?
I assume that by "just uninstalling and installing the app" you mean complete deletion of your deployment e.g.:
kubectl delete deployment nginx-deployment
and creating it again:
kubectl apply -f nginx-deployment.yaml
Note that when using Recreate strategy there is no complete deletion of the deployment so there is fundamental difference here. By choosing this strategy you only inform kubernetes that all the pods managed by your deployment should be deleted and recreated when you update them (e.g. you update the image version of the container) rather than deleting and recreating their new versions one at a time what takes place when using RollingUpdate strategy. This way you make sure that certain number of pods serving an old version of the application are still available when the update occurs and pods with a new version of the image appear.
When you delete your deployment and create a new one, your new deployment has nothing to do with the old one. In other words, completely new Deployment resource is created and no history of the changes you made is preserved.
I believe the best way of explaining things is always an example. So let's move on to the following one.
Let's say you've created a new nginx deployment based on your yaml manifest:
kubectl apply -f nginx-deployment.yaml
and then you decided to update the image version, either by editing nginx-deployment.yaml manifest and re-applying it or this way:
kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.161 --record=true
In either case you will be able to check rollout history by running:
kubectl rollout history deployment nginx-deployment
and you should see something like this:
$ kubectl rollout history deployment nginx-deployment
deployment.apps/nginx-deployment
REVISION CHANGE-CAUSE
1 kubectl apply --filename=nginx-deployment.yaml --record=true
2 kubectl set image deployment nginx-deployment nginx=nginx:1.16.1 --record=true
When you have rollout history you're able to undo your latest change and go back to the previous revision:
kubectl rollout undo deployment.v1.apps/nginx-deployment
Now your rollout history for this deployment may look like this:
$ kubectl rollout history deployment nginx-deployment
deployment.apps/nginx-deployment
REVISION CHANGE-CAUSE
2 kubectl set image deployment nginx-deployment nginx=nginx:1.16.1 --record=true
3 kubectl apply --filename=nginx-deployment.yaml --record=true
When you simply delete your deployment and recreate it again you will have nothing in rollout history for newly created deployment and you won't be able to roll it back to some older revision in such an easy way.
Recreate strategy will delete your Pods and then add new Pods - you will get short downtime, but on the other side you will not use much extra resources during upgrade.
You typically want RollingUpgrade since that takes a few Pods at a time and you can deploy stateless applications without downtime.
Deployment resource object is still not supported in our cluster and not enabled.
We are using Pod resource object Yaml file. something like below:
apiVersion: v1
kind: Pod
metadata:
name: sample-test
namespace: default
spec:
automountServiceAccountToken: false
containers:
I have explored patch and Put rest api for Pod(Kubectl patch and replace) - it will update to new image version and pod restarts.
I need help in below:
When the image version is same, it will not update and pod will not restart.
How can i acheive Pod restart, is there any API for this or any alternate
approach for this. Because My pod also refers configmap and secret. After i
make changes to secret, i want to restart pod so that it can take updated
value.
Suppose when patch applied with new container image and it fails status is failed, I want to rollback to previous version, How can i acheive this with standalone pod without using deployment. Is there any alternate approach.
Achieving solutions for your scenario, can be handled like this:
When the image version is same, it will not update and pod will not restart. How can i acheive Pod restart, is there any API for this or any alternate approach for this. Because My pod also refers configmap and secret. After i make changes to secret, i want to restart pod so that it can take updated value
Create a new secret/configmap each time and update the pod yaml to use the new configmap/secret rather than the old name.
Suppose when patch applied with new container image and it fails status is failed, I want to rollback to previous version, How can i acheive this with standalone pod without using deployment. Is there any alternate approach
Before you do a Pod update, get the current Pod yaml using kubectl like this,
kubectl get pod <pod-name> -o yaml -n <namespace>
After getting the yaml, generate the new pod yaml and apply it. In case of failure, clean up the new resources created(configmaps & secrets) and apply the older version of pod to achieve rollback
I have deployed an application into Kubernetes using the following command.
kubectl apply -f deployment.yaml -n <NAMESPACE>
I have my deployment content in the deployment yaml file.
This is working fine. Now, I have updated few things in the deployment.yaml file and hence would like to update the deployment.
Option 1:- Delete and deploy again
kubectl delete -f deployment.yaml -n <NAMESPACE>
kubectl apply -f deployment.yaml -n <NAMESPACE>
Option 2:- Use set to update changes
kubectl set image deployment/nginx-deployment nginx=nginx:1.91
I don't want to use this approach as I am keeping my deployment.yaml file in GitHUB.
Option 3:- Using edit command
kubectl edit deployment/nginx-deployment
I don't want to use the above 3 options.
Is there any way to update the deployment using the file itself.
Like,
kubectl update deployment.yaml -n NAMESPACE
This way, I will make sure that I will always have the latest deployment file in my GitHub repo.
As #Daisy Shipton has said, what you want to do could be simplified with a simple command: kubectl apply -f deployment.yaml.
I will also add that I don't think it's correct to utilize the Option 2 to update the image utilized by the Pod with an imperative command! If the source of truth is the Deployment file present on your GitHub, you should simply update that file, by modifying the image that is used by your Pod's container there!
Next time you desire to update your Deployment object, unless you don't forget to modify the .yaml file, you will be setting the Pods to use the previous Nginx's image.
So there certainly should exist some restriction in using imperative commands to update the specification of any Kubernetes's object!