Prácticas recomendadas para AWS Lambda

prácticas recomendadas

Prácticas recomendadas para AWS Lambda

Prácticas recomendadas para seguir al trabajar con lambda. Una breve introducción al funcionamiento de lambda.


Componentes de la función lambda

 

Handler: punto de entrada de la función lambda

Event: JSON Payload recibido durante la invocación de la función lambda. Los servicios de AWS generan su propio JSON.

Context: Representación del tiempo de ejecución y entorno de ejecución. function_name , function_version , invoked_function_arn , memory_limit_in_mb , aws_request_id , log_group_name ,log_stream_name , identity , cognito_identity_id , cognito_identity_pool_id , client_context , client.installation_id , client.app_title , client.app_version_name , client.app_version_code , client.app_package_name , custom , dict

Ciclo de vida de la función Lambda

  • Descargar código/imagen (capa, extensión y función) al S3/ECR interno
  • Entorno de ejecución de inicio: procesos y recursos para la función
prácticas recomendadas
Entorno de ejecución: documento de AWS de origen
  • Inicialización

 

Extension Init: ejecuta en paralelo todos los programas de arranque en /opt/extensions/*

Runtime Init: Arranque de tiempo de ejecución específico del idioma (interno o personalizado)

Función init: código fuera del controlador como importaciones

 

  • Invocación
  • Shutdown

 

Apagado en tiempo de ejecución

Cierre de extensión

Prácticas recomendadas
Ciclo de vida del entorno: fuente AWS Doc

Prácticas recomendadas

  • Asigne un rol de IAM con solo una función lambda. Esto ayuda a reducir la escalada de privilegios.
  • Elimine todas las dependencias innecesarias que no son necesarias para ejecutar la función. Además, sea específico acerca de las importaciones. Bloquee la versión del paquete.
  • Reserve la concurrencia para la función crítica. Ayuda tanto con arranques en frío como con un rendimiento constante.
  • Reutilice las capas en todas las funciones. Ayuda a mantener una dependencia común centralizada.
  • Nunca confíe en el orden de invocación lambda, haga que su código sea idempotente. Trate a lambda como apátrida.
  • Evite el código recursivo en lambda. Esto ayudará en caso de casos base incorrectos que mantengan el tiempo de espera de lambda.
  • Utilice el registrador y evite las declaraciones impresas. Además, establezca un nivel de registro específico para el entorno.
  • Lambda es altamente escalable, pero sus conexiones de base de datos no lo son. Utilice la agrupación de conexiones con RDS Proxy. Además, inicialice las conexiones de la base de datos en el contexto global y, si es posible, reinícielas. Además, verifique la existencia de una conexión antes de usarla.
  • Separe el controlador lambda de la lógica central. El controlador Lambda debe ser lo más delgado posible y solo debe iniciar la lógica comercial. La función lógica central debe ser independiente de lambda. Esto ayuda a probar la función lambda sin el entorno lambda.
class BusinessLogicClass: 
def process_event(self, event):
pass
def handler(event, context):
return BusinessLogicClass().process_event(event)
  • Agrupe las unidades lógicas en su propia clase, esto también ayuda en las pruebas. Por ejemplo, una clase para crear clientes de AWS. Empuje las dependencias externas a la clase. Crear métodos con una única responsabilidad. Esto ayuda en las pruebas.
from rdklib import Evaluator, Evaluation, ConfigRule, ComplianceType
class AMI_DEPRECATED_CHECK(ConfigRule):
def evaluate_parameters(self, rule_parameters):
pass
def evaluate_periodic(self, client_factory): 
ec2_client = client_factory.build_client("ec2")
def evaluate_asgs(self, ec2_client, asg_client):
pass
def evaluate_ami(self, ec2_client, ami_id):
pass
  • Inicialice la dependencia externa en el constructor: las dependencias suelen ser costosas de crear. Compartirlos en el código permite reutilizarlos, y los constructores son una buena ubicación para guardarlos. Use funciones más pequeñas para hablar con servicios externos.
class ClientFactory: 
__sts_credentials = None
__role_arn = None
__region = None

def __init__(self, role_arn, sts_credentials region=None): 
self.__role_arn = role_arn
__sts_credentials = get_assume_role_credentials(role_arn)
  • Evite las funciones de ejecución prolongada. Refactorice funciones grandes en conjuntos de funciones más pequeños que funcionen juntos. Use la función de paso para su orquestación si se vuelve compleja.
  • Inicialice los clientes del SDK y las conexiones de la base de datos fuera del controlador de funciones y almacene en caché los activos estáticos localmente en el directorio /tmp. Al usar /tmp, asegúrese de que solo se escriba información estática y no confidencial.
  • Utilice variables de entorno para pasar parámetros operativos a su función.
  • Utilice el paginador para las API de AWS siempre que sea posible.
  • Use el enfoque de decorador para código reutilizable.
@log_cloudwatch
@notify_sns
  • Fracase duro y rápido. No detecte todas las excepciones, solo las que se conocen. Deje que la función falle y luego maneje.
  • Utilice errores personalizados para errores específicos del flujo empresarial. Esto ayuda en la depuración en caso de que varias lambdas trabajen juntas. Además, esto ayuda en la búsqueda de registros.
  • Mida el tiempo de su código. Compruebe siempre cuánto tarda la función. Esto ayudará a seleccionar los tiempos de espera correctos para lambda en su conjunto.

Pruebe su función Lambda

Agregue casos de prueba de unidad para sus funciones lambda.

Pruebe una cosa a la vez.

Ordene los casos de prueba por relevancia. No todos los casos de prueba tendrán la misma importancia.

Simule la dependencia externa, si se utilizan los servicios de AWS, se puede aprovechar localstack para simularlos.

Mantenga siempre el evento de muestra actual, para realizar pruebas.

Configurar linters

 

flake8
yamllint
cfn-lint

 

Recent Post