クラスタリング付き Express アプリケーションを Elastic Beanstalk にデプロイする - AWS Elastic Beanstalk

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

クラスタリング付き Express アプリケーションを Elastic Beanstalk にデプロイする

このチュートリアルでは、Elastic Beanstalk コマンドラインインターフェイス (EB CLI) を使用してサンプルアプリケーションを Elastic Beanstalk にデプロイし、Express フレームワーク、Amazon ElastiCache、クラスタリングを使用するようにアプリケーションを更新する手順を説明します。クラスターはウェブアプリケーションの高可用性、パフォーマンスおよびセキュリティを拡張します。Amazon の詳細については ElastiCache、「Amazon ElastiCache for Memcached ユーザーガイド」の「Amazon for Memcached とは」を参照してください。 ElastiCache

注記

この例では、課金される可能性のある AWS リソースを作成します。 AWS 料金の詳細については、「」を参照してくださいhttps://aws.amazon.com/pricing/。一部の サービスは AWS 無料利用枠の一部です。新規のお客様は、無料でこれらのサービスをテストできる場合があります。詳細については、「https://aws.amazon.com/free/」を参照してください。

前提条件

このチュートリアルでは、次の前提条件が必要です。

  • Node.js ランタイム

  • デフォルトの Node.js パッケージマネージャーソフトウェア、npm

  • Express コマンドラインジェネレーター

  • Elastic Beanstalk コマンドラインインターフェイス(EB CLI)

最初の 3 つのリストされたコンポーネントのインストールとローカル開発環境の設定の詳細については、「Node.js 開発環境を設定します」を参照してください。このチュートリアルでは、 AWS SDK for Node.js をインストールする必要はありません。これは、参照トピックでも説明されています。

EB CLI をインストールおよび設定する手順の詳細については、「EB CLI のインストール」および「EB CLI の設定」を参照してください。

Elastic Beanstalk 環境の作成

アプリケーションディレクトリ

このチュートリアルでは、アプリケーションソースバンドル用に nodejs-example-express-elasticache と呼ばれるディレクトリを使用します。このチュートリアル用の nodejs-example-express-elasticache ディレクトリを作成します。

~$ mkdir nodejs-example-express-elasticache
注記

この章の各チュートリアルでは、アプリケーションソースバンドル用に独自のディレクトリを使用します。ディレクトリ名は、チュートリアルで使用されるサンプルアプリケーションの名前と一致します。

現在の作業ディレクトリを nodejs-example-express-elasticache に変更します。

~$ cd nodejs-example-express-elasticache

次に、Node.js プラットフォームとサンプルアプリケーションを実行する Elastic Beanstalk 環境を設定しましょう。Elastic Beanstalk コマンドラインインターフェイス (EB CLI) を使用します。

アプリケーションの EB CLI リポジトリを設定し、Node.js プラットフォームを実行する Elastic Beanstalk 環境を作成するには
  1. eb init コマンドを使用してリポジトリを作成します。

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

    このコマンドは、.elasticbeanstalk という名前のフォルダに、アプリケーションの環境作成用の設定ファイルを作成し、現在のフォルダに基づいた名前で Elastic Beanstalk アプリケーションを作成します。

  2. eb create コマンドを使用して、サンプルアプリケーションを実行する環境を作成します。

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

    このコマンドは、Node.js プラットフォームと以下のリソース用にデフォルト設定でロードバランスされた環境を作成します。

    • EC2 インスタンス – 選択したプラットフォームでウェブ・アプリケーションを実行するよう設定された Amazon Elastic Compute Cloud (Amazon EC2) 仮想マシン。

      各プラットフォームは、それぞれ特定の言語バージョン、フレームワーク、ウェブコンテナ、またはそれらの組み合わせをサポートするための、特定のソフトウェア、設定ファイル、スクリプトを実行します。ほとんどのプラットフォームでは、Apache または NGINX のいずれかをウェブアプリケーションの前にリバースプロキシとして配置します。そのプロキシがリクエストをアプリケーションに転送し、静的アセットを提供し、アクセスログとエラーログを生成します。

    • インスタンスセキュリティグループ – ポート 80 上のインバウンドトラフィックを許可するよう設定された Amazon EC2 セキュリティグループ。このリソースでは、ロードバランサーからの HTTP トラフィックが、ウェブ・アプリケーションを実行している EC2 インスタンスに達することができます。デフォルトでは、トラフィックは他のポート上で許可されません。

    • ロードバランサー – アプリケーションを実行するインスタンスにリクエストを分散するよう設定された Elastic Load Balancing ロードバランサー。ロードバランサーにより、インスタンスを直接インターネットに公開する必要もなくなります。

    • ロードバランサーセキュリティグループ – ポート 80 上のインバウンドトラフィックを許可するよう設定された Amazon EC2 セキュリティグループ。このリソースでは、インターネットからの HTTP トラフィックが、ロードバランサーに達することができます。デフォルトでは、トラフィックは他のポート上で許可されません。

    • Auto Scaling グループ – インスタンスが終了されたか利用不可になった場合にそのインスタンスを置き換えるよう設定された Auto Scaling グループ。

    • Amazon S3 バケット – Elastic Beanstalk の使用時に作成されるソースコード、ログ、その他のアーティファクトの保存場所。

    • Amazon CloudWatch アラーム – 環境内のインスタンスの負荷を監視し、負荷が高すぎるか低すぎる場合にトリガーされる 2 つの CloudWatch アラーム。アラームがトリガーされると、Auto Scaling グループはレスポンスとしてスケールアップまたはダウンを行います。

    • stackAWS CloudFormation – Elastic Beanstalk は AWS CloudFormation を使用して環境内のリソースを起動し、設定の変更を伝達します。リソースは、AWS CloudFormation コンソールに表示できるテンプレートで定義されます。

    • ドメイン名 – ウェブ・アプリケーションまでのルートとなるドメイン名であり、subdomain.region.elasticbeanstalk.com の形式です。

      注記

      Elastic Beanstalk アプリケーションのセキュリティを強化するため、elasticbeanstalk.com ドメインはパブリックサフィックスリスト (PSL) に登録されています。セキュリティ強化のため、Elastic Beanstalk アプリケーションのデフォルトドメイン名に機密な Cookie を設定する必要が生じた場合は、__Host- プレフィックスの付いた Cookie の使用をおすすめします。この方法は、ドメインをクロスサイトリクエストフォージェリ (CSRF) の攻撃から守るのに役立ちます。詳細については、Mozilla 開発者ネットワークの「Set-Cookie」ページを参照してください。

  3. 環境の作成が完了したら、eb open コマンドを使用して、デフォルトのブラウザでその環境の URL を開きます。

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

これで、サンプルアプリケーションを使用して Node.js Elastic Beanstalk 環境が作成されました。独自のアプリケーションで更新できます。次に、Express フレームワークを使用するようサンプルアプリケーションを更新します。

Express を使用するようアプリケーションを更新する

Elastic Beanstalk 環境にサンプルアプリケーションを更新して、Express フレームワークを使用するようにします。

最終的なソースコードは nodejs-example-express-elasticache.zip からダウンロードできます。

Express を使用するようアプリケーションを更新するには

サンプルアプリケーションの環境を作成したら、その環境を使用するようにアプリケーションを更新できます。この手順では、まず expressnpm install コマンドを実行して、アプリケーションディレクトリで Express フレームワークを設定します。

  1. express コマンドを実行します。これによって、package.jsonapp.js、およびいくつかのディレクトリが生成されます。

    ~/nodejs-example-express-elasticache$ express

    プロンプトが表示されたら、続行するには y と入力します。

    注記

    express コマンドが機能しない場合は、前述の「前提条件」セクションで説明したように Express コマンドラインジェネレーターがインストールされていない可能性があります。または、express コマンドを実行するために、ローカルマシンのディレクトリパス設定を行う必要がある場合があります。開発環境の設定に関する詳細なステップについては、「前提条件」セクションを参照して、このチュートリアルを続行してください。

  2. ローカルの依存関係を設定します。

    ~/nodejs-example-express-elasticache$ npm install
  3. (オプション) ウェブアプリサーバーが起動することを確認します。

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

    次のような出力が表示されます:

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

    サーバーは、デフォルトでポート 3000 で実行されます。テストするには、別のターミナルで curl http://localhost:3000 を実行するか、ローカルコンピュータでブラウザを開いて URL アドレス http://localhost:3000 を入力します。

    サーバーを停止するには、[Ctrl+C] を押します。

  4. nodejs-example-express-elasticache/app.jsnodejs-example-express-elasticache/express-app.js に名前変更します。

    ~/nodejs-example-express-elasticache$ mv app.js express-app.js
  5. nodejs-example-express-elasticache/express-app.jsvar app = express(); 行を次に更新します。

    var app = module.exports = express();
  6. ローカルコンピュータで、以下のコードを含む nodejs-example-express-elasticache/app.js という名前のファイルを作成します。

    /** * 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. nodejs-example-express-elasticache/bin/www ファイルの内容を次に置き換えます。

    #!/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. eb deploy コマンドを使用して変更を Elastic Beanstalk 環境にデプロイします。

    ~/nodejs-example-express-elasticache$ eb deploy
  9. 数分後、環境が更新されます。環境が緑色で示されていて準備完了したら、URL を再表示して正しく動作することを確認します。ウェブページに "Welcome to Express" が表示されます。

アプリケーションを実行している EC2 インスタンスのログにアクセスできます。ログのアクセス手順については、「Elastic Beanstalk 環境の Amazon EC2 インスタンスからのログの表示」を参照してください。

次に、Amazon を使用するように Express アプリケーションを更新します ElastiCache。

Amazon を使用するように Express アプリケーションを更新するには ElastiCache
  1. ローカルコンピュータで、出典バンドルの最上位ディレクトリに .ebextensions ディレクトリを作成します。この例では、nodejs-example-express-elasticache/.ebextensions を使用します。

  2. 次のスニペットを使用して、設定ファイル nodejs-example-express-elasticache/.ebextensions/elasticache-iam-with-script.config を作成します。設定ファイルの詳細については、「Node.js 設定の名前空間」を参照してください。elasticache ノードの検出に必要な許可を持つ IAM ユーザーが作成され、キャッシュが変更されると常にファイルに書き込みされます。nodejs-example-express-elasticache.zip からファイルをコピーすることもできます。プロパティの詳細については、 ElastiCache「」を参照してください例: ElastiCache

    注記

    YAML は、一貫したインデントに依存します。設定ファイルの例でコンテンツを置き換える際はインデントレベルを一致させ、テキストエディタがインデントにタブ文字ではなくスペースを使用していることを確認します。

    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. ローカルコンピュータnodejs-example-express-elasticache/.ebextensions/elasticache_settings.configで、次のスニペットを使用して設定ファイルを作成し、 を設定します ElastiCache。

    option_settings: "aws:elasticbeanstalk:customoption": CacheNodeType: cache.t2.micro NumCacheNodes: 1 Engine: memcached NodeListPath: /var/nodelist
  4. ローカルコンピュータで、nodejs-example-express-elasticache/express-app.js を次のスニペットに置き換えます。このファイルでは、ディスクからノードリストを読み取り(/var/nodelist)、ノードが存在する場合は memcached をセッションを保存するとして使用するよう Express を設定します。ファイルは次のようになります。

    /** * 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. ローカルコンピュータで、package.json を次の内容で更新します。

    "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. npm install を実行します。

    ~/nodejs-example-express-elasticache$ npm install
  7. 更新したアプリケーションをデプロイします。

    ~/nodejs-example-express-elasticache$ eb deploy
  8. 数分後、環境が更新されます。環境が緑色で示され準備が完了したら、コードが機能することを確認します。

    1. Amazon CloudWatch コンソールをチェックして、 ElastiCache メトリクスを表示します。 ElastiCache メトリクスを表示するには、左側のペインでメトリクスを選択し、 を検索しますCurrItemsElastiCache > キャッシュノードメトリクス を選択し、キャッシュノードを選択してキャッシュ内の項目数を表示します。

      注記

      アプリケーションのデプロイ先と同じリージョンを調べていることを確認してください。

      アプリケーション URL をコピーして別のウェブブラウザに貼り付けてページを更新すると、5 分後に CurrItem カウントが上昇するはずです。

    2. ログのスナップショットを取得します。ログの取得の詳細については、「Elastic Beanstalk 環境の Amazon EC2 インスタンスからのログの表示」を参照してください。

    3. ログバンドルの /var/log/nodejs/nodejs.log ファイルをチェックします。次のような結果が表示されます。

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

クリーンアップ

アプリケーションを実行したくない場合は、環境を終了し、アプリケーションを削除してクリーンアップできます。

環境を終了するには eb terminate コマンドを、アプリケーションを削除するには eb delete コマンドを使用します。

環境を終了するには

ローカルリポジトリを作成したディレクトリから、eb terminate を実行します。

$ eb terminate

このプロセスには数分かかることがあります。環境が正常に終了すると、Elastic Beanstalk にメッセージが表示されます。