Conteneurs CI / CD simples dans AWS

14

J'utilise AWS Code Pipeline, Code Build pour créer un nouveau conteneur Docker et le pousser vers ECR.

Mon application est un simple conteneur simple basé sur. Quelle serait l'approche de moindre friction pour retirer le conteneur en cours d'exécution et relancer un nouveau conteneur à partir du registre ECS (sortie de Code Build thru Code Pipeline).

J'ai essayé CloudFormation avec les données utilisateur EC2, les scripts personnalisés d'un côté et CloudFormation avec ECS avec la définition des tâches de l'autre côté (pas encore réussi). Je pense fermement qu'il doit y avoir une approche plus évidente et plus simple.

Naveen Vijay
la source

Réponses:

16

Je garderais les instances de conteneur ECS (je parle des hôtes Docker - je n'aime pas la terminologie AWS ici) et le déploiement comme deux choses distinctes.

Obtenez votre pile ECS opérationnelle. Vous pouvez le gérer via CloudFormation et les groupes de mise à l'échelle automatique, c'est très bien. Il suffit de penser à votre cluster en tant que plate - forme où vous allez déployer pour , pas quelque chose que vous devez redéployer .

Ensuite, pour les CD, la méthode la plus simple est de loin de mettre à jour la définition de service pour utiliser une nouvelle définition de tâche et de laisser ECS Rolling mettre à jour les conteneurs pour vous.

Chaque fois qu'il démarre une tâche, ECS exécute le docker pull image: tag même s'il a l'image localement pour s'assurer qu'il a la dernière version de cette image: tag. Donc, la balise d'image que vous utilisez n'a pas vraiment d'importance (il n'est pas nécessaire de changer la balise sur chaque build).

Cela signifie que vous pouvez créer myimage: les dernières à plusieurs reprises afin de le déployer facilement.

Ce dont vous avez besoin est une définition de tâche où l'image = myimage: latest. Créez un service avec cette définition de tâche et chaque fois que ECS démarre une tâche (une instance de votre service), ce sera la "myimage: latest" la plus récente que vous aurez créée.

À partir de là, il vous manque une seule pièce du puzzle, à partir de CodeDeploy, vous pouvez appeler quelque chose, peut-être une fonction lambda, pour créer une nouvelle révision de votre définition de tâche et mettre à jour votre service et ECS créera automatiquement de nouvelles tâches pour cette révision et supprimer les anciennes tâches.

Un exemple:

Supposons que vous avez créé un service appelé MyService. Que vous avez configuré ce service pour exécuter 2 tâches pour la définition de tâche MyTaskDefinition: 1 (révision 1). Dans cette définition de tâche, vous avez une définition de conteneur dont l'image est définie sur "myimage: latest".

  1. Hier, vous avez construit myimage: latest qui avait l'ID (SHA) 365d8f7bf565.
  2. Votre instance de conteneur ABC exécute une tâche nommée MyTaskDefinition- 1 -containerName-someLongId. lorsque vous inspectez ce conteneur, il exécute l'image "sha256: 365d8f7bf565 .........."
  3. Votre autre instance de conteneur DEF exécute une autre tâche. Il a un nom similaire (seul l'ID diffère), mais il exécute la même image.
  4. Vous proposez un changement à votre référentiel.
  5. CodePipeline reprend cette modification, crée et publie l'image sur ECR.
  6. Cette nouvelle image Docker est aussi myimage: la plus récente, mais son ID (SHA) est f7ec5e54ac96
  7. Vous devez maintenant ajouter une étape à votre pipeline pour utiliser les fonctions Lambda et le kit SDK AWS NodeJS pour effectuer certains appels à votre cluster:
    1. Créez une nouvelle définition de tâche (qui sera exactement la même qu'auparavant). Ce sera MyTaskDefinition: 2
    2. Mettez à jour votre MyService pour utiliser MyTaskDefinition: 2 (au lieu de 1)
  8. ECS créera de nouvelles tâches. Les noms des conteneurs seront MyTaskDefinition- 2 -containerName-someLongId. Lorsque vous inspectez ces conteneurs, vous verrez qu'ils exécuteront "sha256: f7ec5e54ac96 .......". Peut-être que vous aurez 2 tâches sur l'instance de conteneur ABC, peut-être qu'elles seront pulvérisées (cela dépend de la configuration de votre service)
  9. Après un certain temps, ECS supprimera l'ancienne tâche MyTaskDefinition-1-containerName-someLongId d'ABC et DEF.

Remarque: vous n'avez pas réellement besoin de créer une nouvelle définition de tâche. Si vous le souhaitez, vous pouvez récupérer la liste des tâches du service et les arrêter manuellement une par une. Vous devez attendre qu'ECS redémarre une tâche avant d'en arrêter une nouvelle (c'est-à-dire: arrêter le premier conteneur, attendre qu'ECS le remplace, arrêter le deuxième conteneur). Lorsque ECS redémarre le conteneur, il récupère la plus récente myimage: la dernière version, comme expliqué précédemment. Je pense simplement que la création d'une nouvelle définition de tâche est plus facile et moins sujette aux erreurs (aucune logique requise pour attendre et vérifier, ECS gérera la mise à jour continue pour vous si vous avez une nouvelle définition de tâche).

Alexandre
la source
Incroyable - je dirais que votre réponse est le manuel manquant pour le CI / CD pour docker. Je vous remercie.
Naveen Vijay
3

Pour un cas d'utilisation simple décrit, je suggérerais de vérifier Elastic Beanstalk pour Docker, ce n'est pas la solution minimale comme l'utilisation ECS nue, mais vous pouvez bénéficier de services configurés et gérés automatiquement comme ELB, EC2 AutoScale, la surveillance de la santé et bien plus encore.

Résumé de haut niveau:

  1. Configurer Elastic Beanstalk pour utiliser une balise spécifique myimage: testé
  2. Utilisez Code Pipeline / Build pour construire, tester et promouvoir la balise "testé"
  3. Déclenchez le déploiement d'Elastic Beanstalk, qui tirera l'image promue myimage: testé sur toutes les instances, différentes stratégies de déploiement disponibles.

Cette approche basée sur la réutilisation de la même balise, une approche alternative serait de générer une balise avec un identifiant de construction, par exemple myimage: testé-42, cela nécessitera de mettre à jour Elastic Beanstalk à chaque fois avec une nouvelle balise, mais donne un contrôle plus granulaire sur la révision déployée.

rombob
la source
0

Je seconde haricot élastique pour sa simplicité; il est très facile à configurer et à déployer.

Si vous êtes familier avec docker-compose, une autre approche serait de définir docker-compose.yml et de le déployer directement sur ECS avec ecs-cli.

AnthonyC
la source