Skip to content

Commit 2f72379

Browse files
authored
Merge pull request #10 from FireTail-io/docs
Document Deployment & Tidy Makefile
2 parents 95019e2 + 0dde50d commit 2f72379

File tree

3 files changed

+230
-19
lines changed

3 files changed

+230
-19
lines changed

.github/workflows/release.yaml

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Build from release
1+
name: Build & publish
22

33
on:
44
release:
@@ -36,6 +36,20 @@ jobs:
3636
with:
3737
name: firetail-lambda-extension-${{ matrix.arch }}-${{ env.RELEASE_VERSION }}
3838
path: build/firetail-extension-${{ matrix.arch }}-${{ env.RELEASE_VERSION }}.zip
39+
- name: Get release
40+
id: get_release
41+
uses: bruceadams/get-release@v1.3.2
42+
env:
43+
GITHUB_TOKEN: ${{ github.token }}
44+
- name: Upload release binary
45+
uses: actions/upload-release-asset@v1.0.2
46+
env:
47+
GITHUB_TOKEN: ${{ github.token }}
48+
with:
49+
upload_url: ${{ steps.get_release.outputs.upload_url }}
50+
asset_path: build/firetail-extension-${{ matrix.arch }}-${{ env.RELEASE_VERSION }}.zip
51+
asset_name: firetail-extension-${{ matrix.arch }}-${{ env.RELEASE_VERSION }}
52+
asset_content_type: application/zip
3953

4054
publish-package:
4155
runs-on: ubuntu-latest
@@ -56,7 +70,6 @@ jobs:
5670
- name: Set RELEASE_VERSION
5771
run: |
5872
echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
59-
echo "AWS_RELEASE_VERSION=$(echo ${GITHUB_REF#refs/*/} | tr '.' '-')" >> $GITHUB_ENV
6073
6174
- name: Download amd64 package artifact
6275
uses: actions/download-artifact@v3
@@ -72,10 +85,10 @@ jobs:
7285

7386
- name: Publish amd64 layer to AWS
7487
run: |
75-
AWS_LAYER_VERSION=$(make publish ARCH=amd64 VERSION=$RELEASE_VERSION AWS_VERSION=$AWS_RELEASE_VERSION AWS_REGION=${{ matrix.aws-region }})
76-
make public ARCH=amd64 AWS_LAYER_VERSION=$AWS_LAYER_VERSION AWS_VERSION=$AWS_RELEASE_VERSION AWS_REGION=${{ matrix.aws-region }}
88+
AWS_LAYER_VERSION=$(make publish ARCH=amd64 VERSION=$RELEASE_VERSION AWS_REGION=${{ matrix.aws-region }})
89+
make public ARCH=amd64 AWS_LAYER_VERSION=$AWS_LAYER_VERSION VERSION=$RELEASE_VERSION AWS_REGION=${{ matrix.aws-region }}
7790
7891
- name: Publish arm64 layer to AWS
7992
run: |
80-
AWS_LAYER_VERSION=$(make publish ARCH=arm64 VERSION=$RELEASE_VERSION AWS_VERSION=$AWS_RELEASE_VERSION AWS_REGION=${{ matrix.aws-region }})
81-
make public ARCH=arm64 AWS_LAYER_VERSION=$AWS_LAYER_VERSION AWS_VERSION=$AWS_RELEASE_VERSION AWS_REGION=${{ matrix.aws-region }}
93+
AWS_LAYER_VERSION=$(make publish ARCH=arm64 VERSION=$RELEASE_VERSION AWS_REGION=${{ matrix.aws-region }})
94+
make public ARCH=arm64 AWS_LAYER_VERSION=$AWS_LAYER_VERSION VERSION=$RELEASE_VERSION AWS_REGION=${{ matrix.aws-region }}

Makefile

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1+
# Params with defaults
12
ARCH := amd64
23
VERSION := latest
3-
AWS_VERSION := latest
4-
AWS_LAYER_NAME := firetail-extension-${ARCH}-${AWS_VERSION}
54
AWS_REGION := eu-west-1
5+
6+
# Consts & derived values
67
AWS_amd64 := x86_64
78
AWS_arm64 := arm64
89
AWS_ARCH := $(AWS_$(ARCH))
10+
AWS_VERSION := $(subst .,-,${VERSION})
11+
AWS_LAYER_NAME := firetail-extension-${AWS_ARCH}-${AWS_VERSION}
912

1013
.PHONY: test
1114
test:
@@ -26,7 +29,7 @@ publish:
2629
@aws lambda publish-layer-version --layer-name "${AWS_LAYER_NAME}" --compatible-architectures "${AWS_ARCH}" --region "${AWS_REGION}" --zip-file "fileb://build/firetail-extension-${ARCH}-${VERSION}.zip" | jq -r '.Version'
2730

2831
.PHONY: public
29-
public:
32+
public:
3033
aws lambda add-layer-version-permission --layer-name ${AWS_LAYER_NAME} --version-number ${AWS_LAYER_VERSION} --statement-id "${AWS_LAYER_NAME}-${AWS_LAYER_VERSION}-publicAccess" --principal "*" --action lambda:GetLayerVersion --region "${AWS_REGION}"
3134

3235
.PHONY: add

README.md

Lines changed: 205 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,224 @@
1-
# Firetail Logging Extension
1+
# Firetail Lambda Extension
22

3-
This extension is a proof of concept using the Lambda Logs API to extract request & responses and forward them to the Firetail SaaS.
3+
[![License: LGPL v3](https://img.shields.io/badge/License-LGPL_v3-blue.svg)](https://www.gnu.org/licenses/lgpl-3.0) [![Test and coverage](https://github.com/FireTail-io/firetail-lambda-extension/actions/workflows/codecov.yml/badge.svg?branch=defaults)](https://github.com/FireTail-io/firetail-lambda-extension/actions/workflows/codecov.yml) [![codecov](https://codecov.io/gh/FireTail-io/firetail-lambda-extension/branch/main/graph/badge.svg?token=QNWMOGA31B)](https://codecov.io/gh/FireTail-io/firetail-lambda-extension)
4+
5+
6+
7+
## Overview
8+
9+
The Firetail Logging Extension receives AWS Lambda events & response payloads and sends them to the Firetail Logging API.
10+
11+
The extension receives these events and response payloads via a runtime-specific Firetail library which you will need to use in your Function code. The Firetail library outputs specifically formatted logs which the extension then receives via the [Lambda Logs API](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-logs-api.html). You can find a table of Firetail function libraries which correspond with a Lambda runtime in the [Function Libraries](#function-libraries) section.
12+
13+
14+
15+
## Function Libraries
16+
17+
| Supported Runtimes | Library |
18+
| -------------------- | ------------------------------------------------------------ |
19+
| Python 3.7, 3.8, 3.9 | [github.com/FireTail-io/firetail-py-lambda](https://github.com/FireTail-io/firetail-py-lambda) |
420

521

622

723
## Tests
824

9-
Automated testing is setup with the `testing` package, using [github.com/stretchr/testify](https://pkg.go.dev/github.com/stretchr/testify) for shorthand assertions. You can run them with `go test`, or use the provided [Makefile](./Makefile)'s `build` target.
25+
Automated testing is setup with the `testing` package, using [github.com/stretchr/testify](https://pkg.go.dev/github.com/stretchr/testify) for shorthand assertions. You can run them with `go test`, or use the provided [Makefile](./Makefile)'s `test` target, which is as simple as:
26+
27+
```bash
28+
make test
29+
```
30+
31+
This will output a coverage report (`coverage.out`) which you may view in your browser by using the [go tool cover](https://pkg.go.dev/cmd/cover) command:
32+
33+
```bash
34+
go tool cover -html coverage.out
35+
```
1036

1137

1238

1339
## Deployment
1440

15-
You will need to install the [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html), [Golang](https://go.dev/doc/install) and [JQ](https://stedolan.github.io/jq/).
41+
The Firetail Logging Extension is an external Lambda extension, published as a Lambda Layer. Deploying it is a five step process. If you wish to use the publicly accessible Lambda Layer published by Firetail, you can skip to the final step. The full list of steps to build, package, publish and use the Firetail Lambda Extension are as follows:
42+
43+
- The first step is to [build the extension binary](#building-the-extension-binary).
44+
- The second step is to [package the extension binary](#packaging-the-extension-binary).
45+
- The third step is to [publish the package as a Lambda Layer](#publishing-the-package).
46+
- An optional fourth step is to [make the layer public](#making-the-layer-public).
47+
- The final step is to [add the layer to a Lambda Function](#adding-the-layer-to-a-lambda-function).
48+
49+
This process has been partially automated in the provided [Makefile](./Makefile). In order to use this makefile you will need to install the [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html), [Golang](https://go.dev/doc/install) and [JQ](https://stedolan.github.io/jq/). You may observe how this Makefile is used by us in the Github action named "[build & publish](./.github/workflows/release.yaml)".
50+
51+
52+
53+
### Building The Extension Binary
54+
55+
The logging extension is a standard Go project and can be built by [installing Go](https://go.dev/doc/install) and using the [go build](https://pkg.go.dev/cmd/go#hdr-Compile_packages_and_dependencies) command from the root directory of this repository. You will need to set the `GOOS` and `GOARCH` environment variables appropriately for your target Lambda runtime's operating system and architecture. See the [Environment variables](https://pkg.go.dev/cmd/go#hdr-Environment_variables) section of the [go command docs](https://pkg.go.dev/cmd/go) for more information. An example may look like this:
56+
57+
```bash
58+
GOOS=linux GOARCH=amd64 go build
59+
```
60+
61+
This will yield a binary with the same name as the root directory, which if you have just cloned this repository will be `firetail-lambda-extension`.
62+
63+
The target in the provided makefile that corresponds to this step is `build`. It requires a target architecture (`ARCH`) which defaults to `amd64`. For example, you may wish to do:
64+
65+
```bash
66+
make build ARCH=arm64
67+
```
68+
69+
This will yield a `build` and `build/extensions` directory, and a binary within `build/extensions` named `firetail-extension-${ARCH}`.
70+
71+
72+
73+
### Packaging The Extension Binary
74+
75+
To package the extension binary, it must be placed into a directory named `extensions` and then zipped.
76+
77+
> During the `Init` phase, Lambda extracts layers containing extensions into the `/opt` directory in the execution environment. Lambda looks for extensions in the `/opt/extensions/` directory, interprets each file as an executable bootstrap for launching the extension, and starts all extensions in parallel.
78+
>
79+
> [Source](https://docs.aws.amazon.com/lambda/latest/dg/lambda-extensions.html)
80+
81+
The target in the provided makefile that corresponds to this step is `package`, and it depends upon the `build` step. It requries a target architecture (`ARCH`), and extension version (`VERSION`) which defaults to `latest`. For example, you may wish to do:
82+
83+
```bash
84+
make package ARCH=arm64 VERSION=v1.0.0
85+
```
86+
87+
This will yield a `.zip` file in the `build` directory named `firetail-extension-${ARCH}-${VERSION}.zip`, which contains the `extensions` directory and the binary within it such that when it is extracted into `/opt`, the extension binary will be found in the `/opt/extensions/` directory as per the AWS documentation.
88+
89+
90+
91+
### Publishing The Package
92+
93+
To publish the package, you may use the AWS CLI's [publish-layer-version](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/publish-layer-version.html) command. You will need to repeat this process for every region in which you wish to use the layer. You will also need to specify the compatible architectures, and give the layer a name. The output of the command will provide you with the layer's ARN and layer version, which you may use to add it to your Lambdas.
94+
95+
If you reuse the same layer name multiple times, the layer version will be incremented. The approach taken in the provided makefile is to publish each extension version with a new layer name, so the layer version will almost always be `1`.
96+
97+
The target in the provided makefile that corresponds to this step is `publish`. You must make the `build` target before the `publish` target. The `publish` target requires a target architecture (`ARCH`) and extension version (`VERSION`), which match that used when you made the `package` target; and a region in which to publish the layer (`AWS_REGION`). For example, you may wish to do:
98+
99+
```bash
100+
make publish ARCH=arm64 VERSION=v1.0.0 AWS_REGION=eu-west-1
101+
```
102+
103+
104+
105+
106+
### Making The Layer Public
107+
108+
ℹ️ In this step, we make the layer publically available for anyone to use. You may wish to omit this step.
109+
110+
To make the layer public, you may use the AWS CLI's [add-layer-version-permission](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/add-layer-version-permission.html) command. You will need to repeat this process for every layer you publish in every region. You will need to provide the layer name & layer version, a statement ID and region; and to make the layer public an action of `lambda:GetLayerVersion` and principal of `*`.
16111

17-
A [makefile](./makefile) is provided. To build the extension, package it into a layer and then publish that layer simply do:
112+
The target in the provided makefile corresponding to this step is `public`. You must make the `publish` target before the `public` target. The `public` target requires a target architecture (`ARCH`), extension version (`VERSION`) and AWS region (`AWS_REGION`) which match that used when you made the `publish` target, as well as the layer version created when you made the `publish` target (`AWS_LAYER_VERSION`). For example, you may wish to do:
18113

19114
```bash
20-
make publish REGION=your-region
115+
make public ARCH=arm64 VERSION=v1.0.0 AWS_REGION=eu-west-1 AWS_LAYER_VERSION=1
21116
```
22117

23-
The command above will output the ARN of your layer.
24118

25-
You can then use the layer's ARN to add it to a function as follows:
119+
120+
### Adding The Layer To A Lambda Function
121+
122+
There are a number of ways to add the published layer to your Lambda Function:
123+
124+
1. [Using the AWS CLI](#using-the-aws-cli).
125+
2. [Using An AWS Lambda Docker Build](#using-an-aws-lambda-docker-build).
126+
3. [Using Terraform](#using-terraform).
127+
128+
You will need to ascertain the layer ARN of the Lambda Layer containing the Firetail Lambda Extension that you wish to use. If you are not publishing your own Firetail Extension Lambda Layer, you may use the Lambda Layer published publicly by Firetail.
129+
130+
The latest extension version of the publically accessible Lambda Layer published by Firetail can be derived by taking the latest version tag in the [Github Releases](https://github.com/FireTail-io/firetail-lambda-extension/releases) of this repository, and replacing the `.` characters with `-` characters. For example, `v1.2.3` would become `v1-2-3`. You will also need to determine the architecture you need for your Lambda Runtime, which may be either `arm64` or `x86_64`. Once you have these two values, you may substitute them into `${VERSION}` and `${ARCH}` respectively in the following string:
26131

27132
```bash
28-
make add REGION=your-region LAYER_ARN=your:extension:arn FUNCTION_NAME=your-function-name
29-
```
133+
arn:aws:lambda:us-east-1:453671210445:layer:firetail-extension-${ARCH}-${VERSION}:1
134+
```
135+
136+
For example, for `ARCH=arm64` and `VERSION=v1-0-0` this should yield:
137+
138+
```
139+
arn:aws:lambda:us-east-1:453671210445:layer:firetail-extension-arm64-v1-0-0:1
140+
```
141+
142+
143+
144+
#### Using The AWS CLI
145+
146+
To add the Lambda Layer to a Function, you may use the AWS CLI's [update-function-configuration](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-configuration.html) command. You will need to provide a region, the layer ARN and the name of the Function to which the layer is to be added.
147+
148+
The target in the provided makefile corresponding to this step is `add`. The `add` target requires the layer ARN (`LAYER_ARN`), the name of the Function to add the layer to (`FUNCTION_NAME`), and the AWS region in which both the layer and the Function must be found (`AWS_REGION`). For example, you may wish to do:
149+
150+
```bash
151+
make add AWS_REGION=eu-west-1 LAYER_ARN=your-layer-arn FUNCTION_NAME=your-function-name
152+
```
153+
154+
155+
156+
#### Using An AWS Lambda Docker Build
157+
158+
If your lambda is using a container image, you can add the layer to the image from within your Dockerfile. Relevant documentation can be found in [this AWS Compute Blog post](https://aws.amazon.com/blogs/compute/working-with-lambda-layers-and-extensions-in-container-images/).
159+
160+
Find below a docker stage which you may add to your dockerfile to implement the process of downloading and unzipping the Lambda Layer package. This snippet adds as arguments the ARN of the layer to fetch, the region from which to fetch the layer, and the AWS access key & secret access key to use when fetching the layer:
161+
162+
```dockerfile
163+
FROM alpine:latest as firetail-layer-copy
164+
165+
ARG AWS_LAYER_ARN=${AWS_LAYER_ARN:-""}
166+
ENV AWS_LAYER_ARN=${AWS_LAYER_ARN}
167+
ARG AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION:-"us-east-1"}
168+
ENV AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION}
169+
ARG AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID:-""}
170+
ENV AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
171+
ARG AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY:-""}
172+
ENV AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
173+
174+
RUN apk add aws-cli curl unzip
175+
RUN mkdir -p /opt
176+
RUN curl $(aws lambda get-layer-version-by-arn --region ${AWS_DEFAULT_REGION} --arn ${AWS_LAYER_ARN} --query 'Content.Location' --output text) --output layer.zip
177+
RUN unzip layer.zip -d /opt
178+
RUN rm layer.zip
179+
```
180+
You will then need to add the following step into the final stage in your Dockerfile to copy the extension from the `firetail-layer-copy` stage into the `/opt/extensions` directory in your final container image:
181+
182+
```dockerfile
183+
COPY --from=firetail-layer-copy /opt /opt
184+
```
185+
186+
Once these steps are complete you should be able to run your build process as before, except with the addition of the `AWS_DEFAULT_REGION`, `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` and `AWS_LAYER_ARN` build arguments.
187+
188+
⚠️ Ensure you securely use, and store these minimal access credentials ⚠️
189+
190+
```bash
191+
docker build . -t layer-image1:latest \
192+
--build-arg AWS_DEFAULT_REGION=us-east-1 \
193+
--build-arg AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE \
194+
--build-arg AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY \
195+
--build-arg AWS_LAYER_ARN=arn:aws:lambda:us-east-1:453671210445:layer:firetail-extension-x86_64-v1-0-0:1
196+
```
197+
198+
199+
200+
#### Using Terraform
201+
202+
Find below an example Terraform configuration that adds the Firetail extension to a Lambda Function as a layer:
203+
204+
```terraform
205+
resource "aws_lambda_function" "extensions-demo-example-lambda-python" {
206+
function_name = "LambdaFunctionUsingFireTailExtension"
207+
s3_bucket = "lambda-function-s3-bucket-name"
208+
s3_key = "lambda-functions-are-great.zip"
209+
handler = "handler.func"
210+
runtime = "python3.8"
211+
role = aws_iam_role.lambda_role.arn
212+
213+
environment {
214+
variables = {
215+
FIRETAIL_API_TOKEN = "firetail-api-key",
216+
FIRETAIL_API_URL = "https://api.logging.eu-west-1.sandbox.firetail.app/logs/bulk"
217+
}
218+
}
219+
220+
layers = [
221+
"arn:aws:lambda:<AWS_REGION>:453671210445:layer:firetail-extension-<ARCH>-<VERSION>:1"
222+
]
223+
}
224+
```

0 commit comments

Comments
 (0)