Background.
We are using k8s 1.7. We use deployment.yml to maintain/update k8s cluster state. In deployment.yml, pod's image is set to ${some_image}:latest
. Once deployment is created, pod's image will update to ${some_image}:${build_num}
, whenever there is code merge into master.
What happen now is, let's say if we need to modified the resource limited in deployment.yml and re-apply it. The image of deployment will be updated to ${some_image} :latest
as well. We want to keep the image as it is in cluster state, without maintaining the actual tag in deployment.yml. We know that the replcas can be omitted in file, and it takes the value from cluster state by default.
Question,
On 1.7, the spec.template.spec.containers[0].image is required.
${some_image}:latest
as well (an argument like --ignore-image-change
, or a specific field in deployment.yml)? If so, how?Also, I see the image is optional in 1.10 documentation.
--- Updates ---
CI build and deploy new image on every merge into master. At deploy, CI run the command kubectl set image deployment/app container=${some_image}:${build_num}
where ${build_num}
is the build number of the pipeline.
To apply deployment.yml, we run kubectl apply -f deployment.yml
In case you don't want to deal with complex syntax in deployment.yaml in CI, you have the option to use a template processor. For example mustache. It would change the CI process a little bit:
$ mustache env1.yml deployment.mustache > deployment.yaml
$ kubectl apply -f deployment.yaml
The main benefits:
env1.yaml
always contains the latest master build image, so you are creating the deployment object using correct image.env1.yaml
is easy to update or generate at the CI step.deployment.mustache
stays immutable, and you are sure that all that could possibly change in the final deployment.yaml
is an image version.There are many other template rendering solutions in case mustache doesn't fit well in your CI.
Are you aware of the repo.example.com/some-tag@sha256:...
syntax for pulling images from docker registry? It is almost exactly designed to solve the problem you are describing.
updated from a comment:
You're solving the wrong problem; the file is only used to load content into the cluster -- from that moment forward, the authoritative copy of the metadata is in the cluster. The kubectl patch
command can be a surgical way of changing some content without resorting to sed
(or worse), but one should not try and maintain cluster state outside the cluster
Like Const above I highly recommend against using :latest
in any docker image and instead use CI/CD to solve the version problem.
We have the same issue on the Jenkins X project where we have many git repositories and as we change things like libraries or base docker images we need to change lots of versions in pom.xml, package.json, Dockerfiles, helm charts
etc.
We use a simple CLI tool called UpdateBot which automates the generation of Pull Requests on all downstream repositories. We tend to think of this as Continuous Delivery for libraries and base images ;). e.g. here's the current Pull Requests that UpdateBot has generated on the Jenkins X organisation repositories
Then here's how we update Dockerfiles / helm charts as we release, say, new base images: https://github.com/jenkins-x/builder-base/blob/master/jx/scripts/release.sh#L28-L29
However, in deployment.yml file, we specified the latest tag of the image, because it is impossible to keep this field up-to-date
Is it possible to update deployment without updating the image to the file specified. If so, how?