Ifrastructure as Code (IaC)
- Infrastructure as Code (IaC) is defining both your infrastructure and code in a single file. You can use tools to “start up” this infrastructure.
- Amazon’s CloudFormation is one implementation of IaC. You define your infrastructure and code in a YAML file.
- You can define various entities in your YAML file, such as auto-scaled functions, databases, message queues, pub/sub systems, etc.
- You can define when your functions run. For example, when a certain endpoint is hit, or when a certain event is published, etc.
- You can specify env vars that will be present for your functions.
- You can define databases, and give your function(s) read and/or write access to them.
Introduction
Infrastructure as Code (IaC) is basically defining both your infrastructure and the code that runs on it in a single file. You then use tools to “start up” your infrastructure in the cloud and in effect, deploy your code/system to the cloud. Your system is often auto-scaled.
By “defining your infrastructure”, I mean you list out the cloud components that you need, such as auto-scaled servers, auto-scaled functions (lambda), auto-scaled databases, auto-scaled message queues, auto-scaled pub/sub, you get the idea. You list these things in a file, and then in that same file, you define relationships between them. For example, you might say that a certain auto-scaled function should get triggered when a certain endpoint is hit, or when a certain event occurs in your pub/sub system. Furthermore, you can define a connection between your auto-scaled function and your auto-scaled database, so that the function can read and write to the database.
The best way to learn this, as with most other things, is by looking at an example. One implementation of Infrastructure as Code (IaC) is Amazon’s “CloudFormation” service. You define your infrastructure and code in a YAML file. And then you tell CloudFormation to “start up” (deploy) your infrastructure in the cloud. Let’s take a look at a concrete example.
Amazon CloudFormation
Here is an example YAML file that defines a lambda function and an endpoint (API Gateway) that triggers the function. Ignore everything except the commented lines!
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function # we define an auto-scaled function (lambda function)
Properties:
Handler: index.handler # here is the path to the file that houses the function and the name of the function
Runtime: nodejs14.x
CodeUri: hello-world/
Events: # here is the event that triggers the function. In this case when the /hello endpoint is hit
HelloWorldApi:
Type: Api
Properties:
Path: /hello
Method: get
In summary, the above example defines a single lambda function that gets executed when the /hello endpoint is hit. The more this endpoint gets hit, the more the lambda function will scale (i.e. more compute resources will be allocated in order to run more instances of the function).
Let’s take a look at another example. This time, we will define a lambda function that gets triggered when a file is uploaded to an S3 bucket. “S3” is just an amazon service that allows you to store files. Ignore everything except the commented lines.
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2019-06-15
Resources: # notice we define *2* resources this time
S3Bucket: # the first one is an S3 bucket (the file storage service)
Type: AWS::S3::Bucket
FileUploadedLambda: # the second one is a lambda function
Type: AWS::Serverless::Function
Properties:
CodeUri: src/ # again, here is the path to the file that houses the function
Handler: app.lambda_handler # here's the name of the function
Runtime: python3.8 # this time, we specify the runtime to be python (so this is a python function), but don't worry about this too much
Events: # PAY ATTENTION HERE: time time, we specify that the function should run when a file is uploaded to the S3 bucket we defined above
S3FileUpload:
Type: S3
Properties:
Bucket: !Ref S3Bucket
Events: s3:ObjectCreated:*
In summary, the above example:
- defines two resources: an S3 bucket (amazon file storage service) and a lambda function
- specifies that the lambda function should run when a file is uploaded to the S3 bucket
Let’s do a 3rd example, one with a database! What do you say? Well too bad, you have no choice I’m afraid.
Here’s the example. Again, ignore everything except the commented lines.
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
HelloFunction: # our first resource is a lambda function
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs14.x
CodeUri: path/to/your/code
Policies: # here we specify that this function should have read access to a DynamoDB table. DynamoDB is just an amazon NoSQL database.
- DynamoDBReadPolicy:
TableName: !Ref SampleTable # this is the table it needs read access to (the table is defined further below)
Environment: # here we are setting an env var on the server that the lambda function runs on
Variables:
TABLE_NAME: !Ref SampleTable # we put the name of the table as an env var
Events:
HelloApi:
Type: Api
Properties:
Path: /hello
Method: get
SampleTable: # here we define the DynamoDb table resource
Type: AWS::DynamoDB::Table
Properties:
TableName: SampleTable # here is the name of the table
AttributeDefinitions: # here is kinda the "schema" of the table. We are saying objects in this table have a string as the key
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
BillingMode: PAY_PER_REQUEST # this is just how you want to be charged for using the table, don't worry for now!
In summary, the above example:
- defines a lambda function and a DynamoDB table (an amazon NoSQL database table)
- specifies that the lambda function should have read access to the DynamoDB table
- sets an env var on the server housing the lambda function, such that the lambda function can read the table name from this env var
Let’s define some terms.
Terms
Here are some terms you may encounter out in the wild relating to this stuff.
- IaC: Infrastructure as Code - Anytime you write down the infrastructure that your system uses along with the code that runs on it, you are doing IaC. The infrastructure is often auto-scaled. You often use a tool provided by the IaC provider to spin up your system. For example, Amazon’s CloudFormation.
- CloudFormation - Amazon’s IaC service.
- Lambda function - A function that runs in the cloud. It is auto-scaled. It is often triggered by an event, such as an endpoint being hit, a file being uploaded to S3, or a message being published to an SNS topic.
- S3 - Amazon’s file storage service. You can store files in it. You can also trigger events when files are uploaded to it.
- DynamoDB - Amazon’s NoSQL database service. You can store objects in it. You can also trigger events when objects are created, updated, or deleted in it.
- API Gateway - Amazon’s service that allows you to define endpoints that trigger lambda functions.
- SNS - Amazon’s pub/sub service. Supports auto-scaling.
- SQS - Amazon’s message queue service. Supports auto-scaling. Multiple entities can put messages in the queue and multiple entities can take messages out of the queue, however, each message can only be taken out by one entity. This prevents duplicate processing of messages.
Not too bad ay Billy? Super easy to get an auto-scaled system up and running in the cloud using IaC.