[LINUX] Déplacer régulièrement les journaux CloudWatch vers S3 avec Lambda

introduction

CloudWatch est un moyen pratique de collecter des journaux pour votre système AWS. Au travail, j'installe CloudWatch Agent sur mon instance EC2 pour diffuser les journaux d'accès et les journaux d'erreurs de diverses applications (Nginx, Tomcat, etc.) vers CloudWatch Logs.

Cependant, le stockage des journaux dans CloudWatch Logs est assez coûteux, je voudrais donc déplacer régulièrement les anciens journaux vers S3. Dans cet article, je vais donc résumer comment déplacer régulièrement les journaux CloudWatch vers S3 à l'aide de Lambda.

csl.png

divers paramètres

Paramètres Lambda

Tout d'abord, accordez à Lambda les autorisations appropriées pour déployer le code qui effectue le déplacement. Définissez le rôle IAM avec les autorisations suivantes dans Lambda.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "cloudwatch:*",
            "Resource": "*"
        },
        {
            "Action": [
                "s3:Get*",
                "s3:Put*",
                "s3:List*",
            ],
            "Resource": [
                "*"
            ],
            "Effect": "Allow"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "logs:CreateExportTask",
                "logs:DescribeLogGroups",
                "logs:Get*"
            ],
            "Resource": "*"
        }
    ]
}

Donnez à S3 les autorisations de lecture et d'écriture, lisez les journaux CloudWatch et créez des tâches.

Code à déployer sur Lambda (Python)

Quand j'écris le code en Python, cela ressemble à ceci: Autre que la bibliothèque standard, boto3 est utilisé, donc lors du déploiement, téléchargez-le dans un fichier zip avec le code suivant.

import boto3
import datetime
import time

#Requête lors de la recherche de groupes de journaux
PREFIX = 'test-'
#Seau S3 pour stocker les journaux
S3_BUCKET = 'test_bucket'
#Répertoire de s3 pour stocker les journaux
S3_DIR = 'logs'

def main(event,context):
    '''
Fonction appelée en main
    '''
    #client boto3
    client = boto3.client('logs')
    #Obtenir une liste des groupes de journaux
    log_groups = get_log_group_list(client)
    #Stocker le contenu du journal dans s3
    move_logs(client,log_groups)

def get_log_group_list(client):
    '''
Obtenir une liste d'informations sur les groupes de journaux
    '''
    should_continue = True
    next_token = None
    log_groups=[]
    #Il peut ne pas être possible de tout supprimer en même temps, alors acquérez-le à plusieurs reprises.
    while should_continue:
        if next_token == None:
            #Pour la première demande
            response = client.describe_log_groups(
                logGroupNamePrefix=PREFIX,
                limit=50
            )
        else:
            #Pour la deuxième demande et les suivantes
            response = client.describe_log_groups(
                logGroupNamePrefix=PREFIX,
                limit=50,
                nextToken=next_token
            )
        #Ajouter le résultat obtenu à la liste
        for log in response['logGroups']:
            log_groups.append(log)
        #Déterminez également si une demande doit être faite
        if 'nextToken' in response.keys():
            next_token = response['nextToken']
        else:
            should_continue = False
    return log_groups

def create_export_task(client,log_groups):
    '''
Déplacer le contenu du journal vers s3
    '''
    #Obtenir l'heure actuelle et convertir en heure UNIX
    time_now = datetime.datetime.now()
    unix_time_now = int(time_now.timestamp())
    #Répétez pour le nombre de groupes de journaux
    for log in log_groups:
        for x in range(20):
            try:
                response = client.create_export_task(
                    fromTime=0,
                    to=unix_time_now,
                    logGroupName=log['logGroupName'],
                    destination=S3_BUCKET,
                    destinationPrefix=S3_DIR
                )
            except:
                #Si vous avez déjà une tâche, attendez un moment et réessayez
                time.sleep(20)
                continue

Dans la variable PREFIX définie en haut, spécifiez la première chaîne de caractères du groupe de journaux vers lequel vous souhaitez migrer les journaux. Ici, le journal du groupe de journaux commençant par "test-" est défini pour être déplacé vers S3.

La fonction main () est appelée au moment de l'exécution. Cette fonction appelle les deux fonctions suivantes dans l'ordre.

Paramètres S3

Enfin, définissez le compartiment de S3 vers lequel vous souhaitez exporter le journal. Définissez le json suivant comme stratégie.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "logs.ap-northeast-1.amazonaws.com"
            },
            "Action": "s3:PutObject",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "logs.ap-northeast-1.amazonaws.com"
            },
            "Action": "s3:GetBucketAcl",
            "Resource": "*"
        }
    ]
}

Si vous oubliez de le spécifier, vous obtiendrez l'erreur ** "Une erreur s'est produite (InvalidParameterException) lors de l'appel de l'opération CreateExportTask: l'appel GetBucketAcl sur le bucket donné a échoué. Veuillez vérifier si CloudWatch Logs a reçu l'autorisation d'effectuer cette opération." ** , Se produit lors de l'exécution de fonctions Lambda. J'étais confus car le message d'erreur était trompeur, comme s'il s'agissait d'un problème avec les paramètres CloudWatch Logs.

finalement

Si vous utilisez le cron de CloudWatch pour définir la fonction Lambda créée à exécuter régulièrement, par exemple, vous pouvez déplacer les journaux CloudWatch vers S3 chaque jour.

Cependant, il y a une mise en garde. La tâche d'exportation de journaux prend du temps, ce qui signifie que si vous essayez d'exporter plus de 10 groupes de journaux à la fois, cela prendra plus de 15 minutes, ce qui correspond au temps d'exécution maximal de Lambda. C'est gênant.

Si vous souhaitez déplacer un grand nombre de journaux vers s3 à la fois, il peut être préférable de l'exécuter en tant que tâche cron dans EC2 au lieu d'utiliser Lambda.

Recommended Posts

Déplacer régulièrement les journaux CloudWatch vers S3 avec Lambda
Exporter les journaux CloudWatch vers S3 avec AWS Lambda (Pythyon ver)
[Python] Exportez régulièrement de CloudWatch Logs vers S3 avec Lambda
Grattage sans serveur régulier avec AWS lambda + scrapy, partie 1
Connectez-vous à s3 avec AWS Lambda Python
Utilisez AWS lambda pour récupérer les actualités et notifier régulièrement LINE des mises à jour [python]
Afficher les images sur S3 avec API Gateway + Lambda
Exporter un instantané RDS vers S3 avec Lambda (Python)
Comment publier un blog sur Amazon S3 avec le moteur de blog statique `` Pélican '' pour Pythonista
Fonction Lambda (version python) qui décompresse et génère des éléments dans CloudWatch Logs lorsqu'un fichier compressé est téléchargé vers s3
Je veux AWS Lambda avec Python sur Mac!
Je veux lier une variable locale avec lambda
Notez ce que vous avez fait pour utiliser Flycheck avec Python
Créer une application Web de type Flask / Bottle sur AWS Lambda avec Chalice
Une histoire que j'ai corrigée lorsque j'ai obtenu le journal Lambda de Cloudwatch Logs
[Python 3.8 ~] Comment définir intelligemment des fonctions récursives avec des expressions lambda
Envoyer les images prises avec ESP32-WROOM-32 vers AWS (API Gateway → Lambda → S3)
Comment personnaliser U-Boot avec une carte personnalisée pour OSD335X (Remarque)
Utilisez ScraperWiki pour obtenir régulièrement des données de votre site Web
Comment créer une API de machine learning sans serveur avec AWS Lambda
J'ai créé un robot pour publier sur Twitter en grattant sur le Web un site dynamique avec AWS Lambda (suite)
[AWS lambda] Déployer, y compris diverses bibliothèques avec lambda (générer un zip avec un mot de passe et le télécharger vers s3) @ Python
Mettez à jour les données en les téléchargeant sur s3 d'aws avec une commande, et supprimez les données utilisées (en chemin)
Remarques sur l'exécution d'Errbot localement
Montez S3 sur Ubuntu avec goofys
Utilisez boto3 pour accéder à S3
Comment générer un nouveau groupe de journaux dans CloudWatch à l'aide de python dans Lambda
Définissez la fonction Lambda et laissez-la fonctionner avec les événements S3!
Procédure de création d'un environnement virtuel Python avec VS Code sous Windows
J'ai essayé de créer un LINE BOT "Sakurai-san" avec API Gateway + Lambda
J'ai écrit un diagramme de configuration du système avec des diagrammes sur Docker
Comment dessiner une ligne verticale sur une carte de chaleur dessinée avec Python Seaborn
Obtenez des taux de change réguliers avec Heroku et téléchargez des journaux sur Amazon S3
Téléchargez ce que vous avez dans la demande vers S3 avec AWS Lambda Python
Utilisation pratique des couches lors du chargement de bibliothèques sur Lambda