Auto update pod on every image push to GCR - kubernetes

I have a docker image pushed to Container Registry with docker push gcr.io/go-demo/servertime and a pod created with kubectl run servertime --image=gcr.io/go-demo-144214/servertime --port=8080.
How can I enable automatic update of the pod everytime I push a new version of the image?

I would suggest switching to some kind of CI to manage the process, and instead of triggering on docker push triggering the process on pushing the commit to git repository. Also if you switch to using a higher level kubernetes construct such as deployment, you will be able to run a rolling-update of your pods to your new image version. Our process is roughly as follows :
git commit #triggers CI build
docker build yourimage:gitsha1
docker push yourimage:gitsha1
sed -i 's/{{TAG}}/gitsha1/g' deployment.yml
kubectl apply -f deployment.yml
Where deployment.yml is a template for our deployment that will be updated to new tag version.
If you do it manually, it might be easier to simply update image in an existing deployment by running kubectl set image deployment/yourdeployment <containernameinpod>=yourimage:gitsha1

I'm on the Spinnaker team.
Might be a bit heavy, but without knowing your other areas of consideration, Spinnaker is a CD platform from which you can trigger k8s deployments from registry updates.
Here's a codelab to get you a started.
If you'd rather shortcut the setup process, you can get a starter Spinnaker instance with k8s and GCR integration pre-setup via the Cloud Launcher.
You can find further support on our slack channel (I'm #stevenkim).

It would need some glue, but you could use Docker Hub, which lets you define a webhook for each repository when a new image is pushed or a new tag created.
This would mean you'd have to build your own web API server to handle the incoming notifications and use them to update the pod. And you'd have to use Docker Hub, not Google Container Repository, which doesn't allow web hooks.
So, probably too many changes for the problem you're trying to solve.

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

Container deployment with self-managed kubernetes in AWS

I am relatively new to AWS and kubernetes. I have created a self-managed kubernetes cluster running in AWS (not using EKS). I have successfully created a pipeline in AWS CodePipeline that builds my container and uploads it to ECR. Currently I am manually deploying the created image in the cluster by running the following commands:
kubectl delete deployment my-service
kubectl apply -f my-service_deployment.yaml
How can I automate this manual step in AWS CodePipeline? How can I run the above commands as part of the pipeline?
Regarding my deployment yaml files, where should I store these files? (currently I store them locally in the master node.)
I am missing some best practices for this process.
Your yaml manifests should'nt be on your master node (never), they should be stored in a Version Control System (just like github/gitlab/bitbucket etc.).
To automate the deployment of your docker image based on new artifact version in ECR, you can use a great tools named FluxCD, it is actually very simple to install (https://fluxcd.io/docs/get-started/) and you can easily configure it to automatically deploy your images in your cluster each time there is a new image on your ECR registry.
This way your codePipeline will build the code, do the tests, build the image, tag it and push it to ECR and FluxCD will deploy it to kubernetes. (it is also natively configurable to deploy on each X minutes (based on your configuration) on your cluster, so even if you bring a little change into your manifests, it will be automatically deployed !
bguess
you can also make use of argo cd its very easy to install and use compared to aws codepipeline.
argo cd was specifically designed for Kubernetes thus offers much better way to deploy to K8s

Best practice for sanity test a K8s cluster? (ideally all from command line)

I am new here, I tried to search for the topic before I post here, this may have been discussed before, please let me know before being to hash on me :)
In my project, after performing some changes on either the DevOps tool sets or infrastructures, we always do some manual sanity test, this normally includes:
Building a new image and update the helm chart
Push the image to Artifactory and perform a "helm update", and see it it runs.
I want to automate the whole thing, and try to get advice from the community, here's some requirement:
Validate Jenkins agent being able to talk to cluster ( I can do this with kubectl get all -n <some_namespace_jenkins_user_has_access_to)
Validate the cluster has access to Github (let's say I am using Argo CD to sync yamls)
Validate the cluster has access to Artifactory and able to pull image ( I don't want to build a new image with new tag and update helm chart, so that to force to cluster to pull new image)
All of the above can be done in command line (so that I can implement using Jenkins groovy)
Any suggestion is welcome.
Thanks guys
Your best bet is probably a combination of custom Jenkins scripts (i.e. running kubectl in Jenkins) and some in-cluster checks (e.g. using kuberhealthy).
So, when your Jenkins pipeline is triggered, it could do the following:
Check connectivity to the cluster
Build and push an image, etc.
Trigger in-cluster checks for testing if the cluster has access to GitHub and Artifactory, e.g. by launching a custom Job in the cluster, or creating a KuberhealthyCheck custom resource if you use kuberhealthy
During all this, the Jenkins pipeline writes the results of its test as metrics to a Pushgateway which is scraped by your Prometheus. The in-cluster checks also push their results as metrics to the Pushgateway, or expose them via kuberhealthy, if you decide to use it. In the end, you should have the results of all checks in the same Prometheus instance where you can react on them, e.g. creating Prometheus alerts or Grafana dashboards.

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