web-dev-qa-db-fra.com

Je ne peux pas déployer un nouveau conteneur sur mon cluster ECS en raison des ports utilisés

La définition de tâche utilisée par mon service extrait la "dernière" version balisée de mon image.

Quand je mets à jour mon service et "force un nouveau déploiement", je regarde les événements et je vois ceci:

service MYSERVICE was unable to place a task because no container instance met all of its requirements. The closest matching container-instance .... is already using a port required by your task

Je suis ensuite allé dans mon cluster et j'ai arrêté toutes les tâches.

Je suis ensuite retourné à mon service et mis à jour avec force nouveau déploiement. Cela semble avoir fonctionné

Dois-je arrêter toutes les tâches et mettre à jour le service chaque fois que je souhaite déployer une nouvelle image? Ou existe-t-il une "bonne" façon de procéder?

EDIT: Donc, si j'arrête une tâche, le service la remplacera automatiquement. Je peux donc mettre à jour mon service et "forcer un nouveau déploiement" puis arrêter une tâche à la fois pour obtenir une sorte de mise à jour continue. Je ne sais pas s'il existe une fonctionnalité pour automatiser cela au-delà de mes propres scripts

Juste pour faire un suivi, comme indiqué dans les réponses, j'avais juste besoin d'utiliser le mappage de port dynamique.

Initialement, lorsque j'ai commencé, je n'avais pas d'équilibreur de charge, donc je frappais les instances EC2 directement pour accéder aux conteneurs en cours d'exécution. Bien sûr, pour ce faire, j'ai dû exposer un port statique sur l'hôte EC2.

J'ai ajouté un équilibreur de charge mais j'ai conservé ce mappage de port statique sans comprendre comment fonctionnait le mappage de port dynamique. Tout ce que j'avais à faire était de modifier ma définition de tâche pour définir le port d'hôte sur "0". Maintenant, je n'ai aucun mappage de port statique sur les hôtes, la NLB fait le routage pour moi et déploie le travail comme prévu

8
red888

Lorsque vous utilisez ECS (ou tout autre orchestrateur), il est recommandé d'utiliser Dynamic Port Mapping .

Fondamentalement, ECS attribuera un port aléatoire non attribué à votre conteneur. ECS propose ensuite des moyens de récupérer ce numéro de port, en utilisant l'API instrospection d'agent ou le client docker lui-même. Cependant, je n'essaierais pas de récupérer le port, je préférerais plutôt utiliser un équilibreur de charge d'application (ALB) qui vous permet d'utiliser un seul point de terminaison pour accéder à tous les conteneurs ciblés indépendamment de son port attribué dynamiquement. Lors de la mise à jour de votre service, l'ALB effectuera une transition transparente vers la dernière version du conteneur sans aucune interruption.

Enfin, à l'intérieur du conteneur, le port local restera le même afin que vous n'ayez pas à gérer les choses différemment.

5

Bien que les autres réponses soient correctes, je ne pense pas qu'elles s'appliquent au problème que vous rencontrez. Je dis cela parce que c'est un problème auquel mon équipe a également été confrontée et n'a vraiment rien à voir avec le lancement de plusieurs conteneurs sur la même instance - si je comprends bien, vous essayez simplement de remplacer le conteneur existant à partir de une définition de tâche mise à jour. Si vous souhaitez mettre plusieurs copies du même conteneur sur une seule boîte, regardez certainement les suggestions des autres réponses (en plus des détails ci-dessous), mais pour les déploiements roulants, les ports dynamiques ne sont en aucun cas requis.

[[Note complémentaire pour être complet: il est possible que votre déploiement forcé ait jeté l'erreur que vous avez publiée, car EC2 met un certain temps à nettoyer les ressources arrêtées par ECS. Vous verrez le même type de problème si vous essayez de forcer l'arrêt/le démarrage d'une tâche - nous avons vu des erreurs similaires lors de la tentative de redémarrage d'un conteneur configuré pour allouer> 50% de la mémoire d'instance disponible. Vous obtiendrez ces types d'erreurs de ressources jusqu'à ce que l'instance EC2 soit complètement nettoyée et renvoyée à ECS. J'ai vu cela prendre plus de 5 minutes. ]]

À votre question, malheureusement, pour l'instant, il n'y a pas de grande mécanique intégrée d'AWS pour effectuer un redémarrage continu des tâches. Cependant, vous pouvez faites rouler déploie.

Comme vous le savez probablement déjà, votre service repose sur une définition de tâche spécifiée. Notez qu'il dépend du numéro de définition de tâche, et ne se soucie pas des balises de conteneur de la même manière que l'instance EC2.

Les paramètres ci-dessous sont l'endroit où la magie opère pour activer les déploiements roulants; vous pouvez trouver ces options de configuration dans vos paramètres de service.

magic

Pour que vous puissiez effectuer des déploiements continus, vous devez avoir au moins 2 tâches en cours d'exécution.

  • Nombre de tâches - Le nombre de tâches que votre service souhaite exécuter (n)
  • Pourcentage sain minimum - Le% sain minimum de n lors du déploiement de nouvelles tâches
  • Pourcentage maximum - Le% maximum de n pouvant être ajouté lors du déploiement de nouvelles tâches

Donc, pour un exemple réel, supposons que vous avez la configuration suivante:

Number of tasks: 3
Minimum healthy percent:  50
Maximum percent: 100

Si vous modifiez la définition de tâche vers laquelle pointe votre service, il lancera un déploiement continu. Nous avons 3 exécution de tâches, mais autorisez >=50% en bonne santé. ECS tuera l'une de vos tâches, faisant passer le% sain à 66%, toujours au-dessus 50%. Une fois la nouvelle tâche lancée, le service est à nouveau à 100%, et ECS peut poursuivre le déploiement du déploiement vers l'instance suivante.

De même, si vous aviez une configuration où minimum % == 100, et maximum % == 150 (en supposant que vous avez la capacité), ECS va lancer une tâche supplémentaire; une fois qu'il est en place, vous avez un bon pourcentage de 133%, et il peut tuer en toute sécurité l'une des anciennes tâches. Ce processus se poursuit jusqu'à ce que votre nouvelle tâche soit entièrement déployée.

14
MrDuk

Sans ports dynamiques, une seule instance d'un service peut être déployée par conteneur, car le port utilisé par l'instance ne peut être utilisé par aucune autre instance. Lorsque vous mettez à jour le service, il essaiera de redémarrer toutes ses instances et si plusieurs instances sont démarrées sur un seul conteneur EC2, le démarrage échouera.

Mieux vaut utiliser des conteneurs Docker avec un mappage de port dynamique dans le cluster ECS.

4
S.K.

J'avais également rencontré le même problème lorsque une nouvelle instance du même microservice (conteneur) démarre en raison de la mise à l'échelle automatique, car les ports de chaque microservice sont fixes et configurés dans application.yml et lorsque le même service se lève sur le même EC2 en raison de la mise à l'échelle automatique, puis il essaie pour acquérir le même port qui est déjà utilisé par son instance précédente (par exemple, si j'ai X comme microservice en cours d'exécution sur le port 3102, si une autre instance du même service se lève à cause de l'aotoscaling, elle peut se lever sur une machine EC2 différente ou sur la même Machine EC2 dans le cluster ECS mais ECS décide où lancer une nouvelle instance de microservice en fonction de la disponibilité du CPU et de la RAM, si une nouvelle instance se lève sur une machine EC2 différente, aucun problème car le port sera libre, mais si l'instance se lèvera sur le même ec2 machine qu'il ne démarre pas et ne crie pas que le port est déjà utilisé)

Pour résoudre ce problème, nous devons mettre à jour les définitions de tâches de notre cluster ECS uniquement, aucune modification n'est nécessaire dans les images, nous devons activer le mappage de port dynamique dans les définitions de tâches afin que n'importe quel nombre d'instances de microservices puisse s'exécuter sur la même machine Ec2

Sans définition de tâche de mappage de port dynamique, les configurations seront

  1. Mode réseau - Hôte
  2. Dans Port Mapping, Container Port sera: Port de votre application configuré dans application.yml

enter image description here

enter image description here

Pour activer le mappage de port dynamique dans ECS

  • Changer le mode réseau: Pont
  • Configurer le mappage de port, rendre le port d'hôte à 0 et le port de conteneur équivalent au port de votre application configuré dans application.yml

enter image description hereenter image description here

2
ABHAY JOHRI

Tout d'abord, définissez le nombre souhaité sur 0

aws ecs update-service --cluster cluster_name --service service_name --desired-count 0

Après la commande ci-dessous, vous pouvez vérifier dynamiquement le nombre d'instances de conteneurs en cours d'exécution

aws ecs describe-services --cluster cluster_name --service service_name

Ensuite, exécutez la commande ci-dessous

aws ecs update-service --cluster cluster_name --service service_name --desired-count 1
1
erncnerky