Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions blog/2022-12-19-welcome-to-lamby-v4.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ We now encourage bringing your own containers by using Lambda's Runtime Interfac
file needed!

```docker title="Dockerfile"
FROM ruby:3.1-bullseye
FROM ruby:3.2-bullseye
RUN gem install 'aws_lambda_ric'
ENTRYPOINT [ "/usr/local/bundle/bin/aws_lambda_ric" ]
CMD ["config/environment.Lamby.cmd"]
Expand All @@ -81,7 +81,7 @@ CMD ["config/environment.Lamby.cmd"]
The [Crypteia](https://github.com/customink/crypteia) package is Rust Lambda Extension for any Runtime/Container to preload SSM Parameters as secure environment variables. It takes advantages of `LD_PRELOAD` to seamlessly fetch values from SSM when a process starts and then injects them as natively accesible Ruby `ENV` variables. Our <DocLink id="quick-start" /> guide's cookiecutter includes Crypteia already for you via a Docker `COPY` command into the Lambda Extension `/opt` directory.

```docker title="Dockerfile"
FROM ruby:3.1-bullseye
FROM ruby:3.2-bullseye
# highlight-next-line
COPY --from=ghcr.io/customink/crypteia-extension-debian:latest /opt /opt
```
Expand Down
38 changes: 32 additions & 6 deletions docs/anatomy.mdx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
---
id: anatomy
title: How Lamby Works
toc_max_heading_level: 2
toc_max_heading_level: 3
---

import DocLink from "../src/components/DocLink.js"
import ThemedImage from '@theme/ThemedImage'
import useBaseUrl from "@docusaurus/useBaseUrl"

# How Lamby Works

Expand Down Expand Up @@ -70,7 +72,7 @@ gem 'lamby'
You will need some [`Dockerfile`](https://github.com/customink/lamby-cookiecutter/blob/master/%7B%7Bcookiecutter.project_name%7D%7D/Dockerfile) to build your Lambda container image. Referencing architecture diagram above mentions something called a RIC (Rick). The RIC is short for the Lambda [Runtime Interface Client](https://github.com/aws/aws-lambda-ruby-runtime-interface-client). It is a small interface packaged as a Ruby gem that acts as the `ENTRYPOINT` for any [OCI](https://opencontainers.org) continer image to run on the AWS Lambda platform. Below you can see that we are using an [Official Ruby](https://hub.docker.com/_/ruby) Ubuntu variant base image, installing the RIC and setting it as the entrypoint.

```docker title="Dockerfile"
FROM ruby:3.1-bullseye
FROM ruby:3.2-bullseye

RUN gem install 'aws_lambda_ric'
ENTRYPOINT [ "/usr/local/bundle/bin/aws_lambda_ric" ]
Expand All @@ -79,6 +81,10 @@ CMD ["config/environment.Lamby.cmd"]

The RIC allows us to use Docker's `CMD` to load Rails and invoke a function. In this case we are loading our Rails application through its `config/environment.rb` file (.rb extension is implied) and once that is done, calling the `Lamby.cmd` as the Lambda handler.

:::note
Our [cookiecutter](https://github.com/customink/lamby-cookiecutter) project defaults to building a Linux image targeting the `arm64` architecture vs the traditional `x86_64`. However, this is easily changed to accomodate your needs. Check out the <DocLink id="cpu" /> section for more details.
:::

## SAM CloudFormation File

The [`template.yaml`](https://github.com/customink/lamby-cookiecutter/blob/master/%7B%7Bcookiecutter.project_name%7D%7D/template.yaml) file at the root of your project describes your [Serverless Application](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html). Don't worry, we have done some heavy lifting for you. Here is the [Serverless Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html) Resource we start you off with and a brief explanation:
Expand Down Expand Up @@ -133,16 +139,36 @@ So how does that CloudFormation file and container image get created within AWS?
- Sets various ENV variables if not set already. For example, easy to deploy to multiple regions by setting `AWS_REGION`.
- Install gems into local vendor/bundle for deployment via a Docker `COPY`.

If you used our <DocLink id="quick-start" /> guide, you likely made your first deploy using VS Code's integrated terminal within the development container. This is critically important since your Ruby gems with native extensions are built within the context of the Ruby Ubuntu image being built and copied to ECR for Lambda to use. You can automate both the test and deploy process using our provided GitHub Actions which also leverage the [Dev Container Build and Ruby CI](https://github.com/devcontainers/ci) project.
If you used our <DocLink id="quick-start" /> guide, you likely made your first deploy using VS Code's integrated terminal within the development container. This is critically important since your Ruby gems with native extensions are built within the context of the Ruby Ubuntu image being built and copied to ECR for Lambda to use.

- [Deploy GitHub Action Template](https://github.com/customink/lamby-cookiecutter/blob/master/%7B%7Bcookiecutter.project_name%7D%7D/.github/workflows/deploy.yml)
- [Test GitHub Action Template](https://github.com/customink/lamby-cookiecutter/blob/master/%7B%7Bcookiecutter.project_name%7D%7D/.github/workflows/test.yml)
When automating deployments, the system must have permission to create the needed resources and IAM Roles with permission(s) for your application to work. Most hobby users have admin level access to their own AWS account. For more security minded folks, consider creating a [least privilege user](https://docs.aws.amazon.com/lambda/latest/dg/access-control-identity-based.html) for your deployments with [OpenID Connect](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html) identity providers. We found that the `AWSCodeDeployFullAccess` managed policy is often overlooked.

### CircleCI

If `arm64` is your target platform in production, CircleCI make it easy to to do so using their [Arm Execution Environment](https://circleci.com/docs/using-arm/). Our starter includes a CircleCI `config.yml` file that runs tests on each commit or deploy by manually triggering a workflow. It even uses the [Devcontainer CLI](https://github.com/devcontainers/cli) to ensure your CI/CD matches your development experience. Changing between `arm64` and `x86_64` is described in our <DocLink id="cpu" /> guide.

When automating deployments, the user must have permission to create the needed resources and IAM Roles with permission(s) for your application to work. Most hobby users have admin level access to their own AWS account. For more security minded folks, consider creating a [least privilege user](https://docs.aws.amazon.com/lambda/latest/dg/access-control-identity-based.html) for your deployments. We found that the user also needs the `AWSCodeDeployFullAccess` managed policy.
- [Test & Deploy CircleCI Template](https://github.com/customink/lamby-cookiecutter/blob/master/%7B%7Bcookiecutter.project_name%7D%7D/.circleci/config.yml)

Deploying requires manually triggering the workflow. Simply select a branch then click "Trigger Workflow" and pass a string parameter called "workflow" with a value of "deploy". Feel free to change this workflow to suite your needs.

<ThemedImage
alt="CircleCI Trigger Workflow for Deploy"
sources={{
light: useBaseUrl('/img/docs/circle-ci-trigger-workflow-light.png'),
dark: useBaseUrl('/img/docs/circle-ci-trigger-workflow-dark.png'),
}}
/>

### GitHub Actions

You can automate both the test and deploy process using our provided GitHub Actions which also leverage the [Dev Container Build and Ruby CI](https://github.com/devcontainers/ci) project.

- [Deploy GitHub Action Template](https://github.com/customink/lamby-cookiecutter/blob/master/%7B%7Bcookiecutter.project_name%7D%7D/.github/workflows/deploy.yml)
- [Test GitHub Action Template](https://github.com/customink/lamby-cookiecutter/blob/master/%7B%7Bcookiecutter.project_name%7D%7D/.github/workflows/test.yml)

1. Within your project's GitHub repository [add two Encrypted Secrets](https://docs.github.com/en/actions/reference/encrypted-secrets) using the credentials values above with the environment names of `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`.
2. If needed, change the `aws-region` in your `.github/workflows/deploy.yml` file from `us-east-1` to your own region.
3. Trigger a deploy by navigating to the Deploy workflow and clicking "Run workflow".


<img alt="Lambda & Rails deploy with GitHub Actions" src={require('@site/static/img/docs/github-actions-deploy.png').default} style={{width: '100%', borderRadius: '5px'}} />
69 changes: 69 additions & 0 deletions docs/cpu-architecture.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
id: cpu
title: CPU Architecture
toc_max_heading_level: 2
---

import DocLink from "../src/components/DocLink.js"

# CPU Architecture

Our [cookiecutter](https://github.com/customink/lamby-cookiecutter) project defaults to building a Linux container image targeting the `arm64` architecture vs the traditional `x86_64` cpu type. Applications that use arm64 (AWS Graviton2 processor) can achieve significantly better price and performance than the equivalent workloads running an on x86_64 architecture.

Deploying arm64 applications is still a relatively new process and requires a few special considerations from local development to your CI/CD tooling. AWS Lambda makes this easy using the [Architectures](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-architectures) setting of the `AWS::Lambda::Function` CloudFormation resource. However, here are a few things you should know.

## Docker Images

Most base Docker images are now build for [multiple platforms](https://www.docker.com/blog/faster-multi-platform-builds-dockerfile-cross-compilation-guide/). Consider the following `Dockerfile`:

```dockerfile
FROM ruby:3.2-bullseye
```

How does Docker know which platform to use? The anwser is to use the default platform of the host. If you are on a M1 or M2 Mac, arm64 would be the platform used. Which platforms are in a specific base image? We can find out using the `docker manifest` command. For example:

```shell
$ docker manifest inspect ruby:3.2 | grep arch
"architecture": "amd64",
"architecture": "arm64",
$ docker manifest inspect | grep arch
"architecture": "amd64",
"architecture": "arm64",
```

All the images in our starter project are multi-platform. This means any host can be used for development. Your computer, Codespaces, etc will use the proper platform image variants.

## Deployment Gotchas

Though there are numerous ways to deploy containers using techniques such as emulation. However, we recommend you following one simple rule. Matching your “Development Host OS/Arch” to that of your target “Deployment Host OS/Arch” provides the least development friction. Use a CI/CD platform that matches your deployment target.

:::caution
Currently GitHub Actions does not support native arm64 runners. They are [working to add](https://github.com/actions/runner-images/issues/5631) this feature.
:::

Our <DocLink id="quickstart" /> guide has your first deploy happening from your local machine. Since we default to `arm64` this should work fine if you are on a Mac with Apple Silicon. But what if you are on a Windows or Linux system with an `x86_64` architecture? Your function will not work since your application's system dependences (like mysq2) will be compiled for the wrong architecture. Depending on your needs, you may have to switch back to `x86_64` as described below.

For more information on deployments, see our <DocLink id="anatomy" /> guide.

## Switching to x86_64

Based off the current state of our [cookiecutter](https://github.com/customink/lamby-cookiecutter) project, here are the changes required to switch to a `x86_64` deployment target. First, change your CircleCI workflows default machine from `arm.large`` to a standard large.

```diff title=".circleci/config.yml"
default-machine: &default-machine
machine:
image: ubuntu-2204:current
docker_layer_caching: true
- resource_class: arm.large
+ resource_class: large
```

Now open up your AWS SAM serverless `template.yaml` file, find the `RailsLambda` resource and change your Architecture property from `arm64` to `x86_64`.

```diff title="template.yaml"
Properties:
Architectures:
- - arm64
+ - x86_64
```

2 changes: 1 addition & 1 deletion docs/environment.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Globals:
The [Crypteia](https://github.com/customink/crypteia) package is Rust Lambda Extension for any Runtime/Container to preload SSM Parameters as secure environment variables. It takes advantages of `LD_PRELOAD` to seamlessly fetch values from SSM when a process starts and then injects them as natively accesible Ruby `ENV` variables. Our <DocLink id="quick-start" /> guide's cookiecutter includes Crypteia already for you via a Docker `COPY` command into the Lambda Extension `/opt` directory.

```docker title="Dockerfile"
FROM ruby:3.1-bullseye
FROM ruby:3.2-bullseye
# highlight-next-line
COPY --from=ghcr.io/customink/crypteia-extension-debian:latest /opt /opt
```
Expand Down
13 changes: 11 additions & 2 deletions docs/quick-start.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ project_name [my_awesome_lambda]:

## Development Container

:::caution
Is your local computer an `x86_64` system such as an older Intel Mac or Windows? Our starter defaults to an `arm64` deployment target. If needed, see our <DocLink id="cpu" /> guide on how to switch to `x86_64`.
:::

Your new Rails project with Lamby leverages [GitHub Codespaces](https://github.com/features/codespaces) which itself is built atop of the [Development Container](https://containers.dev) specification. In short, this means your project's containers are easy to use by any editor, even outside of Codespaces.

VS Code makes this incredibly easy. Within a new window, open the command pallet and type "dev container open" and select that action to `Open Folder in Container...`. When prompted, select the project folder created in the previous step.
Expand Down Expand Up @@ -99,8 +103,13 @@ Successfully created/updated stack - new-service-production in us-east-1

Open your browser and go to the URL. You should see the familiar welcome to Rails screen.

<img alt="Yay! You're on Rails with AWS Lambda containers" src={require('@site/static/img/docs/you-are-on-rails-and-lambda.png').default} style={{width: '100%', borderRadius: '5px'}} />

<ThemedImage
alt="Yay! You're on Rails with AWS Lambda containers"
sources={{
light: useBaseUrl('/img/docs/you-are-on-rails-and-lambda-light.png'),
dark: useBaseUrl('/img/docs/you-are-on-rails-and-lambda-dark.png'),
}}
/>

## What Just Happened?

Expand Down
1 change: 1 addition & 0 deletions sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const sidebars = {
docsSidebar: [
{ type: 'doc', id: 'quick-start' },
{ type: 'doc', id: 'anatomy' },
{ type: 'doc', id: 'cpu' },
{ type: 'doc', id: 'environment' },
{ type: 'doc', id: 'database' },
{ type: 'doc', id: 'assets' },
Expand Down
1 change: 1 addition & 0 deletions src/components/DocLink.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';

const DocNames = {
"anatomy": "How Lamby Works",
"cpu": "CPU Architecture",
"environment": 'ENV Variables & Secrets',
"assets": 'JavaScript & Assets',
"deploy": 'Build & Deploy',
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed static/img/docs/you-are-on-rails-and-lambda.png
Binary file not shown.