Deploy ephemeral Environments

Set up ephemeral environments using Score with the Humanitec Platform Orchestrator.

Introduction

An “ephemeral environment” is a temporary, on-the-fly instance of an application. It exists solely for the duration of a specific task, such as testing a feature or bug fix via a pull request. Once the task is done, the environment is torn down.

Ephemeral environments are sometimes called “dynamic previews”.

Ephemeral environments are not technically different from other Environments in the Platform Orchestrator. There is no technical flag marking an Environment as “ephemeral”. Their ephemeral nature is a human notion, signifying the limited time span of their existence.

The following tutorial will take you through each step needed to set up ephemeral environments using Score with the Humanitec Platform Orchestrator. You will learn how to:

  • Configure repositories for ephemeral Environments
  • Describe your Workload using Score
  • Configure pipelines with variables and secrets
  • Create a new Environment
  • Trigger automated Deployments with Score
  • Clean up Environments after use

Prerequisites

To get started you’ll need:

  • A Humanitec Organization. If you do not have one yet, sign up here for a free trial
  • The humctl Humanitec CLI
  • Git installed locally
  • A GitHub account
  • A Kubernetes cluster connected to the Platform Orchestrator for Workload deployments. If you do not have one yet, these are your options:
Options to connect your Kubernetes cluster
Five-minute-IDP Bring your own cluster Reference architecture
Set up a local demo cluster following the Five-minute IDP

Duration: 5 min

No need to deploy the demo Workload, just perform the setup

Ephemeral (throw-away) setup for demo purposes
Connect an existing cluster by following the Quickstart up to “Connect your cluster” (guided), or using the instructions in Kubernetes (self-guided)

Duration: 15-30 min

One-time effort per cluster, can be re-used going forward
Set up the reference architecture

Duration: 15-30 min

Creates a new cluster plus supporting cloud infrastructure, and connects it to the Platform Orchestrator
  • (optional, but recommended) kubectl with the current context set to your target cluster

Prepare your environment

  1. Set these environment variables:
export HUMANITEC_APP=ephemeral-environments
export HUMANITEC_ORG=<my-organization-id>

where:

  1. Login to the CLI:
humctl login
  1. Choose the Resource Definition of the target Kubernetes cluster. You can use humctl get resource-definition to get a list of available Resource Definitions, or go to the “Resource Management” section in the Platform Orchestrator UI.
export K8S_RESDEF=<my-k8s-cluster-resource-definition-id>
  1. Create an API token for the Platform Orchestrator. GitHub will need this token to perform deployments via the Orchestrator. Save the token in a secure place.
  1. Choose the GitHub organization you are going to work in. You will later create the demo repo here, and use GitHub’s container registry as the image registry. You may just use your personal GitHub account as well instead of an Organization, in which case the organization name is equal to your GitHub handle.

    Set this environment variable to the name of the Organization or account:

    export GH_ORG=<my-GitHub-org>
    

    When using a GitHub organization, enable the use of public images. This is enabled by default for personal accounts.

    • Go to github.com/your-org, and open the “Settings” tab
    • Select Packages
    • Under “Package creation”, select the “Public” option, and click Save

Create an Application

  1. Create an Application in the Platform Orchestrator:

    humctl create application $HUMANITEC_APP
    
  2. Depending on the Organizational role of the API token you created earlier, you may need to assign an Application level role to the associated service user. If you created a token with the “Artefact Contributor” role, assign that user the “Developer” role on the Application.

  3. Create matching criteria on the target Kubernetes cluster for your Application. This will make the Platform Orchestrator pick that cluster for the subsequent deployments.

    export CRITERIA_ID=$(humctl api post /orgs/$HUMANITEC_ORG/resources/defs/$K8S_RESDEF/criteria \
      -d '{
      "app_id": "'${HUMANITEC_APP}'"
    }' | jq --raw-output '.id' )
    echo $CRITERIA_ID
    

    We capture the CRITERIA_ID for cleaning up again later.

  4. If your target cluster is using the Humanitec Agent, the agent Resource Definition for that cluster also needs matching criteria for your Application. You can use humctl get resource-definition to get a list of available Resource Definitions, or go to the “Resource Management” section in the Platform Orchestrator UI.

    export AGENT_RESDEF=<my-agent-resource-definition-id>
    
    export CRITERIA_ID_AGENT=$(humctl api post /orgs/$HUMANITEC_ORG/resources/defs/$AGENT_RESDEF/criteria \
      -d '{
      "app_id": "'${HUMANITEC_APP}'"
    }' | jq --raw-output '.id' )
    echo $CRITERIA_ID_AGENT
    

Create the repository

Create a new repository using this tutorial’s template repository as the basis:

  • Create the GitHub link:
echo "https://github.com/new?template_name=ephemeral-env-demo&template_owner=humanitec-tutorials&name=ephemeral-env-demo&owner=$GH_ORG"
  • Click on the link to open it in your browser
  • Verify that “Owner” is set to your target GitHub Organization or account, and “Repository name” is set to “ephemeral-env-demo
  • Set the visibility to “Public” if it isn’t already
  • At the bottom of the screen, select Create repository
  • Wait for the new repo to be created and opened
  • Switch to the “Settings” tab
  • In the “Secrets and variables” section, select Actions
  • In the “Secrets” tab, create these Repository secrets:
    • HUMANITEC_TOKEN: set to the Platform Orchestrator API token you created earlier
  • In the “Variables” tab, create these Repository variables:

Clone the repository

To get started, clone your new ephemeral-env-demo repository locally:

git clone https://github.com/${GH_ORG}/ephemeral-env-demo.git
cd ephemeral-env-demo
ls -l

The repo contains:

  • A deliberately simple Node.js web application returning the value of an environment variable on any request
  • A Dockerfile to build the container image from it
  • GitHub workflows in the .github directory. We will look at them in greater detail shortly
  • A Score file (score.yaml) describing the Workload

Inspect the Score file

Output the Score file:

cat score.yaml

Note this line in the containers section:

    image: . # Set by pipeline

The image source is deliberately not coded into the Score file. The deployment pipeline (here: the GitHub workflow) will set it at deployment time depending on the current context.

Deploy the development Environment

On repo creation, GitHub has performed an initial commit which triggered a GitHub workflow within the repo, trying to deploy the Application. The workflow run failed due to missing secrets and variables, but will work now that you have filled in those gaps.

  1. Re-run the GitHub workflow

    • In GitHub, switch to the Actions tab
    • Select the falied Initial commit run
    • In the Re-run jobs menu, select Re-run failed jobs, and confirm with Re-run jobs
    • Wait for the workflow run to complete
  1. Inspect the image

    The workflow has created a GitHub “Package” which contains the container image. It is available at ghcr.io/<your-github-org>/ephemeral-env-demo:latest. Take a look at the image.

    • Select the “Code” tab
    • In the “Packages” section, select the ephemeral-env-demo package
    • Select Package settings
    • Scroll to the bottom and verify that “This package is currently public”
  2. Verify the deployment is running fine

    The workflow run has performed a deployment into your previously created Application in the Platform Orchestrator. Take a look at the result.

  • In the Applications screen, select the development Environment of the ephemeral-environments Application
  • Select the web-app Workload

You should see a status of 1 Pod “Running”

Execute this command:

kubectl get pods,services -A -l app.kubernetes.io/name=web-app

You should see one Pod in status “Running” and one Service, both in the same namespace.

  1. Visit your Application

    This step requires kubectl access to your cluster. Execute this command:

    export APP_NAMESPACE_DEVELOPMENT=$(humctl api get \
      /orgs/$HUMANITEC_ORG/apps/$HUMANITEC_APP/envs/development/resources \
      -o yaml | \
      yq -r '.[] | select(.type == "k8s-namespace") | .resource.namespace')
    
    kubectl port-forward service/web-app 8080:8080 -n $APP_NAMESPACE_DEVELOPMENT
    

    Open http://localhost:8080. You should see the message “Hello deployer!” served by your web application.

    Stop the port-forward via Command+C or CTRL+C.

  2. Inspect the GitHub workflow

    Take a moment to inspect the GitHub workflow located at ./.github/workflows/main.yaml.

    Following a common Docker login, build and push sequence, the workflow performs a deployment of the score.yaml file. Remember that the image is not fixed in the Score file:

        image: . # Set by pipeline
    

    The workflow provides the image to use as part of the humctl score deploy command, using the output of the previous step:

    humctl score deploy \
      ...
      --property "containers.demo.image=${{ steps.build_push.outputs.IMAGE }}"
    

Create a pull request

Now that a base setup is running, you can start creating PRs and ephemeral environments.

  1. Create a new branch change-env-var, apply a change to the code, commit and push it

    git checkout -b change-env-var
    
    # This changes the environment variable. Choose the command for your shell:
    sed -i    -e 's/Hello deployer/Hello ephemeral env/' score.yaml # Bash
    sed -i '' -e 's/Hello deployer/Hello ephemeral env/' score.yaml # MacOS
    
    git commit -a -m "Changed env variable in Score file"
    git push --set-upstream origin change-env-var
    

    Creating the branch alone will not yet trigger any workflows, even with repeated pushes to the branch.

sequenceDiagram
actor Developer
participant "main" branch

Developer->>"main" branch: Create branch
create participant "change-env-var" branch
"main" branch->>"change-env-var" branch: Create branch

"change-env-var" branch-->>"main" branch: Branch created
"main" branch-->>Developer: Branch created

loop Repeatedly
    Developer->>"change-env-var" branch: Push changes
end

participant "development" Environment
  1. Open your repo at https://github.com/<your-GitHub-org>/ephemeral-env-demo and select the “Pull requests” tab

  2. Select New pull request

    • For “base”, select main
    • For “compare”, select change-env-var
  3. Select Create pull request, enter an optional description, and confirm via Create pull request

  4. GitHub assigns consecutive IDs on pull requests in one organization or account. Note the id of your new pull request which you can find at the end of the current URL (.../pull/<id>) or in the PR title ("#<id>"). If you came here in a straight path, this ID will be 1.

    export PR_ID=<id>
    
  5. Wait for the workflow to complete

    The GitHub UI will show a running workflow in the “Checks” section. Wait for it to finish and display the message “All checks have passed”.

  6. Inspect the PR comment

    The GitHub workflow created a PR comment visible in the UI and headlined Deployment successfully completed for PR-<id>!.

    Explore the information provided in the comment. To learn more about the particular topics covered, use these sources:

  7. Verify the deployment is running fine

    The Workflow has created a new Environment in your Platform Orchestrator Application named after your pull request.

    • Click on the link View in Platform Orchestrator in the GitHub comment. It takes you to the deployment in the new Environment
    • Select the web-app Workload
    • You should see a status of 1 Pod “Running”
    • Click on the App ephemeral-environments in the breadcrumb at the top
    • You should see the new Environment named PR-<id> next to the previously existing development Environment

    If you have kubectl set up, execute this command:

    kubectl get pods,services -A -l app.kubernetes.io/name=web-app
    

    You should now see two Pods in status “Running” and two Services in two namespaces. Each namespace houses the objects for one Environment.

  8. Visit your Application

    This step requires kubectl access to your cluster. Execute this command:

    export APP_NAMESPACE_PR=$(humctl api get \
      /orgs/$HUMANITEC_ORG/apps/$HUMANITEC_APP/envs/pr-$PR_ID/resources \
      -o yaml | \
      yq -r '.[] | select(.type == "k8s-namespace") | .resource.namespace')
    
    kubectl port-forward service/web-app 8080:8080 -n $APP_NAMESPACE_PR
    

    Open http://localhost:8080. You should see the message “Hello ephemeral env!” served by your web application. The change in the message is due to the code change you applied earlier in this branch.

    Stop the port-forward via Command+C or CTRL+C.

  9. Inspect the GitHub workflow

    The new PR caused the GitHub workflow at ./.github/workflows/pull_request.yaml to run due to its triggers:

    on:
      pull_request:
        types: [opened, reopened, synchronize]
    

    The synchronize type makes the workflow run on subsequent pushes into the PR’s branch.

    Whenever a pull request is opened or reopened, the workflow will create a new Environment in the Platform Orchestrator Application:

    - name: Create Humanitec Env
      if: ${{ github.event.action == 'opened' || github.event.action == 'reopened' }}
        run: |
          humctl create environment ${{ env.ENVIRONMENT_ID }} \
          ...
    

    Again following a common Docker login, build and push sequence, the workflow performs a deployment of the score.yaml into that new Environment, using the previously built image:

    humctl score deploy \
      ...
      --property "containers.demo.image=${{ steps.build_push.outputs.IMAGE }}"
    

    The following Build Comment Message step demonstrates a range of possible outputs you may want to include in your PR comments with each run of this workflow. It uses the humctl CLI to obtain this information from the Platform Orchestrator.

Push an update into the pull request

Every time you push an update into the branch backing the pull request, the GitHub workflow will re-build the image and perform another deployment into the associated Environment.

  1. Apply and push another code update:

    # This changes the environment variable once more. Choose the command for your shell:
    sed -i    -e 's/Hello ephemeral env/Hello updated ephemeral env/' score.yaml # Bash
    sed -i '' -e 's/Hello ephemeral env/Hello updated ephemeral env/' score.yaml # MacOS
    
    git commit -a -m "Changed env variable once more"
    git push
    
  2. Open your repo at https://github.com/<your-GitHub-org>/ephemeral-env-demo/pull/<id>

  3. Watch as the GitHub workflow runs until “All checks have passed” and created another comment

  4. Verify the deployment is updated

    • Click on the link View in Platform Orchestrator in the new comment to inspect the new Deployment as before

    If you have kubectl set up, execute this command:

    kubectl get pods,services -A -l app.kubernetes.io/name=web-app
    

    You should see the two Pods in status “Running” and two Services in two namespaces, with the Pod in the PR namespace recently started (check the AGE column).

  5. Re-visit your Application

    This step requires kubectl access to your cluster. Execute this command:

    kubectl port-forward service/web-app 8080:8080 -n $APP_NAMESPACE_PR
    

    Open http://localhost:8080. You should see the message “Hello updated ephemeral env!” served by your web application. The change in the message is due to the code change you applied earlier in this branch.

    Stop the port-forward via Command+C or CTRL+C.

    You now have created a new Environment through a pull request creation and pushed another update into it. Any subsequent push into the branch will again trigger an update of the Environment.

sequenceDiagram
actor Developer
participant "main" branch
participant "change-env-var" branch

create participant Pull request 1
Developer->>Pull request 1: Create pull request

Pull request 1->>Pull request 1: Trigger "Pull request" workflow
create participant "PR-1" Environment
Pull request 1->>"PR-1" Environment: Create Environment
Pull request 1->>"PR-1" Environment: Deploy Environment
Pull request 1-->>Developer: Deployment comment

loop Repeatedly
    Developer->>"change-env-var" branch: Push changes
    "change-env-var" branch->>Pull request 1: Trigger "Pull request" workflow
    Pull request 1->>"PR-1" Environment: Deploy Environment
    Pull request 1-->>Developer: Deployment comment
end
participant "development" Environment

Branch away

Any number of ephemeral environments can be active in parallel. To see this in action, create another branch and another PR.

Follow the instructions of the create a pull request step again.

  • Create your new branch off of the main branch
  • Apply a code modification at your own discretion. Make sure it does not conflict with the modification in the existing branch
  • Create another PR and have the new Environment automatically deployed for you

Merge the pull request

Once there are no more code changes imminent, you will want to merge your pull request. We will skip the usually required approval in this demo and merge ourselves.

  1. Open your repo at https://github.com/<your-GitHub-org>/ephemeral-env-demo/pull/<id>

  2. Select Merge pull request and Confirm merge, and then Delete branch

  1. Switch to the “Actions” tab

    • You should see a run for the Close Pull Request workflow on the change-env-var branch
    • This run deleted the Environment associated with the pull request from the Platform Orchestrator
    • You should see another run for the Main workflow on the main branch
    • This run performed the deployment of main into the development environment following the merge of your changes
  2. Verify environment deletion

  • In the Platfom Orchestrator Applications screen, select the ephemeral-environments Application

  • You should see only development in the list of Environments

    If you have kubectl set up, execute this command:

    kubectl get pods,services -A -l app.kubernetes.io/name=web-app
    

    You should see only one Pod and one Service left, representing the development Environment. The Pod has been recently updated according to its AGE.

  1. Re-visit your Application

    This step requires kubectl access to your cluster. Execute this command:

    kubectl port-forward service/web-app 8080:8080 -n $APP_NAMESPACE_DEVELOPMENT
    

    Open http://localhost:8080. You should see the message “Hello updated ephemeral env!” served by your web application. It reflects the merge of your changes into the main branch.

    Stop the port-forward via Command+C or CTRL+C.

    You now have applied your changes to the main branch and updated its accociated development Environment. All intermediary objects - the GitHub branch, pull request, and the additional Environment - are deleted or closed.

sequenceDiagram
actor Developer
participant "main" branch
participant "change-env-var" branch
participant Pull request 1
participant "PR-1" Environment

Developer->>Pull request 1: Merge pull request

Pull request 1->>Pull request 1: Trigger "Close pull request" workflow
destroy "PR-1" Environment
Pull request 1->>"PR-1" Environment: Delete Environment
destroy Pull request 1
Pull request 1->>"change-env-var" branch: Merge
"change-env-var" branch->>"main" branch: Merge

participant "development" Environment
"main" branch->>"main" branch: Trigger "Main" workflow
"main" branch->>"development" Environment: Deploy Environment
"development" Environment-->>"main" branch: Workflow run success
"main" branch-->>Developer: Workflow run success
destroy "change-env-var" branch
Developer->>"change-env-var" branch: Delete branch

Cleaning up

  1. Delete the Application from the Platform Orchestrator. This will make the Orchestrator un-deploy all resources from the cluster.

    humctl delete app $HUMANITEC_APP
    
  2. Delete the matching criteria on the cluster Resource Definition:

    humctl api delete /orgs/${HUMANITEC_ORG}/resources/defs/${K8S_RESDEF}/criteria/${CRITERIA_ID}
    

    If your cluster is using the Humanitec Agent, also delete its matching criteria:

    humctl api delete /orgs/${HUMANITEC_ORG}/resources/defs/${AGENT_RESDEF}/criteria/${CRITERIA_ID_AGENT}
    
  3. Delete the GitHub repository:

    • Open your repo at https://github.com/<your-GitHub-org>/ephemeral-env-demo
    • Select the “Settings” tab
    • At the very bottom, select Delete this repository and confirm
  4. Delete the package:

    • Select the “Packages” tab
    • Select the ephemeral-env-demo package
    • Select Package settings
    • At the very bottom, select Delete this package and confirm
  5. Delete the local repo clone:

    cd ..
    rm -rf ephemeral-env-demo
    
  6. Revoke the API token for the Platform Orchestrator.

Recap

Congratulations! You successfully completed the tutorial and saw how to set up ephemeral Environments. You learned how to:

  • Configure repositories for ephemeral Environments
  • Describe your Workload using Score
  • Design pipelines (here: GitHub workflows) with the proper triggers
  • Automatically create a new Environment
  • Trigger automated Deployments with Score
  • Clean up Environments after use

Apply it to your setup

Merging the pull request(s) completes the cycle of applying and revieweing a code change with the help of the Platform Orchestrator and ephemeral Environments.

The repository you used to work through this tutorial is self-contained with a simple demo application only. If you wish to apply the mechanisms of ephemeral Environments to your own setup, use the repo as a source and integrate those elements into your own repository:

  • Describe your Workload using Score
  • Adapt the three GitHub workflows located in the ./.github/workflows folder
    • If you are using GitHub yourself, they will work out of the box
    • Remember to set variables and secrets in your own repo as shown in the Create the repository step
    • Feel free to to adjust the pull request comment output in ./.github/workflows/pull_request.yaml to your needs
    • If you are not using GitHub, you should be able to transfer the workflow code into your system quite easily. The workflows largely refrain from using specialized GitHub Actions, so the code should be portable to and run on most Linux-based runners.
  • You may choose to let the main branch deploy into a different Environment than development. If so, change the deployment target Environment in main.yaml and the base Environment for the ephemeral Environments in pull_request.yaml.

Next steps

You can customize what happens at deploy time by creating your own Humanitec Deployment Pipelines.

If you are using GitHub, take a look at the ephemeral environments guide. It showcases the specialized Humanitec GitHub action for ephemeral environments. While the overall approach is the same as seen in the present tutorial, using the action may require less code.

Top