Build Edge Artifacts
One of the first steps in deploying an Edge cluster is preparing your Edge host with all the required artifacts. The process of building these artifacts is called EdgeForge, and it is responsible for generating the installer ISO and provider image artifacts.
- Installer ISO: An ISO image that installs the Palette Edge agent on the host.
- Provider Images: Kairos-based images that include the Operating System (OS) and the desired Kubernetes versions. These images install an immutable OS and the software dependencies compatible with the selected Kubernetes version during cluster deployment.
This tutorial teaches you how to build the artifacts required for your Edge deployment. Once built, you will be ready to learn how to reference them in Edge cluster profiles and how they are used to install the Palette agent on hosts.
Prerequisites
To complete this tutorial, ensure the following prerequisites are in place.
- You have completed the steps in the Prepare User Data for Edge Installation tutorial, including cloning the CanvOS repository and creating and validating a user data file.
- A physical or virtual Linux machine with an AMD64 (also known as
x86_64
) processor architecture and the following minimum hardware configuration:- 4 CPUs
- 8 GB memory
- 150 GB storage
- Access to a public image registry and permissions to push images. This tutorial uses Docker Hub as an example. If you need to use a private registry, refer to the Deploy Cluster with a Private Provider Registry guide for instructions on how to configure the credentials.
- The following software installed on the Linux machine:
Define Build Arguments
Open a terminal window on your Linux machine and navigate to the CanvOS
repository that you cloned in the
Prepare User Data for Edge Installation tutorial. This repository contains the utilities
required to build the artifacts.
cd CanvOS
Check the available Git tags.
git tag --sort=v:refname
Check out the desired tag. We recommend using a CanvOS minor version that is the same as, or older than, Palette's minor
version. This tutorial uses the tag v4.6.24
as an example.
git checkout v4.6.24
EdgeForge leverages Earthly to build the installer ISO and provider images artifacts. A .arg
file is used to pass the values of a few arguments, such as the provider image tag and registry name, to Earthly for the
build process.
While both the .arg
file and user-data file are configuration files used during the
EdgeForge process, they serve different purposes. The .arg
file is used to customize the Edge artifact build process.
For example, you can specify the name of the installer ISO to be built, the Kubernetes distribution and version for the
provider images, the registry to push the images to, and more. The
Edge Artifact Build Configurations page contains a
list of all the configurable parameters. In contrast, the user-data
file focuses on customizing the installer ISO.
When the Edge host boots from the installer ISO, it applies the user data configuration to the host.
Set a custom tag for the provider images. The tag must be an alphanumeric lowercase string. This tutorial uses
gs-tutorial
as an example. Additionally, replace spectrocloud
with the name of your registry.
export CUSTOM_TAG=gs-tutorial
export IMAGE_REGISTRY=spectrocloud
Next, issue the following command to create the .arg
file using the custom tag and registry. The remaining arguments
use predefined values. For example, this tutorial uses K3s version 1.32.3
as the Kubernetes
distribution and Ubuntu as the OS distribution. Review the k8s_version.json
file in the CanvOS repository for all
supported Kubernetes versions.
If you are using a CanvOS tag that is earlier than v4.4.12, the k8s_version.json
file does not exist in those tags. In
that case, review the Earthfile
file in the CanvOS repository for all supported Kubernetes versions.
cat << EOF > .arg
CUSTOM_TAG=$CUSTOM_TAG
IMAGE_REGISTRY=$IMAGE_REGISTRY
OS_DISTRIBUTION=ubuntu
IMAGE_REPO=ubuntu
OS_VERSION=22.04
K8S_DISTRIBUTION=k3s
K8S_VERSION=1.32.3
ISO_NAME=palette-edge-installer
ARCH=amd64
UPDATE_KERNEL=false
EOF
Verify that the file was created correctly using the cat
command.
cat .arg
You can also use the Appliance Studio configuration
Graphic User Interface (GUI) to help you create the .arg
file.
Build Artifacts
Issue the following command to build the Edge artifacts.
sudo ./earthly.sh +build-all-images
The build may take 15 to 20 minutes to complete, depending on the hardware resources available on the host machine. Once complete, a success message appears.
========================== 🌍 Earthly Build ✅ SUCCESS ==========================
The output also includes a manifest with predefined values required to create the Edge cluster profile. These parameters reference the built provider image. Copy and save the manifest, as you will need it for the next tutorial.
pack:
content:
images:
- image: "{{.spectro.pack.edge-native-byoi.options.system.uri}}"
# Below config is default value, please uncomment if you want to modify default values
#drain:
#cordon: true
#timeout: 60 # The length of time to wait before giving up, zero means infinite
#gracePeriod: 60 # Period of time in seconds given to each pod to terminate gracefully. If negative, the default value specified in the pod will be used
#ignoreDaemonSets: true
#deleteLocalData: true # Continue even if there are pods using emptyDir (local data that will be deleted when the node is drained)
#force: true # Continue even if there are pods that do not declare a controller
#disableEviction: false # Force drain to use delete, even if eviction is supported. This will bypass checking PodDisruptionBudgets, use with caution
#skipWaitForDeleteTimeout: 60 # If pod DeletionTimestamp older than N seconds, skip waiting for the pod. Seconds must be greater than 0 to skip.
options:
system.uri: "{{ .spectro.pack.edge-native-byoi.options.system.registry }}/{{ .spectro.pack.edge-native-byoi.options.system.repo }}:{{ .spectro.pack.edge-native-byoi.options.system.k8sDistribution }}-{{ .spectro.system.kubernetes.version }}-{{ .spectro.pack.edge-native-byoi.options.system.peVersion }}-{{ .spectro.pack.edge-native-byoi.options.system.customTag }}"
system.registry: spectrocloud
system.repo: ubuntu
system.k8sDistribution: k3s
system.osName: ubuntu
system.peVersion: v4.6.24
system.customTag: gs-tutorial
system.osVersion: 22.04
Confirm that the Edge installer ISO and its checksum have been created correctly.
ls build
palette-edge-installer.iso palette-edge-installer.iso.sha256
List the container images to confirm that the provider images were built successfully.
docker images --filter=reference="*/*:*$CUSTOM_TAG"
REPOSITORY TAG IMAGE ID CREATED SIZE
spectrocloud/ubuntu k3s-1.32.3-v4.6.24-gs-tutorial d28750baa9a6 33 minutes ago 5.05GB
spectrocloud/ubuntu k3s-1.32.3-v4.6.24-gs-tutorial_linux_amd64 d28750baa9a6 33 minutes ago 5.05GB
Push Provider Images
To use the provider image with your Edge deployment, push it to the image registry specified in the .arg
file. Issue
the following command to log in to Docker Hub. Provide your Docker ID and password when prompted.
docker login
Login Succeeded
Once authenticated, push the provider image to the registry so that your Edge host can download it during the cluster deployment.
docker push $IMAGE_REGISTRY/ubuntu:k3s-1.32.3-v4.6.24-$CUSTOM_TAG
The output confirms that the image was pushed to the registry with the correct tag and is ready to be used in a cluster profile.
...
k3s-1.32.3-v4.6.24-gs-tutorial: digest: sha256:518f937c3256e49c31b54ae72404812c99198281ddea647183b6ee8fc6938aaa size: 16576
Automate EdgeForge
The following example script automates the EdgeForge process. It provides an alternative way to build the artifacts if you have already learned the steps and want to replicate them quickly. You can skip this section if you have followed the tutorial and built the artifacts manually.
The script clones the CanvOS repository, creates a sample user-data
file, or uses the one provided by the user. It
then builds the Edge artifacts and pushes the provider images to the registry. The script prompts the user for a few
options, including the CanvOS Git tag, Kubernetes distribution and version for the provider images, and more.
Follow the steps below to build the artifacts using the script.
EdgeForge Automation Example Script
-
Open a terminal window on your Linux machine and issue the following command to create the script file.
cat << EOF > edgeforge.sh
#!/bin/bash
# Prompt user for working directory (defaults to current if empty)
read -p "📂 Enter the absolute path where operations should take place [default: current directory]: " WORKING_DIR
# Use current directory if none provided
if [ -z "$WORKING_DIR" ]; then
WORKING_DIR=$(pwd)
echo "ℹ️ No directory provided. Using current directory: $WORKING_DIR"
fi
# Verify and enter the directory
if [ -d "$WORKING_DIR" ]; then
cd "$WORKING_DIR" || { echo "❌ Failed to change directory: $WORKING_DIR"; exit 1; }
echo "✅ Working directory set to: $WORKING_DIR"
else
echo "❌ Invalid path provided. Please ensure the directory exists."
exit 1
fi
# Clone the CanvOS repository
echo "Cloning CanvOS repository..."
git clone https://github.com/spectrocloud/CanvOS.git
cd CanvOS || { echo "Failed to enter CanvOS directory"; exit 1; }
# Fetch latest git tags
echo "Fetching git tags..."
git fetch --tags
echo "Available tags:"
git --no-pager tag --list | sort --version-sort
# Prompt for tag selection
while true; do
read -p "Enter the CanvOS tag to checkout (for example, v4.6.24): " TAG
# Validate the tag exists
if git --no-pager tag --list | grep --quiet --line-regexp "$TAG"; then
git checkout "$TAG"
break
else
echo "❌ Tag '$TAG' not found in the list of available tags. Please try again."
fi
done
# Prompt for user-data file content
echo "Enter the absolute path to your user-data file (must already contain the Palette registration token)."
echo "If you leave this empty, a default user-data file will be created."
read -p "Absolute path to user-data file (or press Enter to use default): " USER_DATA_PATH
# If user-data file is empty, use the sample user-data
if [ -z "$USER_DATA_PATH" ]; then
# Prompt for Palette registration token in a loop
while true; do
read -p "Enter your Palette registration token: " TOKEN
if [ -n "$TOKEN" ]; then
export TOKEN
break
else
echo "❌ Token cannot be empty. Please enter a valid token."
fi
done
# Create sample user-data file
echo "Creating default user-data file..."
cat << EOF > user-data
#cloud-config
stylus:
site:
edgeHostToken: $TOKEN
paletteEndpoint: api.spectrocloud.com
stages:
initramfs:
- users:
kairos:
passwd: kairos
install:
poweroff: true
EOF
else
# Check if the provided path is a file and copy it to CanvOS directory
if [ -f "$USER_DATA_PATH" ]; then
cp "$USER_DATA_PATH" ./user-data
echo "✅ user-data file copied from: $USER_DATA_PATH"
else
echo "❌ File not found at: $USER_DATA_PATH"
exit 1
fi
fi
# Validate user-data file
echo "Validating user-data file..."
VALIDATION_OUTPUT=$(sudo ./earthly.sh +validate-user-data 2>&1)
if echo "$VALIDATION_OUTPUT" | grep --ignore-case --quiet -e "Validation successful" -e "user data validated successfully"; then
echo "✅ User data validation passed. Proceeding..."
else
echo "❌ User data validation failed. Please check 'user-data' and try again."
exit 1
fi
# Ensure k8s_version.json exists
if [ ! -f "k8s_version.json" ]; then
echo "❌ k8s_version.json not found. Check out a Git tag v4.4.12 or later. Exiting..."
exit 1
fi
# Create .arg file with user input
echo "Creating .arg file..."
# Prompt for Kubernetes distribution
echo "⚙️ Available Kubernetes distributions:"
cat k8s_version.json | jq -r 'keys[]'
while true; do
read -p "Enter a valid Kubernetes distribution to build artifacts for (must be listed above) [default: k3s]: " K8S_DISTRIBUTION
K8S_DISTRIBUTION=${K8S_DISTRIBUTION:-k3s}
# Check if the selected distribution exists
if cat k8s_version.json | jq -e --arg dist "$K8S_DISTRIBUTION" 'has($dist)' > /dev/null; then
break
else
echo "❌ Distribution '$K8S_DISTRIBUTION' not found in k8s_version.json. Please try again."
fi
done
# Show available versions
echo "📦 Available versions for $K8S_DISTRIBUTION:"
AVAILABLE_VERSIONS=$(cat k8s_version.json | jq -r --arg dist "$K8S_DISTRIBUTION" '.[$dist][]')
echo "$AVAILABLE_VERSIONS"
# Prompt for a valid version
while true; do
read -p "Enter a valid Kubernetes version to build artifacts for (must be listed above): " K8S_VERSION
if echo "$AVAILABLE_VERSIONS" | grep --quiet --line-regexp "$K8S_VERSION"; then
break
else
echo "❌ Version '$K8S_VERSION' is invalid. Please enter a valid version from the list above."
fi
done
# Prompt for other .arg file parameters
read -p "Enter custom tag for the artifacts [default: gs-tutorial]: " CUSTOM_TAG
CUSTOM_TAG=${CUSTOM_TAG:-gs-tutorial}
read -p "Enter OS distribution [default: ubuntu]: " OS_DISTRIBUTION
OS_DISTRIBUTION=${OS_DISTRIBUTION:-ubuntu}
read -p "Enter OS version [default: 22.04]: " OS_VERSION
OS_VERSION=${OS_VERSION:-22.04}
while true; do
read -p "Enter Image Registry Name (for example, spectrocloud): " IMAGE_REGISTRY
if [ -n "$IMAGE_REGISTRY" ]; then
break
else
echo "❌ Image registry name cannot be empty. Please enter a valid registry."
fi
done
cat << EOF > .arg
CUSTOM_TAG=$CUSTOM_TAG
IMAGE_REGISTRY=$IMAGE_REGISTRY
OS_DISTRIBUTION=$OS_DISTRIBUTION
IMAGE_REPO=$OS_DISTRIBUTION
OS_VERSION=$OS_VERSION
K8S_DISTRIBUTION=$K8S_DISTRIBUTION
K8S_VERSION=$K8S_VERSION
ISO_NAME=palette-edge-installer
ARCH=amd64
UPDATE_KERNEL=false
EOF
echo "✅ .arg file created."
# Build artifacts
echo "Building Edge artifacts... This will take approximately 15 minutes."
# Create a temp file to capture the output
TEMP_BUILD_LOG=$(mktemp)
# Run the build, tee output to console and save it to temp file
if sudo ./earthly.sh +build-all-images | tee "$TEMP_BUILD_LOG"; then
echo "✅ Artifacts built successfully."
# Extract the manifest profile YAML from build output
awk '/^pack:/{flag=1} flag' "$TEMP_BUILD_LOG" > manifest-profile.yaml
if [ -s manifest-profile.yaml ]; then
echo "✅ Extracted manifest profile YAML to 'manifest-profile.yaml'."
else
echo "❌ Failed to extract manifest profile YAML from build output."
fi
else
echo "❌ Failed to build artifacts. Please check the logs and try again."
rm -f "$TEMP_BUILD_LOG"
exit 1
fi
# Push images to registry
echo "Pushing provider image to registry..."
if docker push "$IMAGE_REGISTRY/$OS_DISTRIBUTION:$K8S_DISTRIBUTION-$K8S_VERSION-$TAG-$CUSTOM_TAG"; then
echo "✅ Image pushed successfully to registry: $IMAGE_REGISTRY/$OS_DISTRIBUTION:$K8S_DISTRIBUTION-$K8S_VERSION-$TAG-$CUSTOM_TAG"
else
echo "❌ Failed to push the image to the registry."
exit 1
fi
echo "✅ Build completed successfully."
echo "Artifacts are located in the 'CanvOS/build' folder."
echo "The manifest to paste into your cluster profile is available in 'CanvOS/manifest-profile.yaml'"
EOF -
Grant execution permissions to the script.
chmod +x edgeforge.sh
-
Log in to the image registry that you will use to host the provider images. This tutorial uses Docker Hub as an example. Provide your Docker ID and password when prompted.
docker login
Login Succeeded
-
Invoke the script to build the artifacts, answering the prompts.
./edgeforge.sh
-
Once the build is complete, the script generates a manifest in
CanvOS/manifest-profile.yaml
with predefined values required to create the cluster profile. Ensure to save this manifest, as you will need it for the next tutorial. -
Confirm that the Edge installer ISO and its checksum have been created correctly.
ls CanvOS/build
palette-edge-installer.iso palette-edge-installer.iso.sha256
Next Steps
In this tutorial, you built the artifacts required for your Edge deployment. We recommend proceeding to the Create Edge Cluster Profile tutorial, where you will learn how to create an Edge native cluster profile that references the built provider image. You will then learn how to use the installer ISO to bootstrap the Edge installation on your host and use it as a node for deploying your first Edge cluster.