Cross-cloud orchestration
Provisioning that spans AWS and GCP usually means two runbooks and a handoff. Here's one OrchStep workflow that applies both clouds in parallel and verifies them together.
blog/cross-cloudWhen a service straddles two clouds, the provisioning story usually splits in two: an AWS runbook, a GCP runbook, and a human in the middle copying an endpoint from one to the other. The two halves drift. One gets a fix the other doesn't. And nobody can answer "is the whole thing up?" without checking two consoles.
The work is genuinely parallel — neither cloud depends on the other to stand up — so it should run in parallel and be verified as one unit. This post puts both clouds in a single OrchStep workflow: a parallel: block applies AWS and GCP at the same time, then one verify step checks both, and a gate refuses to call it live until both report in.
One workflow, both clouds
The clouds step fans out: aws and gcp run concurrently, each capturing its endpoint as an output. The steps after the fan-out see both.
name: multicloud
# One workflow, two clouds. Provision AWS and GCP in parallel, then run a
# single verification across both — no two-runbook handoff.
defaults:
stage: staging
tasks:
# `orchstep run provision --var stage=production`
provision:
steps:
- name: clouds
parallel:
- name: aws
func: shell
do: echo "applying the AWS stack in {{ vars.stage }}"
outputs:
endpoint: "api.aws.internal"
- name: gcp
func: shell
do: echo "applying the GCP stack in {{ vars.stage }}"
outputs:
endpoint: "api.gcp.internal"
- name: verify
func: shell
do: echo "health-checking {{ steps.aws.endpoint }} and {{ steps.gcp.endpoint }} in {{ vars.stage }}"
- name: gate
func: assert
args:
condition: '{{ and (ne steps.aws.endpoint "") (ne steps.gcp.endpoint "") }}'
message: "both clouds must report an endpoint before {{ vars.stage }} is live"Note the variable name is stage, not env — env is reserved in OrchStep. Every do: is echo-only, so the demo runs anywhere; swap each branch for terraform apply against the right provider and the structure holds.
What the parallel block buys you
Two things the two-runbook setup can't give you:
Wall-clock time. Both clouds apply at once instead of one-after-the-other. Each branch inside parallel: is a full step — it can have its own outputs:, retry:, and timeout: — so you're not trading safety for speed.
A single source of truth for "up." After the fan-out, verify references both cloud endpoints — the aws and gcp outputs — in one place, and the gate asserts both are non-empty. There's no window where AWS is provisioned, GCP isn't, and a human has to notice. The run either brings up both or fails — and a failed run is a non-zero exit your pipeline already understands.
The stage variable carries through every step, so the same workflow provisions staging or production with a single --var stage= change instead of a forked runbook per environment.
See the fan-out before it applies
A dry run shows both branches of the parallel: block and the resolved endpoints — without touching either cloud:
orchstep run provision --var stage=production --dry-runThat's a cheap way to confirm the prod path provisions both clouds before you let it. More: Previewing with Dry Run.
What you gained
| Concern | two runbooks | OrchStep |
|---|---|---|
| AWS + GCP timing | sequential, by hand | parallel: fan-out |
| "Is it all up?" | check two consoles | one verify + gate |
| Drift between halves | inevitable | one file, one change |
| staging vs. production | a forked runbook | --var stage= |
If your clouds are genuinely independent products with separate teams, two runbooks may be the right call. When they're one service split across providers, treat them as one workflow.
Where to go next
- Variables & Outputs — capturing endpoints with
outputs: - Error Handling —
retry:andtimeout:inside parallel branches - Previewing with Dry Run — read the fan-out before it applies
Provisioning split across two clouds and two runbooks? Fan them out in one workflow and verify them together.
curl -fsSL https://orchstep.dev/install.sh | sh