Migration & Modernization
One Stack, Full VCF: Deploying VMware Cloud Foundation 9 on Amazon EVS with the EVS Deployment Orchestrator
Earlier this year we walked through deploying VCF 9 on Amazon Elastic VMware Service (Amazon EVS) using a phased automation workflow. Since then, we’ve improved and streamlined that automation into the EVS Deployment Orchestrator (EDO), now available in the solutions-for-amazon-evs repository.
EDO is a tool that automates an end-to-end VMware Cloud Foundation (VCF) 9.x deployment on Amazon EVS. It’s open source, uses AWS CloudFormation, and runs an automated workflow that takes customers from a set of input parameters (a blueprint) to a fully configured VCF environment. Once launched, a full deployment takes about 4–7 hours and runs unattended, with no manual steps.
What changed
| Phased deployment (previous) | EVS Deployment Orchestrator (EDO) | |
| Entry point | Three phases, run in order | One CloudFormation stack |
| Base infrastructure | Terraform | Created automatically by the orchestrator |
| Where it runs | Your workstation | A small “runner” EC2 instance in your account |
| Configuration | Inputs per phase | One YAML blueprint |
| Your involvement | Run and hand off each phase | Launch, then watch the logs |
How it works
When you start an EDO deployment, it creates a small runner instance (a t3.large by default) plus base networking components and finishes in about five minutes. The runner then takes over. It creates a second, orchestrator-managed infrastructure stack holding:
- NAT gateway
- DNS zones
- Route Server
- Security groups
Next it provisions the EVS environment and bare-metal ESXi hosts, and then installs and configures VCF 9, including:
- vCenter Server
- NSX Manager
- SDDC Manager
- VCF Operations
Last, it deploys and configures an NSX edge cluster connecting the overlay to your VPC.
Our tests show the whole run takes about 4 hours and needs no attention from you. Bare-metal hosts come online about 50 minutes in, which is also when host billing starts. Every appliance credential lands in AWS Secrets Manager.
What you need before you start
- An AWS account with Business or Enterprise Support
- A Broadcom depot token from your VCF entitlement
- The VCF SDDC Manager OVA (VCF 9.0.2 or 9.1.0; it must match the version in your blueprint)
- VMware ovftool (Linux zip)
- A machine with AWS CLI v2 and Python 3.9+, if you prefer the CLI to the console (note that the AWS CloudShell home directory is too small for the OVA)
- Git
The blueprint: one file, many shapes
Everything about your environment lives in a single YAML blueprint. The repo ships one reference file, custom.all-options.example.yaml, with every supported option listed and commented out alongside inline notes. Rather than picking from a menu of presets, you copy it and uncomment what you need. The CloudFormation template supplies the AWS networking values (VPC, subnets, region) itself, so the blueprint stays focused on the VCF design.
What every blueprint needs
| Section | Required fields | Notes |
dns |
fqdn |
Any private domain; a private hosted zone is created for you. Keep it short, since hostnames become <name>.<fqdn>. |
evs |
environment_name, instance_type, vcf_version, terms_accepted, simple_deployment |
vcf_version is 9.0.2 or 9.1.0 and must match your OVA. |
sizing |
vcenter_size, vcenter_storage_size, nsx_size, operations_appliance_size, operations_collector_appliance_size, edge_form_factor |
No defaults; a missing field fails validation at launch. |
hostnames |
esxi (list), vcenter, nsx, sddc_manager |
The number of entries in esxi is your host count. |
Everything else is optional.
Use case 1: Lab, demo, or proof of concept
Set simple_deployment: true and list three ESXi hosts. You get a single NSX Manager and a single VCF Operations node, which is the smallest footprint the orchestrator will deploy.
dns:
fqdn: "vcf.example.internal"
evs:
environment_name: "vcf-lab"
instance_type: "i7i.metal-24xl"
vcf_version: "9.1.0"
terms_accepted: true
simple_deployment: true
sizing:
vcenter_size: "small"
vcenter_storage_size: "lstorage"
nsx_size: "medium"
operations_appliance_size: "medium"
operations_collector_appliance_size: "small"
edge_form_factor: "small"
hostnames:
esxi: ["esxi01", "esxi02", "esxi03"]
vcenter: "vc"
nsx: "nsx"
sddc_manager: "sddcm"
Pair it with the smaller sizing options (for example vcenter_size: small, nsx_size: medium).
Use case 2: Production-style HA
Set simple_deployment: false. This deploys a three-node NSX Manager cluster and a three-node VCF Operations cluster, so it needs at least four hosts. Validation also tightens; operations_appliance_size must be medium, large, or xlarge in HA mode.
Choosing instance type and host count
To add capacity, add entries to hostnames.esxi. Each host is one bare-metal server, so your EC2 On-Demand Standard vCPU quota must cover hosts multiplied by vCPUs per host. The orchestrator checks this before it starts, and check-quotas.py will tell you ahead of time.
dns:
fqdn: "vcf.example.internal"
evs:
environment_name: "vcf-lab"
instance_type: "i7i.metal-24xl"
vcf_version: "9.1.0"
terms_accepted: true
simple_deployment: false
sizing:
vcenter_size: "large"
vcenter_storage_size: "xlstorage"
nsx_size: "large"
operations_appliance_size: "large"
operations_collector_appliance_size: "large"
edge_form_factor: "large"
hostnames:
esxi: ["esxi01", "esxi02", "esxi03", "esxi04"]
vcenter: "vc"
nsx: "nsx"
sddc_manager: "sddcm"
edge01: "edge01"
edge02: "edge02"
vcf_ops: "vcfops"
Use case 3: Workload migration with VMware HCX
Set hcx.enabled: true to prepare the environment for HCX migration and network extension. HCX needs public addressing, and you have two options:
- Bring your own /28 by setting
hcx.public_cidr. It must be genuinely public space your account can associate (an IPAM-provisioned Amazon block or your own BYOIP range). - Let the orchestrator provision one. Omit
public_cidrand it creates an IPAM pool, provisions a public /28, and allocates the three Elastic IPs HCX needs (Manager, Interconnect, and Network Extension). Amazon-provided contiguous blocks are limited (two per Region by default), so plan accordingly.
dns:
fqdn: "vcf.example.internal"
evs:
environment_name: "vcf-lab"
instance_type: "i7i.metal-24xl"
vcf_version: "9.1.0"
terms_accepted: true
simple_deployment: false
sizing:
vcenter_size: "large"
vcenter_storage_size: "xlstorage"
nsx_size: "large"
operations_appliance_size: "large"
operations_collector_appliance_size: "large"
edge_form_factor: "large"
hostnames:
esxi: ["esxi01", "esxi02", "esxi03", "esxi04"]
vcenter: "vc"
nsx: "nsx"
sddc_manager: "sddcm"
edge01: "edge01"
edge02: "edge02"
vcf_ops: "vcfops"
hcx:
enabled: true
public_cidr: "203.0.113.0/28"
Use case 4: Console access
The vCenter, NSX, and SDDC Manager UIs live on private addresses inside the VPC. Set jumpbox.enabled: true to add a Windows Server 2022 jumpbox in the public subnet (default t3.xlarge). It ships with no inbound rules; you add an RDP rule scoped to your own IP when you need it.
dns:
fqdn: "vcf.example.internal"
evs:
environment_name: "vcf-lab"
instance_type: "i7i.metal-24xl"
vcf_version: "9.1.0"
terms_accepted: true
simple_deployment: false
sizing:
vcenter_size: "large"
vcenter_storage_size: "xlstorage"
nsx_size: "large"
operations_appliance_size: "large"
operations_collector_appliance_size: "large"
edge_form_factor: "large"
hostnames:
esxi: ["esxi01", "esxi02", "esxi03", "esxi04"]
vcenter: "vc"
nsx: "nsx"
sddc_manager: "sddcm"
edge01: "edge01"
edge02: "edge02"
vcf_ops: "vcfops"
jumpbox:
enabled: true
instance_type: "t3.xlarge"
Other parameters worth knowing
- Pin an ESXi build with
evs.esx_version(for example a specific, previously validated build). Leave it out to get the newest build for your VCF version. On a resume, the orchestrator keeps the build it already resolved, so a mid-deployment rerun never drifts. - NTP defaults to
time.aws.comviaphase3.ntp. Link-local addresses (169.254.x.x) are rejected because VCF won’t accept them. - CEIP telemetry is opt-in via
phase3.ceip. - Hostname overrides for edges and VCF Operations (
edge01,edge02,vcf_ops) are optional; sensible defaults are used.
Validation catches mistakes in seconds, not hours
Before anything is created, the orchestrator validates the blueprint:
- DNS label rules
- Combined FQDN length
- Unique ESXi hostnames
- Sizing enums
- HA host minimum
- Booleans are real booleans (a quoted
"false"forhcx.enabledis rejected rather than silently enabling HCX)
It then checks your instance type against the live EVS supported-versions catalog and confirms you have the vCPU quota.
Deploying, step by step
- Clone the repo.
git clone https://github.com/aws/solutions-for-amazon-evs.git cd solutions-for-amazon-evs/Deploy/EVS-Deployment-Orchestrator - Store your depot token. Save it as a Secrets Manager secret (default name
evs-depot-token). You’ll reference this name at launch. - Build your blueprint. Copy
blueprints/custom.all-options.example.yamltoblueprint.yamland set the fields markedREQUIRED. The next section walks through how to shape it for your use case. - Check your quotas (recommended). Bare-metal deployments run into service quotas more often than anything else. The included preflight script compares what your blueprint needs against your quotas and current usage, and prints the exact commands to fix any shortfall. It is read-only. For Linux:
python3 check-quotas.py --blueprint blueprint.yaml --region us-east-2 --availability-zone us-east-2aFor Windows PowerShell:
py check-quotas.py --blueprint blueprint.yaml --region us-east-2 --availability-zone us-east-2a - Upload to S3. Put the blueprint, the OVA, and the ovftool zip in a bucket.
- Launch the stack. Use
evs-deployment-orchestrator.yamlfrom the console or the CLI. Only five parameters are required: the three S3 URIs, the depot secret name, and an Availability Zone that offers your instance type. For Linux:aws cloudformation create-stack \ --stack-name my-evs-deployment \ --region us-east-2 \ --template-body file://evs-deployment-orchestrator.yaml \ --capabilities CAPABILITY_IAM \ --parameters \ ParameterKey=BlueprintKey,ParameterValue=s3://$BUCKET/blueprint.yaml \ ParameterKey=OvaKey,ParameterValue=s3://$BUCKET/$OVA \ ParameterKey=OvfKey,ParameterValue=s3://$BUCKET/$OVF \ ParameterKey=AvailabilityZone,ParameterValue=us-east-2a \ ParameterKey=DepotSecretName,ParameterValue=evs-depot-tokenFor Windows PowerShell:
aws cloudformation create-stack ` --stack-name my-evs-deployment ` --region us-east-2 ` --template-body file://evs-deployment-orchestrator.yaml ` --capabilities CAPABILITY_IAM ` --parameters ` "ParameterKey=BlueprintKey,ParameterValue=s3://$BUCKET/blueprint.yaml" ` "ParameterKey=OvaKey,ParameterValue=s3://$BUCKET/$OVA" ` "ParameterKey=OvfKey,ParameterValue=s3://$BUCKET/$OVF" ` "ParameterKey=AvailabilityZone,ParameterValue=us-east-2a" ` "ParameterKey=DepotSecretName,ParameterValue=evs-depot-token"Optional parameters include an SNS topic for notifications, your own EC2 key pair, a CIDR prefix for VLAN addressing, and the bring-your-own-VPC settings.
Under the hood: the nine deployment stages
Once the runner starts, the orchestrator works through nine checkpointed stages. Each stage records its result, so a resume skips anything already complete.
| # | Stage ID | What it does | Typical duration |
| 1 | aws_config |
Builds the deployment infrastructure as a second CloudFormation stack: Route 53 forward and reverse zones, inbound Resolver endpoint, DHCP options, NAT gateway, EVS security group, EC2 key pair, VPC Route Server with BGP peers, and DNS records for every host and appliance. Also adds the jumpbox and HCX networking if enabled | 5 to 10 mins |
| 2 | generate_config |
Translates the blueprint into the internal deployment config, including the VLAN layout derived from your CIDR prefix. | Seconds |
| 3 | validate_dns |
Confirms every ESXi host and appliance hostname resolves before anything expensive happens. | Seconds |
| 4 | phase2_deploy |
Creates the EVS environment and bare-metal ESXi hosts, waits for them to reach CREATED, provisions credentials, associates VLAN subnets, associates HCX Elastic IPs (if enabled), and attaches a temporary EBS volume. |
45 to 100 mins |
| 5 | esxi_vlan_tag |
Tags the staging host’s VM Network port group for the management VLAN. | Seconds |
| 6 | esxi_vmfs_create |
Creates a temporary VMFS datastore on the EBS volume to stage the installer (vSAN doesn’t exist yet). | Few mins |
| 7 | esxi_ova_deploy |
Pulls the SDDC Manager OVA and ovftool from S3 and deploys the VCF Installer appliance. | 15 to 30 mins |
| 8 | esxi_ova_verify |
Waits for the installer API to actually accept authentication, not just respond. | Up to 40 mins |
| 9 | phase3_deploy |
Syncs the Broadcom depot, runs VCF bringup (vCenter, vSAN, NSX, SDDC Manager, VCF Operations), deploys the NSX edge cluster, and registers the environment connector. | 3 to 5.5 hours |
Stages 5 through 8 are the “ESXi prep” work that used to be manual steps between phases in the old workflow.
Notification along the way
If you set SnsTopicArn, the orchestrator keeps the inbox noise down. You get a message when:
- Deployment starts
- When preparation finishes after
validate_dns - When the infrastructure is ready and bringup begins after
esxi_ova_verify - A heartbeat about every two hours during the long stages
- Final success or failure. Note that a failure message includes the stage that broke, recent error lines, and the exact resume command.
Resuming and rerunning
--resumepicks up at the first incomplete stage. The stack’sResumeCommandoutput has it ready to paste.--start-from <stage-id>reruns from a specific stage, even one already checkpointed.- If you change the blueprint, the checkpoint is invalidated and the run starts fresh, so you never resume against a config that no longer matches.
- Resume is safe: an existing EVS environment is reused rather than duplicated, and hosts that failed to create are removed and recreated.
Watching it run, and recovering
Open the OrchestratorLogsUrl link in the first stack’s Outputs tab to follow progress in Amazon CloudWatch Logs. If you set SnsTopicArn, you’ll get the milestone notifications described above. The deployment is done when the log reports ALL STAGES COMPLETE.
If something fails, you don’t start over; see the resume options above.
After deployment
The vCenter, NSX, and SDDC Manager UIs are only reachable from inside the VPC. For access, set jumpbox.enabled: true in your blueprint before launch and the deployment adds a Windows jumpbox. Credentials are stored in Secrets Manager as evs-<environment-id>_<role>.
Bring your own VPC
Already have a landing zone? Point the stack at an existing VPC with an internet gateway and three subnets in the same AZ (public, service-access, and runner). Teardown only removes what the stack created; nothing pre-existing is touched.
Teardown
Run destroy.py before deleting the stack. It has three levels:
- Environment only (the safest option; keeps infrastructure for redeployment)
--include-infrato also remove the NAT gateway, Route Server, security group, and key pair--allto return the account to a clean, non-billing state
Wrapping up
The phased workflow proved that VCF on Amazon EVS could be automated end to end. The orchestrator makes that automation something you can hand to anyone on your team: fill in a blueprint, launch a stack, and come back to a working VCF 9 environment. Every merge to the repo is validated with a full deployment and unattended teardown, so what you clone is what we test.
Give it a try, and open an issue on the repo with feedback or feature requests.