Tutorial Using a Sample Online Boutique App
Overview
In this tutorial you'll experience the basic usage of Raftt operating in connect mode - adding development capabilities to an existing env deployed to a Kubernetes namespace.
If you wish to try Raftt operating in orchestration mode - the mode in which Raftt is also responsible for spawning and managing dev envs, see our orchestration mode tutorial.
This tutorial includes the following steps -
- Spawn the Online Boutique demo project - the project used for this tutorial
- Add Raftt to the env to enable an excellent developer experience (DevX)
- Experience the DevX first-hand by changing the project's code - fixing a backend bug and modifying the UX
- Interactively debug the project
- Onboard an additional workload to Raftt to allow developing it easily and efficiently
The Project
We forked Online Boutique, a sample microservices application (originally created by Google), as a sample project to help you onboard Raftt quickly, without using your code.
The project includes microservices written in a variety of languages, but familiarity with these languages isn't necessary to complete the tutorial.
Prerequisites
This tutorial demonstrates Raftt's ability to enhance the development experience of existing K8s envs. It means that you need a K8s cluster (local or remote) on which you can deploy the demo environment using helm charts. You also need kubectl and helm installed locally (see here and here for installation guides).
If you don't have a cluster but want to try this tutorial, you can use tools like minikube to create a local Kubernetes cluster.
Install Raftt
- macOS
- Linux
- Windows
Use Homebrew or cURL to install Raftt CLI on macOS.
brew install rafttio/tap/raftt
Or
curl -fsSL get.raftt.io/install | bash
Use Snapd or cURL to install Raftt CLI on Linux.
sudo snap install raftt --classic
Or
curl -fsSL get.raftt.io/install | bash
Download and run Raftt installer (x64).
The installation adds the Raftt binary to your PATH
. You must start a new shell after the installation to have the up-to-date environment variables.
To verify the installation was successful, run raftt version
in your shell.
Deploying the Project
In this section, we'll deploy the Online Boutique app to your cluster. Take the following steps -
- Make sure that your Kubernetes context is correct
kubectl config get-contexts
- Clone the Online Boutique repo
git clone https://github.com/rafttio/online-boutique
cd
into the repo's folder -
cd online-boutique
- Create a namespace called
demo
and deploy the app in it -
helm install -n demo --create-namespace demo ./helm-chart
- See all pods were started successfully -
kubectl get pods -n demo
- After connecting Raftt to the env in the next section, you'll be able to access the application from your browser.
Development Mode
Now we're getting to the interesting part - adding advanced dev capabilities to the existing env, using Raftt. To do it, perform the following actions -
- Add Raftt to the environment by running
raftt connect demo
- You will be prompted to log in to Raftt using one of several third-party services (Google, GitHub, etc.).
- Once completed, you can see a list of all the namespace workloads.
raftt connect demo
- Convert some of the workloads into dev-mode -
raftt dev frontend recommendations
. It will allow you to experience the DevX provided by Raftt in the following tutorial sections.
raftt dev frontend recommendations
- Run
raftt status
to see they are marked as in "dev-mode" and the list of mapped ports.
raftt status
- As seen in the command output, the open port of the frontend container is mapped to the local port 8888. Let's see what happens when you browse it.
Under the Hood
If you're interested in the inner workings of Raftt, this section explains what happened internally when running the raftt connect
and raftt dev
commands. You can jump to the next section, if you just want to continue with the tutorial.
When you ran raftt connect
, you started a sequence of events -
- Raftt's env controller is added to your namespace (a workload named sandcastle).
- Your repo is mirrored to the cluster and live syncing is started.
- You can start using
raftt sh
andraftt logs
commands to inspect all your workloads.
After connecting to the env, you got the frontend
and recommendations
deployments into dev-mode, using raftt dev frontend recommendations
. This triggered the following actions -
- The dev-mode definitions of the
frontend
andrecommendations
workloads are read from the .raftt file (found here). - The existing
frontend
andrecommendations
deployments are taken down (scaled down to 0 replicas in case of deployments) and new deployments are spawned. - The new deployments differ from the old ones in the following characteristics -
- Their name has the suffix
-raftt
. This is only true for deployments and replica sets. All other resource kinds are replaced if they enter dev-mode. - The lifecycle of the container is split from the lifecycle of its main process. You can restart the process without respawning the container, and the main process crashing doesn't result in the termination of the container, allowing much better inspection. See here for more information.
- All changes defined in the
.raftt
file for the specified resources are applied. In this case, the changes are -- Code is now continuously synced to the container, allowing you to write code in your favorite local IDE and see the changes affect the cluster (lines 8 and 13).
- A port is mapped locally from the
frontend
container (line 9).
- You can now run all raftt commands that are relevant to workloads, e.g.,
restart
andrebuild
.
- Their name has the suffix
- All the rest of the namespace resources (those not specified in the
dev
/rebuild
command) remain unchanged.
Let's Develop!
Since your env is up and you got some workloads into dev-mode you can play around with the code and see how your changes affect the app!
Change the page title
We'll start with an easy to do and easy to see change - change the title.
Let's say you want to bring some honesty into your marketing, and admit that the products you present on the frontpage aren't actually hot, they are the entire catalog. To do that, you need to change the string inside the h3
tag in home.html
line 36 to "All Products".
<h3>All Products</h3>
To see this change taking effect, run raftt restart frontend
to restart the workload's main process.
raftt restart frontend
Fix the recommendations engine
If you click any of the products, you'll see the recommendation engine is broken - it always shows the same product. This must be solved so you can push people to spend more in your boutique!
To solve this we need to modify the code of the recommendation engine workload. On line 78, you can see that it doesn't iterate properly over the filtered_products
list - try replacing filtered_products[0]
with filtered_products[i]
.
prod_list = [filtered_products[i] for i in indices]
After fixing the bug you need to run raftt restart recommendations
to restart the workload's main process.
raftt restart recommendations
Note the fast cycle time - with Raftt it only takes seconds from code change to seeing it in the env - no need to rebuild and redeploy images, which takes from minutes to over an hour in some cases.
Debugging the Workloads
Once a workload is in dev-mode, you can debug it using Visual Studio Code or any JetBrains IDE. For details on how to configure debug configuration see the debugging docs section. For this tutorial we already have the debug configurations committed to the repo, so you don't need to configure anything.
To debug the application, follow these steps -
- Open the project in the IDE.
- Install Raftt's plugin from the marketplace (JetBrains, VS Code)
- Add a breakpoint inside the function
ListRecommendations
in the filerecommendation_server.py
. - Start debugging using the debug configuration
recommendations
.- JetBrains IDEs may ask you to configure a Python interpreter. You can ignore the request or choose any interpreter of your choice. It doesn't affect the remote environment that uses its own interpreter.
- Click one of the products to get to its page.
- Success! - it stopped where you added the breakpoint.
- Debug the remote service as if it were local.
Raftt currently supports interactively debugging Python, Go, Node.js and Java code using Visual Studio Code or any JetBrains IDE. Join our Slack community or contact us to let us know need support for other languages, adding such support is very fast.
Configure Additional Workloads
The Online Boutique repo comes pre-configured for developing the frontend
and recommendations
workloads using Raftt. Now let's add the configuration for the email
service. To enjoy the dev capabilities provided by Raftt, you need to add a few definitions for the email
service in the env definition file.
The .raftt
File - the Env Configuration File
A .raftt
file is a file in which your Raftt environment is defined. It is written in Starlark - a Python-like scripting language. It usually starts with importing the resources definitions. In connect mode the definitions are usually loaded using the namespace_resources
function, but there are other ways to load them. Once imported (to a Resources
object), the definitions can be modified and enhanced. For the modification to take effect you need to use the deploy()
function with the relevant resource/s as an argument. In this tutorial's case, we already have the calls to namespace_resources
and deploy()
in place, so you just need to get the handle to the relevant resource, and call the relevant functions between these two calls.
On every call to raftt dev RESOURCE
(and every following call to raftt rebuild RESOURCE
) the .raftt
file is interpreted and the currently running instance of RESOURCE
is replaced by the one defined in the .raftt
file. All other resources remain unchanged.
Mount the Source Code
Mounting your code to the container allows you to enjoy hot-reloading of files into the container which enables a much shorter dev cycle. Depending on the language and framework used, it will require something between refreshing a page to building and restarting the main process. In any case it's much faster than rebuilding the whole container, which is rarely required when using Raftt.
To sync a local folder to the container, you can use the repo_volume()
and mount()
functions (see here for more details).
To understand what is the exact folder that needs to be mounted, you can refer to the Dockerfile of the email
service.
As you can see in lines 40 and 49, the entry point is email_server.py
and it runs from the workdir which is /email-server
. It is copied to the image from the context of the Dockerfile execution (line 46).
It means that the context of the Dockerfile - src/emailservice
needs to be mapped to the workload's workdir - /email_service
. In the syntax of the .raftt
file, it will look like this (using the repo_root
variable that was already assigned in the first line of env.raftt
) -
email = resources.deployments["email"]
email.mount(repo_root.subpath("src/emailservice"), "/email_server")
To get email
into dev-mode and apply these changes, run
raftt dev email
Add an Annotation
You can change many of the workload attributes using the .raftt
file. You can find a list of all modifiable attributes in our docs. In this example we'll add an annotation using the following line of code -
email.metadata.annotations["raftt"] = "In dev-mode!!!"
Apply this change using
raftt rebuild email
Or if it's not yet in dev-mode, use
raftt dev email
You can verify it worked by reading the deployment annotation by running
kubectl -n demo get deploy email-raftt -o jsonpath='{.metadata.annotations.raftt}'
The expected output is -
Monitor Dependency Changes
If you wish to add a new dependency to your Python code, you change the requirements.txt
and then run pip install -r requirements.txt
inside the workload. Raftt could monitor the file and run it automatically every time you change it, using Raftt's file watching mechanism.
This can be done by adding the following snippet to env.raftt
-
register_hook(
on=events.OnFileChanged(
workload=email,
patterns="/email_server/requirements.txt"
),
do=actions.CMD(
workload=email,
cmd=["pip", "install", "-r", "requirements.txt"]
)
)
Apply this change using
raftt rebuild email
After applying this change, modify the requirements.txt
file of the email
service and check out the hook logs using
raftt logs --hooks
Additional Capabilities
You can do many other things in your .raftt
file that are beyond what we can demonstrate in a short tutorial. You can find the full documentation of the .raftt
file in our docs, to which we already referred many times on this tutorial.
Try It With Your Project
After seeing how easy it is to work with Raftt, you're welcome to use raftt on any project of yours - open source or private.
We'd love to hear about your experience in our Slack community or by contacting us directly.