Controlá automáticamente la retención de los grupos de logs de CloudWatch con una función Lambda
De forma predeterminada, la mayoría de los servicios de AWS que escriben logs en Amazon CloudWatch —AWS Lambda, Amazon ECS, Amazon API Gateway, AWS CodeBuild, entre muchos otros— crean sus grupos de logs con una configuración de retención de Nunca caduca. Con el tiempo, esto significa que tu cuenta acumula cientos o miles de grupos de logs llenos de datos que ya nadie consulta, mientras AWS continúa cobrándote por almacenar toda esa información.
En este Teratip, te mostramos cómo resolverlo con una pequeña solución serverless: una función Lambda que establece una política de retención para cada grupo de logs de CloudWatch de tu cuenta.
La solución se activa de dos maneras: de forma reactiva, en el momento en que se crea un nuevo grupo de logs, y de forma periódica, para detectar aquellos que no se configuraron correctamente o que ya existían antes de implementar esta solución. Ambos disparadores se implementan mediante Amazon EventBridge.
¡Empecemos!
Paso 1: Crear la política de permisos de IAM
Antes de crear la función Lambda, vamos a crear la política personalizada de IAM que necesitará, además de los permisos básicos de ejecución.
Abrí el servicio IAM en la consola de AWS.
En Administración de acceso, ingresá a Políticas y hacé clic en Crear política.
Seleccioná la pestaña JSON y pegá la siguiente política:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:DescribeLogGroups",
"logs:PutRetentionPolicy"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}La primera declaración es la que permite a la función listar todos los grupos de logs de la cuenta y modificar su período de retención. La segunda declaración le permite escribir sus propios logs de ejecución.
Hacé clic en Siguiente, asignale a la política el nombre set-cw-log-group-retention-lambda-policy, agregá una descripción opcional y hacé clic en Crear política.
Paso 2: Crear el rol de IAM para la función Lambda
En IAM, ingresá a Roles y hacé clic en Crear rol.
En Tipo de entidad de confianza, seleccioná Servicio de AWS y, en Caso de uso, elegí Lambda. Hacé clic en Siguiente.
Adjuntá dos políticas: la política administrada por AWS AWSLambdaBasicExecutionRole (incluye el permiso logs:CreateLogGroup para el propio grupo de logs de la función) y la política set-cw-log-group-retention-lambda-policy que acabás de crear. Hacé clic en Siguiente.
Asignale al rol el nombre set-cw-log-group-retention-role y hacé clic en Crear rol.
La política de confianza que AWS genera para este rol se ve así:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}

Paso 3: Crear la función Lambda
Abrí el servicio Lambda y hacé clic en Crear función.
Seleccioná Crear desde cero.
Establecé el nombre de la función como set-cw-log-group-retention.
Elegí Python 3.14 como runtime.
En Permisos, desplegá Cambiar rol de ejecución predeterminado, seleccioná Usar un rol existente y elegí set-cw-log-group-retention-role.
Hacé clic en Crear función.

Una vez creada la función, reemplazá el contenido de lambda_function.py en el editor de código integrado por el siguiente código y, luego, hacé clic en Implementar:
import boto3
import os
logs = boto3.client('logs')
RETENTION_DAYS = int(os.environ.get("RETENTION_DAYS", "30")) # 30 is the default value
def lambda_handler(event, context):
# Reactive execution (a log group was just created)
if "detail" in event and "requestParameters" in event["detail"]:
log_group = event["detail"]["requestParameters"]["logGroupName"]
set_retention(log_group)
return {"status": "updated", "logGroup": log_group}
# Periodic execution (check every log group in the account)
paginator = logs.get_paginator('describe_log_groups')
for page in paginator.paginate():
for lg in page["logGroups"]:
set_retention(lg["logGroupName"])
return {"status": "completed"}
def set_retention(log_group_name):
logs.put_retention_policy(
logGroupName=log_group_name,
retentionInDays=RETENTION_DAYS
)
print(f"Retention set for {log_group_name}")La misma función se encarga de gestionar ambos disparadores. Cuando EventBridge la invoca de forma reactiva para un único grupo de logs recién creado, el evento incluye el campo detail.requestParameters.logGroupName, por lo que la función simplemente actualiza ese grupo de logs. Cuando se invoca según la programación periódica, este campo no está presente, por lo que la función pasa a recorrer, mediante paginación, describe_log_groups y actualiza todos los grupos de logs de la cuenta.
Ahora configuremos la función:
Andá a la pestaña Configuración > Variables de entorno > Editar > Agregar variable de entorno y agregá RETENTION_DAYS con la cantidad de días que querés conservar tus logs, por ejemplo, 30.
La función utiliza de forma predeterminada 128 MB de memoria, 512 MB de almacenamiento efímero y un tiempo de espera de 3 segundos, lo que es suficiente para cuentas con una cantidad moderada de grupos de logs. Si tu cuenta tiene una cantidad muy grande de grupos de logs, andá a Configuración > Configuración general > Editar y aumentá el Tiempo de espera, ya que la ejecución periódica debe recorrer todos los grupos en una única invocación.

Paso 4: Probar la función manualmente
Andá a la pestaña Prueba.
Creá un nuevo evento de prueba (podés usar cualquier nombre; la plantilla predeterminada {} funciona). Esto simula la ruta de ejecución periódica, ya que no contiene detail.requestParameters.
Hacé clic en Probar.
Revisá el resultado de la ejecución y, en la pestaña Monitorear, consultá los logs de CloudWatch. Deberías ver una línea Retention set for <log group name> por cada grupo de logs de la cuenta.

Paso 5: Activar la función de forma reactiva ante nuevos grupos de logs
Esta primera regla de EventBridge se activa en el momento en que se crea un nuevo grupo de logs en cualquier parte de la cuenta, utilizando los eventos de administración de CloudTrail que AWS entrega automáticamente al bus de eventos predeterminado (no es necesario crear un trail de CloudTrail).
Abrí el servicio Amazon EventBridge.
En el panel de navegación izquierdo, hacé clic en Reglas y luego en Crear regla. Usá el Generador avanzado.
Asignale el nombre on-log-group-create, elegí el bus de eventos default y establecé el tipo de regla como Patrón de eventos.
Seleccioná Patrón personalizado (editor JSON) y pegá lo siguiente:
{
"source": ["aws.logs"],
"detail-type": ["AWS API Call via CloudTrail"],
"detail": {
"eventSource": ["logs.amazonaws.com"],
"eventName": ["CreateLogGroup"]
}
}En Destino, seleccioná Servicio de AWS > Función Lambda y elegí set-cw-log-group-retention.
Avanzá por los pasos restantes y hacé clic en Crear regla.

Paso 6: Agregar una verificación periódica con Amazon EventBridge
La segunda regla se ejecuta según una programación establecida, como una medida de seguridad que vuelve a verificar todos los grupos de logs. Esto resulta útil para detectar aquellos que se crearon antes de implementar esta solución o cualquier caso excepcional que la regla reactiva pueda pasar por alto.
En el panel de navegación izquierdo, hacé clic en Programaciones y luego en Crear programación.
Asignale el nombre periodic-log-group-retention-check y elegí el bus de eventos default.
Cambiá el patrón de programación a Programación recurrente y el tipo de programación a Programación basada en frecuencia. Establecé la expresión de frecuencia; por ejemplo, rate(1 day) (ajustá la frecuencia según lo que tenga sentido para tu cuenta).
Establecé la Ventana de tiempo flexible en Desactivada.
En Seleccionar destino, elegí AWS Lambda y seleccioná nuevamente set-cw-log-group-retention.
Avanzá por los pasos restantes y hacé clic en Crear regla.

Paso 7: Verificar que todo funcione correctamente
Creá un grupo de logs temporal (o esperá a que se cree uno de forma natural, por ejemplo, al implementar cualquier función Lambda) y confirmá que la regla reactiva se active en uno o dos minutos. Luego, ingresá a CloudWatch > Grupos de logs y revisá la columna Retención en toda tu cuenta: los grupos de logs que anteriormente mostraban Nunca caduca deberían mostrar ahora el valor que configuraste en RETENTION_DAYS.
¡Eso es todo! A partir de ahora, todos los grupos de logs de tu cuenta —incluidos los que creen los servicios que implementes el próximo mes— tendrán automáticamente una política de retención adecuada, sin que nadie tenga que acordarse de configurarla manualmente.

Ignacio Rubio
Cloud Engineer



