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

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_cidr and 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.com via phase3.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" for hcx.enabled is 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

  1. Clone the repo.

    git clone https://github.com/aws/solutions-for-amazon-evs.git 
    cd solutions-for-amazon-evs/Deploy/EVS-Deployment-Orchestrator
  2. Store your depot token. Save it as a Secrets Manager secret (default name evs-depot-token). You’ll reference this name at launch.
  3. Build your blueprint. Copy blueprints/custom.all-options.example.yaml to blueprint.yaml and set the fields marked REQUIRED. The next section walks through how to shape it for your use case.
  4. 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-2a

    For Windows PowerShell:

    py check-quotas.py --blueprint blueprint.yaml --region us-east-2 --availability-zone us-east-2a
  5. Upload to S3. Put the blueprint, the OVA, and the ovftool zip in a bucket.
  6. Launch the stack. Use evs-deployment-orchestrator.yaml from 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-token

    For 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

  • --resume picks up at the first incomplete stage. The stack’s ResumeCommand output 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-infra to also remove the NAT gateway, Route Server, security group, and key pair
  • --all to 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.