概要
- AWS Elastic Beanstalkを使えば、EC2でのOSやミドルウェアのセットアップ不要でコマンド1つでWebアプリ実行環境を構築することができます。セキュリティパッチ等も自動適用できるため運用が軽くなるメリットもある上、ベースはEC2等AWSのコンポーネントの組み合わせなので、その気になれば色々カスタマイズもできるという、とても使い勝手の良いサービスです。
- 本稿ではEB CLIというツールをつかってコマンド1つでJava Web アプリの実行環境を構築します。
- Java Webアプリは、Tomcatで動作するWARではなく、Java SEでつくったスッピンのWebアプリ(JAR)が対象です。
(つまり概念さえ理解できればWebアプリFrameworkはSpring BootでもPlay frameworkでもかまいませんし、アプリサーバーもTomcatでもJettyでもGlassfishでもOKです) - また、続編で独自ドメイン対応、HTTPS対応、HTTP→HTTPSへのリダイレクト対応、Auto Scaling設定をします。
環境・構成
以下のような構成をコマンドラインから作ります
(コマンドラインから作るので環境の量産、再構築もカンタン)
- アプリ・プラットフォーム
- AWS Elastic Beanstalkの Java 8 プラットフォーム
- 本稿ではJSP/ServletのWebアプリをJetty9で実行
- クラウド環境
- サービス:AWS Elastic Beanstalk (EC2 + Application Loadbalancer on VPC)
- リージョン:東京(ap-northeast-1) →東京じゃなくてもOK
ソースコード
本稿で紹介する全ソースコードはこちらにあります
https://github.com/riversun/java-jetty-app-on-elasticbeanstalk
本編
Elastic Beanstalk コマンドラインインターフェイス(EB CLI)のインストール
Elastic BeanstalkアプリはWeb GUIをつかっても構築できるが、環境構築の自動化など本番運用を考えるとコマンドラインを使うと同じような操作を何度もせずにすみ手間もへるし、アプリ・環境の構築・変更がコマンド一発で済のでCIに組み込むなどすれば安定した運用が可能となる。
1.EB CLIをインストールする
EB CLIのインストールにはPythonが必要となる。
もし、PCにPythonがインストールされていなければ、
https://www.anaconda.com/distribution/
などからインストールしておく。最新版をインストールしておけばOK
Pythonがインストールが完了していれば、以下のコマンドで EB CLI をインストールできる
pip install awsebcli --upgrade --user
2.以下のコマンドでインストール終了チェック
EB CLIがインストールされ、コマンドラインで利用可能になっているかどうか、以下のコマンドで確認する
eb --version
EB CLI 3.15.2 (Python 3.7.1)
ちゃんとインストールできた模様
TIPS
Windows環境の場合、eb コマンドがみつからない場合がある。
そのときは、
C:\Users\[ユーザー名]\AppData\Roaming\Python\Python37\Scripts
をパスに追加する
JavaでWebアプリを作る
Elastic Beanstalkで作るJavaアプリは FAT JAR形式で作る
Elastic BeanstalkでJava Webアプリを実行するにはいくつかの方法がある。
- warファイルをアップロード(Tomcatで実行する)
- JARファイルをアップロード(Java SE環境で実行する)
本稿では JARファイルをアップロード する方式を採用する。
JARファイルとは、Javaで作ったアプリ(Webアプリ)のソースコード+依存ファイルを1つのJARにまとめたモノの事を言う。全部1つにしてサイズの大きなJARを作るので「FAT JAR」とも言う。
JARを使うメリットは、作ったWebアプリをJARファイルにさえできれば、何でもOKということ。
FrameworkはPlay Frameworkでも、Spring Bootでも、Strutsでも、JSFでも良いし(もちろん素のJSP/ServletでもOK)、APサーバーもTomcatでもJettyでもGlassfishでもUndertow(Wildfly)でもOK。
ただしJARをつくってElastic Beanstalkで動かすには、「Elastic Beanstalkのお作法」があるので、そちらをみていく。
といっても、難しくはない。
Elastic Beanstalk用のJavaソースコード構成
Web APサーバーとしてJettyを使ったJava Webアプリを考える。
まず、全体像は以下のとおり。「★」印がついているところが Elastic Beanstalkのための構成
その他はJavaのMavenプロジェクトの標準的なソースコード構成となる
elastic-beantalk-java-app
├── src/main/java ・・・Javaのソースコードのルートディレクトリ
│ └── myserver
│ └── StartServer.java
├── src/main/resources
│ └── webroot ・・・静的WebコンテンツやJSPのルートディレクトリ
│ ├── index.html
│ └── show.jsp
├── src/main/assembly
│ └── zip.xml ・・・★elastic beanstalkにアップロードするZIPファイルの生成ルールを記述
├── .elasticbeanstalk ・・・★Elastic Beanstalkへのデプロイ情報を格納するディレクトリ
│ └── config.yml ・・・★Elastic Beanstalkへのデプロイ情報のYAMLファイル
├── target ・・・ビルドした結果(jarなど)が生成されるディレクトリ
├── Procfile ・・・★Elastic BeanstalkのEC2上でJARファイルを実行するためのスクリプトを記述する
└── pom.xml ・・・Maven用設定ファイル
ソースコードや設定ファイル等の中身については後で説明するとして、
先にこのソースコードがどのようにビルドされて Elastic Beanstalkにアップロードされるかをみておく。
Elastic BeanstalkにアップロードするZIPファイルの構造
本稿では、手元のPCでソースコードをビルドして、それを1つのJARファイルにパッケージし、さらにJARファイル以外にもElastic Beanstalkに必要なファイル含めてZIPファイルを生成する。
ここで、JavaのソースコードをビルドしてできたFAT JARのファイル名をeb-app-jar-with-dependencies.jarとする。(maven-assembly-pluginで生成する、後で説明)
ElasticBeanstalkにアップロードするためのZIPファイル名をmy-jetty-app-eb.zipとすると、そのZIPファイルの中身構造は以下となる。
my-jetty-app-eb.zip
├── my-jetty-app-jar-with-dependencies.jar ・・・Javaのソースコードを1つのJARにパッケージしたもの
└── Procfile ・・・Elastic BeanstalkのEC2内でJARを実行するためのスクリプト
ZIPファイルの中には、ソースをまとめたJARファイルと、実行スクリプトの書いてあるファイルであるProcfileの2つとなる。
ということで、この形式のZIPファイルをEB CLI経由でElastic Beanstalkにアップロードすればデプロイできる。
これが「Elastic Beanstalkのお作法」の1つということになる。
次は、Javaアプリのソースをみていく。
とくに「Elastic Beanstalkのお作法」に関連する部分を中心に説明する
Javaアプリのソースコードの作り方
これからJavaアプリを動かそうとしているElastic Beanstalk環境は以下のようなもので、Java Webアプリとしてケアしておくべき点はポート番号 5000をListenするところ
つまり、Javaでポート番号 5000をListenするサーバープログラムを作ってあげればひとまずOK
サンプルコード
ということでサンプルコードを以下のリポジトリに置いた
https://github.com/riversun/java-jetty-app-on-elasticbeanstalk
このサンプルはServlet/JSP/プッシュ通知機能をJetty上動作させている
このコードをクローンすると
clone https://github.com/riversun/java-jetty-app-on-elasticbeanstalk.git
前述したとおり以下のようなソースコード構成となっている。
(一部ファイルは省略)
elastic-beantalk-java-app
├── src/main/java ・・・Javaのソースコードのルートディレクトリ
│ └── myserver
│ └── StartServer.java
├── src/main/resources
│ └── webroot ・・・静的WebコンテンツやJSPのルートディレクトリ
│ ├── index.html
│ └── show.jsp
├── src/main/assembly
│ └── zip.xml ・・・★elastic beanstalkにアップロードするZIPファイルの生成ルールを記述
├── .elasticbeanstalk ・・・★Elastic Beanstalkへのデプロイ情報を格納するディレクトリ
│ └── config.yml ・・・★Elastic Beanstalkへのデプロイ情報のYAMLファイル
├── target ・・・ビルドした結果(jarなど)が生成されるディレクトリ
├── Procfile ・・・★Elastic BeanstalkのEC2上でJARファイルを実行するためのスクリプトを記述する
└── pom.xml ・・・Maven用設定ファイル
※「★」印がついているところが Elastic Beanstalkのための構成
Javaアプリとしてのメインクラス(エントリーポイント)は StartServer.javaとなる。
これをローカル実行して http://localhost:5000/ にアクセスすれば、以下のようになり
JSPやServletなどのシンプルな実装を試すことができるサンプルとなっている。
ここからは、ソースコードで重要なところを以下に説明する
src/main/java myserver.StartServer.java
メインクラス。
Jettyを起動してServlet/JSPをホストしポート5000で待ち受ける
/pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.riversun</groupId>
<artifactId>my-jetty-app</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>my-jetty-app</name>
<description>jetty app on elastic beanstalk</description>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.riversun</groupId>
<artifactId>my-jetty-app</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>my-jetty-app</name>
<description>jetty app on elastic beanstalk</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jetty-version>9.4.19.v20190610</jetty-version>
</properties>
<dependencies>
<!-- for server -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-annotations</artifactId>
<version>${jetty-version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>${jetty-version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>apache-jsp</artifactId>
<version>${jetty-version}</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>apache-jstl</artifactId>
<version>${jetty-version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.9</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<excludes>
<exclude>examples/**/*</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
<configuration>
<author>true</author>
<source>1.7</source>
<show>protected</show>
<encoding>UTF-8</encoding>
<charset>UTF-8</charset>
<docencoding>UTF-8</docencoding>
<doclint>none</doclint>
<additionalJOption>-J-Duser.language=en</additionalJOption>
</configuration>
</plugin>
<!-- add source folders -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>src/main/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<!-- ソースコードをfat-jar化する -->
<execution>
<id>package-jar</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<appendAssemblyId>true</appendAssemblyId>
<archive>
<manifest>
<mainClass>myserver.StartServer</mainClass>
</manifest>
</archive>
<finalName>${project.artifactId}</finalName>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
<!-- Elastic Beanstalkにアップロードするzip(fat.jarや関連ファイルを含む)を作成する -->
<execution>
<id>package-zip</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<appendAssemblyId>true</appendAssemblyId>
<finalName>${project.artifactId}</finalName>
<descriptors>
<descriptor>src/main/assembly/zip.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
</project>
以下、ポイントだけみていく。
mavenのartifactId
以下はartifactIdとしてmy-jetty-appとした。
この後のビルドで生成されるファイル名などもこのartifactIdの値が使われる
<groupId>org.riversun</groupId>
<artifactId>my-jetty-app</artifactId>
maven-assembly-pluginの設定
以下はmaven-assembly-pluginの設定を行っている。
maven-assembly-pluginとは、配布用のjarファイルやzipファイルを作るためのmavenプラグイン。
このmaven-assembly-pluginには2つのタスクをさせている。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<!-- ソースコードをfat-jar化する -->
<execution>
<id>package-jar</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<appendAssemblyId>true</appendAssemblyId>
<archive>
<manifest>
<mainClass>myserver.StartServer</mainClass>
</manifest>
</archive>
<finalName>${project.artifactId}</finalName>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
<!-- Elastic Beanstalkにアップロードするzip(fat.jarや関連ファイルを含む)を作成する -->
<execution>
<id>package-zip</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<appendAssemblyId>true</appendAssemblyId>
<finalName>${project.artifactId}</finalName>
<descriptors>
<descriptor>src/main/assembly/zip.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
その1 JARファイル生成
まず前半の設定に注目。
<execution>
<id>package-jar</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<appendAssemblyId>true</appendAssemblyId>
<archive>
<manifest>
<mainClass>myserver.StartServer</mainClass>
</manifest>
</archive>
<finalName>${project.artifactId}</finalName>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
ここで記述しているのはJavaソースコードを1つのJARファイルにまとめること。
つまり、FAT JARを作るためのタスク設定となる。
<mainClass>myserver.StartServer</mainClass>
はJARファイルを実行するときの起動クラス。
<finalName>${project.artifactId}</finalName>
は、最終的にできあがるJARファイルのファイル名がartifactIdで指定された値=my-jetty-app-[AssemblyId].jarとなる。
<descriptorRef>jar-with-dependencies</descriptorRef>
はmavenのdependenciesに記載した依存ライブラリも一緒にJARファイルとしてパッケージする。
<appendAssemblyId>true</appendAssemblyId>
は、生成されるJARファイルのファイル名にAssemblyIdをつけるか否かをセットする。もしこれをtrueにすると、JARファイル名はmy-jetty-app-jar-with-dependencies.jarとなる。
ここで設定した条件でJARファイルを生成するには
mvn package
とすればよい。するとtargetディレクトリにmy-jetty-app-jar-with-dependencies.jarが生成される
その2 ZIPファイルの生成
次は後半の設定
<execution>
<id>package-zip</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<appendAssemblyId>true</appendAssemblyId>
<finalName>${project.artifactId}</finalName>
<descriptors>
<descriptor>src/main/assembly/zip.xml</descriptor>
</descriptors>
</configuration>
</execution>
ここで記述しているのは、上でつくったJARファイルとElastic Beanstalk関連ファイル(Procfileなど)をZIPファイルにまとめるタスクとなる。
<finalName>${project.artifactId}</finalName>
としているところはJARのときと同じく生成されるファイル名を指定している。
ZIPの生成ルールは外だしされた設定ファイルである<descriptor>src/main/assembly/zip.xml</descriptor>
で設定する。
src/main/assembly/zip.xml
さて、その外だしされた zip.xmlをみてみる。
これは最終的にZIPファイルを生成するときの生成ルールとなる。
<include>
でJARファイルとProcfileなどを指定して、Elastic Beanstalkにアップロードする形式のZIPファイルの生成方法を指示している。
<?xml version="1.0" encoding="UTF-8"?>
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>eb</id>
<baseDirectory>/</baseDirectory>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<directory>${project.basedir}</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>Procfile</include>
<include>Buildfile</include>
<include>.ebextensions/*</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>my-jetty-app-jar-with-dependencies.jar</include>
<!-- <include>*.jar</include> -->
</includes>
</fileSet>
</fileSets>
</assembly>
最終的に生成されるZIPファイルのファイル名はmy-jetty-app-[id].zipとなる。
zip.xmlでは、<id>eb</id>
と指定しているので、生成されるZIPファイル名はmy-jetty-app-eb.zipとなる。
まとめると必要パッケージを生成するためのmavenコマンド mvn package
を実行するとmy-jetty-app-jar-with-dependencies.jarとmy-jetty-app-eb.zipの両方がtargetディレクトリ以下に生成されることになる。
ここは、あとで実際にdeployファイルを生成するところでもう一度確認する。
/Procfile
ProcfileはElastic BeanstalkのEC2内でJARを実行するためのファイル。
Elastic BeanstalkのEC2上でアプリを起動するためのコマンドをweb:
以下に記載する。
web: java -jar my-jetty-app-jar-with-dependencies.jar
↓のように起動オプションを記述してもOK
web: java -jar my-jetty-app-jar-with-dependencies.jar -Xms256m
詳細は公式参照
.elasticbeanstalk/config.yml
config.ymlにはデプロイ情報を記述する
ここにはElastic Beansalkにデプロイするファイルtarget/my-jetty-app-eb.zip
を指定している。
deploy:
artifact: target/my-jetty-app-eb.zip
Elastic Beanstalkにデプロイする際に、このファイルが参照される。
いまはdeploy:artifact:
しか記述していないが、これからEB CLIをつかってElastic Beanstalkのデプロイ設定をしていく過程でこのconfig.ymlに必要な値が追加されていく。
EB CLIを使ってアプリをデプロイする
ファイルの意味をざっくり理解できたところで、さっそくElastic Beanstalkにアプリをデプロイする。
EB CLIを使ってElastic BeanstalkアプリケーションをAWS上に作る
1.アプリのディレクトリに移動する
cd java-jetty-app-on-elasticbeanstalk
2.Elastic BeanstalkにJava用の箱*を作る
(* 箱=アプリケーション)
そのためのEB CLIのコマンドは以下の形式となる。
eb init アプリ名 --region リージョン名 --platform プラットフォーム |
ここではアプリ名をmy-eb-app、リージョンは東京リージョン(ap-northeast-1)、プラットフォームをjava-8とする
コマンドは以下のようになる。
eb init my-eb-app --region ap-northeast-1 --platform java-8
すると
Application my-eb-app has been created.
というメッセージがでて、
AWS Elasticbeanstalk上にアプリケーションの箱ができる
さっそくWebコンソールで確認すると箱(アプリケーション)ができている
さて、ソースコードにある**/.elasticbeanstalk/config.yml**を見てみる。
上記コマンドで、config.ymlも更新され、以下のようになっている。
branch-defaults:
master:
environment: null
deploy:
artifact: target/my-jetty-app-eb.zip
global:
application_name: my-eb-app
branch: null
default_ec2_keyname: null
default_platform: java-8
default_region: ap-northeast-1
include_git_submodules: true
instance_profile: null
platform_name: null
platform_version: null
profile: eb-cli
repository: null
sc: git
workspace_type: Application
TIPS
------------
もし、Credential情報が登録されていなければ、以下のようにaws-access-idとaws-secret-keyを聞かれるので入力する。
eb init my-eb-app --region ap-northeast-1 --platform java-8
You have not yet set up your credentials or your credentials are incorrect
You must provide your credentials.
(aws-access-id): xxxxx
(aws-secret-key): xxxxx
Application my-eb-app has been created.
1回入力すれば、[user]/.aws
ディレクトリ以下にconfigファイルができるので、次からは聞かれない。
------------
デプロイ用のパッケージを作る
さきほどみてきたように、Elastic BeanstalkにデプロイするためのZIPファイルを生成する。
ZIP生成はMavenでやるのでmaven package
コマンドをたたく
(cleanもついでにやっておくと、コマンドは以下のとおり)
mvn clean package
以下のようになり、無事 target/ディレクトリにmy-jetty-app-eb.zipが生成できた。
[INFO] --- maven-assembly-plugin:2.2-beta-5:single (package-zip) @ my-jetty-app ---
[INFO] Reading assembly descriptor: src/main/assembly/zip.xml
[INFO] Building zip: jetty-app-on-eb\target\my-jetty-app-eb.zip
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 32.984 s
[INFO] Finished at: 2019-07-01T15:55:14+09:00
[INFO] Final Memory: 37M/449M
[INFO] ------------------------------------------------------------------------
Elastic Beanstalkにデプロイし環境を構築する
いまから、つくったZIPファイルをEB CLIをつかってElastic Beanstalkにデプロイする
Elastic Beanstalkにデプロイするには、eb createコマンドを使う
eb createコマンドの使い方
eb createコマンドは以下のように指定する。
eb create 環境の名前 [オプション][オプション]・・・[オプション] |
オプションは以下のとおり
オプション | 説明 |
--cname | URLのCNAMEを指定。 例 CNAMEにmy-jetty-app-test を指定すると http://my-jetty-app-test.ap-northeast-1.elasticbeanstalk.com/ としてアクセスできる |
--instance_type | インスタンスタイプ。 t2シリーズを指定する場合はVPC必須 |
--elb-type | ロードバランサーのタイプ 「application」を指定すると アプリケーションロードバランサーになる。 あとで、独自ドメインやHTTPS対応するときにも ロードバランサーあると楽 |
--vpc.id | VPCのID |
--vpc.elbpublic | ロードバランサーを パブリックサブネットに置く |
--vpc.elbsubnets | ロードバランサーのサブネットIDを指定。 複数指定するときはカンマ区切り |
--vpc.publicip | Elastic BeanstalkのEC2を パブリックサブネットに置く |
--vpc.ec2subnets | Elastic Beanstalkの EC2のサブネットIDを指定。 複数指定するときはカンマ区切り |
詳しくは公式参照
それでは、
コマンドラインから以下を実行する。
eb create my-jetty-app-test --cname my-jetty-app-test --instance_type t2.small --elb-type application --vpc.id vpc-xxxxxxxxxxxxxxxxx --vpc.elbpublic --vpc.elbsubnets subnet-xxxxxxxxxxxxxxxxx,subnet-yyyyyyyyyyyyyyyyy --vpc.publicip --vpc.ec2subnets subnet-xxxxxxxxxxxxxxxxx,subnet-yyyyyyyyyyyyyyyyy
上記は実際のID等はダミーだが、環境名my-jetty-app-test、cnameがmy-jetty-app-testでEC2のインスタンスタイプがt2.small、ELB(ロードバランサー)がapplicationロードバランサー、VPCのIDがvpc-xxxxxxxxxxxxxxxxxとしてさきほどのZIPファイルをデプロイするコマンドとなる。
(どのZIPファイルがアップロードされるかは、.elasticbeanstalk/config.ymlで指定されているのでそれが参照される)
また、--vpc.elbpublic、--vpc.publicipはELB(ロードバランサー)とElastic BeanstalkのEC2が指定したVPC内のパブリックサブネットで実行されることを示している。--vpc.elbsubnetsと**--vpc.ec2subnets**それぞれおなじパブリック・サブネット(2つ)を指定してある。ELBはパブリックにアクセスできないとアプリにアクセスできないのでパブリックサブネットに置く。EC2側はパブリックサブネットに置く方法とプライベートサブネットにおく方法がある。本稿の例では、パブリックサブネットにおいているが、自動生成されたセキュリティグループによってELBからしかアクセスできないようになっている。ただし、パブリックIPは割り当てられる。
(よりセキュアにするにはEC2はプライベートサブネットに置くなど工夫ができるが、これはElastic BeanstalkというよりEC2,VPCまわりのセキュリティイシューなのでここでは割愛とする。)
さて、上記コマンドを実行すると、以下のようにアップロードから環境構築までが自動的に実行される。
Uploading: [##################################################] 100% Done...
Environment details for: my-jetty-app-test
Application name: my-eb-app
Region: ap-northeast-1
Deployed Version: app-1d5f-190705_00000
Environment ID: e-2abc
Platform: arn:aws:elasticbeanstalk:ap-northeast-1::platform/Java 8 running on 64bit Amazon Linux/2.8.6
Tier: WebServer-Standard-1.0
CNAME: my-jetty-app-test.ap-northeast-1.elasticbeanstalk.com
Updated: 2019-07-01 07:08:01.989000+00:00
Printing Status:
2019-07-01 07:08:00 INFO createEnvironment is starting.
2019-07-01 07:08:02 INFO Using elasticbeanstalk-ap-northeast-1-000000000000 as Amazon S3 storage bucket for environment data.
2019-07-01 07:08:23 INFO Created target group named: arn:aws:elasticloadbalancing:ap-northeast-1:000000000000:targetgroup/awseb-AWSEB-LMAAAA/000000000
2019-07-01 07:08:23 INFO Created security group named: sg-11111111111111111
2019-07-01 07:08:39 INFO Created security group named: sg-22222222222222222
2019-07-01 07:08:39 INFO Created Auto Scaling launch configuration named: awseb-e-xxxxxxxxxx-stack-AWSEBAutoScalingLaunchConfiguration-3V
2019-07-01 07:09:41 INFO Created Auto Scaling group named: awseb-e-xxxxxxxxxx-stack-AWSEBAutoScalingGroup-XXXXXXXXXXXX
2019-07-01 07:09:41 INFO Waiting for EC2 instances to launch. This may take a few minutes.
2019-07-01 07:09:41 INFO Created Auto Scaling group policy named: arn:aws:autoscaling:ap-northeast-1:000000000000:scalingPolicy:4e:autoScalingGroupName/awseb-e-
xxxxxxxxxx-stack-AWSEBAutoScalingGroup-XXXXXXXXXXXX:policyName/awseb-e-xxxxxxxxxx-stack-AWSEBAutoScalingScaleUpPolicy-FA
2019-07-01 07:09:42 INFO Created Auto Scaling group policy named: arn:aws:autoscaling:ap-northeast-1:000000000000:scalingPolicy:8a:autoScalingGroupName/awseb-e-
xxxxxxxxxx-stack-AWSEBAutoScalingGroup-XXXXXXXXXXXX:policyName/awseb-e-xxxxxxxxxx-stack-AWSEBAutoScalingScaleDownPolicy-SSZW
2019-07-01 07:09:57 INFO Created CloudWatch alarm named: awseb-e-xxxxxxxxxx-stack-AWSEBCloudwatchAlarmHigh-H0N
2019-07-01 07:09:57 INFO Created CloudWatch alarm named: awseb-e-xxxxxxxxxx-stack-AWSEBCloudwatchAlarmLow-BX
2019-07-01 07:10:34 INFO Created load balancer named: arn:aws:elasticloadbalancing:ap-northeast-1:000000000000:loadbalancer/app/awseb-AWSEB-1BQ
2019-07-01 07:10:34 INFO Created Load Balancer listener named: arn:aws:elasticloadbalancing:ap-northeast-1:000000000000:listener/app/awseb-AWSEB-1BQ
2019-07-01 07:11:05 INFO Application available at my-jetty-app-test.ap-northeast-1.elasticbeanstalk.com.
2019-07-01 07:11:05 INFO Successfully launched environment: my-jetty-app-test
環境構築が開始されると、Webコンソールでも状況を把握することができる。
デプロイできた模様
無事アプリが http://my-jetty-app-test.ap-northeast-1.elasticbeanstalk.com/ にデプロイされた模様
アクセスすると、
ちゃんとJSPやServletも動いている模様
まとめ
-
Java SEをつかったWebアプリをEB CLIをつかって、AWS Elastic Beanstalkにデプロイするまでの手順をハンズオン方式で紹介しました
-
結果、以下のような構成をコマンドから構築することができました
-
紹介した全ソースコードはこちらです
https://github.com/riversun/java-jetty-app-on-elasticbeanstalk.git -
続編「ゼロから始めるAWS Elastic Beanstalk #2」では、独自ドメイン対応、HTTPS対応、HTTP→HTTPSへのリダイレクト対応、Auto Scaling設定について、取り扱います。