Déploiement d'une application Express avec une mise en cluster dans Elastic Beanstalk - AWS Elastic Beanstalk

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Déploiement d'une application Express avec une mise en cluster dans Elastic Beanstalk

Ce didacticiel explique comment déployer un exemple d'application sur Elastic Beanstalk à l'aide de l'CLIinterface de ligne de commande (EB) d'Elastic Beanstalk, puis comment mettre à jour l'application pour utiliser le framework Express, Amazon et le clustering. ElastiCache La mise en cluster permet d'améliorer la haute disponibilité, les performances et la sécurité de votre application web. Pour en savoir plus sur Amazon ElastiCache, rendez-vous sur Qu'est-ce qu'Amazon ElastiCache (Memcached) ? dans le guide de l'utilisateur d'Amazon ElastiCache (Memcached).

Note

Cet exemple crée AWS des ressources qui peuvent vous être facturées. Pour plus d'informations sur la AWS tarification, consultezhttps://aws.amazon.com/pricing/. Certains services font partie du niveau d'utilisation AWS gratuit. Si vous êtes un nouveau client, vous pouvez essayer ces services gratuitement. Pour plus d’informations, consultez https://aws.amazon.com/free/.

Prérequis

Ce tutoriel nécessite les prérequis suivants :

  • Les exécutions Node.js

  • Le logiciel de gestion des packages Node.js par défaut, npm

  • Le générateur de ligne de commande Express

  • L'interface de ligne de commande (EB) d'Elastic Beanstalk CLI

Pour plus d'informations sur l'installation des trois premiers composants et la configuration de votre environnement de développement local, consultez Configuration de votre environnement de développement Node.js. Pour ce didacticiel, il n'est pas nécessaire d'installer le fichier AWS SDK for Node.js, qui est également mentionné dans la rubrique référencée.

Pour plus de détails sur l'installation et la configuration de l'EBCLI, reportez-vous Installation de l'interface de ligne de commande EB aux sections etConfiguration de l'interface de ligne de commande EB.

Créer un environnement Elastic Beanstalk

Votre répertoire d'application

Ce tutoriel utilise un répertoire appelé nodejs-example-express-elasticache pour la création de la solution groupée de l'application. Créez le répertoire nodejs-example-express-elasticache pour ce tutoriel.

~$ mkdir nodejs-example-express-elasticache
Note

Chaque tutoriel de ce chapitre utilise son propre répertoire pour la solution groupée de l'application. Le nom du répertoire correspond au nom de l'exemple d'application utilisé par le tutoriel.

Changez votre répertoire de travail actuel vers nodejs-example-express-elasticache.

~$ cd nodejs-example-express-elasticache

Configurons maintenant un environnement Elastic Beanstalk exécutant la plateforme Node.js et l'exemple d'application. Nous utiliserons l'interface de ligne de commande (EB) d'Elastic Beanstalk. CLI

Pour configurer un CLI référentiel EB pour votre application et créer un environnement Elastic Beanstalk exécutant la plateforme Node.js
  1. Créez un référentiel à l'aide de la commande eb init.

    ~/nodejs-example-express-elasticache$ eb init --platform node.js --region <region>

    Cette commande crée un fichier de configuration dans un dossier nommé .elasticbeanstalk qui spécifie les paramètres de création d'environnements pour votre application et crée une application Elastic Beanstalk dont le nom est basé sur le dossier actif.

  2. Créez un environnement qui exécute un exemple d'application à l'aide de la commande eb create.

    ~/nodejs-example-express-elasticache$ eb create --sample nodejs-example-express-elasticache

    Cette commande crée un environnement à charge équilibrée avec les paramètres par défaut de la plateforme Node.js et les ressources suivantes :

    • EC2instance — Une machine virtuelle Amazon Elastic Compute Cloud (AmazonEC2) configurée pour exécuter des applications Web sur la plateforme de votre choix.

      Chaque plateforme exécute un ensemble spécifique de logiciels, de fichiers de configuration et de scripts pour prendre en charge une version de langage, une infrastructure ou un conteneur web spécifiques, ou une combinaison de ces éléments. La plupart des plateformes utilisent Apache ou NGINX un proxy inverse qui se trouve devant votre application Web, lui transmet les demandes, fournit des ressources statiques et génère des journaux d'accès et d'erreurs.

    • Groupe de sécurité d'instance : groupe EC2 de sécurité Amazon configuré pour autoriser le trafic entrant sur le port 80. Cette ressource permet au HTTP trafic provenant de l'équilibreur de charge d'atteindre l'EC2instance qui exécute votre application Web. Par défaut, le trafic n'est pas autorisé sur les autres ports.

    • Équilibreur de charge – Équilibreur de charge Elastic Load Balancing configuré pour répartir les demandes vers les instances exécutant votre application. De plus, l'équilibreur de charge vous évite d'exposer directement vos instances sur Internet.

    • Groupe de sécurité d'équilibrage de charge : groupe EC2 de sécurité Amazon configuré pour autoriser le trafic entrant sur le port 80. Cette ressource permet au HTTP trafic provenant d'Internet d'atteindre l'équilibreur de charge. Par défaut, le trafic n'est pas autorisé sur les autres ports.

    • Groupe Auto Scaling – Groupe Auto Scaling configuré pour remplacer une instance si elle est résiliée ou devient indisponible.

    • Compartiment Amazon S3 – Emplacement de stockage pour votre code source, les journaux et autres artefacts qui sont créés lorsque vous utilisez Elastic Beanstalk.

    • CloudWatch Alarmes Amazon : deux CloudWatch alarmes qui surveillent la charge sur les instances de votre environnement et qui sont déclenchées si la charge est trop élevée ou trop faible. Lorsqu'une alarme est déclenchée, votre groupe Auto Scaling s'adapte en fonction, à la hausse ou à la baisse.

    • AWS CloudFormation stack — Elastic AWS CloudFormation Beanstalk utilise pour lancer les ressources de votre environnement et propager les modifications de configuration. Les ressources sont définies dans un modèle, que vous pouvez afficher dans la console AWS CloudFormation.

    • Nom de domaine : nom de domaine qui permet d'accéder à votre application Web sous la forme subdomain.region.elasticbeanstalk.com.

      Note

      Pour renforcer la sécurité de vos applications Elastic Beanstalk, le domaine elasticbeanstalk.com est enregistré dans la liste des suffixes publics (). PSL Pour plus de sécurité, nous vous recommandons d'utiliser des cookies avec un préfixe __Host- si vous devez définir des cookies sensibles dans le nom de domaine par défaut de vos applications Elastic Beanstalk. Cette pratique vous aidera à défendre votre domaine contre les tentatives de falsification de requêtes intersites ()CSRF. Pour plus d'informations, consultez la page Set-Cookie du Mozilla Developer Network.

  3. Lorsque la création de l'environnement est terminée, utilisez la eb opencommande pour ouvrir l'environnement URL dans le navigateur par défaut.

    ~/nodejs-example-express-elasticache$ eb open

Vous avez maintenant créé un environnement Node.js Elastic Beanstalk avec un exemple d'application. Vous pouvez le mettre à jour avec votre propre application. Ensuite, nous mettons à jour l'exemple d'application afin d'utiliser l'infrastructure Express.

Mise à jour de l'application pour utiliser Express

Mettez à jour l'exemple d'application dans l'environnement Elastic Beanstalk pour utiliser le cadre Express.

Vous pouvez télécharger le code source final depuis le nodejs-example-express-elasticachefichier .zip.

Pour mettre à jour votre application afin d'utiliser Express

Une fois que vous avez créé un environnement avec un exemple d'application, vous pouvez le mettre à jour à l'aide de votre propre application. Dans cette procédure, nous exécutons d'abord les commandes express et npm install pour configurer le cadre Express dans votre répertoire d'application.

  1. Exécutez la commande express. Il en résulte la génération de package.json, app.js, et de quelques répertoires.

    ~/nodejs-example-express-elasticache$ express

    Lorsque vous êtes invité à continuer, tapez y.

    Note

    Si la commande express ne fonctionne pas, il se peut que vous n'ayez pas installé le générateur de ligne de commande Express, comme décrit dans la section précédente sur les prérequis. Il se peut également que le chemin d'accès au répertoire de votre ordinateur local doive être configuré pour permettre l'exécution de la commande express. Consultez la section Prérequis pour connaître les étapes détaillées de la configuration de votre environnement de développement, afin de pouvoir poursuivre ce tutoriel.

  2. Configurez les dépendances locales.

    ~/nodejs-example-express-elasticache$ npm install
  3. (Facultatif) Vérifiez que le serveur de l'application web démarre.

    ~/nodejs-example-express-elasticache$ npm start

    Vous devez voir des résultats similaires à ce qui suit :

    > nodejs@0.0.0 start /home/local/user/node-express > node ./bin/www

    Par défaut, le serveur s'exécute sur le port 3000. Pour le tester, lancez-le curl http://localhost:3000 dans un autre terminal ou ouvrez un navigateur sur l'ordinateur local et entrez URL l'adressehttp://localhost:3000.

    Appuyez sur Ctrl+C afin d'arrêter le serveur.

  4. Renommez nodejs-example-express-elasticache/app.js en nodejs-example-express-elasticache/express-app.js.

    ~/nodejs-example-express-elasticache$ mv app.js express-app.js
  5. Mettez à jour la ligne var app = express(); dans nodejs-example-express-elasticache/express-app.js avec les éléments suivants :

    var app = module.exports = express();
  6. Sur votre ordinateur local, créez un fichier nommé nodejs-example-express-elasticache/app.js avec le code suivant.

    /** * Module dependencies. */ const express = require('express'), session = require('express-session'), bodyParser = require('body-parser'), methodOverride = require('method-override'), cookieParser = require('cookie-parser'), fs = require('fs'), filename = '/var/nodelist', app = express(); let MemcachedStore = require('connect-memcached')(session); function setup(cacheNodes) { app.use(bodyParser.raw()); app.use(methodOverride()); if (cacheNodes.length > 0) { app.use(cookieParser()); console.log('Using memcached store nodes:'); console.log(cacheNodes); app.use(session({ secret: 'your secret here', resave: false, saveUninitialized: false, store: new MemcachedStore({ 'hosts': cacheNodes }) })); } else { console.log('Not using memcached store.'); app.use(session({ resave: false, saveUninitialized: false, secret: 'your secret here' })); } app.get('/', function (req, resp) { if (req.session.views) { req.session.views++ resp.setHeader('Content-Type', 'text/html') resp.send(`You are session: ${req.session.id}. Views: ${req.session.views}`) } else { req.session.views = 1 resp.send(`You are session: ${req.session.id}. No views yet, refresh the page!`) } }); if (!module.parent) { console.log('Running express without cluster. Listening on port %d', process.env.PORT || 5000) app.listen(process.env.PORT || 5000) } } console.log("Reading elastic cache configuration") // Load elasticache configuration. fs.readFile(filename, 'UTF8', function (err, data) { if (err) throw err; let cacheNodes = [] if (data) { let lines = data.split('\n'); for (let i = 0; i < lines.length; i++) { if (lines[i].length > 0) { cacheNodes.push(lines[i]) } } } setup(cacheNodes) }); module.exports = app;
  7. Remplacez le contenu du fichier nodejs-example-express-elasticache/bin/www par ce qui suit :

    #!/usr/bin/env node /** * Module dependencies. */ const app = require('../app'); const cluster = require('cluster'); const debug = require('debug')('nodejs-example-express-elasticache:server'); const http = require('http'); const workers = {}, count = require('os').cpus().length; function spawn() { const worker = cluster.fork(); workers[worker.pid] = worker; return worker; } /** * Get port from environment and store in Express. */ const port = normalizePort(process.env.PORT || '3000'); app.set('port', port); if (cluster.isMaster) { for (let i = 0; i < count; i++) { spawn(); } // If a worker dies, log it to the console and start another worker. cluster.on('exit', function (worker, code, signal) { console.log('Worker ' + worker.process.pid + ' died.'); cluster.fork(); }); // Log when a worker starts listening cluster.on('listening', function (worker, address) { console.log('Worker started with PID ' + worker.process.pid + '.'); }); } else { /** * Create HTTP server. */ let server = http.createServer(app); /** * Event listener for HTTP server "error" event. */ function onError(error) { if (error.syscall !== 'listen') { throw error; } const bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port; // handle specific listen errors with friendly messages switch (error.code) { case 'EACCES': console.error(bind + ' requires elevated privileges'); process.exit(1); break; case 'EADDRINUSE': console.error(bind + ' is already in use'); process.exit(1); break; default: throw error; } } /** * Event listener for HTTP server "listening" event. */ function onListening() { const addr = server.address(); const bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port; debug('Listening on ' + bind); } /** * Listen on provided port, on all network interfaces. */ server.listen(port); server.on('error', onError); server.on('listening', onListening); } /** * Normalize a port into a number, string, or false. */ function normalizePort(val) { const port = parseInt(val, 10); if (isNaN(port)) { // named pipe return val; } if (port >= 0) { // port number return port; } return false; }
  8. Déployez les modifications dans votre environnement Elastic Beanstalk avec la commande eb deploy.

    ~/nodejs-example-express-elasticache$ eb deploy
  9. Votre environnement est mis à jour au bout de quelques minutes. Une fois que l'environnement est vert et prêt, actualisez-le URL pour vérifier qu'il fonctionne. Vous devriez voir une page web indiquant « Welcome to Express ».

Vous pouvez accéder aux journaux des EC2 instances qui exécutent votre application. Pour plus d'informations sur l'accès à vos journaux, consultez Affichage des journaux des instances Amazon EC2 dans votre environnement Elastic Beanstalk.

Ensuite, mettons à jour l'application Express pour utiliser Amazon ElastiCache.

Pour mettre à jour votre application Express afin d'utiliser Amazon ElastiCache
  1. Sur votre ordinateur local, créez un répertoire .ebextensions dans le répertoire de niveau supérieur de votre groupe source. Dans cet exemple, nous utilisons nodejs-example-express-elasticache/.ebextensions.

  2. Créez un fichier de configuration nodejs-example-express-elasticache/.ebextensions/elasticache-iam-with-script.config avec l'extrait suivant. Pour plus d'informations sur le fichier de configuration, consultez Espaces de noms de la configuration Node.js. Cela crée un IAM utilisateur avec les autorisations requises pour découvrir les nœuds Elasticache et écrit dans un fichier chaque fois que le cache change. Vous pouvez également copier le fichier depuis un fichier nodejs-example-express-elasticache.zip. Pour plus d'informations sur les ElastiCache propriétés, consultezExemple : ElastiCache.

    Note

    YAMLrepose sur une indentation cohérente. Respectez le niveau de retrait lorsque vous remplacez du contenu dans un exemple de fichier de configuration et veillez à ce que votre éditeur de texte utilise des espaces, et non des caractères de tabulation, pour la mise en retrait.

    Resources: MyCacheSecurityGroup: Type: 'AWS::EC2::SecurityGroup' Properties: GroupDescription: "Lock cache down to webserver access only" SecurityGroupIngress: - IpProtocol: tcp FromPort: Fn::GetOptionSetting: OptionName: CachePort DefaultValue: 11211 ToPort: Fn::GetOptionSetting: OptionName: CachePort DefaultValue: 11211 SourceSecurityGroupName: Ref: AWSEBSecurityGroup MyElastiCache: Type: 'AWS::ElastiCache::CacheCluster' Properties: CacheNodeType: Fn::GetOptionSetting: OptionName: CacheNodeType DefaultValue: cache.t2.micro NumCacheNodes: Fn::GetOptionSetting: OptionName: NumCacheNodes DefaultValue: 1 Engine: Fn::GetOptionSetting: OptionName: Engine DefaultValue: redis VpcSecurityGroupIds: - Fn::GetAtt: - MyCacheSecurityGroup - GroupId AWSEBAutoScalingGroup : Metadata : ElastiCacheConfig : CacheName : Ref : MyElastiCache CacheSize : Fn::GetOptionSetting: OptionName : NumCacheNodes DefaultValue: 1 WebServerUser : Type : AWS::IAM::User Properties : Path : "/" Policies: - PolicyName: root PolicyDocument : Statement : - Effect : Allow Action : - cloudformation:DescribeStackResource - cloudformation:ListStackResources - elasticache:DescribeCacheClusters Resource : "*" WebServerKeys : Type : AWS::IAM::AccessKey Properties : UserName : Ref: WebServerUser Outputs: WebsiteURL: Description: sample output only here to show inline string function parsing Value: | http://`{ "Fn::GetAtt" : [ "AWSEBLoadBalancer", "DNSName" ] }` MyElastiCacheName: Description: Name of the elasticache Value: Ref : MyElastiCache NumCacheNodes: Description: Number of cache nodes in MyElastiCache Value: Fn::GetOptionSetting: OptionName : NumCacheNodes DefaultValue: 1 files: "/etc/cfn/cfn-credentials" : content : | AWSAccessKeyId=`{ "Ref" : "WebServerKeys" }` AWSSecretKey=`{ "Fn::GetAtt" : ["WebServerKeys", "SecretAccessKey"] }` mode : "000400" owner : root group : root "/etc/cfn/get-cache-nodes" : content : | # Define environment variables for command line tools export AWS_ELASTICACHE_HOME="/home/ec2-user/elasticache/$(ls /home/ec2-user/elasticache/)" export AWS_CLOUDFORMATION_HOME=/opt/aws/apitools/cfn export PATH=$AWS_CLOUDFORMATION_HOME/bin:$AWS_ELASTICACHE_HOME/bin:$PATH export AWS_CREDENTIAL_FILE=/etc/cfn/cfn-credentials export JAVA_HOME=/usr/lib/jvm/jre # Grab the Cache node names and configure the PHP page aws cloudformation list-stack-resources --stack `{ "Ref" : "AWS::StackName" }` --region `{ "Ref" : "AWS::Region" }` --output text | grep MyElastiCache | awk '{print $4}' | xargs -I {} aws elasticache describe-cache-clusters --cache-cluster-id {} --region `{ "Ref" : "AWS::Region" }` --show-cache-node-info --output text | grep '^ENDPOINT' | awk '{print $2 ":" $3}' > `{ "Fn::GetOptionSetting" : { "OptionName" : "NodeListPath", "DefaultValue" : "/var/www/html/nodelist" } }` mode : "000500" owner : root group : root "/etc/cfn/hooks.d/cfn-cache-change.conf" : "content": | [cfn-cache-size-change] triggers=post.update path=Resources.AWSEBAutoScalingGroup.Metadata.ElastiCacheConfig action=/etc/cfn/get-cache-nodes runas=root sources : "/home/ec2-user/elasticache" : "https://elasticache-downloads.s3.amazonaws.com/AmazonElastiCacheCli-latest.zip" commands: make-elasticache-executable: command: chmod -R ugo+x /home/ec2-user/elasticache/*/bin/* packages : "yum" : "aws-apitools-cfn" : [] container_commands: initial_cache_nodes: command: /etc/cfn/get-cache-nodes
  3. Sur votre ordinateur local, créez un fichier de configuration nodejs-example-express-elasticache/.ebextensions/elasticache_settings.config avec l'extrait de code suivant à configurer. ElastiCache

    option_settings: "aws:elasticbeanstalk:customoption": CacheNodeType: cache.t2.micro NumCacheNodes: 1 Engine: memcached NodeListPath: /var/nodelist
  4. Sur votre ordinateur local, remplacez nodejs-example-express-elasticache/express-app.js par l'extrait suivant. Ce fichier lit la liste des nœuds depuis le disque (/var/nodelist) et configure Express de façon à utiliser memcached comme magasin de sessions s'il existe des nœuds. Votre fichier doit se présenter comme suit :

    /** * Module dependencies. */ var express = require('express'), session = require('express-session'), bodyParser = require('body-parser'), methodOverride = require('method-override'), cookieParser = require('cookie-parser'), fs = require('fs'), filename = '/var/nodelist', app = module.exports = express(); var MemcachedStore = require('connect-memcached')(session); function setup(cacheNodes) { app.use(bodyParser.raw()); app.use(methodOverride()); if (cacheNodes) { app.use(cookieParser()); console.log('Using memcached store nodes:'); console.log(cacheNodes); app.use(session({ secret: 'your secret here', resave: false, saveUninitialized: false, store: new MemcachedStore({'hosts': cacheNodes}) })); } else { console.log('Not using memcached store.'); app.use(cookieParser('your secret here')); app.use(session()); } app.get('/', function(req, resp){ if (req.session.views) { req.session.views++ resp.setHeader('Content-Type', 'text/html') resp.write('Views: ' + req.session.views) resp.end() } else { req.session.views = 1 resp.end('Refresh the page!') } }); if (!module.parent) { console.log('Running express without cluster.'); app.listen(process.env.PORT || 5000); } } // Load elasticache configuration. fs.readFile(filename, 'UTF8', function(err, data) { if (err) throw err; var cacheNodes = []; if (data) { var lines = data.split('\n'); for (var i = 0 ; i < lines.length ; i++) { if (lines[i].length > 0) { cacheNodes.push(lines[i]); } } } setup(cacheNodes); });
  5. Sur votre ordinateur local, mettez à jour package.json avec le contenu suivant :

    "dependencies": { "cookie-parser": "~1.4.4", "debug": "~2.6.9", "express": "~4.16.1", "http-errors": "~1.6.3", "jade": "~1.11.0", "morgan": "~1.9.1", "connect-memcached": "*", "express-session": "*", "body-parser": "*", "method-override": "*" }
  6. Exécutez npm install.

    ~/nodejs-example-express-elasticache$ npm install
  7. Déployez l'application mise à jour.

    ~/nodejs-example-express-elasticache$ eb deploy
  8. Votre environnement est mis à jour au bout de quelques minutes. Une fois que votre environnement est prêt (il apparaît en vert), assurez-vous que le code a fonctionné.

    1. Consultez la CloudWatch console Amazon pour consulter vos ElastiCache statistiques. Pour afficher vos ElastiCache statistiques, sélectionnez Métriques dans le volet de gauche, puis recherchez CurrItems. Sélectionnez ElastiCache > Mesures du nœud de cache, puis sélectionnez votre nœud de cache pour afficher le nombre d'éléments contenus dans le cache.

      Amazon CloudWatch console showing ElastiCache metrics graph with CurrItems count over time. (AI generated)
      Note

      Vérifiez que vous consultez bien la même région que celle dans laquelle vous avez déployé votre application.

      Si vous copiez et collez votre application URL dans un autre navigateur Web et que vous actualisez la page, vous devriez voir votre CurrItem compte augmenter au bout de 5 minutes.

    2. Prenez un instantané de vos journaux. Pour de plus amples informations sur la récupération des journaux, veuillez consulter Affichage des journaux des instances Amazon EC2 dans votre environnement Elastic Beanstalk.

    3. Vérifiez le fichier /var/log/nodejs/nodejs.log dans le groupe des journaux. Le résultat devrait être similaire à ce qui suit :

      Using memcached store nodes: [ 'aws-my-1oys9co8zt1uo.1iwtrn.0001.use1.cache.amazonaws.com:11211' ]

Nettoyage

Si vous ne souhaitez plus exécuter votre application, vous pouvez effectuer un nettoyage en suspendant votre environnement et en supprimant votre application.

Utilisez la commande eb terminate pour mettre votre environnement hors service et la commande eb delete pour supprimer votre application.

Pour résilier votre environnement

Depuis le répertoire où vous avez créé votre référentiel local, exécutez eb terminate.

$ eb terminate

Ce processus peut prendre quelques minutes. Elastic Beanstalk affiche un message une fois que l'environnement est arrêté.