To ensure your product functions correctly, you need to conduct thorough tests. However, testing in a local development environment or a staging environment is vastly different from the production environment where the product will eventually live. Preview environments are a much better option for testing because you can have a realistic production-like environment at your fingertips. Testing in this type of environment increases the likelihood of identifying problems and bugs before the product goes live.
What is a preview environment?
A preview environment is a safe, temporary, fully functional instance of a live (or production) environment that can be created or destroyed as needed. It improves collaboration between development and operations teams and reduces the risk of introducing bugs or breaking changes to the production environment. This type of environment makes it easy to preview pull request (PR) changes in a real-world setting before merging. In addition, provisioning preview environments on demand removes the bottlenecks caused by manual provisioning.
An ideal preview environment should be lightweight, easy to manage, and should not require any complex setup. However, in practice, achieving the above with Kubernetes can be difficult. This is where Garden helps to make preview environments a breeze to set up and use.
Using Garden to manage preview environments
As a modern, open source DevOps platform, Garden helps you build, deploy, and manage containerized applications running on a Kubernetes cluster. It provides a simple, intuitive, and efficient way for developers to manage their projects, regardless of the size or complexity of the application. It also integrates with popular tools and services, including Kubernetes, Docker, and Helm, making it easy to leverage your existing infrastructure.
With Garden, you can easily create and manage multiple preview environments for your different branches using infrastructure as code (IaC). To do so, you define your infrastructure using a YAML file. When you store this infrastructure code in a version control system, like Git, you can easily track changes, collaborate with other team members, and audit your environment to ensure security and regulatory requirements have been met.
The following diagram depicts how Garden deploys a preview environment on a Kubernetes cluster:
As you can see, the Garden CLI is installed on a GitHub agent that is running the workflow. Once a new pull request is created, GitHub Actions calls the Garden CLI command to provision a preview environment. In turn, Garden reads the environment details from a project config file (<span class="p-color-bg">project.garden.yml</span>), builds Docker containers, and pushes them into the container registry. Finally, it uses kubectl to communicate with the remote Kubernetes API server to deploy the resources as needed.
Implementing on-demand preview environments
In this tutorial, you'll learn how to spin up a Kubernetes preview environment after creating a pull request in GitHub. Then you'll set up a Garden project and create GitHub Actions that automatically provision the preview environment when there is a push to the branch with a PR on it.
Before you begin, you'll need the following:
- Git installed on your OS.
- A GitHub account.
- A Google Kubernetes Engine (GKE) cluster. You'll deploy a demo application to this cluster.
- Garden installed on your OS.
- For simplicity, this tutorial is based on this Garden tutorial that uses GKE.
Create a demo project
To begin, you need to clone the demo project and navigate to its base directory:
Make sure you have a single-zone Kubernetes cluster provisioned and ready to operate. You also need to install and configure kubectl to interact with your cluster and store the kubectl context in <span class="p-color-bg">kubeconfig</span>. For more information on how to do this, check out this documentation from Google.
In addition, you need to set up your container registry and enable in-cluster building with the Google Container Registry (GCR). If you need help with this step, this documentation from Garden is a great resource.
Lastly, you need to create a GKE service account so that GitHub Actions can deploy to GKE.
Please note: You need to give the service account the proper permissions. The example code for this article uses a service account named "sa-deploy" with the roles "Kubernetes Engine Developer" and "Storage Admin". If you encounter any issues with this, you can read through this GitHub article to help troubleshoot.
Set up the Garden environment
After cloning your project, you need to update it and add a preview environment to your project config file.
Garden's environments are a software deployment space where the source code will be deployed and executed. For the purpose of this tutorial, a preview environment will be deployed within a separate namespace in the same GKE cluster.
To define your preview environment configuration, navigate back to the demo project base directory and open the <span class="p-color-bg">garden.yml</span> file with the text editor of your choice.
Find the <span class="p-color-bg">environments</span> section:
The <span class="p-color-bg">local</span> environment can be used to deploy your work-in-progress code to a local Kubernetes cluster. However, for the purpose of this preview environment, replace the existing <span class="p-color-bg">remote</span> environment with the <span class="p-color-bg">preview</span> environment configuration. For full customization, refer to the official documentation. Otherwise, the following configuration can be used as a starting point:
Here, you describe a <span class="p-color-bg">preview</span> environment that corresponds to a new namespace in the GKE cluster. GCR is utilized to store the container images.
To simplify the setup, you can remove the ingress configuration from both the backend and frontend services. To do so, open the <span class="p-color-bg">garden.yml</span> file for each service and delete the <span class="p-color-bg">ingresses</span> section, as shown here:
At this point, you need to run a few Garden commands locally to verify that everything is working:
Then run the following commands to verify the setup is correct:
The <span class="p-color-bg">garden deploy</span> command deploys an environment and builds any necessary modules and dependencies. While this is very useful in a CI/CD context, you can also use the <span class="p-color-bg">garden dev</span> command when running locally. The <span class="p-color-bg">garden dev</span> command launches the Garden dev console, which builds, deploys, and tests all your modules and services, and then rebuilds, redeploys, and retests as you modify the code.
The <span class="p-color-bg">garden get status</span> command outputs the full status of your environment.
Next, run the dev console and navigate to the Garden dashboard to view the setup:
You can access the dashboard by opening the URL that can be found in your terminal:
The dashboard should display the status of both the backend and frontend services as "Ready":
Now, it's time to create a GitHub workflow.
Create a GitHub workflow
In this section, you'll create a workflow file to run your GitHub Actions.
First, create a GitHub workflow file under the folder <span class="p-color-bg">.github/workflows</span> and name it <span class="p-color-bg">pr-preview-env.yml</span>:
Open the file in your preferred text editor and insert the content of the GitHub Garden workflow. The most important steps are highlighted here:
In the first portion of this code, you install the Garden CLI tool. Then you use the Garden CLI to deploy/destroy a preview environment as needed. For more information on the Garden commands, check out the official docs.
This workflow should authenticate to the GKE cluster using the service account you created previously. This example uses authentication as workload identity federation, which is a recommended way to authenticate to GKE clusters in Google Cloud.
Create a pull request
Now that you've created a GitHub workflow, you need to create a pull request to see the preview environment in action.
Create a new repository on GitHub and push the changes from the <span class="p-color-bg">demo-project-start</span> that you modified previously. If you experience any problems, check out this GitHub documentation to help troubleshoot.
Create a new branch (*ie* <span class="p-color-bg">feature/feature1</span>) and copy and paste a <span class="p-color-bg">backend</span> folder to simulate the introduction of a new service. Rename the folder to <span class="p-color-bg">backend2</span> and update the <span class="p-color-bg">garden.yml</span> file with the following:
Commit and push your changes; then navigate to your GitHub repository and make a new pull request.
Preview the changes
In the previous section, you created a pull request, which automatically triggers the creation of a preview environment on the Kubernetes cluster. To test the workflow, you need to verify that the deployment has been successfully applied to the Kubernetes cluster by checking that it exists in the correct namespace. Then, you need to make local changes and push them to the repository. At that point, the preview environment will be automatically updated by the GitHub Actions workflow.
To see the workflow run, navigate to GitHub Actions and click on the job **Deploy to Preview**:
View the results of the **Deploy** step, and it should contain detailed logs from <span class="p-color-bg">Garden</span>:
The **Deploy** step logs display information about the deployment process, including the Kubernetes namespace that corresponds to your preview environment.
Next, navigate to your Kubernetes cluster and verify that there are services and pods running in the namespace <span class="p-color-bg">runner-pr1-preview</span>:
If you see multiple sets of frontend and backend services deployed into distinct Kubernetes namespaces, well done! The workflow you created works as expected and deploys a distinct preview environment when raising a pull request.
You can also use port forwarding to send API requests from your local machine. To set up port forwarding, select the service **backend**, scroll down to **Ports**, select **PORT FORWARDING**, and follow the instructions:
You should get a URL that looks like this:
"https://ssh.cloud.google.com/devshell/proxy?port=8080". This URL will help you access your service. Open the URL in your browser and append the API endpoint <span class="p-color-bg">/hello-backend</span>. You should see the response message <span class="p-color-bg">Hello from Go!</span>:
You can push more changes in your pull request to see that the preview environment has been updated. To finish, complete the pull request and ensure the preview environment has been deleted.
Use One-Click Preview Environments
Garden Cloud simplifies the deployment process further by allowing you to connect to your Git repository and use one-click preview environments. One-click preview environments are branch-specific namespaces that are created from the Garden Cloud UI to avoid creating a GitHub workflow file, which Garden Cloud creates automatically.
One-click preview environments also come with a web dashboard that provides a comprehensive overview of all preview environments, including the status, health, and resources of each environment. This makes it easy for developers to keep track of preview environments and quickly spin them up for applications.
A preview environment for every pull request
Preview environments provide a safe, controlled environment for testing and help you get feedback quickly. Having a preview environment that is automatically created upon making a pull request ensures the quality of the final product and increases the velocity of the development process.
In this article, you learned about the importance of preview environments in software development and how to use Garden to deploy a preview environment on a Kubernetes cluster.
Garden is designed to simplify the management and testing of cloud-native applications running on Kubernetes. It helps to improve the developer experience and speed up the software delivery cycle by automating the deployment process and reducing time wasted while switching between tasks.