Updating a Docker images used by a Kubernetes deployment can be painful since there are several steps that have to be accomplished:
- the deployment must use the ‘latest’ tag in the pod spec section
- update the code
- build the image
- push the image to Docker Hub or have it available inside Minikube cluster
- run the command: $ kubectl rollout restart deployment [deployment_name]
The steps above are important since they have to be followed in a production environment.
In a development environment there is an easier approach: when we are developing code actively inside of a Kubernetes cluster we can use a tool called Skaffold.
Skaffold is a command line tool for the dev environment:
- automates many tasks in a Kubernetes dev environment
- makes it really easy to update code in a running pod
- makes it really easy to create/delete all objects tied to a project at once
- homepage https://skaffold.dev/
After installing Skaffold (https://skaffold.dev/docs/install/) check if it exists on your system:$ scaffold
NOTE: Skaffold is a tool that runs outside of our cluster.
Configuring Skaffold
- configuration is done using an YAML file
- the config file is going to tell Skaffold how to manage all the different sub-projects inside of our cluster
Use as reference the following project: https://github.com/luckpp/microservices-demo
Steps:
- in the root folder of your project creae a file skaffold.yaml
- in the config ‘deploy’ section this tells Skaffold that there is a collection of config files for Kubernetes inside infra/k8s/ folder that should be watched
- anytime we make a change to a config file, Skaffold is going to automatically reapply that config file to our Kubernetes cluster
- the config files will be applied also when we start Skaffold
- all the objects associated with those config files will be deleted when we stop Skaffold
=> this is helpful when switching between different projects -> we will end-up with a clean cluster
- in the config ‘build’ section
- in ‘local’ sub-section make sure that whenever an image is rebuild, it is not pushed to Docker Hub
- in ‘artifacts’ sub-section tell Skaffold about the sections in our project it needs to maintain
- in the example below we actually tell that there is going to be some pod that is running code out of the ‘client’ directory
- whenever something changes in the ‘client’ directory Skaffold will try to take those changes and update our pod; there are two ways in which Skaffold is going to update our pod:
- if we are going to make a change to a *.js file Skaffold is going to take that change and throw it into our pod
- if we make a change inside the directory and that change is not a *.js file, Skaffold will try to rebuild that image
apiVersion: skaffold/v2alpha3 kind: Config deploy: kubectl: manifests: - ./infra/k8s/* build: local: push: false artifacts: - image: luckpp/client context: client docker: dockerfile: Dockerfile sync: manual: - src: "src/**/*.js" dest: . # all other sub-projects should follow
Make sure to make docker command point to your shell to minikube’s docker-daemon, run:$ minikube docker-env
-> execute the command suggested by the output of this command
In order to start Skaffold up run the following command form the folder where skaffold.yaml is located:$ skaffold dev
Make some changes to one or more files inside your project and notice the Skaffold output.
To close Skaffold hit CTRL+c:
- Skaffold closes
- all objects associated with the config files handled by Skaffold will be deleted
Critical info to understand:
- with the configuration we saw above, whenever Skaffold detects a change inside a *.js file it will copy it into the appropriate pod
- inside the pod we host containers that have the entry command: ‘npm start’
- if we look into the package.json files, we see that ‘npm start’ actually starts ‘nodemon’
- in the end ‘nodemon’ is the tool that detects a change to a *.js file from the underlying project and restarts the Node.js service code inside the container
As a conclusion we can say we have 2 levels of change detection:
- outside Kubernetes we have Skafflod detection change
- inside the container we have detection change with ‘nodemon’
NOTE: Using change detection or file change detection inside Docker containers traditionally has requested great attention to details:
- there are file watchers like nodemon or create-react-app that do not always detect changes inside a Docker container
- I will try to give a couple of more notes on the issue above in my next blog posts