3.1 Provision Compute¶
Compute provisioning on AWS has two stages: building the Talos AMI, then deploying EC2 instances via Formae.
Prerequisites: Build the Talos AMI¶
There is no official Talos AMI in af-south-1. You must build and register a custom AMI using the bootstrap pipeline.
Step 1: Deploy Bootstrap Resources¶
The bootstrap.pkl forma creates the S3 bucket and IAM vmimport role needed for AMI registration:
This creates:
- S3 bucket:
rciis-talos-images-af-south-1with a 30-day lifecycle expiry - IAM role:
vmimportwith permissions for EC2 VM Import/Export
Step 2: Generate the Talos Disk Image¶
Option A — Vanilla image (no extensions):
Download the official Talos disk image for AWS:
Option B — Custom image with extensions:
Edit schematic.yaml to enable the extensions you need, then submit to Image Factory:
# Submit schematic and get the schematic ID
$SCHEMATIC_ID = Invoke-RestMethod -Method Post -InFile schematic.yaml -Uri "https://factory.talos.dev/schematics"
# Download the custom disk image
Invoke-WebRequest -Uri "https://factory.talos.dev/image/$SCHEMATIC_ID/v1.12.2/aws-amd64.raw.xz" -OutFile "aws-amd64.raw.xz"
7z x aws-amd64.raw.xz
Available extensions are listed at github.com/siderolabs/extensions.
Step 3: Upload to S3¶
Step 4: Import as EBS Snapshot¶
Check import progress (optional)
If you want to monitor progress while the import is running (e.g. in a separate terminal), use describe-import-snapshot-tasks. Unlike wait, this returns immediately with the current status and percentage:
Step 5: Wait for Import and Get Snapshot ID¶
The wait snapshot-imported command blocks until the import finishes — it polls automatically and returns when the snapshot is ready:
aws ec2 wait snapshot-imported \
--region af-south-1 \
--import-task-ids $IMPORT_TASK
SNAPSHOT_ID=$(aws ec2 describe-import-snapshot-tasks \
--region af-south-1 \
--import-task-ids $IMPORT_TASK \
--query 'ImportSnapshotTasks[0].SnapshotTaskDetail.SnapshotId' \
--output text)
echo "Snapshot: $SNAPSHOT_ID"
aws ec2 wait snapshot-imported `
--region af-south-1 `
--import-task-ids $IMPORT_TASK
$SNAPSHOT_ID = aws ec2 describe-import-snapshot-tasks `
--region af-south-1 `
--import-task-ids $IMPORT_TASK `
--query 'ImportSnapshotTasks[0].SnapshotTaskDetail.SnapshotId' `
--output text
Write-Output "Snapshot: $SNAPSHOT_ID"
Step 6: Register the AMI¶
VolumeSize must match the snapshot size
The VolumeSize in --block-device-mappings must be equal to or larger than the imported snapshot. The Talos v1.12.2 snapshot is 11 GiB. Using a smaller value (e.g. 4) will fail with InvalidParameterValue.
AMI=$(aws ec2 register-image \
--region af-south-1 \
--name "talos-v1.12.2-rciis" \
--root-device-name /dev/xvda \
--block-device-mappings "DeviceName=/dev/xvda,Ebs={SnapshotId=${SNAPSHOT_ID},VolumeSize=11,VolumeType=gp3,DeleteOnTermination=true}" \
--virtualization-type hvm \
--architecture x86_64 \
--ena-support \
--query 'ImageId' --output text)
echo "AMI: $AMI"
$AMI = aws ec2 register-image `
--region af-south-1 `
--name "talos-v1.12.2-rciis" `
--root-device-name /dev/xvda `
--block-device-mappings "DeviceName=/dev/xvda,Ebs={SnapshotId=$SNAPSHOT_ID,VolumeSize=11,VolumeType=gp3,DeleteOnTermination=true}" `
--virtualization-type hvm `
--architecture x86_64 `
--ena-support `
--query 'ImageId' --output text
Write-Output "AMI: $AMI"
Deploy EC2 Instances¶
With the AMI ready, deploy the full cluster infrastructure:
Formae will display a deployment summary and prompt for confirmation before creating resources.
What Gets Created¶
The modules/compute.pkl module provisions:
Control Plane Instances (default: 3):
| Property | Value |
|---|---|
| Instance type | t3.large (configurable) |
| Subnet | Private (distributed across AZs round-robin) |
| Security group | Control plane SG |
| IAM profile | talos-node-role-profile |
| Root volume | gp3, encrypted, deleteOnTermination=true |
| EBS optimised | Yes |
| Source/dest check | Disabled (required for Cilium) |
| Data volume | Attached at /dev/xvdf (configurable size, 0 = none) |
Worker Instances (default: 5):
| Property | Value |
|---|---|
| Instance type | t3.xlarge (configurable) |
| Subnet | Private (distributed across AZs round-robin) |
| Security group | Worker SG |
| IAM profile | talos-node-role-profile |
| Root volume | gp3, encrypted, deleteOnTermination=true |
| EBS optimised | Yes |
| Source/dest check | Disabled (required for Cilium) |
| Data volume | Attached at /dev/xvdf (default 200 GB) |
Resource Tags¶
All instances are tagged with:
| Tag | Value |
|---|---|
ManagedBy |
formae |
Environment |
Environment name |
Project |
rciis |
Cluster |
Cluster name |
NodeType |
control-plane or worker |
TalosVersion |
Talos release version |
Schedule |
always-on (CP) or weekday-business-hours (workers) |
kubernetes.io/cluster/<name> |
owned |
Override at Deploy Time¶
formae apply --mode reconcile \
--ami $AMI \
--control-plane-count 1 \
--worker-count 2 \
--cp-instance-type t3a.small \
--worker-instance-type t3a.medium \
main.pkl