Skip to main content
POST
Create an AWS EC2 cluster (browser session)

Authorizations

ankra_session
string
cookie
required

Browser session. Mutations also require X-Ankra-CSRF.

Headers

X-Ankra-CSRF
string
required

Must match the ankra_csrf browser cookie.

Body

application/json

POST /clusters/aws body. Two network shapes (ADR 0015 §3): omit vpc_id and Ankra creates the VPC from network_ip_range over availability_zones (one public /24 and one private /20 per zone, an internet gateway, and NAT gateways as the default egress), all torn down with the cluster; pass vpc_id with node_subnet_ids and bastion_subnet_id to adopt an existing VPC, whose network Ankra never modifies. Nodes never receive a public IP; the bastion holds the elastic IP and is the SSH hop (and the NAT instance in bastion_nat mode).

name
string
required
credential_id
string<uuid>
required

An organisation aws credential: a keys credential, or a role onboarded with scope provisioning or self_managed (cost-scoped roles are refused).

ssh_key_credential_id
string<uuid>
required
region
string
required

Region slug, validated against ec2:DescribeRegions.

bastion_allowed_ips
string[]
required

IPv4 CIDRs allowed to SSH to the bastion. Optional: omitted or empty means 0.0.0.0/0 (open to everyone; key-only, password login off, sshd rate-limited on the host). Name your own CIDRs to restrict it; preflight reports the exposure as bastion_ssh_exposure.

description
string | null
vpc_id
string | null

An existing VPC to adopt; node_subnet_ids and bastion_subnet_id are then required and network_ip_range / availability_zones / nat_gateway_single_zone are refused. Omitted (or empty): Ankra creates the VPC (network_ownership created).

node_subnet_ids
string[] | null

Adopted VPC only: private subnets the nodes spread across; one or more, their zones become the cluster's zone pool. Refused (422) when no vpc_id is given - a created VPC lays out its own subnets.

Minimum array length: 1
bastion_subnet_id
string | null

Adopted VPC only: a public subnet (internet-gateway default route) for the bastion. Refused (422) when no vpc_id is given.

network_ip_range
string
default:10.0.0.0/16

Created VPC only: the IPv4 CIDR the VPC is created with, /16 to /20 as a network address; it must hold a private /20 and a public /24 per availability zone (the preflight's cidr item says what it holds). Refused (422) alongside vpc_id.

availability_zones
string[] | null

Created VPC only: the zones the VPC is laid out over, in the order the spread walks them (the bastion and the first control plane land in the first). Each must exist and be available in the region; more than one needs control_plane_count >= 3. Omitted: the preflight picks one zone when control_plane_count < 3 and three otherwise, from the region's available zones in name order, and reports them as resolved_availability_zones. Refused (422) alongside vpc_id.

nat_gateway_single_zone
boolean
default:false

Created VPC with nat_gateway egress only: false creates one NAT gateway (and elastic IP) per zone; true creates one in the first zone that every private subnet routes through - cheaper, one egress failure domain. Refused (422) when true alongside vpc_id.

egress_mode
enum<string> | null

Which modes apply depends on the network shape. Created VPC: nat_gateway (default; Ankra-created NAT gateways with their own elastic IPs) or bastion_nat (the bastion is the NAT instance); existing is refused (422). Adopted VPC: omitted is resolved by preflight; existing keeps the subnets' NAT routing; bastion_nat makes the bastion the NAT instance behind one Ankra-owned route table and is refused when a node subnet carries instances Ankra did not create; nat_gateway is refused (422) because it would re-point the customer's route tables.

Available options:
nat_gateway,
bastion_nat,
existing
bastion_instance_type
string
default:t3.small
control_plane_count
integer
default:1

At least 3 when the cluster spans more than one availability zone (an adopted VPC's node subnets, or a created VPC's availability_zones); it also decides how many zones a created VPC defaults to (1 below 3, 3 otherwise).

Required range: 1 <= x <= 9
control_plane_type
string
default:t3.medium
worker_count
integer
default:1
Required range: 0 <= x <= 100
worker_type
string
default:t3.medium
node_groups
object[] | null
distribution
enum<string>
default:kubeadm
Available options:
k3s,
kubeadm
kubernetes_version
string | null
etcd_topology
enum<string>
default:stacked
Available options:
stacked,
external
etcd_node_count
integer
default:3
etcd_type
string
default:t3.medium
cni
enum<string>
default:cilium

Defaults to cilium for both distributions: the AWS stack's IMDS guard is a network policy only Cilium and Calico enforce. flannel is accepted with a preflight warning; kubeadm requires cilium.

Available options:
flannel,
calico,
cilium
cni_features
object
k3s_disabled_components
string[] | null
ubuntu_series
string
default:24.04
architecture
enum<string>
default:amd64

arm64 is refused with a 422 naming the pending image-catalogue audit (ADR 0015 §6).

Available options:
amd64
root_volume_gib
integer
default:40

Encrypted gp3 root volume of every instance.

Required range: 20 <= x <= 2000
gitops_credential_name
string
gitops_repository
string
gitops_branch
string
default:master
gitops_provider
enum<string>
default:github

GitOps provider of the repository the cluster is bootstrapped onto. Omitted is github, where gitops_repository is owner/name. bitbucket_cloud names the repository by gitops_workspace and gitops_repo_slug (or gitops_repository as workspace/repo_slug) and binds it as a Bitbucket Cloud repository.

Available options:
github,
bitbucket_cloud
gitops_workspace
string | null

Bitbucket Cloud workspace of the GitOps repository. Only with gitops_provider bitbucket_cloud; provided together with gitops_repo_slug.

gitops_repo_slug
string | null

Bitbucket Cloud repository slug of the GitOps repository. Only with gitops_provider bitbucket_cloud; provided together with gitops_workspace.

include_networking
boolean
default:true
include_dns
boolean
default:true
retention_policy
enum<string>
default:retain
Available options:
delete,
retain
external_cloud_provider
boolean
default:true

Must be true when present: the AWS cloud-controller-manager is mandatory.

environment
string | null
criticality
string | null

Response

Successful response

cluster_id
string<uuid>
required
name
string
required
kind
string
required
Allowed value: "aws"
state
string
required
operation_id
string<uuid> | null
required