It's more of an open question and I'm just hoping for any opinions and suggestions. I have AWS in mind but it probably can relate also to other cloud providers.
I'd like to provision IaaC solution that will be easily maintainable and cover all the requirements of modern serverless architecture. Terraform is a great tool for defining the infrastructure, has many official resources and stable support from the community. I really like its syntax and the whole concept of modules. However, it's quite bad for working with Lambdas. It also raises another question: should code change be deployed using the same flow as infrastructure change? Where to draw the line between code and infrastructure?
On the other hand, Serverless Framework allows for super easy development and deployment of Lambdas. It's strongly opinionated when it comes to the usage of resources but it comes with some many out-of-the-box features that it's worth it. It shouldn't really be used for defining the whole infrastructure.
My current approach is to define any shared resources using Terraform and any domain-related resources using Serverless. Here I have another issue that is related to my previous questions: deployment dependency. The simple scenario: Lambda.1 adds users to Cognito (shared resource) which has Lambda.2 as a trigger. I have to create a custom solution for managing the deployment order (Lambda.2 has to be deployed first, etc.). It's possible to hook up the Serverless Framework deployment into Terraform but then again: should the code deployment be mixed with infrastructure deployment?
It is totally possible to mix the two and I have had to do so a few times. How this looks actually ends up being simpler than it seems.
First off, if you think about whatever you do with the Serverless Framework as developing microservices (without the associated infrastructure management burden), that takes it one step in the right direction. Then, what you can do is decide that everything that is required to make that microservice work internally is defined within that microservice as a part of the services configuration in the serverless.yml, whether that be DynamoDB tables, Auth0 integrations, Kinesis streams, SQS, SNS, IAM permissions allocated to functions, etc. Keep that all defined as a part of that microservice. Terraform not required.
Now think about what that and other microservices might need to interact with more broadly. They aren't critical for that services internal operation but are critical for integration into the rest of the organisations infrastructure. This includes things like deployment IAM roles used by the Serverless Framework services to deploy into CloudFormation, Relational Databases that have to be shared amongst multiple services and resources, networking elements (VPC's, Security Groups, etc), monolithic clusters like ElasticSearch and Redis ... all of these elements are great candidates for definition outside of the Serverless Framework and work really well with Terraform.
Any resource would be able to connect to these Terraform defined resource as needed, unlike that hard association such as Lambda functions triggered off of an API Gateway endpoint.
Hope that helps
Related
I've been building serverless applications on AWS for the past few years, utilizing services such as Lambda, DynamoDB, SNS, SQS, Kinesis, etc., relying on the Serverless framework for local development and deployments. Due to professional reasons, I have now to switch to Google Cloud and I've been exploring the serverless space in that platform. Unfortunately, at first glance it doesn't seem to be as mature as AWS, which I don't know whether it's true or just caused by my lack of expertise. The reasons that make me claim that are basically the following:
There is no logical grouping of functions and resources: on AWS, Lambda functions are grouped in Applications, and can be deployed as a whole via SAM or the Serverless framework, which also allow creating any associated resource (databases, queues, event buses, etc.). It seems that on GCP functions are treated as individual entities, which makes managing them and orchestrating them harder.
Lack of tooling: both the SAM cli and the Serverless framework provide tools for local development and deployments. I haven't found anything on GCP like the former (the Functions Framework seems to cover it partially, but it doesn't handle deployments), and even though that the latter supports GCP, it's missing basic features, such as creating resources other than functions. What is more, GCP is not in the core framework and the plugin is looking for maintainers.
Less event sources: Lambda is directly integrated with a long list of services. On the other hand, Cloud Functions is integrated with just a few services, making HTTP triggers the only option on most cases. It seems they're trying to address this issue with Eventarc, but I don't think it's generally available yet.
Does anybody have any tips on how to setup a local environment for this kind of applications and how to manage them effectively?
Here some documentation that might be helpful for your case, even though required to take a deep look into it.
Configure Serverless VPC Access (which i think applies for 'setting up your local environment').
Cloud Run Quick start (which contains how to built and deploy serverless services with GCP Cloud Run using node.js, python, java, etc.
Why would anyone use Serverless framework CLI to write the lambda functions or deploy them when we have AWS console GUI? Are there any specific benefits out of it?
Normally you don't develop and deploy a lambda function in isolation, instead it is one part of your cloud infrastructure. That can include other lambdas, S3 buckets, databases, API Gateways, IAM roles, environment variables and much more.
Serverless framework is allows you to write your infrastructure as code. For AWS services, it translates serverless.yaml config files into AWS cloudformation files, and from there deploys any new or updated services you define. You lambda function is just one part of that.
A major benefit of writing and deploying this way is that you can use your favourite editor locally, and can check your code into version control (i.e. git). This is not just for your lambda code, but also your infrastructure config i.e. serverless.yaml and associated files.
The Serverless Framework is more than just a replacement for the AWS Console (GUI). You can definitely set everything up via the AWS console for a Serverless application but how do you share that with your team? What if you wish to deploy that repeatedly into multiple applications? The Serverless Framework gives you a configuration file, usually called serverless.yml, where you define all the services within AWS (and other vendors, there is support for more than just AWS) and then you use the CLI to perform functions on this configuration file such as deploy, invoke and lot more.
Then there are the Serverless Framework plugins designed by the community around the project to make other tasks even easier such as unit testing, configuration of S3 buckets, CloudFront and domains to make frontend deployment easier and a lot, lot more.
Lastly, but most importantly, there is a professional product provided in addition to the open source framework that you can use to add on monitoring, deployment management, troubleshooting, optimisation, CI/CD and too many other benefits to list here.
Definitely, if you are doing a big project the Serverless framework has a lot of benefits, imagine you developing an MVC c# project with notepad. How do you feel about that?
The framework are done to make our life ( for developers ) very much easier.
I recently started working with AWS and IaC, I'm using Cloudformation to provision my AWS resources, but I discovered that AWS provide both a SDK and a CDK to enable you to provision resources programmatically instead of plain json/yaml.
But based on the documentation I did not really understand how they differ, can someone explain me how they differ and for what use case you should use what?
CDK: Is a framework to model and provision your infrastructure or stack. Stack can consist of a database for ex: DynamoDB, S3 Bucket, Lambda, API Gateway etc. It provides a facility to write code to create an infrastructure in AWS. Also called Infrastructure as code.
Check here
SDK: These are the code libraries provided by Amazon in various languages, like Java, Python, PHP, Javascript, Typescript etc. These libraries help interact with AWS services (like creating data in DynamoDB) which you either create through CDK or console. SDKs simplify using AWS services in your application with an API.
Check here
AWS SDK is a library primarily to ease the access to the AWS services by handling for you the data (de)serialization, credentials management, failure handling, etc. Perhaps, for specific scenarios, you could use the AWS SDK as the infrastructure as a code tool, however it could be cumbersome as it is not the intended usage of the library.
Based on the https://docs.aws.amazon.com/whitepapers/latest/develop-deploy-dotnet-apps-on-aws/infrastructure-as-code.html, dedicated tools for the IaC are AWS CloudFormation and AWS CDK.
AWS CDK is an abstraction on top of CloudFormation. CDK scripts are in fact transformed to the CloudFormation definitions when scripts are synthesized.
The difference can be best described on an example: Imagine that for each lambda function in your stack you want to create an error CloudWatch alarm and connect to the SNS topic.
With CloudFormation you will either a) need to write a pretty much similar bunch of yaml/json definitions for each lambda function to ensure the monitoring, b) use the nested stack templates, c) use CloudFormation modules.
With CDK you can write a generic code construct - class or method, which can create the alarm for the given lambda function and create the SNS alarm action for given topic.
In other words, CDK helps you generalize and re-use your IaC in a very familiar way to how you develop your business code. The code is shorter and more readable than the CF definitions.
The difference is even more remarkable when you need to set up similar resources in different AWS regions and when you have different AWS account per environment. You can manage all AWS accounts and regions with a single CDK codebase.
Some background first: CloudFormation is Amazon's solution for an “Infrastructure as Code” approach to managing the definition, provisioning and deployment of a bunch of resources across accounts/regions. This is done by using their declarative yaml/json-based template language to define it all, and then executing the templates through various means (console, cli, APIs...). More info:
white paper: https://docs.aws.amazon.com/whitepapers/latest/develop-deploy-dotnet-apps-on-aws/infrastructure-as-code.html
faq: https://aws.amazon.com/cloudformation/faqs/
There are other popular IaC solutions or tools to help achieve it more easily out there, such as Terraform and Kubernetes (container orchestration that also uses declarative templates to define desired states).
Potential benefits of IaC: At a high level, you can better track & audit your infra, reuse definitions/processes, make all your changes in a more consistent manner, faster thanks to all the automation and assurances you can get with an infra-as-code approach. You may be familiar with these as mentioned in previous answers and more, such as:
version controlling your infrastructure definitions,
more efficient and logically complex ways of constructing templates,
ability to write tests against them,
do diffs (see "change sets") before making real infra changes with the templates,
detect when live infra differs from your definitions,
automate rollbacks,
and lots of other state management assistance through a framework like CF that might be needed when performing regular ops duties.
CDK:
This is for helping to automate CloudFormation as part of an IaC approach to provisioning and deploying resources. It lets you use various popular programming languages to help with the creation, testing, and management of your CF setup. Some of AWS’s motivations: “YAML is an excellent format for describing the desired state of your cluster, but it is does not have primitives for expressing logic and reusable abstractions.“ “AWS CDK uses the familiarity and expressive power of programming languages for modeling your applications.”
More info: https://docs.aws.amazon.com/cdk/v2/guide/home.html
However, Amazon knows about other solutions, and happily points them out on the main CDK page now, downplaying its original connection to CF. You don't need to use CloudFormation if you don't want to; specifically, they mention you can use the same CDK constructs with the help of:
cdktf for Terraform maintained by its creators, Hashicorp
cdk8s for Kubernetes by AWS. re: “We realized this was exactly the same problem our customers had faced when defining their applications through CloudFormation templates, a problem solved by the AWS Cloud Development Kit (AWS CDK), and that we could apply the same design concepts from the AWS CDK to help all Kubernetes users.”
SDK:
AWS has an API for all of their services, and the various SDKs give you access to them. For example, I can use AWS’s Java SDK to manage an API Gateway. If I wanted to script some custom deployment process, I could do so with the SDK, managing all the state, etc. myself. You could probably even re-implement the CloudFormation service with the various underlying APIs... The APIs have varying levels of documentation though. E.g. CloudFormation Java APIs are only mentioned in the raw API reference, not the friendlier Developer Guide.
I find that the difference for me is that the CDK codifies the CloudFormation JSON/YAML. First response, is great ya okay in code but the benefit on the code side of things is you can write unit testing against the code. Therefore you get to build that sense of security or insurance policy against the provisioned services in the CDK.
There are other ways to test CF, however, with a dev background, this feels more comfortable.
Is it a good practice for CloudFormation deployment be done via CI/CD? I am currently considering the safety & performance aspect.
If someone accidentally removed a DB for example, CloudFormation will just remove it ... There could be code reviews to prevent this ... but just wondering if its a good practice.
With a serverless application there maybe no choice? Like otherwise its too manual to deploy everything
Another observation is performance, CloudFormation is rarely changed but it will need to run anyway if its part of the CI/CD process. Is there any way to speed this up?
Definitely.
You cannot achieve CI/CD in true sense until you do that.
Consider a scenario that for a particular release you added a messaging queue (AWS SQS). Now if you haven't integrated your Cloudformation with your CI/CD then your code that reads/write to/from SQS goes into your environment but will fail to do either operations just for the simple fact that SQS does not exist because your cloudformation change that would have created the SQS did not execute. So, eventually you end up having half baked environment.
To avoid this pitfall it is highly recommended that you execute your cloudformation as part of your CI/CD
Regarding your concern 'If someone accidentally removed a DB for example, CloudFormation will just remove it', this can happen even with the actual code. For example the developer had put in some test code to cleanup the database but forgot to remove that and that code gets executed in production environment. But ideally this would not happen because of the guard rails of manual testing, automated testing and JUnits. So in similar context treat Cloudformation as any other code (in fact Cloudformation is best described as Infrastructure as Code) which should be tested thoroughly. To check out on details for Unit Testing Cloudformation , see Is there a way to unit test AWS Cloudformation template
Yes absolutely. If you treat Infrastructure as Software (IaS), then you should be able to implement modern CI/CD software practices like syntax checking, unit testing, functional testing, verification, automated testing and deployment etc on your Cloudformation templates as well.
AWS provides a best practices solution here:
https://aws.amazon.com/answers/devops/aws-cloudformation-validation-pipeline/
The solution provides this introduction:
>
"Many Amazon Web Services (AWS) customers use AWS CloudFormation to manage their infrastructure as code and to help deploy AWS resources in a controlled and predictable way. DevOps teams are commonly tasked with validating AWS CloudFormation templates before launch to ensure they follow industry best practices and satisfy company-specific business and governance requirements. These teams often leverage AWS Developer Tools, which is a set of services designed to help DevOps professionals follow continuous integration and continuous delivery (CI/CD) practices and create their own pipelines to automatically build, validate, and deploy code."
Recently I have been looking into AWS Lambdas and how to build Serverless API using .Net Core. From what I understand, you can do it in 2 different ways.
1) Write multiple separate Lambdas in C# and deploy them to AWS. Requests come in via API gateway and each lambda acts as an endpoint.
2) Build a Serverless Web API using .Net core. When you create the serverless Web API project a Lambda is automatically created which becomes the entry point to the Web API.
Are there any limitations of 1 vs 2, or use cases where one approach might be beneficial over other? Or is it just 2 different ways of achieving the same thing?
I don't think your options are correct. The two options for building a Lambda backed API are:
1- Build lambdas and deploy them independently to AWS in one or more project. Then Manually create API Gateway endpoints that point to your one or more lambdas.
2- Use a Serverless project to combine your lambdas in one project. Define your endpoints in that project and have Cloudformation create the API Gateway endpoints and hook them up to your lambdas on deployment.
As far as pros and cons,
Option 1:
Pros: has the flexibility of deploying lambdas independently, also you can configure your API Gateway endpoints however way you want without having to understand Cloudformation definition syntax which took some ramp up time in my experience.
Cons: If you have a lot of lambdas this becomes a management nightmare. Also your endpoint definition is not in the source code and changes to the endpoint configuration will not be tracked.
Option 2:
Pros: If you figure out Cloudformation or if you want to go with the default configuration deploying a lambda and hooking it to an API Gateway endpoint is super easy. AWS will create the endpoint for you and will create dev and prod stages, policies, IAM roles, etc. This being deployed by Cloudformation directly from Visual Studio causes the whole deployment and all related objects to fall under the same "Stack" in AWS Cloudformation which can be changed, repliocated, or deleted very easily. Also your Infrastructure is now code and changes to it are auditable in your git repo.
Cons: The biggest con in my opinion is the fact that the stack doesn't span the VS Solution but rather just the project, so all your lambdas have to live in the same project which means that if you have a lot they will end up all in one monolith lambda binary. The generated large project binary will costing you memory runtime on AWS and efficiency problems. The other con is that if you want to have specific or out of the ordinary API Gateway you will need to understand Cloudformation syntax to change your serverless.template file.
Conclusion: My preferred solution was to divide my true application into smaller chunks of related lambdas based on the API object and place these lambdas in a few Serverless application projects. For example I have an order project which contains all lambdas related to the order API, and a Product project that contains the lambdas related to product API etc. Both of them would live in the same solution and would get deployed separately. I'm currently working on a way to deploy the entire solution at once.