šŸ§  Strategizing for Multi-Cloud Agnosticity

Joshua Ben-Tzion Quek
digital-coe
Published in
9 min readApr 14, 2021

Having been in the digital consulting space for quite a while already, one of the major challenges observed for many customers would revolve around moving from an on-premise implementation to the cloud, or that of migrating from an existing cloud provider to a different cloud provider. The appalling thing about this is that sometimes, the migration effort requires a colossal amount of time and effort to execute, sometimes taking months on end to do so, especially for larger projects. This takes into consideration the number of moving parts involved in the architecture of the many end-to-end solutions that are being moved over from one cloud provider to another.

The one thing that I have observed from leading delivery for multiple agile squads in the past is that lift-and-shift cloud migrations are often easiest for solutions that are have been designed in a cloud agnostic manner. Meaning that the end-to-end architecture, the DevOps pipelines, as well as the codebases contain little to no traces of cloud provider lock-in.

Consider a simple example of building a To-do web application that has a NodeJS API microservice on the backend which writes to a transactional database. There are a hundred and one ways that one can architect this, but for brevityā€™s sake, we will take a look a few options, using AWS as our ā€œas-isā€ cloud provider in this example, with Azure and GCP as our ā€œto-beā€ cloud provider that we intend to hypothetically migrate to:

Option A: The šŸ§© ā€œNative Managed Servicesā€ Architecture

  • Frontend:
    ā€¢ React/Vue/Angular Webapp hosted on AWS Amplify
    ā€¢ AWS Amplify fronted with your domain name via Route53 DNS
  • Backend:
    ā€¢ NodeJS API app hosted on AWS Elastic Beanstalk
    ā€¢ AWS RDS based PostgresDB (managed service)
  • DevOps:
    ā€¢ Code Repo is hosted in AWS CodeCommit
    ā€¢ Deployed using AWS CodePipeline & AWS Codebuild

Option B: The ļøļøāš”ļø ā€œServerlessā€ Architecture

  • Frontend:
    ā€¢ React/Vue/Angular Webapp hosted on a fully private S3 bucket
    ā€¢ S3 bucket is fronted with a CDN ā€” AWS Cloudfront distribution, which is then fronted with your domain name via AWS Route53 DNS
  • Backend:
    ā€¢ Serverless Framework Deployment (https://serverless.com)
    |-- ā€¢ Cloudformation Script (Auto Deploy via Serverless Framework)
    |-- ā€¢ NodeJS API Lambda (Auto Deploy via Serverless Framework)
    |-- ā€¢ AWS API Gateway (Auto Deploy via Serverless Framework)
    |-- ā€¢ Warmup Lambda (Auto Deploy via Serverless Framework)
    ā€¢ PostgresDB database on AWS Aurora
  • DevOps:
    ā€¢ Code Repo is hosted on Gitlab.com / Github.com / Atlassian Bitbucket
    ā€¢ Deployed using Gitlab CI / Github Actions / Travis CI

Option C: The šŸ“¦ ā€œContainerā€ Architecture

  • Frontend:
    ā€¢ React/VueJS/Angular Webapp built into a container image
    ā€¢ Kubernetes cluster hosted on AWS EKS (AWS Fargate / AWS ECS / AWS Proton are other container hosting options)
    ā€¢ Container URL is then fronted with your domain name via Route53 DNS
  • Backend:
    ā€¢ Containerized NodeJS API app
    ā€¢ PostgresDB database on AWS RDS
  • DevOps:
    ā€¢ Code Repo is hosted on a containerized Gitlab instance (The example above is for AWS EKS)
    ā€¢ Deployed using Gitlab CI via a containerized Gitlab Runner / agent

From the three options listed above, which would be the easiest to do a lift-and-shift migration to another provider, say Microsoft Azure, or Google Cloud Platform?

The biggest factor to look at when it comes to planning and designing for a cloud agnostic architecture would be to first have a clear understanding of the common technologies that all major cloud providers use. This will then provide one with the discernment to ensure that there will be minimal changes/refactoring for each component being migrated.

Letā€™s now take a look at how much time and effort it could take if we were to do a migration over from AWS to say, Azure or GCP. If we were to objectively evaluate the options, either Option A or C would save the most time and effort, but C would be the safest option. Let us take a look why:

Option A : šŸ§© ā€œNative Managed Servicesā€ Architecture ā€” AWS to Azure or Google Cloud Platform (GCP)

For Option A, if we wanted to move the Frontend over, we would need to refactor the code repo to add or remove cloud provider specific application config files to run in the new target environment, which would then require a low amount of refactoring effort. However, doing so might affect how the code behaves, and could introduce bugs. If say we wanted to deploy into Azureā€™s App Service or GCPā€™s App Engine, these config files (usually yaml files) would need to be replaced.

Database-wise, since it is a PostgresDB on AWS RDS, it will be a simple database dump /export into a bucket or local machine, before doing an import into the next cloud providerā€™s PostgresDB database instance.

However, DevOps-wise since Option A is all about using a cloud providerā€™s native services, then moving to Azure or GCP would mean having to completely overhaul the DevOps pipelines, since AWS Codepipline and AWS Codebuild does not exist in an Azure/GCP context, and if one were to use the target cloud providerā€™s native CI/CD services, then that would mean having to write the pipelines from scratch on Azure DevOps Pipelines or on GCP Cloudbuild.

Due to this, Option A will most probably require a fair amount of time and effort to migrate, with low effort on replacing application config files, but a substantial amount of effort for the Deployment pipelines ā€” a full CI/CD pipeline(s) overhaul.

Option B: āš”ļø ā€œServerlessā€ Architecture ā€” AWS to Azure or Google Cloud Platform (GCP)

For Option B, the migration of the Frontend would require minimal effort on the developerā€™s side, but a fair amount of effort from the DevOps teamā€™s side. If one is migrating the frontend to Azure, then it will be simply taking the current static site files, downloading them from the current AWS S3 bucket and then uploading them into the new environmentā€™s buckets ā€” Azure Blob Storage or GCP Cloud Storage bucket. Infrastructure wise, the target bucket would then need to be connected accordingly to their own cloud providersā€™ CDN service and DNS service (For Azure: Azure CDN & Azure DNS, For GCP: Cloud CDN & Cloud DNS), if we truly want the ā€œto-beā€ architecture to mimic the ā€œas-isā€ architecture.

For the backend NodeJS API Lambda, if it has incorporated the Serverless Framework ( https://www.serverless.com/framework/docs/providers/ ) into its codebase, which is cloud agnostic, then it will require some tweaking on the serverless.yml file within the codebase or DevOps pipelines, in order to deploy to Azure and GCP ā€” with Azure Functions or GCP Cloudfunctions being the intended deployment target(s). This would require a fair amount of effort. However, if one is using the native AWS Lambda SDK instead of the Serverless Framework, then migration from AWS Lambda to another cloud providerā€™s serverless offering (Azure Functions / GCP Cloudfunctions )would require a high amount of development effort, as it would mean a partial or full overhaul of the codebase on the developersā€™ side to adapt to the target cloud providerā€™s serverless technology SDK.

Database-wise, since AWS Aurora is essentially PostgresDB, a database dump export using oneā€™s local machine can be done, before doing an import into the target cloud providerā€™s ā€œserverlessā€ database ā€” Azure SQL ā€œServerless Compute Tierā€ DB or into GCP CloudSQL (for now, GCP does not have a serverless offering for PostgresDB)

On the bright side, DevOps-wise, since Option B uses Gitlab.com, which is a cloud provider agnostic code hosting option, existing pipelines can be easily tweaked to point to the new cloud provider to execute a deployment. In fact, the existing pipeline config yaml file might not even need to be replaced, but simply a new pipeline yaml file can be added on, which triggers when an engineer pushes to a specific branch (ā€œazure-stagingā€ branch for deployment into Azure, or ā€œgcp-stagingā€ to deploy into GCP)

If one were to architect it in a way that it were to use AWSā€™s native DevOps tools (AWS Codebuild & Code Pipeline), then it would take even more time and effort required for such a migration, as described previously for Option A.

On average, Option B would require the most amount of time and effort, due to the provider lock in if one were to use the native SDK serverless technology SDKs. If one desires to reduce the time and effort required, the Serverless Framework should be considered ā€” it is geared to automate each cloud providerā€™s serverless technology offering, so that cross cloud deployment complexity is reduced and cloud agnosticity can be achieve when deploying serverless technologies.

Option C: šŸ“¦ ā€œContainerā€ Architecture ā€” AWS to Azure or Google Cloud Platform (GCP)

For Option C, since most of the architecture consist of containers, whether it be the Frontend or Backend services, and a migration strategy would literally be to build the existing container instances into container images, and then redeploy them into the target cloud providerā€™s container environment, with minimal to no changes required, since the code has been locked into the container image already before being shipped over to the new cloud providerā€™s environment.

Most of the time and effort for Option C would be on the infrastructure level, which would have to do with container orchestration and setup of the new container infrastructure to ensure that the infrastructure configuration of the ā€œAs-Isā€ architecture is the same as the ā€œTo-beā€ architecture. This would be especially be so if one is migrating from say, AWS EKS (Elastic Kubernetes Service)to Azure AKS (Azure Kubernetes Service) or to GCP GKE (Google Kubernetes Engine).

Overall, Option C would require less effort to migrate as compared to Option B, and probably an equal amount of effort to migrate as compared to Option A, but with more expertise would be required on the DevOps side ā€” container orchestration ā€” as compared to both Options A and B. In terms of overall product stability, Option C might be the best option, as no changes are done to the application codebases themselves. For Options A and B, they require the application config files or codebase codes to be modified, which might introduce bugs to the existing codebases.

In Conclusion

From the above, if you have noticed, we did not cover financial costing as well as end-to-end Testing when it comes to the three options, which could be put into another article altogether. For brevityā€™s sake and also in view of our hypothetical ā€œTo-do Appā€ example above, Option B would probably cost the least (financially) due to the pay-as-your-customer-uses nature of how serverless offerings are charged, followed by Option A or C costing around the same (all this is debatable). However, the focus of the article is not on application runtime costing, but time and effort costing of migration efforts from one cloud provider to another.

Based on that premise, Option A and C would then be the choices that would require less time and effort as compared to Option B, which has the highest Cloud Provider lock-in. However, Option C would be the safest when it comes to a lift and shift migration across different cloud providers, especially when you want to ensure that all of your application codebases are frozen into container images (ā€œstrictly not modifiedā€) so that they runs ā€œas-isā€ even in a migrated ā€œto-beā€ environment. We can see that Option C has the highest degree of cloud agnosticity overall.

From here, we can understand why Cloud Agnosticity is so important in the digital consulting world ā€” if you are deploying multiple end-to-end white-labelled solutions that you have built for Customer A in AWS, and then Customer B comes along and they also want the same solutions, but now in Azure or GCP, how long and how much effort would it take to do so? This could mean the difference between winning a sales bid and losing it to a competitor.

In short, architecting oneā€™s digital solutions in a cloud agnostic manner could give your business a competitive advantage when planning for a future-proof architecture. Ultimately, it will save you a lot of time, effort and unneeded technical complexity when it comes architecting solutions in an ever changing digital landscape.

--

--

Joshua Ben-Tzion Quek
digital-coe

יְהוֹשֻׁעַ בֶּן-צ֓יּוֹן ā€¢ Digital Multi-cloud Architect ā€¢ https://linkedin.com/in/joshua-quek ā€¢ https://github.com/joshuaquek