Running Elastalert on AWS Lambda (and optionally using dynamic values in rules at runtime) #1169
Replies: 1 comment
-
This is very interesting. Do you have any interest in submitting a PR with the changes to this project, in a way such that it doesn't conflict with the main usage format? Perhaps place the new python code into an elastalert.lambda directory, and add a startup parameter to tell it to use "lambda" mode. The new code would need unit test coverage, and the documentation would need updated. Looking at the Dockerfile, it looks like it might be possible to have a single ElastAlert 2 Docker image that can handle both run modes (original and lamba). Unless that base image you are using is a Lambda requirement. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
I wanted to share some code that we're using to run Elastalert2 in an AWS Lambda container function. The main benefits of this for us are that it gives us less server infrastructure to maintain, and we can include dynamic values in our rules at runtime (via a custom rules loader that loads rules from S3 and renders them using Jinja2 templating).
There are some existing issues and solutions out there for running on Lambda:
None of these work since Elastalert started using APScheduler's
BackgroundScheduler
, which returns immediately after starting. This causes the Lambda function to exit before any rules have a chance to run (also detailed in this comment on an issue about running Elastalert once and then exiting).I worked around this by extending the
ElastAlerter
class and overriding thestart
method. The new method schedules all jobs to run immediately, and only exits once all jobs have run (it uses an APScheduler listener function attached to the scheduler to determine when all jobs are complete).handle_pending_alerts
is then called manually (instead of being added as a job to the scheduler). Here's an incomplete example (just the class) from my Lambda function code.Also note that I overrode the
handle_error
method because I wanted to make the Lambda exit and report a failure if anything went wrong (with the exception of read timeouts from Elasticsearch, which I was seeing somewhat often with Amazon OpenSearch Service).This is a minimal example of a Lambda handler that uses this class. Because of some issues with ever-increasing memory usage between Lambda warm starts that I couldn't track down (I tried a lot of different combinations of
del
ing objects and manually callinggc.collect()
, with no luck), it runs Elastalert in a separate process using Python'smultiprocessing
module to ensure that memory is freed when it's done. This example creates an Elastalert config file as a Python dict and then dumps it to a YAML file at/tmp/config.yml
, but you could also just copy your config file into place with a step in the Dockerfile.We're deploying this as a container on Lambda, using the following
Dockerfile
andrequirements.txt
.If all you want to do is run Elastalert on Lambda, you could stop here (and maybe add a
COPY
step to the Dockerfile to copy your rule files). But we're also using the following custom rules loader to download rules from S3.If you save this as
custom_loaders.py
, you can copy it into the Lambda image by adding this to the Dockerfile:To use the S3 rule loader (and also enable Jinja templating) add the following lines to the Elastalert config defined in the Lambda code.
You could then write an Elastalert rule with a filter like this, which will query for
some_value
:This is the main reason we define the Elastalert config in Python, so that we can dynamically extend the Jinja context that is passed to the rules loader.
I hope this is helpful for anyone else looking to run Elastalert on Lambda!
Beta Was this translation helpful? Give feedback.
All reactions