[PYTHON] Je souhaite définir un cycle de vie dans la définition de tâche d'ECS

introduction

Lors de l'écriture d'un traitement par lots, etc. en utilisant la fonction de planification de tâches d'ECS, si la tâche est mise à jour plusieurs fois à l'aide de ʻecs-cli, la révision` de la définition de tâche augmentera.

Il est gênant de supprimer la révision (désenregistrer) en cliquant sur l'écran de la console d'aws, et il existe également une méthode pour la supprimer en utilisant deregister-task-definition de ʻawscli`, mais il est également gênant de l'exécuter à partir de la ligne de commande. ..

Comment supprimer avec awscli https://docs.aws.amazon.com/cli/latest/reference/ecs/deregister-task-definition.html

J'ai donc décidé de lancer Lambda pour désenregistrer (désenregistrer) la révision.

Ce qui a été utilisé

--Pour le déploiement de ServerlessFrameWork lambda --serverless-python-requirements Pour déployer des packages externes de Python

Obtenir une liste des définitions de tâches ECS

Utilisez ʻecs.list_task_definitions dans boto3` pour obtenir toutes les définitions de tâches. https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ecs.html#ECS.Client.list_task_definitions

J'ai défini sort = 'DESC' comme argument, mais je l'ai défini sur' DESC' car cela est nécessaire lors de l'utilisation de ʻitertools.groupby` plus tard.


import json
import boto3
import logging

logger = logging.Logger(__name__)
logger.setLevel(logging.DEBUG)

def get_task_definitions():
    """Obtenir la définition de tâche ECS

    Returns:
        list --Liste des définitions de tâches arn
    """

    client = boto3.client('ecs')
    try:
        res = client.list_task_definitions(
            status='ACTIVE',
            sort='DESC')
        logger.info(json.dumps(res))
    except Exception as e:
        logger.info(e)
    else:
        logger.info('Acquisition réussie de la définition des tâches')

    list_task_definitions = res['taskDefinitionArns']
    return list_task_definitions

Vous pouvez l'obtenir comme ça

[
    'arn:aws:ecs:ap-northeast-1:XXXXXXXXXXXXX:task-definition/task_a:3',
    'arn:aws:ecs:ap-northeast-1:XXXXXXXXXXXXX:task-definition/task_a:2',
    'arn:aws:ecs:ap-northeast-1:XXXXXXXXXXXXX:task-definition/task_a:1',
    'arn:aws:ecs:ap-northeast-1:XXXXXXXXXXXXX:task-definition/task_b:5',
    'arn:aws:ecs:ap-northeast-1:XXXXXXXXXXXXX:task-definition/task_b:4',
    'arn:aws:ecs:ap-northeast-1:XXXXXXXXXXXXX:task-definition/task_b:3',
    'arn:aws:ecs:ap-northeast-1:XXXXXXXXXXXXX:task-definition/task_b:2',
    'arn:aws:ecs:ap-northeast-1:XXXXXXXXXXXXX:task-definition/task_b:1',
    'arn:aws:ecs:ap-northeast-1:XXXXXXXXXXXXX:task-definition/task_c:5',
    'arn:aws:ecs:ap-northeast-1:XXXXXXXXXXXXX:task-definition/task_c:4',
    'arn:aws:ecs:ap-northeast-1:XXXXXXXXXXXXX:task-definition/task_c:3',
    'arn:aws:ecs:ap-northeast-1:XXXXXXXXXXXXX:task-definition/task_c:2',
    'arn:aws:ecs:ap-northeast-1:XXXXXXXXXXXXX:task-definition/task_c:1'
]

Mettre en forme les données de définition de tâche

Maintenant que nous avons la définition de la tâche, nous la regrouperons par le même nom de tâche et formaterons les données afin que nous puissions voir le nombre de révisions de la tâche. J'ai eu la définition de la tâche, mais pour être exact, il s'agit de la définition de la tâche, donc je la formate uniquement avec le nom de la tâche.


#La forme que vous souhaitez façonner
{
    'task_a': ['3', '2', '1'],
    'task_b': ['5', '4', '3', '2', '1'],
    'task_c': ['5', '4', '3', '2', '1']
}

ʻUtilisez itertools.groupby pour les grouper. J'ai mis le tri dans ʻecs.list_task_definitions parce que je dois trier à l'avance pour utiliser ʻitertools.groupby`.


a = [('a', '3'), ('a', '2'), ('a', '1'), ('b', '4'), ('b', '3'),
     ('b', '2'), ('b', '1'), ('c', '2'), ('c', '1')]

for key, group in groupby(a, lambda x: x[0]): 
    for team in group: 
        print(team)
    print('')

Il sera regroupé comme ceci, donc je vais le formater dans un dictionnaire.

('a', '3')
('a', '2')
('a', '1')

('b', '4')
('b', '3')
('b', '2')
('b', '1')

('c', '2')
('c', '1')
from itertools import groupby

def groupby_task_definitions(list_task_definitions):
    """Mettre en place une liste d'arn dans la définition de tâche

    Arguments:
        list_task_definitions {list} --Liste des définitions de tâches arn

    Returns:
        dict --Nom de la tâche et liste des révisions

    Example:
        {
            task_a: ['4', '3', '2', '1'],
            task_b: ['2', 1]
        }
    """
    group_list = []
    for task_definition in list_task_definitions:
        #Couper uniquement le nom et la révision de la tâche
        task_definition = task_definition.rsplit('/', 1)[1]
        task_name, revision = task_definition.split(':')

        #Ajouter à la liste sous forme de taple
        group_list.append((task_name, revision))

    result_dict = {}
    for key, group in groupby(group_list, lambda x: x[0]):
        revision_list = []
        for _, v in group:
            revision_list.append(v)
        result_dict[key] = revision_list

    return result_dict

Supprimer la tâche ECS (désinscrire)

Maintenant que nous avons créé un dictionnaire de définitions de tâches, nous allons supprimer les tâches ECS. Tournez le dictionnaire avec «for» et supprimez-le par «pop ()» jusqu'à ce que la longueur de la liste de «révision» obtenue atteigne le nombre spécifié.

ʻEcs.deregister_task_definition` peut être exécuté facilement en donnant le nom de la définition de tâche à l'argument.

def deregister_task_definition(groupby_task_definitions_dict, leave):
    """Supprimer la définition de tâche, en laissant les deux dernières révisions

    Arguments:
        groupby_task_definitions_dict {dict} --Un dict qui stocke une liste de noms de tâches et de révisions
    """
    client = boto3.client('ecs')

    for name, revision_list in groupby_task_definitions_dict.items():
        logger.info(name)
        try:
            while len(revision_list) > 2:
                revision = revision_list.pop()
                client.deregister_task_definition(
                    taskDefinition='{}:{}'.format(name, revision)
                )
        except Exception as e:
            logger.error(e)
        else:
            logger.info('{} : OK!'.format(name))

Rendre disponible dans Lambda

Nous n'avons défini aucun événement à ce stade, mais vous pouvez utiliser lambda invoke ou vous pouvez utiliser CloudWatch Events pour le faire régulièrement.

serverless.yml Nous allons créer Lambda en utilisant Serverless Framework, donc exposez serverless.yml.

serverless.yml


service: ecs-task

provider:
  name: aws
  runtime: python3.7
  region: ap-northeast-1
  logRetentionInDays: 30

  iamRoleStatements:
    - Effect: Allow
      Action:
        - ecs:*
      Resource: "*"

functions:
  definition-lifecycle :
    handler: handler.main

plugins:
  - serverless-python-requirements

custom:
  pythonRequirements:
    usePipenv: true 

handler Le gestionnaire exécute simplement une fonction qui fait ce qu'il a fait jusqu'à présent.

def main(event, context):
    list_task_definitions = get_task_definitions()
    groupby_task_definitions_dict = groupby_task_definitions(
        list_task_definitions)
    logger.info(groupby_task_definitions_dict)
    deregister_task_definition(groupby_task_definitions_dict, leave)

Code entier

handler.py



import boto3
import json
from itertools import groupby
import logging

logger = logging.Logger(__name__)
logger.setLevel(logging.DEBUG)


def get_task_definitions():
    """Obtenir la définition de tâche ECS

    Returns:
        list --Liste des définitions de tâches arn
    """

    client = boto3.client('ecs')
    try:
        res = client.list_task_definitions(
            status='ACTIVE',
            sort='DESC')
        logger.info(json.dumps(res))
    except Exception as e:
        logger.info(e)
    else:
        logger.info('Acquisition réussie de la définition des tâches')

    list_task_definitions = res['taskDefinitionArns']
    return list_task_definitions


def groupby_task_definitions(list_task_definitions):
    """Mettre en place une liste d'arn dans la définition de tâche

    Arguments:
        list_task_definitions {list} --Liste des définitions de tâches arn

    Returns:
        dict --Nom de la tâche et liste des révisions

    Example:
        {
            task_a: ['4', '3', '2', '1'],
            task_b: ['2', 1]
        }
    """
    group_list = []
    for task_definition in list_task_definitions:
        #Couper uniquement le nom et la révision de la tâche
        task_definition = task_definition.rsplit('/', 1)[1]
        task_name, revision = task_definition.split(':')

        group_list.append((task_name, revision))

    result_dict = {}
    for key, group in groupby(group_list, lambda x: x[0]):
        revision_list = []
        for _, v in list(group):
            revision_list.append(v)
        result_dict[key] = revision_list

    return result_dict


def deregister_task_definition(groupby_task_definitions_dict):
    """Supprimer la définition de la tâche, en laissant les deux dernières révisions

    Arguments:
        groupby_task_definitions_dict {dict} --Un dict qui stocke une liste de noms de tâches et de révisions
    """
    client = boto3.client('ecs')

    for name, revision_list in groupby_task_definitions_dict.items():
        logger.info(name)
        try:
            while len(revision_list) > 2:
                revision = revision_list.pop()
                client.deregister_task_definition(
                    taskDefinition='{}:{}'.format(name, revision)
                )
        except Exception as e:
            logger.error(e)
        else:
            logger.info('{} : OK!'.format(name))


def main(event, context):
    list_task_definitions = get_task_definitions()
    groupby_task_definitions_dict = groupby_task_definitions(
        list_task_definitions)
    logger.info(groupby_task_definitions_dict)
    deregister_task_definition(groupby_task_definitions_dict)

AWS en quelque sorte

Vous pouvez supprimer (désinscrire) une définition de tâche uniquement pour les tâches ʻActive, puis passer à l'état ʻInactive. Dans cet état, il ne peut pas être complètement effacé à ce stade, nous attendons donc la réponse d'AWS.

À ce stade, la définition de tâche INACTIVE reste indéfiniment détectable dans votre compte. Cependant, ce comportement est sujet à changement à l'avenir et ne doit pas dépendre de la définition de la tâche ACL conservée tout au long du cycle de vie de la tâche et du service associés.

image.png

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/deregister-task-definition.html

Recommended Posts

Je souhaite définir un cycle de vie dans la définition de tâche d'ECS
Je souhaite trier une liste dans l'ordre des autres listes
Je souhaite voir une liste de fichiers WebDAV dans le module Requêtes
Je veux imprimer dans la notation d'inclusion
[Introduction à StyleGAN] J'ai joué avec "The Life of a Man" ♬
Je veux connaître la population de chaque pays du monde.
Je veux convertir par lots le résultat de "chaîne de caractères" .split () en Python
Je veux colorer une partie de la chaîne Excel avec Python
Je souhaite laisser une commande arbitraire dans l'historique des commandes de Shell
J'ai fait un programme pour vérifier la taille d'un fichier avec Python
J'ai essayé d'afficher la valeur d'altitude du DTM dans un graphique
Python: je souhaite mesurer proprement le temps de traitement d'une fonction
Je souhaite personnaliser l'apparence de zabbix
Je veux afficher la progression en Python!
Si vous souhaitez changer d'utilisateur d'exécution au milieu d'une tâche Fabric, le gestionnaire de contexte des paramètres
Je veux utiliser quatre règles compliquées dans l'instruction IF du modèle Django! → Utilisez un modèle personnalisé
L'histoire de l'adresse IPv6 que je souhaite conserver au minimum
[Django memo] Je souhaite définir à l'avance les informations de l'utilisateur connecté dans le formulaire.
J'ai créé une commande appdo pour exécuter des commandes dans le contexte de l'application
Je veux ajouter du silence pendant 1 seconde au début d'un fichier wav
Je souhaite stocker les résultats de% time, %% time, etc. dans un objet (variable)
Je souhaite intégrer une variable dans une chaîne Python
Je veux facilement implémenter le délai d'expiration en python
Je veux faire la transition avec un bouton sur le ballon
Je veux grep le résultat de l'exécution de strace
Je veux écrire en Python! (2) Écrivons un test
Je veux échantillonner au hasard un fichier avec Python
Je veux bien comprendre les bases de Bokeh
Je veux travailler avec un robot en python.
Je souhaite installer un package de Php Redis
Je veux écrire en Python! (3) Utiliser des simulacres
Je veux utiliser le jeu de données R avec python
Je souhaite augmenter la sécurité de la connexion SSH
Je veux configurer un serveur fictif pour python-flask en quelques secondes en utilisant swagger-codegen.
Je souhaite prendre une capture d'écran du site sur Docker en utilisant n'importe quelle police
Trouvez une ligne directrice pour le nombre de processus / threads à définir sur le serveur d'applications
[Python] Je souhaite obtenir un ensemble commun entre numpy
Je souhaite utiliser uniquement le traitement de normalisation SudachiPy
Je veux obtenir des informations sur le fonctionnement de Yahoo Route
J'ai fait une fonction pour vérifier le modèle de DCGAN
Je veux déterminer l'authenticité d'un élément du tableau numpy
Je veux connaître la nature de Python et pip
Je veux rendre le type de dictionnaire dans la liste unique
Keras Je veux obtenir la sortie de n'importe quelle couche !!
Je veux aligner les nombres valides dans le tableau Numpy
Je veux connaître la légende du monde des technologies informatiques
Je veux ajouter un joli complément à input () en python
Je veux créer un Dockerfile pour le moment.
Je ne voulais pas écrire la clé AWS dans le programme
Notez ce que vous voulez faire à l'avenir avec Razpai
Je veux voir le graphique en 3D! Je peux réaliser un tel rêve.
Je veux trouver l'intersection d'une courbe de Bézier et d'une ligne droite (méthode de découpage de Bézier)
Je souhaite produire une carte thermique magnifiquement personnalisée de la matrice de corrélation. édition matplotlib
J'ai écrit un doctest dans "J'ai essayé de simuler la probabilité d'un jeu de bingo avec Python"