single command deployのための gradle-aws-plugin講座
TRANSCRIPT
Single Command Deployのためのgradle-aws-plugin講座
~自動ビルド厨はここまで大きくなりました~
2015-09-26 クラスメソッド株式会社
都元ダイスケ
#seasarcon
自己紹介✦ よく訓練されたアップル信者、都元です。 ✦ Java屋出身のAWS屋 ✦ Java歴約10年?(since 2006) ✦ AWS歴約4年(since 2011夏) ✦ SSHしたら負けだと思っている。 ✦ Twitter @daisuke_m ✦ Seasar2からSpringへ
2009-03-14 Seasar Conference 2009 White
2008-09-06 Seasar Conference 2008 Autumn
2009-06-13 Seasar Conference 2009 Spring
Do you know?
✦ DBの進化的設計を実現する開発プロセス ✦ 要するにRailsのmigrationのような ✦ 現在のJavaでいうFlywayのような ✦ EclipseプラグインによるER図エディタ
2006-20Jiemam
スマートビルド / デプロイ
–Miyamoto, Daisuke (2006)
“リポジトリからコードをチェックアウトし、 必要に応じて環境固有の設定をした後、
コマンド1つで起動・デプロイができるべき”
2006年にここまで言ってたかどうか忘れましたが、 Seasar Conference 2008では確実に言ってた。
この考えは現在も変わっていません。
本日のアジェンダ✦ AWSというインフラ環境をざっとご紹介 ✦ 実演 Single Command Deploy
✦ Spring(!?)Bootアプリケーションを ✦ Dockerを使ってコンテナ化して ✦ Gradleによるタスクで ✦ AWS Elastic Beanstalk環境にデプロイ
いきなり実演(裏で✦ 前提条件(下記を満たしていれば、みんな出来るはず)
✦ Mac OS(Winでも動くかも…。未確認) w/ git ✦ インターネット接続回線があって ✦ AWSアカウントを持っていて ✦ EC2キーペアの発行・登録が終わっていて ✦ S3のバケットが1つ作ってあって ✦ アクセスキーを↓規定の場所に記述してある~/.aws/credentials
✦ http://dev.classmethod.jp/cloud/aws/exclusive-aws-credentials-location/
$ ### チェックアウト###
$ git clone [email protected]:classmethod-aws/berserker.git ~/tmp/sis-demo
$ cd ~/tmp/sis-demo
$ git checkout refs/tags/sis-demo
$ #### ここは各環境で異なるところ ###
$ cp env/_sample.gradle env/personal.gradle
$ sed -i '' -e 's/templateBucket:.*$/templateBucket: "cf-templates-1r72h3gknbax2-ap-northeast-1",/' env/personal.gradle
$ sed -i '' -e 's/KeyName:.*$/KeyName: "miyamoto-kp1",/' env/personal.gradle
$ diff env/_sample.gradle env/personal.gradle
$ ### デプロイ・HTTPアクセス・撤収 ###
$ ./gradlew -is awsFullDeploy
$ curl -s ...
$ ./gradlew -is awsFullUndeploy
Amazon VPC✦ VPC = 1つのプライベートネットワーク
✦ インターネット接続は任意 ✦ Availability Zone (AZ)
✦ 物理的に離れているけど高速な専用線で結ばれたDC
✦ VPC × AZ → Subnet
基本的な構成 (1) Single-AZ構成
✦ 可用性が足りない ✦ サービスを止めずにメンテナンスできない
✦ スケーラビリティが足りない ✦ 付加が増えても垂直にしかスケールできない
サーバは落ちるものだし、水平スケール出来るのが望ましい 可用性が欲しい・スケーラビリティが欲しい
Amazon EC2
✦ 結構気軽に「メンテだから再起動してね」って言われる。
✦ Multi-AZ による冗長化構成が前提。 ✦ メンテナンスだけでなく、障害にも対応。 ✦ Design for failure
基本的な構成 (2) Multi-AZ構成
✦ AZ(≒AWSのデータセンター)が1つ丸ごとぶっ飛んでも、サービスが継続できる
✦ 負荷が増えたら水平にスケールできる ✦ ただし、アプリケーション・サーバをステートレスに保たなければならない ✦ データをファイルシステムに書かない ✦ RDBやS3に書き出す
最近のJavaフレームワーク✦ Play Framework ✦ Dropwizard ✦ Ninja framework ✦ Spring Boot
✦ アプリケーションサーバ(コンテナ)準備不要の、スタンドアローンアプリ。
✦ Javaプロセスを1つ立ち上げればHTTPサーバが動く。
Spring Bootの主な特徴✦ 簡単起動
✦ $ java -jar your-app.jar ✦ クラスパス設定やコンテナ準備不要。
✦ 設定の自動化 ✦ classpath内のクラスの有無によって自動設定 ✦ 設定のカスタマイズはアノテーションで
✦ Spring Bootを使ってみよう ✦ http://dev.classmethod.jp/server-side/spring-boot/
Flyway ~ DBの進化的設計✦ Jiemamy is dead
✦ スキーマにバージョンを付与 ✦ 前バージョンからの差分SQLを自作する ✦ どこまで適用したかは、実際のDB上に管理テーブルを作って記録 ✦ 未適用の差分SQLを順次適用することによるマイグレーション ✦ ただし、自動化されたロールバックは不可能 ✦ Flyway with Spring Boot でDBマイグレーションを自動化する
✦ http://dev.classmethod.jp/server-side/flyway-with-spring-boot/
1プロセスのための環境✦ 一般的にサーバ上では様々なプロセスが起動 ✦ Applicationの実行には直接関係無いものも多数 ✦ Applicationプロセスとしてはザックリと、これだけあれば充分じゃない? ✦ プロセスが稼働する基盤(OSとメモリ空間?) ✦ プロセスが読み書きする状態(ファイルシステム)
✦ 他のプロセスは見えなくて良い。 ✦ 他のプロセス用のファイルも見えなくていい。
Docker for Spring Boot✦ 最小限のファイルシステムにJavaをインストールし、your-app.jar を取り込んだDockerイメージを作成
✦ イメージからDockerコンテナ(プロセス環境)を作成し、その中で java プロセスを起動
✦ Docker と Spring Boot は相性が良い。
Dockerfileの例FROM java:openjdk-8-jdkEXPOSE 8080WORKDIR /opt/berserker/ADD logback.xml /opt/berserker/logback.xmlADD berserker-x.xx.jar /opt/berserker/CMD /usr/bin/java \ -DJDBC_CONNECTION_STRING=$JDBC_CONNECTION_STRING \ ... -Dspring.profiles.active=$SPRING_PROFILES_ACTIVE \ -Dlogging.config=/opt/berserker/logback.xml \ -Dserver.port=8080 \ -jar berserker-x.xx.jar
OpenJDK 8 インストール済みの ファイルシステムイメージ
アプリケーション本体jarの組み込み
起動コマンド
Elastic Beanstalk
✦ AWS上のWebシステムの基本構成を自動構築 ✦ 開発者はApplication Bundle(後述)を作成し、AWSに食わせる
✦ これだけで、アプリの動作環境が構築完了する
Application Bundle
✦ Beanstalkの作法に従ったApp一式を含むZIPファイル ✦ Spring Bootアプリケーション(jar) ✦ logback.xml(ログ設定) ✦ Dockerfile(前述)
✦ これをZIPで固めてAmazon S3にアップロード
CloudFormation✦ Beanstalkの守備範囲
✦ アプリケーションサーバシステム ✦ ELB, EC2 (AutoScaling) ...
✦ CloudFormationの守備範囲 ✦ システム全体を構成する周辺AWSリソース
✦ Beanstalk, VPC, S3, RDS ...
アプリケーションのデプロイと システムのデプロイ
–Miyamoto, Daisuke
“リポジトリからコードをチェックアウトし、 必要に応じて環境固有の設定をした後、
コマンド1つでシステムの起動・デプロイができるべき”
CloudFormation
Template
+Parameter
Parameter
Stack
Bucket withObjects
DynamoDB Table
ELB
Instances Auto Scaling Amazon CloudFront
基本的システム構成S3, DynamoDB, EC2,
IAM, AutoScaling, SecurityGroup,ELB, CloudFront
Instance Type, クラスタの台数,
SSH接続元IP, キー名, ...等
インフラの進化的設計
• インフラの構成をTemplateとしてバージョン管理する
• TemplateからStackを作る(構築)
• インフラ構成を追加・編集(そしてバージョン管理)
• 既存Stackを新しいテンプレートで更新する(成長)
Gradle
✦ ビルド等を中心としたジョブ実行基盤 ✦ Javaの依存ライブラリ管理~ ビルド、パッケージング
✦ Spring Bootアプリケーションの起動 ✦ プラグイン:spring-boot-gradle-plugin
ではこれを…
✦ App Bundleの作成に使えないだろうか? ✦ App BundleのS3 uploadに使えないだろうか? ✦ Beanstalkの環境起動に使えないだろうか?
✦ 全部Yes!!
App Bundle作成task createBundle(type: Zip, dependsOn: bootRepackage) { archiveName = ... // zipファイル名 from "src/main/bundle" // Dockerfile等 from jar.archivePath // jar}
gradle-aws-plugin
✦ GradleからAWSリソースを操作したい ✦ 参考: https://github.com/classmethod-aws/gradle-aws-plugin
導入buildscript { repositories { mavenCentral() maven { url "https://plugins.gradle.org/m2/" } } dependencies { classpath "jp.classmethod.aws:gradle-aws-plugin:0.21" } } apply plugin: "jp.classmethod.aws.s3" apply plugin: "jp.classmethod.aws.cloudformation"apply plugin: "jp.classmethod.aws.beanstalk"
CloudFormation操作cloudFormation { stackName = 'berserker' conventionMapping.stackParams = { // (snip) return stackParams } capabilityIam true templateFile = file('berserker.template') templateBucket = ... templateKeyPrefix = ... } awsCfnMigrateStack.mustRunAfter uploadBundleawsCfnMigrateStack.dependsOn awsCfnUploadTemplate
S3へのリソースアップロード
task createBundle(type: Zip, dependsOn: ...) { // (snip) }
task uploadBundle(dependsOn: createBundle, type: AmazonElasticBeanstalkUploadBundleTask) { file project.createBundle.archivePath overwrite project.version.endsWith('-SNAPSHOT')}
一発タスクtask awsFullDeploy(dependsOn: [ uploadBundle, awsCfnUploadTemplate, awsCfnMigrateStackAndWaitComplete ]) task awsFullUndeploy(dependsOn: [ awsCfnDeleteStackAndWaitCompleted ])
Full Described System✦ システム構築及び運用のコード化・自動化―― Automated
✦ 自動化しない・できない部分はポエムを書く―― Documented
✦ システムの構成全てが「記述」されている。
✦ 1つのAWSアカウント内に複数の環境を構築できる。 ✦ 例えば本番環境と開発環境等。 ✦ 社内で共通のAWSアカウントに展開する。
✦ あらゆるAWSアカウントに環境を構築できる。 ✦ 例えば個人検証環境。サンドボックス。 ✦ 開発者毎の個人検証用AWSアカウントに展開する。
✦ あらゆるリージョンに環境を構築できる。 ✦ と、いいかもね。DRの視点で。
環境依存設定✦ プロジェクト直下のenvディレクトリに設定ファイルを置き、それを動的に読み込む
-Penv=prd
✦env/ ✦ .gititnore ✦ _sample.gradle ✦prd.gradle ✦dev.gradle ✦personal.gradle
✦profile名(AWSのキー) ✦リージョン名 ✦EC2キーファイルのパス ✦各種CFnパラメータ ✦ローカルDB名、user、pass ✦ログ設定ファイルのパス
portability✦ ./gradlew awsFullDeploy -Penv=prd
✦ ./gradlew awsFullDeploy -Penv=dev
✦ ./gradlew awsFullDeploy -Penv=personal
✦ 詳しくは Developers.IO「プロジェクトに対する環境固有設定の導入」http://bit.ly/gradle-env-dep-config を参照。