web-dev-qa-db-fra.com

Service AWS ECS 503 temporairement indisponible pendant le déploiement

J'utilise Amazon Web Services EC2 Container Service avec un équilibreur de charge d'application pour mon application. Lorsque je déploie une nouvelle version, le service 503 est temporairement indisponible pendant environ 2 minutes. C'est un peu plus que le temps de démarrage de mon application. Cela signifie que je ne peux pas faire de déploiement sans temps d'arrêt maintenant.

Existe-t-il un paramètre pour ne pas utiliser les nouvelles tâches lors de leur démarrage? Ou qu'est-ce qui me manque ici?

MISE À JOUR:

Les numéros de contrôle de santé pour le groupe cible de l'ALB sont les suivants:

Healthy threshold:     5
Unhealthy threshold:   2
Timeout:               5 seconds
Interval:              30 seconds
Success codes:         200 OK

Seuil sain est "Le nombre de succès des contrôles de santé consécutifs requis avant de considérer un objectif malsain sain"
Seuil malsain est 'Le nombre d'échecs de contrôle de santé consécutifs requis avant de considérer un objectif malsain.'
Timeout est 'La quantité de temps, en secondes, pendant laquelle aucune réponse ne signifie un échec de contrôle de santé.'
Intervalle est 'La durée approximative entre les contrôles de santé d'une cible individuelle'

MISE À JOUR 2: Mon cluster comprend donc deux instances EC2, mais peut évoluer si nécessaire. Le nombre souhaité et minimum est de 2. J'exécute une tâche par instance, car mon application a besoin d'un numéro de port spécifique. Avant de déployer (jenkins exécute un script aws cli), j'ai défini le nombre d'instances sur 4. Sans cela, AWS ne peut pas déployer mes nouvelles tâches (c'est un autre problème à résoudre). Le mode réseau est bridge.

12
vargen_

Ainsi, le problème semble résider dans les mappages de ports de mes paramètres de conteneur dans la définition de tâche. Avant, j'utilisais 80 comme hôte et 8080 comme port de conteneur. Je pensais que je devais les utiliser, mais le port hôte peut avoir n'importe quelle valeur en fait. Si vous le définissez sur 0, ECS attribuera un port dans la plage de 32768-61000 et il est donc possible d'ajouter plusieurs tâches à une instance. Pour que cela fonctionne, j'ai également dû changer mon groupe de sécurité en laissant le trafic provenir de l'ALB vers les instances sur ces ports.
Ainsi, lorsque ECS peut exécuter plusieurs tâches sur la même instance, le pourcentage sain 50/200 min/max est logique et il est possible de déployer une nouvelle révision de tâche sans avoir besoin d'ajouter de nouvelles instances. Cela garantit également le déploiement sans interruption.

Merci à tous ceux qui ont demandé ou commenté!

9
vargen_

Puisque vous utilisez AWS ECS, puis-je vous demander quel est le "pourcentage de santé minimum" et le "pourcentage de santé maximum" du service

Assurez-vous que vous disposez d'un "pourcentage de santé maximal" de 200 et d'un "pourcentage de santé minimal" de 50 afin que, lors du déploiement, tous vos services ne tombent pas en panne.

Veuillez trouver la définition de la documentation de ces deux termes:

Le pourcentage maximum fournit une limite supérieure du nombre de tâches en cours d'exécution pendant un déploiement, vous permettant de définir la taille du lot de déploiement.

Le pourcentage sain minimal fournit une limite inférieure sur le nombre de tâches en cours d'exécution pendant un déploiement, vous permettant de déployer sans utiliser de capacité de cluster supplémentaire.

Une limite de 50 pour le "pourcentage de santé minimum" garantira que seulement la moitié de votre conteneur de services sera tuée avant de déployer la nouvelle version du conteneur, c'est-à-dire si la valeur de tâche souhaitée du service est "2" qu'au moment du déploiement seul le conteneur "1" avec l'ancienne version sera tué en premier et une fois la nouvelle version déployée, le deuxième ancien conteneur sera tué et un nouveau conteneur de version sera déployé. Cela garantira qu'à tout moment, des services traitent la demande.

De même, une limite de 200 pour le "pourcentage de santé maximal" indique à l'agent ecs qu'à un moment donné pendant le déploiement, le conteneur du service peut tirer jusqu'à un maximum du double de la tâche souhaitée.

Veuillez me le faire savoir en cas de question supplémentaire.

3
Manish Joshi

Avec vos paramètres, le démarrage de votre application devrait prendre plus de 30 secondes pour échouer 2 contrôles de santé et être marqué comme malsain (en supposant un premier contrôle immédiatement après la fermeture de votre application). Et cela prendra au moins 2 minutes et jusqu'à 3 minutes pour être à nouveau marqué comme sain (vérifiez d'abord immédiatement après la remise en ligne de votre application dans le meilleur des cas ou vérifiez immédiatement avant que votre application ne revienne dans le pire des cas).

Ainsi, une solution rapide et sale consiste à augmenter le seuil malsain afin qu'il ne soit pas marqué comme malsain lors des mises à jour. Et peut être abaissé le seuil sain pour qu'il soit à nouveau marqué plus rapidement comme sain.

Mais si vous voulez vraiment atteindre zéro temps d'arrêt, vous devez utiliser plusieurs instances de votre application et dire à AWS de planifier les déploiements comme suggéré par Manish Joshi (afin qu'il y ait toujours suffisamment d'instances saines derrière votre ELB pour maintenir votre site opérationnel).

2
Seva

Comment j'ai résolu cela était d'avoir un fichier plat dans la racine de l'application que l'ALB surveillerait pour rester en bonne santé. Avant le déploiement, un script supprimera ce fichier tout en surveillant le nœud jusqu'à ce qu'il enregistre OutOfService.

De cette façon, toute connexion en direct se serait arrêtée et perdue. À ce stade, le déploiement est ensuite démarré en arrêtant le nœud ou le processus d'application. Après le déploiement, le nœud est ajouté à nouveau au LB en ajoutant à nouveau ce fichier plat et surveillé jusqu'à ce qu'il enregistre Inservice pour ce nœud avant de passer au deuxième nœud pour effectuer la même étape ci-dessus.

Mon script ressemble à ceci

# Remove Health Check target
echo -e "\nDisabling the ELB Health Check target and waiting for OutOfService\n"
rm -f /home/$USER/$MYAPP/server/public/alive.html

# Loop until the Instance is Out Of Service
while true
do
        RESULT=$(aws elb describe-instance-health --load-balancer-name $ELB --region $REGION --instances $AMAZONID)
        if echo $RESULT | grep -qi OutOfService ; then
                echo "Instance is Deattached"
                break
        fi
        echo -n ". "
        sleep $INTERVAL
done
2
Innocent Anigbo

Vous parliez de Jenkins , donc je répondrai en gardant à l'esprit le service Jenkins master , mais ma réponse reste valable pour tout autre cas (même si ce n'est pas un bon exemple pour ECS , un maître Jenkins ne se met pas à l'échelle correctement, donc il ne peut y avoir que une instance).

503 mauvaise passerelle

J'ai souvent rencontré 503 gateway erreurs liées à load balancer failing healthchecks (pas d'instance saine). Jetez un œil à l'onglet de surveillance de votre équilibreur de charge pour vous assurer que le nombre d'hôtes sains est toujours supérieur à 0.

Si vous effectuez un contrôle de santé HTTP , il doit renvoyer un code 200 (la liste des codes valides est configurable dans les paramètres de l'équilibreur de charge) uniquement lorsque votre serveur est vraiment opérationnel. Sinon, l'équilibreur de charge pourrait mettre à disposition des instances qui ne sont pas encore entièrement exécutées.

Si le problème est que vous obtenez toujours une 503 bad gateway, cela peut être dû au fait que vos instances mettent trop de temps à répondre (pendant l'initialisation du service), alors ECS les considérer comme fermés et les fermer avant la fin de leur initialisation. C'est souvent le cas lors de la première exécution de Jenkins .

Pour éviter ce dernier problème, vous pouvez envisager d'adapter votre équilibreur de charge cible ping ( cible de contrôle de santé pour un équilibreur de charge classique , écouteur pour une application équilibreur de charge ):

  • Avec un équilibreur de charge d'application , essayez avec quelque chose qui renverra toujours 200 (pour Jenkins, il peut s'agir d'un fichier public comme /robots.txt par exemple ).
  • Avec un équilibreur de charge classique , utilisez un test de port TCP plutôt qu'un test HTTP . Il réussira toujours si vous avez correctement ouvert le port.

Un nœud par instance

Si vous devez vous assurer que vous n'avez qu'un seul nœud par instance, vous pouvez utiliser un équilibreur de charge classique (il se comporte également bien avec ECS ). Avec équilibreurs de charge classiques , ECS garantit qu'une seule instance s'exécute par serveur. C'est aussi la seule solution à avoir des ports non HTTP accessibles (par exemple Jenkins a besoin de 80, mais aussi 50000 pour les esclaves).

Cependant, comme les ports ne sont pas dynamiques avec un équilibreur de charge classique, vous devez effectuer un mappage de port, par exemple:

myloadbalancer.mydomain.com:80 (port 80 de l'équilibreur de charge) -> instance: 8081 (port externe de votre conteneur) -> service: 80 (port interne de votre conteneur).

Et bien sûr, vous avez besoin d'un équilibreur de charge par service.

Bilan de santé Jenkins

Si c'est vraiment un service Jenkins que vous souhaitez lancer, vous devez utiliser le Jenkins Metrics plugin pour obtenir une bonne URL de contrôle de santé .

Installez-le, et dans les options globales, générez un jeton et activez le ping, et vous devriez pouvoir atteindre une URL ressemblant à ceci: http://myjenkins.domain.com/metrics/mytoken12b3ad1/ping

Cette URL ne répondra au code HTTP 200 que lorsque le serveur est en cours d'exécution, ce qui est important pour l'équilibreur de charge pour l'activer uniquement lorsqu'il est complètement prêt.

Journaux

Enfin, si vous voulez savoir ce qui arrive à votre instance et pourquoi elle échoue, vous pouvez ajouter des journaux pour voir ce que le conteneur dit dans AWS Cloudwatch.

Ajoutez simplement ceci dans la définition de tâche (conteneur conf):

Configuration du journal: awslogs
awslogs-group: mycompany (la clé Cloudwatch qui regroupera vos journaux de conteneur)
awslogs-region: us-east-1 (votre région de cluster)
awslogs-stream-prefix: myservice (un préfixe pour créer le nom du journal)

Il vous donnera plus d'informations sur ce qui se passe lors de l'initialisation d'un conteneur, si cela prend trop de temps ou s'il échoue.

J'espère que cela aide!!!

1
arvymetal