Kubernetes not updates Docker image on redeployment [duplicate] - kubernetes

This question already has answers here:
Kubernetes how to make Deployment to update image
(8 answers)
Closed 2 years ago.
Automation builds Docker image with microservice and push this image into JFrog Artifactory registry labeled by branch name registry/service-name:branch. At the next step it applies Kubernetes yaml manifest file and application starts after pulling image at the appropriate Kubernetes node.
The problem is following - when I push changes in microservice source code into repository the automation starts:
rebuild the project and push updated docker image into registry with the same label(branch)
redeploy the microservice in Kubernetes
microservice redeployed but with old image
I guess it is occurs because there are no changes in 'Deployment' section of Kubernetes yaml manifest file and Kubernetes not pull updated image from JFrog registry. As workaround, I implement inserting timestamp annotation into template section on each redeployment:
"template": {
"metadata": {
"labels": {
"app": "service-name"
},
"annotations": {
"timestamp": "1588246422"
But miracle is not happened - image updated only when I delete Kubernetes deployment and redeploy the application (may be in this case it just starts at the another node and docker pull is necessary).
Is it possible to setup Kubernetes or configure manifest file some how to force Kubernetes pull image on each redeployment?

I would suggest labeling the images in the pattern of registry/service-name:branch-git-sha or registry/service-name:git-sha which will pull the images automatically.
Or as a workaround, you can keep the current image labeling system and add an environment variable in the template which gets sets to the timestamp.
Changing the environment variable will always result in the restarting of the pods along with the config imagePullPolicy: Always.

Related

About CI/CD for kubernetes

I am using kubernetes.
I can do docker builds from GitHub and upload them to docker hub on our own.
However, I would like to automate the creation and updating of pods.
How about Circle CI for example?
Or is it possible to use the k8s library to update the pods?
You can use ArgoCD image updator
The Argo CD Image Updater can check for new versions of the container images that are deployed with your Kubernetes workloads and automatically update them to their latest allowed version using Argo CD. It works by setting appropriate application parameters for Argo CD applications, i.e. similar to argocd app set --helm-set image.tag=v1.0.1 - but in a fully automated manner.
auto-update-features
With auto image update, you just need to update the image in the docker registry and the image updater will take of the rest.
Here is the minimal annotation that will be required for the image updater to consider the specific application
annotations:
argocd-image-updater.argoproj.io/image-list: image-alias=1234.dkr.ecr.us-east-1.amazonaws.com/staging-app
argocd-image-updater.argoproj.io/image-alias.update-strategy: latest
argocd-image-updater.argoproj.io/image-alias.force-update: "true"
argocd-image-updater.argoproj.io/image-alias.allow-tags: "regexp:^build-version-tag-[0-9]+$"
argocd-image-updater.argoproj.io/image-alias.pull-secret: pullsecret:argocd/aws-registry-secret
argocd-demo-app

Application deployment over EKS using Jenkins

Can anyone tell me the deployment flow for deploying the application over Kubernetes or EKS cluster using Jenkins. How is the deployment files updated based on the change of the docker image. If we have multiple deployment files and we change any image for any one of them. Do all of them are redeployed?
Can anyone tell me the deployment flow for deploying the application over Kubernetes or EKS cluster using Jenkins.
Make sure that your Jenkins instance has an IAM Role and updated kubeconfig so that it can access the Kubernetes cluster. If you consider running the pipeline on the Kubernetes cluster, Jenkins X or Tekton Pipelines may be good alternatives that are better designed for Kubernetes.
How is the deployment files updated based on the change of the docker image.
It is a good practice to also keep the deployment manifest in version control, e.g. Git. This can be in the same repository or in a separate repository. For updating the image after a new image is built, consider using yq. An example yq command to update the image in a deployment manifest (one line):
yq write --inplace deployment.yaml 'spec.template.spec.containers(name==<myapp>).image' \
<my-registy-host>/<my-image-repository>/<my-image-name>:<my-tag-name>
If we have multiple deployment files and we change any image for any one of them. Do all of them are redeployed?
Nope, Kubernetes Yaml is declarative so it "understand" what is changed and only "drives" the necessary deployments to its "desired state" - since the other deployments already are in its "desired state".

Best practices for storing images locally to avoid problems when the image source is down (security too)?

I'm using argocd and helm charts to deploy multiple applications in a cluster. My cluster happens to be on bare metal, but I don't think that matters for this question. Also, sorry, this is probably a pretty basic question.
I ran into a problem yesterday where one of the remote image sources used by one of my helm charts was down. This brought me to a halt because I couldn't stand up one of the main services for my cluster without that image and I didn't have a local copy of it.
So, my question is, what would you consider to be best practice for storing images locally to avoid this kind of problem? Can I store charts and images locally once I've pulled them for the first time so that I don't have to always rely on third parties? Is there a way to set up a pass-through cache for helm charts and docker images?
If your scheduled pods were unable to start on a specific node with an Failed to pull image "your.docker.repo/image" error, you should consider having these images already downloaded on the nodes.
Think of how you can docker pull the images on your nodes. It may be a linux cronjob, kubernetes operator or any other solution that will ensure presence of docker image on the node even if you have connectivity issues.
As one of the options:
Create your own helm chart repository to store helm charts locally (optionally)
Create local image registry and push there needed images, also tag them accordingly for future simplicity
On each node add insecure registry by editing /etc/docker/daemon.json and adding
{
"insecure-registries" : ["myregistrydomain.com:5000"]
}
restart docker service on each node to apply changes
change your helm charts templates, set proper image path from local repo
recreate chart with new properties, (optionally)push chart to created in step 1 local helm repo
FInally install the chart - this time it should pick up images from local repo.
You may also be interested in Kubernetes-Helm Charts pointing to a local docker image

Kubernetes: --image-pull-policy always does not work

I have a Kubernetes deployment which uses image: test:latest (not real image name but it's the latest tag).
This image is on docker hub. I have just pushed a new version of test:latest to dockerhub. I was expecting a new deployment of my pod in Kubernetes but nothing happends.
I've created my deployment like this:
kubectl run sample-app --image=`test:latest` --namespace=sample-app --image-pull-policy Always
Why isn't there a new deployment triggered after the push of a new image?
Kubernetes is not watching for a new version of the image. The image pull policy specifies how to acquire the image to run the container. Always means it will try to pull a new version each time it's starting a container. To see the update you'd need to delete the Pod (not the Deployment) - the newly created Pod will run the new image.
There is no direct way to have Kubernetes automatically update running containers with new images. This would be part of a continuous delivery system (perhaps using kubectl set image with the new sha256sum or an image tag - but not latest).
One way to force the update to happen is to run this in your CI script (after pushing the new image and with image-pull-policy set to Always in the applied yaml):
kubectl rollout restart deployment/<name> --namespace=<namespace>
In Azure Devops enter "rollout" as the command, use the namespace feature above and put "restart ..." in the parameters field.
If you are working with yml files, executing deployment with
kubectl apply -f myfile.yml
and
imagePullPolicy: Always
on your file, k8s will not pull a new image. You will first need to delete the pod, and the K8s deployment will automatically pull the image.

How can we setup kubernetes to automatically change containers when a new one is pushed?

I'm using google cloud to store my Docker images & host my kubernetes cluster. I'm wondering how I can have kubernetes pull down the container which has the latest tag each time a new one is pushed.
I thought imagePullPolicy was the way to go, but it doesn't seem to be doing the job (I may be missing something). Here is my container spec:
"name": "blah",
"image": "gcr.io/project-id/container-name:latest",
"imagePullPolicy": "Always",
"env": [...]
At the moment I'm having to delete and recreate the deployments when I upload a new docker image.
Kubernetes it self will never trigger on container image update in repository. You need some sort of CI/CD pipeline in your tooling. Furthermore, I do strongly advise to avoid using :latest as it makes your container change over time. It is much better in my opinion to use some sort of versioning. Be it semantic like image:1.4.3 commit based image:<gitsha> or as I use image:<gitsha>-<pushid> where push is a sequentially updated value for each push to repo (so that label changes even if I reupload from the same build).
With such versioning, if you change image in your manifest, the deployment will get a rolling update as expected.
If you want to stick to image:latest, you can add a label with version to your pod template, so if you bump it, it will roll. You can also just kill pods manually one by one, or (if you can afford downtime) you can scale deployment to 0 replicas and back to N
Actually, you can patch your deployment so it can re-pull the spec part of your manifest (put your deployment name there)
kubectl patch deployment YOUR-DEPLOYMENT-NAME -p "{\"spec\":{\"template\":{\"metadata\":{\"annotations\":{\"date\":\"`date +'%s'`\"}}}}}"
Now, every time you push a new version in your container registry (DockerHub,ECR...), go to your kubernetes CLI and :
kubectl rollout restart deployment/YOUR-DEPLOYMENT-NAME