Kardinal is an open-source framework for creating extremely lightweight ephemeral development environments within a shared Kubernetes cluster. Between dev environments, Kardinal shares every microservice or database that can be feasibly be shared, optimizing for cloud costs and fast spin-up/tear-down. To see how much you would save using Kardinal for your particular architecture, check out the cost saving calculator.
In Kardinal, an environment is called a "flow" because it represents a path that a request takes through the cluster. Versions of services that are under development are deployed on-demand, and then shared across all development work that depends on that version. Read more about Kardinal in our docs.
- Ephemeral Environments: Spin up a new environment exactly when you need it, and just as quickly spin it down when you’re done.
- Minimal Resource Usage: Only deploy the services you’re actively working on. Kardinal takes care of the rest, so you don’t waste resources.
- Flexible Environment Types: Whether you need to test a single service or an entire application, Kardinal has you covered:
- Single-Service Flows: Perfect for when you’re tweaking just one service.
- Multi-Service Flows: Ideal for when your feature involves multiple services.
- State-Isolated Flows: Great for features that need their own isolated databases or caches.
- Full Application Flows: For those times when you need end-to-end testing with full isolation.
- Cost Savings: Kardinal can help you save big by avoiding unnecessary resource duplication. It’s a game-changer for teams looking to cut costs. Check out this calculator to run your own calculations.
- Open Source: Kardinal is open source, so use it however fits best within your workflows
To install Kardinal, run the following command:
curl get.kardinal.dev -sL | sh
All you need is a Kubernetes cluster with Istio enabled, and kubectl installed on your machine, pointing to your cluster. If you need help with this, read more here
Make sure that kubectl is pointing to your cluster, and then run the following command:
kardinal manager deploy kloud-kardinal-kontrol
Once installed check out our docs on creating your first flow.
Once you have Kardinal installed, you can run through the following demo. For step 1, since this guide is using minikube, you'll need to set up the minikube tunnel to access the frontend of the application you're about to deploy:
minikube tunnel
You can leave the tunnel running. In a new terminal window, deploy the demo app via Kardinal:
curl https://raw.githubusercontent.com/kurtosis-tech/new-obd/main/release/obd-kardinal.yaml > ./obd-kardinal.yaml
kardinal deploy -k ./obd-kardinal.yaml
You can view the frontend of the demo app by going to:
http://baseline.app.localhost
Feel free to click around, add items to your cart, and shop!
The Kardinal dashboard will show the architecture of your application, along with any logical environments (flows) you create on top of it. To view the dashboard, run:
kardinal dashboard
and click on the "Traffic configuration" sidebar item.
Create a new flow by specifying a service name and a container image.
Here is an example of creating a dev flow for the frontend service, using an image we've prepared for this demo:
kardinal flow create frontend kurtosistech/frontend:demo-frontend
This command will output a URL that you can use to access the frontend of the development environment. You can view the frontend of the application by going to the URL provided.
Notice that there are already items in your cart in the development environment. We've configured the development "flow" in this demo to run with it's own database which is seeded with test data. This demonstrates how dev flows can be configured with the data that the development team needs to do their testing work.
To inspect the resources in your cluster, and see how Kardinal is reusing resources in your stable environment in the dev environment, go to the dashboard again:
kardinal dashboard
and click on the "Traffic configuration" sidebar item.
When you're done with your development flow, you can delete it by running:
kardinal flow delete <flow_id>
The flow_id is in the output of the kardinal flow create command, but if you've lost it, you can get it again by running:
kardinal flow ls
Once you've deleted the flow, you can verify that the resources have been cleaned up by going to the dashboard again.
Expand to see how to Develop with Kardinal + Tilt
Is it possible to develop your app with Kardinal + Tilt. Here’s how to do it::
- Kardinal CLI
- Tilt
- Local K8s cluster, it could be Minikube or Docker desktop for instance
- Istio
- Gateway API
-
kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v1.1.0" | kubectl apply -f -;
-
Assuming you’ve already deployed your application’s manifest using the kardinal deploy
command, your cluster topology is prepared for deployment with Tilt. Check the following example to learn how to do it:
Example:
- Create this
Tiltfile
kardinal_topology_yaml = local(['kardinal', 'topology', 'print-manifest', '--add-trace-router'], quiet=True)
kardinal_topology_yaml_str = str(kardinal_topology_yaml)
if kardinal_topology_yaml_str != '':
k8s_yaml(kardinal_topology_yaml, allow_duplicates = True)
local_resource(
name='ingress-gateway-port-forward',
serve_cmd=['kubectl', 'port-forward', 'service/istio-ingressgateway', '80:80', '-n', 'istio-system']
)
- Run
sudo tilt up
The first local
call retrieves the cluster topology from Kardinal Kontrol using the kardinal topology
command. This command prints a multi-resource manifest that Tilt captures and then applies with the k8s_yaml
command.
Finally, the local_resource
function executes the port forwarding command, allowing the Ingress Gateway to handle browser requests on the default port 80. This command requires sudo
privileges because it binds to the default port 80.
You can also include the kardinal deploy
command inside the Tilt to handle all the deployment flow directly with the tilt up
command.
Example:
- Create a
Tiltfile
like this, replacing the placeholder data with your own.
local(['kardinal', 'deploy', '-k', '{your-kardinal-manifest-yaml-filepath}'])
kardinal_topology_yaml = local(['kardinal', 'topology', 'print-manifest', '--add-trace-router'], quiet=True)
kardinal_topology_yaml_str = str(kardinal_topology_yaml)
if kardinal_topology_yaml_str != '':
k8s_yaml(kardinal_topology_yaml, allow_duplicates = True)
local_resource(
name='ingress-gateway-port-forward',
serve_cmd=['kubectl', 'port-forward', 'service/istio-ingressgateway', '80:80', '-n', 'istio-system']
)
- Run
sudo tilt up
In this example, the kardinal deploy
command is used at the start to deploy the multi-resource manifest file to Kardinal Kontrol.
You can also integrate Kardinal with Tilt to build your app’s containers and set up development workflows that automatically reflect changes whenever you save your files.
Example:
- Create a
Tiltfile
like this, replacing the placeholder data with your own.
local(['kardinal', 'deploy', '-k', '{your-kardinal-manifest-yaml-filepath}'])
local(['kardinal', 'flow', 'create', '{service}', '{service-dev-image}'])
docker_build(
'{service-dev-image}',
context='{./src/}',
dockerfile='{./src/Dockerfile}',
)
kardinal_topology_yaml = local(['kardinal', 'topology', 'print-manifest', '--add-trace-router'], quiet=True)
kardinal_topology_yaml_str = str(kardinal_topology_yaml)
if kardinal_topology_yaml_str != '':
k8s_yaml(kardinal_topology_yaml, allow_duplicates = True)
local_resource(
name='ingress-gateway-port-forward',
serve_cmd=['kubectl', 'port-forward', 'service/istio-ingressgateway', '80:80', '-n', 'istio-system']
)
- Run
sudo tilt up
This example introduces two new elements: first, the kardinal flow
local execution to create the development flow post-deployment. Note the image name service-dev-image
, as it will be used in the second element.
The second element is the docker build
function call, where, we use service-dev-image
as the first argument. This creates a link, between the container being built and the service in the development flow. Consequently, any changes to files within the specified context (the second argument) will trigger Tilt's hot reload mechanism, updating the Kardinal development flow.
Note that in this example we are building the service’s container with the docker_build
instruction but you can also use another build way as the custom image builders
The prod
and dev
application URLs are printed on the logs screen of the Tiltfile execution, you can click on their links to access both flows in the browser.
After completing the development cycle, you can remove all created resources from the cluster by running the following command:
tilt down --delete-namespaces
The delete-namespaces
flag is used to remove the application’s namespace, it won’t delete the default
namespace
For additional examples of configuring Kardinal with Tilt, refer to the Tiltfile in the Kardinal Boutique demo app.
Expand to see how to Develop with Kardinal + Telepresence
Is it possible to use Telepresence in a Kardinal dev flow. Here’s how to do it:
- Kardinal CLI
- Telepresence
- Local K8s cluster, it could be Minikube or Docker desktop for instance
- Istio
- kubectl
Assuming you’ve already deployed your application’s manifest using the kardinal deploy
command, your cluster topology is prepared for creating dev flows. Check the following example to learn how to do it:
Example:
- Install Telepresence manager with Istio integration in your cluster (make sure that you have selected the targe cluster with kubectl before running it)
telepresence helm install --set trafficManager.serviceMesh.type=istio
- Create a dev flow with
Kardinal
.
kardinal flow create frontend kurtosistech/frontend:demo-on-sale
- Take note of the flow ID created
- Start the
frontend
app locally in a local port either with the terminal or your IDE, you can even start it in debug mode. - Take note the
port
where it's running because it will be used later - Run the Kardinal flow
telepresence-intercept
command to intercept the traffic (replace the values between the brackets)
kardinal flow telepresence-intercept {{flow-id}} {{service-name}} {{local-port}}
- Navigate the website in the browser to receive the request in the app running locally outside the cluster