AWS
AWS Self-Hosted (Vanilla) K8s Cluster Provisioner
The Astro platform deploys a Kubernetes cluster on EC2 instances on your behalf, allowing you to select the instance type, size, zone, region, and other configurations. This approach is beneficial when you require a cluster that is not managed by the cloud provider, providing you with full control over the cluster, including the control plane.
Prerequisites
To create a self-hosted cluster on AWS, ensure the following CLI tools are installed on your local machine:
- AWS CLI for AWS cluster communication
- kubectl (optional) for AWS cluster interaction
- astroctl for cluster management
CLI Workflow
The astroctl cloud aws selfHosted command group manages the full lifecycle of AWS self-hosted prerequisites. There are five subcommands:
| Command | Purpose | Used By |
|---|---|---|
setup | Create IAM user, policies, S3 bucket and auto-store credentials in vault | Platform team |
connect | Validate existing credentials and store in vault | Developer |
disconnect | Revoke stored credentials from vault (keeps infrastructure) | Platform team |
validate | Pre-flight validation only (no storage) | CI/CD, troubleshooting |
cleanup | Delete CloudFormation stack and purge vault credentials | Platform team |
Setup (Platform Team)
The platform team creates all AWS prerequisites and auto-stores credentials in the vault with a single command:
# Create IAM user, policies, and S3 state store bucket via CloudFormation
astroctl cloud aws selfHosted setup \
--account-id <aws-account-id> \
--region <region> \
--cluster-name <cluster-name>
Connect (Developer / BYOC)
For existing credentials (Bring Your Own Credentials), validate and store them in the vault:
# Connect with auto-detected credentials (env vars or ~/.aws/credentials)
astroctl cloud aws selfHosted connect \
--region <region> \
--bucket <bucket-name> \
--cluster-name <cluster-name>
# Connect with a named AWS profile
astroctl cloud aws selfHosted connect \
--profile <aws-profile> \
--region <region> \
--bucket <bucket-name> \
--cluster-name <cluster-name>
# Connect with explicit credentials
astroctl cloud aws selfHosted connect \
--account-id <aws-account-id> \
--region <region> \
--access-key <access-key> \
--secret-key <secret-key> \
--bucket <bucket-name> \
--cluster-name <cluster-name>
On success, credentials are stored in the platform vault and the command outputs the provisioner block to paste into your cluster YAML:
provisioner:
type: selfHosted
selfHosted:
accountId: "<detected-account-id>"
bucketName: "<bucket-name>"
credentials:
type: vault
The connect command auto-detects credentials in this order:
- Explicit
--access-key/--secret-keyflags --profileflag (reads from~/.aws/credentials)- Environment variables (
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY) - Default credential chain (
~/.aws/credentialsdefault profile, EC2 instance role, etc.)
Validate
Run validations without generating output — useful for CI/CD pipelines or troubleshooting:
# Validate using AWS profile
astroctl cloud aws selfHosted validate \
--profile <aws-profile> \
--region <region> \
--bucket <bucket-name>
# Or validate with explicit credentials
astroctl cloud aws selfHosted validate \
--account-id <aws-account-id> \
--region <region> \
--access-key <access-key> \
--secret-key <secret-key> \
--bucket <bucket-name>
Disconnect
Revoke stored credentials from the vault without removing infrastructure — useful for credential rotation:
astroctl cloud aws selfHosted disconnect --cluster-name <cluster-name>
After disconnecting, run connect with new credentials to re-store them in the vault.
Cleanup
When you no longer need the self-hosted prerequisites:
astroctl cloud aws selfHosted cleanup \
--account-id <aws-account-id> \
--region <region> \
--cluster-name <cluster-name>
This deletes the CloudFormation stack (IAM user, policies, S3 bucket) and purges vault credentials.
This is a destructive operation. Ensure no clusters depend on these resources before running cleanup.
Complete Field Reference
The selfHosted type represents the spec for the AWS self-hosted provisioner. This is the authoritative reference for all available fields.
Core Fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
accountId | string | Yes | - | AWS account ID where the cluster will be created |
bucketName | string | Yes | - | S3 bucket name for storing cluster configuration. Must be in the same region as the cluster. |
credentials | object | Yes | - | AWS credentials. Use type: vault (recommended for self-hosted) or type: static for inline credentials. The vault type is only supported for the selfHosted provisioner. |
Networking Fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
networkId | string | No | - | VPC ID for BYOVPC. If not provided, platform creates a new VPC |
Cluster Configuration Fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
kubernetesVersion | string | No | Platform default | Kubernetes version. Must be full semantic version (e.g., 1.30.14) |
Field Validation Rules
| Field | Validation |
|---|---|
accountId | Must be a valid AWS account ID |
bucketName | Must be a valid S3 bucket name |
networkId | Must start with vpc- followed by alphanumeric characters |
kubernetesVersion | Must be full semantic version format: 1.30.14 (major.minor.patch) |
Self-hosted clusters require the full semantic version format (e.g., 1.30.14). The major.minor format (e.g., 1.30) is not supported for self-hosted clusters.
BYOA (Bring Your Own Account)
Option 1: Platform Vault (recommended)
Run setup or connect to store credentials in the platform vault, then reference them with type: vault — no sensitive data in your YAML:
provider: aws
provisioner:
type: selfHosted
selfHosted:
accountId: "<account-id>"
bucketName: "<bucket-name>"
credentials:
type: vault
The setup command automatically stores credentials in the vault after creating AWS prerequisites. For existing credentials, run connect to store them manually. The platform retrieves credentials from the vault at provision time — no secrets in YAML files.
Option 2: Credentials in YAML (explicit)
If you cannot use the vault, you can still provide credentials inline:
provider: aws
provisioner:
type: selfHosted
selfHosted:
accountId: "<account-id>"
bucketName: "<bucket-name>"
credentials:
type: static
data:
AWS_ACCESS_KEY_ID: "<access-key>"
AWS_SECRET_ACCESS_KEY: "<secret-key>"
Avoid committing credentials to version control. Prefer type: vault (Option 1) or ensure your YAML files are in .gitignore.
Bring Your Own VPC (BYOVPC)
Add the networkId field to your cluster YAML to use an existing VPC:
provider: aws
provisioner:
type: selfHosted
selfHosted:
accountId: "<account-id>"
networkId: "vpc-xxxx" # your existing VPC ID
bucketName: "<bucket-name>"
credentials:
type: vault
Requirements for the VPC:
- Must be in the same region as the cluster
- Internet gateway must be attached
- DNS hostnames and DNS resolution must be enabled
You can generate a VPC CloudFormation template using the CLI:
# Generate VPC template
astroctl cloud aws generate-vpc --region us-east-1 --vpc-cidr 10.0.0.0/16 --cluster-name prod
# Generate subnet configuration for an existing VPC
astroctl cloud aws generate-subnets --region us-east-1 --vpc-cidr 10.0.0.0/16
KubeConfig
With simple command like below, you can set the context to the cluster and have the access to the cluster. You need to make sure to install the kubectl CLI as required.
astroctl infra k8s set-context <cluster-name>
The cluster uses the client authentication type mutual TLS authentication to authenticate the kubeconfig. The platform lets you to configure the duration for the kubeconfig to be valid. Only the platform admin or admin of the organization can export the kubeconfig.
Cluster Updates
Self-hosted clusters support updates to Kubernetes version and node group configurations. You can use either the Console UI or the CLI.
Self-hosted clusters require the full semantic version format (e.g., 1.30.14). The major.minor format (e.g., 1.30) is not supported.
Option 1: Console (Upgrade Wizard)
The Console provides a guided 5-step upgrade wizard:
- Preflight Check - Validates upgrade paths and checks for issues
- Readiness Report - Generates comprehensive upgrade analysis with risk score
- Pre-Upgrade Checklist - Interactive checklist with verification commands
- Configuration - Select target version and rolling update settings
- Confirmation - Review summary and confirm by typing cluster name
To access: Go to Clusters → Select cluster → Click Upgrade button
The wizard shows:
- Visual version timeline (current → next → locked future versions)
- Node group scaling controls (min/max nodes)
- Control plane configuration (self-hosted only)
- Rolling update settings (maxSurge, maxUnavailable)
- Impact summary before execution
Option 2: CLI Commands
Version Discovery
# List available versions for this cluster
astroctl infra k8s upgrade <cluster-name> --list-versions
# Check self-hosted versions
astroctl cloud aws k8s-versions --self-hosted
astroctl cloud aws k8s-versions --self-hosted --show-upgrade-paths
Kubernetes Version Upgrade
# Dry-run validation first
astroctl infra k8s upgrade <cluster-name> 1.30.14 --dry-run
# Generate readiness report
astroctl infra k8s upgrade <cluster-name> 1.30.14 --generate-report
# Execute upgrade
astroctl infra k8s upgrade <cluster-name> 1.30.14
# Skip confirmation (for automation)
astroctl infra k8s upgrade <cluster-name> 1.30.14 --yes
Scaling Node Groups
# List node groups
astroctl infra k8s scale <cluster-name> --list
# Scale a node group
astroctl infra k8s scale <cluster-name> <nodegroup-name> --min 3 --max 10
# Preview changes
astroctl infra k8s scale <cluster-name> <nodegroup-name> --min 5 --max 20 --dry-run
Advanced Updates (YAML)
# Show YAML examples for your cluster
astroctl infra k8s update <cluster-name> --example
# Apply update
astroctl infra k8s update <cluster-name> -f update.yaml
# Dry-run validation
astroctl infra k8s update <cluster-name> -f update.yaml --dry-run
# Skip confirmation
astroctl infra k8s update <cluster-name> -f update.yaml --auto-approve
Monitor Progress
# Stream real-time progress
astroctl infra k8s progress stream <cluster-name>
# Get current status
astroctl infra k8s progress get <cluster-name>
# View operation history
astroctl infra k8s progress history <cluster-name>
Update File Reference
apiVersion: platform.astropulse.io/v1
kind: K8sClusterUpdate
spec:
# Kubernetes version (full semver required)
kubernetesVersion: "1.30.14"
# Rolling update configuration
updateConfig:
maxSurge: "1" # Nodes added during update (number or %)
maxUnavailable: "1" # Nodes down during update (number or %)
dryRun: false # Validate without applying
generateReport: false # Generate readiness report
# Worker node groups
nodeGroups:
- name: "worker-ng-0"
minNode: 2
maxNode: 6
machineTypes: ["t3.large"]
instanceType: "ondemand" # or "spot"
labels:
workload: "general"
# Control plane configuration (self-hosted only)
selfHosted:
controlPlane:
name: "control-plane"
minNode: 3
maxNode: 3
machineTypes: ["t3.medium"]
Upgrade Process
- Control plane nodes are upgraded first (one at a time for HA)
- etcd cluster is upgraded
- Worker nodes are upgraded using rolling replacement
- Progress is tracked and reported in real-time
- Self-hosted clusters only support upgrades to sequential minor versions (cannot skip versions)
- Ensure you have recent etcd backups before upgrading
- Always test upgrades in a non-production environment first
Rollback
Self-hosted clusters support full rollback including control plane downgrade — unlike managed providers (EKS/GKE/AKS) which only downgrade node pools.
# List valid rollback versions
astroctl infra k8s rollback <cluster-name> --list-versions
# Dry-run validation
astroctl infra k8s rollback <cluster-name> <target-version> --dry-run
# Execute rollback
astroctl infra k8s rollback <cluster-name> <target-version>
# Skip confirmation (automation)
astroctl infra k8s rollback <cluster-name> <target-version> --yes
- Control plane + worker nodes are all downgraded via rolling update
- Workloads will be drained and migrated to new nodes
- Ensure workloads are compatible with the older Kubernetes version
When changing machine types, nodes are replaced using a rolling strategy. Ensure your maxSurge and maxUnavailable settings allow for the desired replacement behavior.