One Off-Hours Schedule Across AWS, GCP and Azure VMs
The same 07:00 to 19:00 weekday window, expressed three ways, and the three places each native scheduler behaves differently.
Say the policy is simple: development VMs run 07:00 to 19:00 on weekdays, office time in Bengaluru, and are off otherwise. Each cloud has a native way to do this, and each takes the time, the timezone and the start in a different form. This page writes the same window three times and points out where the results diverge.
AWS: EventBridge Scheduler
EventBridge Scheduler takes a six-field cron and a named timezone, and calls the EC2 API through a universal target. The full role and target setup is in automating EC2 stop and start with EventBridge Scheduler; the schedule expressions for this window are:
--schedule-expression "cron(0 19 ? * MON-FRI *)" --schedule-expression-timezone "Asia/Kolkata" # stop--schedule-expression "cron(0 7 ? * MON-FRI *)" --schedule-expression-timezone "Asia/Kolkata" # startStopped instances stop billing for compute; EBS volumes and Elastic IPs keep billing.
Google Cloud: instance schedules
Compute Engine has a built-in instance schedule, which is a resource policy with both a start and a stop cron in standard five-field form:
gcloud compute resource-policies create instance-schedule dev-office-hours \ --region=asia-south1 \ --vm-start-schedule="0 7 * * 1-5" \ --vm-stop-schedule="0 19 * * 1-5" \ --timezone="Asia/Kolkata" \ --description="Dev VMs, weekday office hours"
gcloud compute instances add-resource-policies dev-vm-01 \ --resource-policies=dev-office-hours --zone=asia-south1-aBefore it works, grant the Compute Engine Service Agent the Compute Instance Admin (v1) role (roles/compute.instanceAdmin.v1) on the project; the person creating the schedule needs it too. Google documents several limits worth planning around:
- The schedule and its VMs must be in the same region, and each VM can follow only one schedule.
- An operation can begin up to 15 minutes after the scheduled time, and start and stop should be at least 15 minutes apart.
- Instance schedules cannot stop a VM that has Local SSD disks.
A stopped VM keeps its disks, IP addresses and metadata, and Google keeps charging for resources that stay attached to it.
Azure: auto-shutdown
Azure’s built-in option is auto-shutdown, set in the portal under the VM’s Operations section or from the CLI:
az vm auto-shutdown -g dev-rg -n dev-vm-01 --time 1330 --email "platform@example.com"Two differences stand out. --time is the UTC time of day in hhmm format, so 19:00 in India is 1330 and there is no named-timezone option in the command. And the command sets a shutdown only; nothing in az vm auto-shutdown starts the VM again, so the morning start needs a separate mechanism. Remove the setting with --off.
Check the resulting power state. Azure bills a VM in the Stopped (allocated) state, which is what a shutdown from inside the guest OS produces. Only Stopped (deallocated) stops compute billing, and disks and networking continue to charge either way.
az vm get-instance-view -g dev-rg -n dev-vm-01 \ --query "instanceView.statuses[?starts_with(code,'PowerState')].displayStatus" -o tsvVerify all three the same evening
aws ec2 describe-instances --filters "Name=tag:env,Values=dev" \ --query "Reservations[].Instances[].[InstanceId,State.Name]" --output textgcloud compute instances list --filter="name~^dev-" --format="table(name,status)"Expect stopped on AWS and TERMINATED on Google Cloud (the state Compute Engine uses for a stopped VM). On Azure, the instance-view query above should report a deallocated power state, which the portal shows as Stopped (deallocated).
Keeping three definitions in step
The weak point is drift: someone moves the AWS stop to 20:00 and the other two stay at 19:00, or the Azure UTC offset is wrong after a team moves region. ZopNight keeps one schedule definition, with an IANA timezone and cron start and stop expressions, and attaches it to EC2, Compute Engine and Azure VMs alike; on Azure the execution deallocates rather than just stopping. Resource groups let a mixed set of VMs share the schedule, and a weekly 24-hour grid shows the window before you save. Per-resource details live on the Compute Engine and Azure VM scheduling pages.