AWS

Official AMI Images

RegionVersionInstance TypeArchitectureAMI
ap-northeast-1 v0.9.0 hvmamd64ami-063285d29bedf0a6a
ap-northeast-1 v0.9.0 hvmarm64ami-0a51cb31d3f7a6160
ap-northeast-2 v0.9.0 hvmarm64ami-07568dc427ce24aa6
ap-northeast-2 v0.9.0 hvmamd64ami-0e9544704321f1239
ap-northeast-3 v0.9.0 hvmamd64ami-021c4a4a7f3e1318c
ap-northeast-3 v0.9.0 hvmarm64ami-0aa209fb78f6bf352
ap-southeast-1 v0.9.0 hvmamd64ami-0bc7f51e55b9562d1
ap-southeast-1 v0.9.0 hvmarm64ami-0088f1112127d593d
ap-southeast-2 v0.9.0 hvmamd64ami-0f192c8ebfea24c3d
ap-southeast-2 v0.9.0 hvmarm64ami-063a56a0a91169927
ca-central-1 v0.9.0 hvmamd64ami-062996f75fa0a8abd
ca-central-1 v0.9.0 hvmarm64ami-02367c867f252f431
eu-central-1 v0.9.0 hvmamd64ami-06405c65400d7af5a
eu-central-1 v0.9.0 hvmarm64ami-0f8201c9cea4ab3cd
eu-north-1 v0.9.0 hvmarm64ami-0e412c3e893e601d6
eu-north-1 v0.9.0 hvmamd64ami-0dce80f5550ebe8b4
eu-west-1 v0.9.0 hvmamd64ami-0edc0bedb38550778
eu-west-1 v0.9.0 hvmarm64ami-07ab00ad86efe59d8
eu-west-2 v0.9.0 hvmamd64ami-0ab3228c2442d962f
eu-west-2 v0.9.0 hvmarm64ami-01ba16616a5c8eea2
eu-west-3 v0.9.0 hvmamd64ami-0f89a6acf962b9a84
eu-west-3 v0.9.0 hvmarm64ami-029421a3e62583302
sa-east-1 v0.9.0 hvmarm64ami-0116f8912d253cb1d
sa-east-1 v0.9.0 hvmamd64ami-051cc3eff0981dc23
us-east-1 v0.9.0 hvmarm64ami-06c89f4e127c9803d
us-east-1 v0.9.0 hvmamd64ami-05cdaf5837708ba49
us-east-2 v0.9.0 hvmarm64ami-00d8edce31c41f6b9
us-east-2 v0.9.0 hvmamd64ami-0fa15b54ffd448e69
us-west-1 v0.9.0 hvmarm64ami-07f4c25029d96d4a0
us-west-1 v0.9.0 hvmamd64ami-053dc722d046347d7
us-west-2 v0.9.0 hvmarm64ami-0abd696737a82caa9
us-west-2 v0.9.0 hvmamd64ami-016466266f3fc6117

Creating a Cluster via the AWS CLI

In this guide we will create an HA Kubernetes cluster with 3 worker nodes. We assume an existing VPC, and some familiarity with AWS. If you need more information on AWS specifics, please see the official AWS documentation.

Create the Subnet

aws ec2 create-subnet \
    --region $REGION \
    --vpc-id $VPC \
    --cidr-block ${CIDR_BLOCK}

Create the AMI

Prepare the Import Prerequisites

Create the S3 Bucket
aws s3api create-bucket \
    --bucket $BUCKET \
    --create-bucket-configuration LocationConstraint=$REGION \
    --acl private
Create the vmimport Role

In order to create an AMI, ensure that the vmimport role exists as described in the official AWS documentation.

Note that the role should be associated with the S3 bucket we created above.

Create the Image Snapshot

First, download the AWS image from a Talos release:

curl -LO https://github.com/talos-systems/talos/releases/latest/download/aws-amd64.tar.gz | tar -xv

Copy the RAW disk to S3 and import it as a snapshot:

aws s3 cp disk.raw s3://$BUCKET/talos-aws-tutorial.raw
aws ec2 import-snapshot \
    --region $REGION \
    --description "Talos kubernetes tutorial" \
    --disk-container "Format=raw,UserBucket={S3Bucket=$BUCKET,S3Key=talos-aws-tutorial.raw}"

Save the SnapshotId, as we will need it once the import is done. To check on the status of the import, run:

aws ec2 describe-import-snapshot-tasks \
    --region $REGION \
    --import-task-ids

Once the SnapshotTaskDetail.Status indicates completed, we can register the image.

Register the Image
aws ec2 register-image \
    --region $REGION \
    --block-device-mappings "DeviceName=/dev/xvda,VirtualName=talos,Ebs={DeleteOnTermination=true,SnapshotId=$SNAPSHOT,VolumeSize=4,VolumeType=gp2}" \
    --root-device-name /dev/xvda \
    --virtualization-type hvm \
    --architecture x86_64 \
    --ena-support \
    --name talos-aws-tutorial-ami

We now have an AMI we can use to create our cluster. Save the AMI ID, as we will need it when we create EC2 instances.

Create a Security Group

aws ec2 create-security-group \
    --region $REGION \
    --group-name talos-aws-tutorial-sg \
    --description "Security Group for EC2 instances to allow ports required by Talos"

Using the security group ID from above, allow all internal traffic within the same security group:

aws ec2 authorize-security-group-ingress \
    --region $REGION \
    --group-name talos-aws-tutorial-sg \
    --protocol all \
    --port 0 \
    --group-id $SECURITY_GROUP \
    --source-group $SECURITY_GROUP

and expose the Talos and Kubernetes APIs:

aws ec2 authorize-security-group-ingress \
    --region $REGION \
    --group-name talos-aws-tutorial-sg \
    --protocol tcp \
    --port 6443 \
    --cidr 0.0.0.0/0 \
    --group-id $SECURITY_GROUP
aws ec2 authorize-security-group-ingress \
    --region $REGION \
    --group-name talos-aws-tutorial-sg \
    --protocol tcp \
    --port 50000-50001 \
    --cidr 0.0.0.0/0 \
    --group-id $SECURITY_GROUP

Create a Load Balancer

aws elbv2 create-load-balancer \
    --region $REGION \
    --name talos-aws-tutorial-lb \
    --type network --subnets $SUBNET

Take note of the DNS name and ARN. We will need these soon.

Create the Machine Configuration Files

Generating Base Configurations

Using the DNS name of the loadbalancer created earlier, generate the base configuration files for the Talos machines:

$ talosctl gen config talos-k8s-aws-tutorial https://<load balancer IP or DNS>:<port>
created init.yaml
created controlplane.yaml
created join.yaml
created talosconfig

At this point, you can modify the generated configs to your liking.

Validate the Configuration Files

$ talosctl validate --config init.yaml --mode cloud
init.yaml is valid for cloud mode
$ talosctl validate --config controlplane.yaml --mode cloud
controlplane.yaml is valid for cloud mode
$ talosctl validate --config join.yaml --mode cloud
join.yaml is valid for cloud mode

Create the EC2 Instances

Note: There is a known issue that prevents Talos from running on T2 instance types. Please use T3 if you need burstable instance types.

Create the Bootstrap Node

aws ec2 run-instances \
    --region $REGION \
    --image-id $AMI \
    --count 1 \
    --instance-type t3.small \
    --user-data file://init.yaml \
    --subnet-id $SUBNET \
    --security-group-ids $SECURITY_GROUP \
    --tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=talos-aws-tutorial-cp-0}]"

Create the Remaining Control Plane Nodes

CP_COUNT=1
while [[ "$CP_COUNT" -lt 3 ]]; do
  aws ec2 run-instances \
    --region $REGION \
    --image-id $AMI \
    --count 1 \
    --instance-type t3.small \
    --user-data file://controlplane.yaml \
    --subnet-id $SUBNET \
    --security-group-ids $SECURITY_GROUP \
    --tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=talos-aws-tutorial-cp-$CP_COUNT}]"
  ((CP_COUNT++))
done

Make a note of the resulting PrivateIpAddress from the init and controlplane nodes for later use.

Create the Worker Nodes

aws ec2 run-instances \
    --region $REGION \
    --image-id $AMI \
    --count 3 \
    --instance-type t3.small \
    --user-data file://join.yaml \
    --subnet-id $SUBNET \
    --security-group-ids $SECURITY_GROUP
    --tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=talos-aws-tutorial-worker}]"

Configure the Load Balancer

aws elbv2 create-target-group \
    --region $REGION \
    --name talos-aws-tutorial-tg \
    --protocol TCP \
    --port 6443 \
    --vpc-id $VPC

Now, using the target group's ARN, and the PrivateIpAddress from the instances that you created :

aws elbv2 register-targets \
    --region $REGION \
    --target-group-arn $TARGET_GROUP_ARN \
    --targets Id=$CP_NODE_1_IP  Id=$CP_NODE_2_IP  Id=$CP_NODE_3_IP

Using the ARNs of the load balancer and target group from previous steps, create the listener:

aws elbv2 create-listener \
    --region $REGION \
    --load-balancer-arn $LOAD_BALANCER_ARN \
    --protocol TCP \
    --port 443 \
    --default-actions Type=forward,TargetGroupArn=$TARGET_GROUP_ARN

Retrieve the kubeconfig

At this point we can retrieve the admin kubeconfig by running:

talosctl --talosconfig talosconfig config endpoint <control plane 1 IP>
talosctl --talosconfig talosconfig config node <control plane 1 IP>
talosctl --talosconfig talosconfig kubeconfig .