GNU/Linux >> Tutoriales Linux >  >> Panels >> Docker

Terraform:implemente Python Lambda (imagen del contenedor)

A fines de 2020, AWS anunció la compatibilidad con imágenes de contenedores para Lambda. Esta característica le permite empaquetar e implementar funciones de Lambda como imágenes de contenedor de hasta 10 GB de tamaño. Este artículo cubrirá cómo puede usar Terraform para implementar funciones de Python Lambda respaldadas por la imagen del contenedor. En este artículo, cubrimos cómo puede usar Terraform para implementar funciones Python Lambda respaldadas por la imagen del contenedor.

Una de las tareas comunes en el mundo de la nube es replicar repositorios de código fuente desde las instalaciones a la nube o entre entornos de nube. Entonces, para ilustrar el enfoque, decidimos agregar compatibilidad con Git y GitPython a la función Lambda.

Estructura del proyecto

Aquí hay una estructura de proyecto que usaremos durante esta demostración:

$ tree lambda_container
lambda_container
├── README.md
├── lambdas
│   └── git_client
│       ├── Dockerfile
│       └── index.py
└── main.tf

2 directories, 4 files
  • lambdas – la carpeta donde ponemos el código fuente de las funciones de Lambda
  • main.tf – Código de demostración de Terraform, que construirá el contenedor Docker para la función git_client Lambda y luego implementará la función

Dockerfile

Describamos un contenedor Docker que alojará todas las dependencias para nuestras funciones lambda. Aquí está el Dockerfile contenido:

FROM public.ecr.aws/lambda/python:3.8

RUN yum update -y && \
  yum install -y git && \
  rm -Rf /var/cache/yum && \
  pip install git-remote-codecommit boto3 GitPython awscli

COPY index.py ${LAMBDA_TASK_ROOT}

CMD [ "index.handler" ]

Estamos tomando la imagen Docker pública de Python 3.8 de Amazon como base. Luego, instalamos Git, limpiamos los cachés de yum para hacer que el contenedor sea más pequeño e instalamos las dependencias requeridas, lo que nos permite usar Git con CodeCommit mediante IAM para la autenticación.

A continuación, estamos copiando el index.py archivo a la carpeta donde debe residir el código de la función Lambda. Consulte Uso de variables de entorno de AWS Lambda para obtener información adicional.

Finalmente, estamos especificando ejecutar el método del controlador desde el archivo index.py en el lanzamiento del contenedor.

Código Lambda

Tan pronto como finalice la declaración del contenedor Lambda, podemos escribir una función Lambda, que la usará. Aquí hay un ejemplo de código, que mostrará cómo clonar el repositorio de Git. Estoy seguro de que podrá ajustar este ejemplo a sus necesidades personales:

import logging
import os
import git
 
TMP_DIR = "/tmp"
REPO_DIR = 'aws-config-rules'
REPO_URL = f'https://github.com/andreivmaksimov/{REPO_DIR}'
CLONE_PATH = os.path.join(TMP_DIR, REPO_DIR)
 
LOGGER = logging.getLogger(__name__)
LOGGER.setLevel(logging.INFO)
 
def clone(branch='master'):
   repo = git.Repo.clone_from(REPO_URL, CLONE_PATH, branch=branch)
 
   with repo.config_writer() as git_config:
       git_config.set_value('user', 'email', '[email protected]')
       git_config.set_value('user', 'name', 'Git Lambda')
  
def handler(event, context):
   LOGGER.info('Event: %s', event)
 
   LOGGER.info('Cloning repo: %s', REPO_URL)
   clone()

En este código, declaramos las bibliotecas de Python necesarias, algunas constantes, la configuración del registrador y un par de funciones:

  • def clone(branch='master') – esta función muestra cómo clonar el repositorio de Git
  • def handler(event, context) – esta función es el punto de entrada principal a la función Lambda, registra el evento entrante y llama a clone función

Código de Terraform

Tan pronto como tengamos el código Lambda y declaremos su contenedor, podemos escribir código Terraform para automatizar la implementación. Aquí está:

variable region {
 default = "us-east-1"
}
 
provider aws {
 region = var.region
}
 
data aws_caller_identity current {}
 
locals {
 prefix = "git"
 account_id          = data.aws_caller_identity.current.account_id
 ecr_repository_name = "${local.prefix}-demo-lambda-container"
 ecr_image_tag       = "latest"
}
 
resource aws_ecr_repository repo {
 name = local.ecr_repository_name
}
 
resource null_resource ecr_image {
 triggers = {
   python_file = md5(file("${path.module}/lambdas/git_client/index.py"))
   docker_file = md5(file("${path.module}/lambdas/git_client/Dockerfile"))
 }
 
 provisioner "local-exec" {
   command = <<EOF
           aws ecr get-login-password --region ${var.region} | docker login --username AWS --password-stdin ${local.account_id}.dkr.ecr.${var.region}.amazonaws.com
           cd ${path.module}/lambdas/git_client
           docker build -t ${aws_ecr_repository.repo.repository_url}:${local.ecr_image_tag} .
           docker push ${aws_ecr_repository.repo.repository_url}:${local.ecr_image_tag}
       EOF
 }
}
 
data aws_ecr_image lambda_image {
 depends_on = [
   null_resource.ecr_image
 ]
 repository_name = local.ecr_repository_name
 image_tag       = local.ecr_image_tag
}
 
resource aws_iam_role lambda {
 name = "${local.prefix}-lambda-role"
 assume_role_policy = <<EOF
{
   "Version": "2012-10-17",
   "Statement": [
       {
           "Action": "sts:AssumeRole",
           "Principal": {
               "Service": "lambda.amazonaws.com"
           },
           "Effect": "Allow"
       }
   ]
}
 EOF
}
 
data aws_iam_policy_document lambda {
   statement {
     actions = [
         "logs:CreateLogGroup",
         "logs:CreateLogStream",
         "logs:PutLogEvents"
     ]
     effect = "Allow"
     resources = [ "*" ]
     sid = "CreateCloudWatchLogs"
   }
 
   statement {
     actions = [
         "codecommit:GitPull",
         "codecommit:GitPush",
         "codecommit:GitBranch",
         "codecommit:ListBranches",
         "codecommit:CreateCommit",
         "codecommit:GetCommit",
         "codecommit:GetCommitHistory",
         "codecommit:GetDifferences",
         "codecommit:GetReferences",
         "codecommit:BatchGetCommits",
         "codecommit:GetTree",
         "codecommit:GetObjectIdentifier",
         "codecommit:GetMergeCommit"
     ]
     effect = "Allow"
     resources = [ "*" ]
     sid = "CodeCommit"
   }
}
 
resource aws_iam_policy lambda {
   name = "${local.prefix}-lambda-policy"
   path = "/"
   policy = data.aws_iam_policy_document.lambda.json
}
 
resource aws_lambda_function git {
 depends_on = [
   null_resource.ecr_image
 ]
 function_name = "${local.prefix}-lambda"
 role = aws_iam_role.lambda.arn
 timeout = 300
 image_uri = "${aws_ecr_repository.repo.repository_url}@${data.aws_ecr_image.lambda_image.id}"
 package_type = "Image"
}
 
output "lambda_name" {
 value = aws_lambda_function.git.id
}

Este código de Terraform se probó con la versión 0.14.8 de Terraform.

En este ejemplo, estamos utilizando los siguientes recursos de terraformación:

  • aws_ecr_repository – crea un registro ECR donde Terraform guardará la imagen del contenedor Docker, que luego será utilizada por la función Lambda
  • null_resource – se utiliza para crear el contenedor Docker y enviarlo al registro ECR, activa los cambios en el código de la función Lambda y Dockerfile y permite que Terraform comprenda cuándo reconstruir la imagen y actualizar la función Lambda
  • aws_ecr_image – nos permite consultar información sobre la imagen de Docker publicada
  • aws_iam_role , aws_iam_policy_document y aws_iam_policy – declara permisos (enviar registros a CloudWatch, acceso CodeCommit) para la función Lambda
  • aws_lambda_function – Declaración de la función Lambda en sí

Implementación

Para probar la solución, primero debe implementar el código de Terraform:

terraform init
terraform apply -auto-approve

Luego debe ejecutar la función Lambda:

aws lambda invoke --function-name git-lambda out --log-type Tail --query 'LogResult' --output text |  base64 -d

Aquí hay un resultado esperado:

START RequestId: b8b742d6-5bd6-4098-90e3-5e30f5c6e816 Version: $LATEST
[INFO]  2021-03-16T02:10:28.064Z        b8b742d6-5bd6-4098-90e3-5e30f5c6e816    Event: {}
[INFO]  2021-03-16T02:10:28.064Z        b8b742d6-5bd6-4098-90e3-5e30f5c6e816    Cloning repo: https://github.com/andreivmaksimov/aws-config-rules
END RequestId: b8b742d6-5bd6-4098-90e3-5e30f5c6e816
REPORT RequestId: b8b742d6-5bd6-4098-90e3-5e30f5c6e816  Duration: 4069.15 ms    Billed Duration: 6131 ms        Memory Size: 128 MB     Max Memory Used: 83 MB  Init Duration: 2061.73 ms

Limpieza

Para limpiar todo, ejecute el siguiente comando:

terraform destroy

Resumen

Este artículo creó un contenedor Docker para la función AWS Lambda e implementó la solución completa mediante Terraform. Esperamos que este artículo le haya resultado útil. Si es así, por favor, ayúdanos a difundirlo por el mundo. Si tiene alguna pregunta, no dude en hacerla en la sección de chat a continuación.


Docker
  1. Cómo construir el contenedor Docker Anaconda Python Data Science

  2. ¿Extraer archivo de la imagen de Docker?

  3. Cómo implementar un contenedor nginx con Docker en Linode

  4. Cómo implementar PostgreSQL como un contenedor Docker

  5. Cómo crear una imagen de Docker a partir de un contenedor y un archivo Docker

Cómo crear una imagen de Docker desde un contenedor en ejecución

Implementar una instalación de MariaDB de Docker de producción

Cómo implementar un contenedor Docker en AWS Elastic Beanstalk

Cómo implementar una aplicación API de Python Flask en Docker

Cómo implementar y administrar un contenedor Docker MongoDB

Cómo usar Docker Commit para cambiar imágenes de contenedores