Hi there Agent, read the instructions below.
Spin up a simple Kubernetes cluster on Atlas Cloud (our CloudStack at https://sky.runatlas.is/client/api) using the cmk (CloudMonkey) CLI.
---
STEP 0 — CREDENTIALS
The CloudStack API needs CLOUDSTACK_API_KEY and CLOUDSTACK_SECRET_KEY. Check both are set:
printenv CLOUDSTACK_API_KEY | wc -c
printenv CLOUDSTACK_SECRET_KEY | wc -c
Both should return > 1. If either is zero or missing, stop and ask the user to write a .env file in the working directory:
CLOUDSTACK_API_KEY=<key>
CLOUDSTACK_SECRET_KEY=<secret>
Do not proceed until both are confirmed non-empty. Never print or echo the values.
Important: export in the user's terminal does not propagate to your Bash subshell. Every command that needs credentials must begin with:
set -a && source .env && set +a &&
---
STEP 1 — INSTALL AND CONFIGURE cmk
Check if cmk is installed (which cmk). If not, detect architecture (uname -m) and download the correct binary from the latest GitHub release at https://github.com/apache/cloudstack-cloudmonkey/releases:
arm64 -> cmk.darwin.arm64
x86_64 -> cmk.darwin.x86-64
Install:
curl -sL https://github.com/apache/cloudstack-cloudmonkey/releases/download/6.5.0/cmk.darwin.arm64 \
-o /usr/local/bin/cmk
chmod +x /usr/local/bin/cmk
Configure (source .env first so the keys are in scope):
cmk set url https://sky.runatlas.is/client/api
cmk set apikey "$CLOUDSTACK_API_KEY"
cmk set secretkey "$CLOUDSTACK_SECRET_KEY"
cmk set output json
cmk sync
Verify with: cmk list zones
Expected: zone named "is1".
---
STEP 2 — DISCOVER RESOURCES
cmk list zones
cmk list kubernetessupportedversions zoneid=<zone-id>
cmk list serviceofferings
cmk list sshkeypairs
Expected on Atlas Cloud:
Zone: is1
Kubernetes: Kubernetes 1.33.1 Calico (only version available)
Minimum per node: 2 vCPU / 2 GB RAM
Service offerings: Atlas.a4 (1 vCPU / 4 GB)
Atlas.a5 (2 vCPU / 8 GB) <-- use this as default
Atlas.a6 (4 vCPU / 16 GB)
Atlas.a7 (8 vCPU / 32 GB)
Pick up the IDs for the zone, Kubernetes version, and Atlas.a5 service offering from the output.
For SSH key pairs: if one or more exist, use the first one and note its name. If none
exist, stop and ask the user to create and register one themselves:
ssh-keygen -t ed25519 -f ./atlas-k8s-key -N "" -C "atlas-k8s"
PUBKEY=$(cat ./atlas-k8s-key.pub)
cmk register sshkeypair name=atlas-k8s-key publickey="$PUBKEY"
Ask them to come back with the key pair name once done, then continue.
---
STEP 3 — CREATE THE CLUSTER
cmk create kubernetescluster \
name=atlas-k8s \
zoneid=<zone-id> \
kubernetesversionid=<k8s-version-id> \
serviceofferingid=<atlas-a5-id> \
controlnodes=1 \
size=2 \
keypair=<keypair-name> \
description="Simple CKS cluster on Atlas Cloud"
CRITICAL: Do not pass networkid. Let CKS auto-create its own isolated network.
Specifying an existing user network causes a 530 error ("Kubernetes service has not
been configured properly") even when the network exists and CKS is otherwise fully
functional. Omitting networkid is the correct approach.
CRITICAL: Do not run this command in the background or retry it if it appears to hang.
The API call is synchronous and returns only after all nodes are provisioned and Running.
Running it twice creates two clusters. Wait for the full JSON response.
A successful response includes the cluster id, endpoint (API server URL), keypair field
set to the key name, and all three VMs listed with state=Running.
---
STEP 4 — FETCH KUBECONFIG
cmk get kubernetesclusterconfig id=<cluster-id> \
| python3 -c "import json,sys; print(json.load(sys.stdin)['clusterconfig']['configdata'], end='')" \
> ./kubeconfig
chmod 0600 ./kubeconfig
---
STEP 5 — VERIFY NODES
kubectl --kubeconfig ./kubeconfig get nodes -o wide
All three nodes (1 control plane + 2 workers) should show Ready.
---
REPORT BACK
Cluster name, cluster ID, API server endpoint, kubeconfig path, kubectl get nodes output