DevSpace focuses on team productivity with features
such as Profiles and Custom Commands.
Version 4 of DevSpace comes with two very exciting new features:
- Profiles: allow to patch the config for certain use cases or targets
- Custom Commands: allow teams to share custom commands
Additionally, DevSpace v4 makes it much easier to switch between different Kubernetes clusters, e.g. between local clusters (e.g. minikube, kind, Docker Kubernetes) and remote clusters (e.g. GKE, EKS, bare-metal clusters). This is possible because DevSpace is now much closer tied to the kube-context and even provides a bunch of convenience commands, e.g. for switching the context, setting the default namespace of a context and more.
When we released the first stable version of DevSpace on GitHub in August 2018, we wanted to build the best Kubernetes development tool and make Kubernetes development much faster. Our ultimate goal is to enable every developer to easily build applications that seamlessly run and scale on top of Kubernetes (k8s), even without being a Kubernetes expert. DevSpace as an open-source project has evolved to a cloud-native developer tool that is used not only by individual developers but also by small and large dev teams which streamline their Kubernetes development workflows as part of their transition to the cloud-native development approach.
At its core, DevSpace lets developers create a declarative config for any existing project and add it as
devspace.yaml to the project's root directory. Committing this config file to the code repository allows developers to share and version the build and deployment configuration for this project with their colleagues. With this configuration, you can already define:
- which images should be built using different tools (e.g. docker, kaniko)
- how these images should be tagged after building them
- which registries the Docker images should be pushed to
- which deployment tools should be used (kubectl, helm, kustomize)
- which k8s manifests, Helm charts, components should be deployed
- how the application should be started in development mode
Although this process is customizable with config variables and hooks, it is still a single process with a pre-defined set of steps. For extended modifications of this process (e.g. skipping images, adding new deployment steps), DevSpace was providing a feature called Overrides and Multiple Configs. While Overrides were very limited in terms of modifying the workflows (e.g. overriding arrays was overriding all or nothing, no option to append or remove items), Multiple Configs was quite hard to understand and even harder to manage as multiple config files had to be kept in sync manually.
While developers are starting to spread the word about DevSpace within their teams, the feedback from DevOps engineers managing configurations for their teammates let us realize that DevSpace was missing easier to use functionalities for:
- adapting the config for certain environments (e.g. staging, dev, prod)
- adapting the config for certain development tasks (e.g. start a remote debugger for service X and attach to it)
- providing pre-defined workflows for additional tasks not necessarily related to the build and deployment process (e.g. populate a database with test data)
To address these issues, version 4 of DevSpace introduces:
- Custom Commands: allow teams to share custom commands
- Profiles: allow to patch the config for certain scenarios
Custom commands are inspired by the
scripts you can define in a
package.json when using Node. We believe this is an incredibly powerful pattern to share workflows by defining a set of commands and version them together with your code.
Custom commands are pretty to use: Someone defines the commands within the
devspace.yaml, checks this change into the git repo, other team members check out the code together with the config file and then, they can run the commands via
devspace run [command-name]
Define & Run Custom Commands
Custom commands can be added to the array
commands within the
devspace.yaml. Each command has a
name property which defines how the command will be executed and a
command property which is a simple string containing the bash code that will be executed.
# File: devspace.yaml # Images to be built images: frontend: image: myteam/frontend context: ./frontend/ backend: image: myteam/backend dockerfile: ./backend/Dockerfile context: ./backend/ # Deployment Configuration deployments: - name: backend kubectl: manifests: - ./manifests/* - name: frontend component: containers: - image: myteam/frontend # Custom Commands commands: - name: debug-frontend command: "devspace dev -i frontend" - name: debug-backend command: "devspace dev -i backend"
The above example defines two custom commands:
debug-backend command shown above is as easy as running:
devspace run debug-backend
While this example is rather trivial, custom commands can get pretty complex when many flags and environment variables or even pipes using
|| are being used. The power of custom commands lies in enabling others to quickly execute workflows without having to read pages of internal documentation.
If users want to know which commands are available, they can simply run:
devspace list commands
With custom commands, engineering teams can speed up their Kubernetes development workflows even beyond image building and deployment of Kubernetes manifests and Helm charts.
Take a look at the Documentation for Custom Commands to learn more.
What About Cross-Platform Commands?
All commands should be specified in
bash syntax and will be parsed and executed accordingly on any platform. The only thing that is required is that all binaries (e.g.
kubectl) used within the command are present on the machine executing the custom command.
This level of portability across different operating systems is possible due to an incredible open-source Golang library maintained by Daniel Martí. Thanks for publishing this amazing piece of software.
What About Variables in Custom Commands?
Custom commands are essentially just bash scripts, so you can use any environment variable defined on the host machine. However, shortly after publishing v4, users also requested to allow the use of Config Variables within custom commands. We are excited to see this enthusiasm for solving more complex use cases with custom commands, so we are working on a solution for using config variables in custom commands.
For updates on this feature, take a look at GitHub issue #698.
Profiles & Config Patches
While DevSpace is designed to be a developer tool, teams are also starting to integrate DevSpace into their CI/CD pipelines which is very exciting for us to see. However, deploying to Kubernetes for development is very different than running integration tests on Kubernetes or deploying an application to a staging environment.
In consequence, users often created multiple
devspace.yaml files for these different scenarios which is certainly useful in some situations. However, we saw that a large portion of such configuration files was identical which makes config changes much harder as developers and DevOps engineers need to go through all config files and make sure that their configuration stays in sync.
Following this observation, we decided to dedicate some effort in reworking the handling of multiple configs or config variations. As a result, we decided to get rid of
devspace-configs.yaml which served as an alternative root configuration referencing multiple config files and defining overrides for configurations. This seemed too inflexible and at the same time very hard to maintain and understand.
The decision to remove
devspace-configs.yamlwas the main reason why this release is a major release. We are following the SemVer convention and removing this file is a breaking change.
profiles section in
devspace.yaml is an array that allows you to define as many profiles as needed.
images: backend: image: john/devbackend backend-debugger: image: john/debugger deployments: - name: app-backend component: containers: - image: john/devbackend - image: john/debugger profiles: - name: staging patches: - op: replace path: images.backend.image value: john/stagingbackend - op: remove path: deployments.component.containers - name: production patches: - op: replace path: images.backend.image value: john/prodbackend - op: remove path: deployments.component.containers - op: add path: deployments.component.containers value: image: john/cache
The above example defines two profiles:
production. However, there is always an additional default profile which resembles the basic configuration without any changes. While profiles allow you to redefine the top-level configuration sections (e.g.
deployments), they also allow you to apply config patches which can have different levels of granularity. Using a patch, you can add or remove entries from an array or simply replace a single string value in your configuration.
There are 3 types of patches defined by the patch operation:
op: replace(to replace a single value or an entire section)
op: add(to add a key or an entire section)
op: remove(to remove a key or an entire section)
The first two types require to provide a
value and all of the operations require a
path which is either a JSONPath or an XPath that defines where to apply this path within the configuration.
A big thank you to Kris Hicks who open-sourced the Golang package yaml-patch implementing the RFC 6902 JSON Patch logic for yamls. The fact that we can build upon this work is amazing and shows what makes open-source so powerful for accelerating innovation in software engineering.
Take a look at the Documentation for Profiles & Patches to learn more.
Use Profiles On-The-Fly
With v4 of DevSpace, we are introducing the global flag
-p / --profile which allows you to apply the patches of a profile for any DevSpace command.
devspace deploy -p staging
Running this command with the above example configuration would tell DevSpace to use the base configuration:
images: backend: image: john/devbackend backend-debugger: image: john/debugger deployments: - name: app-backend component: containers: - image: john/devbackend - image: john/debugger
... and transform it using the patches for profile
staging to get the following configuration:
images: backend: image: john/devbackend backend-debugger: image: john/debugger deployments: - name: app-backend component: containers: - image: john/stagingbackend
This configuration would then be used to run the
devspace deploy command.
Switch Profile Permanently
Instead of using the
-p / --profile flag, you can also switch to a profile permanently by running the
devspace use profile command.
devspace use profile staging
This command would set the profile to
staging allowing the user to run any following command using this profile without providing the
-p / --profile flag every time.
To reset the profile and use the base configuration, simply run:
devspace use profile --reset
Take a look at the Documentation for Profiles & Patches to learn more.
Multi-Container Log Streaming
While talking to users, we saw a very common pattern: The sleep entrypoint we add during
devspace init was replaced with a custom development entrypoint and the terminal was disabled in the
devspace.yaml which tells DevSpace to stream the logs of one container instead of opening the interactive terminal.
This made sense after we understood that in most teams, 1-2 engineers had set up the
devspace.yaml and the remainder of the team simply runs commands like
devspace deploy|dev|logs|.... In consequence, the engineers configuring DevSpace wanted to set up everything in a way that developers did not need to know which command to run when the terminal opens up. Additionally, we received comments on Slack and via the website chat stating that opening a terminal is very odd for languages such as PHP where developers expect the Apache or NGINX web server to run without starting it manually.
In response to this, we decided to make log streaming the default behavior but instead of streaming the logs of a single container, we decided to implement a logic that would stream the logs of every container that was deployed using an image that is defined in the
images section of
devspace.yaml. Each log line will be prepended with the image name. This behavior can be fully customized using the
dev.logs section in
Take a look at the Documentation for Log Streaming to learn more.
The ability to override the entrypoint of an image with
[sleep, 999999] and opening an interactive terminal to manually start the application is now called Interactive Mode and can be invoked using the
-i / --interactive flag when running
devspace dev -i
Take a look at the Documentation for Interactive Mode to learn more.
Use Current Kube-Context
Previously, DevSpace used to remember the kube-context used to deploy a project by writing the context name and the namespace in a cache file called
.devspace/generated.yaml. After switching the context and running
devspace deploy or another command that triggers deployments, DevSpace would still use the context that was previously used. The benefits of this approach were:
- users could redeploy to the old context without having to switch the current context first
- users did not have to remember which namespace or context they deployed to because DevSpace remembered it for them
- users did not have to worry about accidentally deploying to the wrong cluster or namespace
However, the approach had the major disadvantage that it was very confusing for users because if they had deployed to context A but the current context is B, DevSpace would still keep on deploying to context A. The most confusing part, however, was that only deployment commands such as
devspace deploy or
devspace dev would use the old context A, other general-purpose commands such as
devspace enter or
devspace logs as well as any
kubectl command would obviously use the current context B.
To resolve the confusion, DevSpace v4 will now always use the current context and the default namespace of this context for all commands.
However, to mitigate accidental deployments to the wrong cluster or namespace, DevSpace will print a warning and wait 10 seconds if the user deploys to a different context or namespace than before.
-s / --switch-context
DevSpace v4 adds the global flag
-s / --switch-context to allow users to tell DevSpace to automatically switch to the previously used context:
devspace dev -s
Unlike the old behavior, however, using the
-s / --switch-context flag tells DevSpace to transparently switch the current context instead of just using it for deployment. This allows users to run a DevSpace command such as
devspace deploy using the
-s / --switch-context flag and they would end up in the last namespace, where it is now possible to run general-purpose commands such as
devspace enter or
devspace logs or even
Convenience Commands for Contexts
DevSpace v4 adds the following convenience commands:
devspace use context # Shows a picker with all contexts, selected one will be set as current context devspace use context [name] # Switches the current context devspace use namespace [namespace] # Sets the default namespace of the current context devspace remove context # Shows a picker with all contexts, selected one will be deleted devspace remove context [name] # Removes a context from the kube config file
If you do not provide a context, for example, DevSpace will show you a picker with possible options which lets you select a context using the
down keys on your keyboard as shown in this example:
$ devspace use context ? Which context do you want to use? [Use arrows to move, space to select, type to filter] > gke_devspace-demo_us-central1-a_demo-cluster-1 do-sfo2-demo-cluster-1 devspace-blog devspace-docs docker-desktop minikube
Especially the commands
devspace use context and
devspace use namespace make it super easy to switch between different Kubernetes clusters and namespaces. DevSpace works with any Kubernetes cluster (local and remote).
Even if you are using Spaces in DevSpace Cloud, you can seamlessly switch between environments.
Look at this set of commands for an example workflow:
devspace init # initializes the project devspace create space my-app # creates a Space in DevSpace Cloud and sets the current kube-context to `my-app` devspace deploy # deploys the project to Space `my-app` devspace use context minikube # switches the current kube-context devspace use namespace app123 # sets the default namespace of context `minikube` to `app123` devspace deploy # deploys to context `minikube` and namespace `app123` devspace use space my-app # sets the current kube-context to `my-app` devspace deploy # deploys the project to Space `my-app`
Binding DevSpace behavior to the current kube-context makes it incredibly easy to switch between local Kubernetes clusters, Spaces and even other remote environments.
Install & Upgrade
To install and get started with DevSpace and Kubernetes development, follow our Quickstart Guide on GitHub.
If you already have DevSpace installed and want to upgrade to the newest DevSpace version, simply run:
Verify which version you are currently using with the following command:
Feedback or Questions?
If you have any feedback or questions regarding this release or if you have any feature requests for an upcoming release, reach out to us via:
Get involved, let us build the best developer tool for Kubernetes!
We hope you will enjoy the new features and are looking forward to hearing how DevSpace v4 helps you to improve your Kubernetes development flow.