Last update: 2019-12-09

Deploying an AWS Lambda function using Ansible


Recently I wrote a post on how to create a Lambda function to check the health of your ELB targets. Today, we'll see how to deploy this same function automatically using Ansible, instead of going in the AWS console and doing it manually. While a single function is not that big of a deal to do manually, the goal of DevOps is to automate everything, because once you have a dozen functions or more, the last thing you want is to manage all that code manually. With a deployment system like Ansible, you can make sure all your code is in one centralized location and gets deployed all at the same time.

Creating support files

The first thing to do is make sure you have Ansible installed along with the AWS libraries:

<bash>
yum install ansible
pip install boto botocore boto3

Then, let's create a folder for your playbook, and save the Lambda function from my previous post under templates/elb_check.py in that folder. Then, let's create two policy documents:

templates/trust_policy.json:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "events.amazonaws.com",
          "lambda.amazonaws.com"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

templates/lambda_policy.json

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "LambdaPolicy01",
            "Effect": "Allow",
            "Action": [
                "elasticloadbalancing:DescribeTargetGroups",
                "ec2:DescribeRegions",
                "SNS:Publish",
                "logs:*"
            ],
            "Resource": "*"
        }
    ]
}

Basically, these policies will be used to create the necessary role for your Lambda function to run and access the relevant AWS resources it needs.

Creating our playbook

The playbook is a YAML file which will describe each step that has to be done in order to deploy our solution. Let's create it in the main folder for our project and name it deploy_lambda.yml. At the top we will start by specifying localhost as our target:

- hosts: localhost
  gather_facts: false
  connection: local
  user: admin
  tasks:

The first task will be creating the necessary roles. This will use our policy documents in order to specify what permissions the Lambda function will have:

  - name: Creating lambda_role
    iam_role:
      name: "lambda_role"
      assume_role_policy_document: "{{ lookup('template', 'trust_policy.json', convert_data=False) }}"
      state: present
    register: lambda_role
  - name: Sleeping for 10 sec for the role to be available
    pause: seconds=10
    when: lambda_role.changed
  - name: Assign IAM policy to role
    iam_policy:
      iam_type: role
      iam_name: "lambda_role"
      policy_name: "lambda_iam_role_policy"
      state: present
      policy_json: "{{ lookup('template', 'lambda_policy.json', convert_data=False) }}"

Next, we'll package the function file and upload it to AWS Lambda, along with information on which runtime to use:

  - name: Creating ZIP file for elb_check function
    shell: "zip -j /tmp/elb_check.zip ./templates/elb_check.py"
  - name: Creating function elb_check
    lambda:
      region: "us-west-2"
      state: present
      description: "Check ELB resources for health problems"
      name: "elb_check"
      zip_file: "/tmp/elb_check.zip"
      runtime: python3.7
      role: "{{ lambda_role.arn }}"
      handler: "elb_check.main"
      timeout: 360
    register: lambda_function

Finally, we will create a Cloudwatch event to run our function every 5 minutes:

  - name: Creating event rule elb_check_event
    cloudwatchevent_rule:
      name: "elb_check_event"
      schedule_expression: "rate(5 minutes)"
      description: "Run the elb_lambda function every 5 minutes"
      role_arn: "{{ lambda_role.arn }}"
      region: "us-west-2"
      targets:
        - id: "elb_check"
          arn: "{{ lambda_function.configuration.function_arn }}"

Running the playbook

By now, you should have your playbook in the current folder, along with a sub-folder called templates with 2 policy files and your Python function. Now it's time to run the playbook:

<bash>
ansible-playbook -v deploy_lambda.yml

If everything went fine, you should see a number of success messages for each of the steps defined. You can then check your AWS console to see the function by going to the Lambda section:

You can test it manually by clicking on it and using the Test button.

To see the output of the function, you can check the Cloudwatch event logs. You should see a new log group being created after the function has run at least once:

That's all there is to it. Remember to remove the Cloudwatch event rule and the function once you're done if you aren't going to be keeping them, or it will incur some costs for your Amazon account.


Looking to expand into the cloud? See what a certified AWS administrator can do for you.


 
© 2007-2020 Patrick Lambert - All resources on this site are provided under the MIT License - You can contact me at: contact@dendory.net