Jérôme Decoster

Jérôme Decoster

3x AWS Certified - Architect, Developer, Cloud Practionner

02 Dec 2021

AWS Grafana + Lambda + Terraform

The Goal
  • Create an API Gateway and a Lambda function with Terraform
  • Setup a Managed Grafana workspace
  • Configure AWS Single Sign-On
  • Import and setup 2 Grafana dashboards
  • Use curl to test the dashboards

    architecture.svg

    Install and setup the project

    Get the code from this github repository :

    # download the code
    $ git clone \
        --depth 1 \
        https://github.com/jeromedecoster/managed-grafana-lambda.git \
        /tmp/aws
    
    # cd
    $ cd /tmp/aws
    

    To setup the project, run the following command :

    # terraform setup
    $ make setup
    

    This command will :

    We can validate HCL files with this command :

    # terraform validation
    $ make validate
    

    We are now deploying our application :

    # terraform plan + apply (deploy)
    $ make apply
    

    We can see that our Lambda function is ready :

    lambda.png

    A little test to see if it works. Everything is fine because some JSON data is returned :

    $ make curl-get 
    {
      "method": "GET",
      "path": "/"
    }
    

    Creation of the Grafana workspace

    We will create a Grafana workspace from the web interface

    My default region eu-west-3 Paris is not yet available, so I choose eu-west-2 London :

    managed-create-01.png

    I give the name of our project. But before validating with the Next button, I must activate AWS Single Sign-On :

    managed-create-02.png

    To be able to continue I must make sure that AWS Single Sign-On is enabled :

    In another tab of my browser I connect via the web interface :

    I make sure I am in the same eu-west-2 London region as my Grafana workspace :

    sso-activate-01.png

    I clicked on Enable, I wait a few seconds :

    sso-activate-02.png

    Activation completed successfully :

    sso-activate-03.png

    Without closing my SSO browser tab, I go back to the one open on Managed Grafana.

    I now validate the creation of my workspace by clicking Next :

    managed-create-02.png

    Everything works, I continue :

    managed-create-03.png

    I choose to collect my data via X-Ray and CloudWatch :

    managed-create-04.png

    I have a summary before launching the creation :

    managed-create-05.png

    Creation takes a few seconds :

    managed-create-06.png

    If I want to add a user to my workspace :

    managed-create-07.png

    I currently have no user available.

    I must first create and validate one from the AWS Single Sign-On interface :

    managed-user-01.png

    I now return to my SSO browser tab. I will create a user :

    sso-user-01.png

    I fill in the requested data :

    sso-user-02.png

    I ignore the group creation step :

    sso-user-03.png

    The user is created. A validation email has been sent :

    sso-user-04.png

    I click the link received in the validation email :

    sso-user-05.png

    I activate this user by setting a password :

    sso-user-06.png

    I am redirected to the application activation page :

    sso-user-07.png

    I can now select a user to associate it with my Grafana workspace :

    managed-user-02.png

    The user is associated as Viewer :

    managed-user-03.png

    I select the user to pass it as Admin :

    managed-user-04.png

    It is done :

    managed-user-05.png

    I can now open my workspace by clicking on its URL :

    managed-create-08.png

    Setup Grafana data source

    We will add the CloudWatch logs as data source :

    grafana-setup-data-01.png

    It’s extremely simple :

    grafana-setup-data-02.png

    Configuration of a CloudWatch dashboard

    We will add a first dashboard dedicated to CloudWatch logs :

    grafana-setup-1-03.png

    We select Manage :

    grafana-setup-1-01.png

    We click on the Import button :

    grafana-setup-1-02.png

    We set the dashboard id and click on the Load button :

    grafana-setup-1-04.png

    I rename the dashboard by adding its identifier.

    I select my data source :

    grafana-setup-1-05.png

    We can finish the import :

    grafana-setup-1-06.png

    Here are the log groups generated by our application :

    grafana-setup-1-07.png

    I copy and paste the path of the log group in the interface :

    grafana-setup-1-08.png

    I edit the Logs panel :

    grafana-setup-1-09.png

    I indicate the path of the log group :

    grafana-setup-1-10.png

    I modify the filter and I refresh the interface.

    The log generated by my previous call is now displayed :

    grafana-setup-1-11.png

    Coming back to the interface, I see the activity going up.

    The 4 events indicated correspond to 4 log lines.

    It is in fact 1 event but which breaks down into 4 lines : START, INFO, END and REPORT.

    grafana-setup-1-12.png

    We invoke the function by generating a voluntary error :

    # post /api/deplay 10 ~ 29 seconds
    $ make curl-error
    

    This command runs a script that will run the Lambda asking it to wait 25 seconds.

    Here is a snippet of asynchronous Lambda code with a setTimeout function :

    async function timeout(success, time) {
        return new Promise(function(resolve, reject) {
            setTimeout(function() {
                if (success === false) resolve(buildResponse(400, `error ${success} ${time}`))
                else resolve(buildResponse(200, `ok ${success} ${time}`))
            }, time)
        })
    }
    

    Our Lambda has the default timeout of 3 sec. Our invocation will therefore generate a timeout error :

    grafana-setup-1-13.png

    I can save my dashboard :

    grafana-setup-1-14.png

    I memorize some parameters :

    grafana-setup-1-15.png

    Configuration of a Lambda dashboard

    We will add a second dashboard dedicated to Lambda events :

    grafana-setup-2-00.png

    We indicate the dashboard id and click on the Load button :

    grafana-setup-2-01.png

    We can finish the import :

    grafana-setup-2-02.png

    I select the parameters to target my Lambda function :

    grafana-setup-2-03.png

    We now invoke the function with an immediate result :

    # get /
    $ make curl-get
    

    This is a success :

    grafana-setup-2-04.png

    We now invoke the function with a random result :

    • 50 % chance of being successful after 1 or 2 seconds
    • 50 % chance of being a failure via a timeout
    # post /api/deplay 1 ~ 4 seconds (lambda timeout after 3 seconds)
    $ make curl-rand-success
    

    As we can see below, our call lasted 3 seconds or more, the lambda timeout generated an error :

    grafana-setup-2-05.png

    The demonstration is over. We can delete our resources with this command :

    # destroy all resources
    $ make destroy