I want to have cloud redundancy - define the same ...
# general
g
I want to have cloud redundancy - define the same set of resources (in my case DNS records) and have these apply to both Cloudflare and Route53, in case I ever need to failover from Cloudflare in a hurry due to them deleting or disabling the account without notice like has happened to a few people in the last year. Due to the different structure of the resource and field names due to differences between the Cloudflare and AWS providers, I'm not sure how to do this. Has anyone done such a thing before? I've theory-crafted a couple of approaches but I don't really like any of them. I'd really like to have the different clouds as different pulumi stacks. 1. Define my records external to Pulumi, then have code that ingests and parses them, formats into appropriate resource format, and spins up the record in both Route53 and Cloudflare. a. Problem: not discrete stacks for different accounts (two environments in one stack) 2. Write two different pulumi projects and then have an external script that replicates the config between them a. Potentially complex, still requires parsing and conversion. May be simpler than the above though. 3. Have two different Pulumi projects, and have one use outputs from the other a. Unsure if this many outputs (hundreds of records) would be supported 4. Have two different Pulumi projects, write my parser, and have the parser query Cloudflare API for DNS records, and convert these into Pulumi aws Route53 resources As seen above, the potential solutions are complex and it would be ideal to have a single resource definition (source of truth) which is then applied via two providers.
f
Why can't it just be one stack? Could you have one "project" that stands up two separate stacks? One driver file that passes the list of entry definitions into two different functions; one for each stack?
l
Two stacks in one project wouldn't be sensible, since the code in each stack would be entirely different. One project with one stack is not going to help: remember, one of your main triggers for this is "can I run it if one of the clouds isn't working?", and if half your resources refuse to deploy because their API endpoints are gone, then you can't run it. If I was in this situation, I would almost certainly want different deployment schedules for these two groups of resources. I may want to make changes and test in one, before making the changes in the other. For DNS, I can see cars where the "live" instance might have different records, for domain-name proof required by some apps (no point in duplicating that). Given those considerations, I would definitely go with two Pulumi projects. Your option 4 would work but it seems to me to be the most complicated and fragile solution. I would rule out 3, as that's just 2 with hard dependencies from one cloud to the other. And if the first project won't deploy because its cloud is gone, then the second project can't be updated. I think both 1 and 2 would work. I don't understand your point about not-discrete stacks, but you've given this more thought than I have, so option 2 ends up being the winner. I think?
g
@little-cartoon-10569 Yes good point about having two projects to avoid having a dependency between them. Wouldn't want to have to deal with
pulumi up
failures because of being unable to access some aspect of the other cloud if it became unavailable. This requirement of eliminating dependencies between them as you say rules out 3. My point in 1a is referring to the violation of best practice (different stack per different environment) and the danger of having everything in a single stack. The code in 1 would generate two Pulumi resources for each DNS record - one in route53 format, one in cloudflare format. A single
pulumi up
would create both records, one in each cloud. As we've established, having this kind of dependency is a big risk as
pulumi up
would fail when being unable to access one of the clouds. This completely rules out 1. This leaves option 2. Although I may go with a modified aspect of 1, i.e. defining my records in a single agnostic format, then having my parser read this and generate the pulumi resources, and output generated resources into two separate projects instead of two stacks. I already have a parser I wrote in golang which converts route53 zone exports into pulumi cloudflare yaml resources, which I wrote for a previous migration project migrating a very large Route53 zone with many hundreds of records, to Cloudflare. So will just need to adapt this to output in both route53 and Cloudflare formats, and make it output to two files. Thanks for your input.