Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite lambda-promtail to use subscription filters. #4315

Merged
merged 9 commits into from
Sep 28, 2021
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ require (
github.com/NYTimes/gziphandler v1.1.1
github.com/Workiva/go-datastructures v1.0.53
github.com/alicebob/miniredis/v2 v2.14.3
github.com/aws/aws-lambda-go v1.17.0
github.com/aws/aws-sdk-go v1.38.68
github.com/bmatcuk/doublestar v1.2.2
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b
Expand Down
3 changes: 0 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,6 @@ github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:o
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef h1:46PFijGLmAjMPwCCCo7Jf0W6f9slllCkkv7vyc1yOSg=
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
github.com/aws/aws-lambda-go v1.17.0 h1:Ogihmi8BnpmCNktKAGpNwSiILNNING1MiosnKUfU8m0=
github.com/aws/aws-lambda-go v1.17.0/go.mod h1:FEwgPLE6+8wcGBTe5cJN3JWurd1Ztm9zN4jsXsjzKKw=
github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
github.com/aws/aws-sdk-go v1.15.24/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
github.com/aws/aws-sdk-go v1.15.78/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM=
Expand Down Expand Up @@ -1992,7 +1990,6 @@ github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
github.com/vishvananda/netlink v0.0.0-20171020171820-b2de5d10e38e/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
Expand Down
23 changes: 23 additions & 0 deletions tools/lambda-promtail/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
FROM golang:1-alpine3.12 AS build-image

WORKDIR /app

RUN go version

RUN apk update && apk upgrade && \
apk add --no-cache bash git

COPY go.mod go.sum ./
RUN go mod download

COPY lambda-promtail/main.go main.go
RUN go build -tags lambda.norpc -ldflags="-s -w" main.go


FROM alpine:3.12

WORKDIR /app

COPY --from=build-image /app/main ./

ENTRYPOINT ["/app/main"]
19 changes: 7 additions & 12 deletions tools/lambda-promtail/Makefile
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
UNAME_S := $(shell uname -s)
LOCAL_PORT ?= 8080
ifeq ($(UNAME_S),Linux)
LOCAL_ENDPOINT=http://localhost:$(LOCAL_PORT)/loki/api/v1/push
else
LOCAL_ENDPOINT=http://host.docker.internal:$(LOCAL_PORT)/loki/api/v1/push
endif

.PHONY: build
all: build docker

build:
sam build
GOOS=linux CGO_ENABLED=0 go build lambda-promtail/main.go

docker:
docker build --pull .

dry-run:
echo $$(sam local generate-event cloudwatch logs) | sam local invoke LambdaPromtailFunction -e - --parameter-overrides PromtailAddress=$(LOCAL_ENDPOINT)
clean:
rm main
88 changes: 42 additions & 46 deletions tools/lambda-promtail/README.md
Original file line number Diff line number Diff line change
@@ -1,90 +1,86 @@
# lambda-promtail

This is a sample template for lambda-promtail - Below is a brief explanation of what we have generated for you:
This is a sample deployment for lambda-promtail - Below is a brief explanation of what we have generated for you:

```bash
.
├── Makefile <-- Make to automate build
├── Dockerfile <-- Uses the AWS Lambda Go base image
├── README.md <-- This instructions file
├── lambda-promtail <-- Source code for a lambda function
│ └── main.go <-- Lambda function code
└── template.yaml
```

## Requirements

* AWS CLI already configured with Administrator permission
* [Terraform](https://www.terraform.io/downloads.html)

If you want to modify the lambda-promtail code you will also need:
* [Docker installed](https://www.docker.com/community-edition)
* [Golang](https://golang.org)
* SAM CLI - [Install the SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html)

## Setup process

### Installing dependencies & building the target
### Building and Packaging

In this example we use the built-in `sam build` to automatically download all the dependencies and package our build target.
Read more about [SAM Build here](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-build.html)
The provided Makefile has targets `build`, `docker`, `all`, and `clean`.

The `sam build` command is wrapped inside of the `Makefile`. To execute this simply run

```shell
make
```
`build`, `docker`, and `all` build the lambda-promtail as a Go static binary and use the AWS Lambda Go runtime base image to generate an image that you
can upload to your AWS ECR and use via Lambda. `clean` will remove the built Go binary.

### Local development
### Packaging and deployment

**Invoking function locally
The easiest way to deploy to AWS Lambda using the Golang runtime is to use the `lambda-promtail` image by uploading it to your ECR.

Alternatively you can build the Go binary and upload it to Lambda as a zip:
```bash
make dry-run
GOOS=linux CGO_ENABLED=0 go build main.go
zip function.zip main
```

## Packaging and deployment

AWS Lambda Golang runtime requires a flat folder with the executable generated on build step. SAM will use `CodeUri` property to know where to look up for the application:
To deploy your application for the first time, first make sure you've set the following value in the Terraform file:
- `WRITE_ADDRESS`

```bash
make build
```
This is the [Loki Write API](https://grafana.com/docs/loki/latest/api/#post-lokiapiv1push) compatible endpoint that you want to write logs to, either promtail or Loki.

To deploy your application for the first time, first make sure you've set the following parameters in the template:
- `LogGroup`
- `PromtailAddress`
- `ReservedConcurrency`
The `lambda-promtail` code picks this value up via an environment variable.

These can also be set via overrides by passing the following argument to `sam deploy`:
```
--parameter-overrides Optional. A string that contains AWS
CloudFormation parameter overrides encoded
as key=value pairs.For example, 'ParameterKe
y=KeyPairName,ParameterValue=MyKey Parameter
Key=InstanceType,ParameterValue=t1.micro' or
KeyPairName=MyKey InstanceType=t1.micro
```
Also, if your deployment requires a [VPC configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function#vpc_config), make sure to edit the `vpc_config` field in `main.tf` manually. Additonal documentation for the Lambda specific Terraform configuration is [here](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function#vpc_config).

Also, if your deployment requires a VPC configuration, make sure to edit the `VpcConfig` field in the `template.yaml` manually.

Then run the following in your shell:
Then use Terraform to deploy:

```bash
sam deploy --guided --capabilities CAPABILITY_IAM,CAPABILITY_NAMED_IAM --parameter-overrides PromtailAddress=<>,LogGroup=<>
terraform apply -var "<ecr-repo>:<tag>" -var "write_address=https://your-loki-url/loki/api/v1/push" -var "password=<basic-auth-pw>" -var "username=<basic-auth-username>" -var 'log_group_names=["log-group-01", "log-group-02"]'
```

The command will package and deploy your application to AWS, with a series of prompts:
or CloudFormation:

* **Stack Name**: The name of the stack to deploy to CloudFormation. This should be unique to your account and region, and a good starting point would be something matching your project name.
* **AWS Region**: The AWS region you want to deploy your app to.
* **Confirm changes before deploy**: If set to yes, any change sets will be shown to you before execution for manual review. If set to no, the AWS SAM CLI will automatically deploy application changes.
* **Allow SAM CLI IAM role creation**: Many AWS SAM templates, including this example, create AWS IAM roles required for the AWS Lambda function(s) included to access AWS services. By default, these are scoped down to minimum required permissions. To deploy an AWS CloudFormation stack which creates or modified IAM roles, the `CAPABILITY_IAM` value for `capabilities` must be provided. If permission isn't provided through this prompt, to deploy this example you must explicitly pass `--capabilities CAPABILITY_IAM` to the `sam deploy` command.
* **Save arguments to samconfig.toml**: If set to yes, your choices will be saved to a configuration file inside the project, so that in the future you can just re-run `sam deploy` without parameters to deploy changes to your application.
```bash
aws cloudformation create-stack --stack-name lambda-promtail-stack --template-body file://template.yaml --capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM --region us-east-2 --parameters ParameterKey=WriteAddress,ParameterValue=https://your-loki-url/loki/api/v1/push ParameterKey=Username,ParameterValue=<basic-auth-username> ParameterKey=Password,ParameterValue=<basic-auth-pw> ParameterKey=LambdaPromtailImage,ParameterValue=<ecr-repo>:<tag>
```

# Appendix

### Golang installation
## Golang installation

Please ensure Go 1.x (where 'x' is the latest version) is installed as per the instructions on the official golang website: https://golang.org/doc/install

A quickstart way would be to use Homebrew, chocolatey or your linux package manager.
For example:

```bash
GO_VERSION=go1.16.6.linux-amd64.tar.gz

rm -rf /usr/local/bin/go*
rm -rf /usr/local/go
curl -O https://storage.googleapis.com/golang/$GO_VERSION
tar -zxvf $GO_VERSION
sudo mv go /usr/local/
rm $GO_VERSION
ln -s /usr/local/go/bin/* /usr/local/bin/
```

A quickstart way would be to use Homebrew, chocolatey or your Linux package manager.

#### Homebrew (Mac)

Expand Down Expand Up @@ -117,4 +113,4 @@ choco upgrade golang

## Limitations
- Error handling: If promtail is unresponsive, `lambda-promtail` will drop logs after `retry_count`, which defaults to 2.
- AWS does not support passing log lines over 256kb to lambdas.
- AWS CloudWatch [quotas](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/cloudwatch_limits_cwl.html) state that the event size is limited to 256kb. `256 KB (maximum). This quota can't be changed.`
14 changes: 14 additions & 0 deletions tools/lambda-promtail/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module main

go 1.16

require (
github.com/aws/aws-lambda-go v1.26.0
github.com/cortexproject/cortex v1.10.0
github.com/gogo/protobuf v1.3.2
github.com/golang/snappy v0.0.4
github.com/grafana/loki v1.6.1
github.com/prometheus/common v0.30.0
)

replace k8s.io/client-go => k8s.io/client-go v0.21.0
Loading