はじめに
Rには、スクリプトをREST APIにできる"plumber"というパッケージがあります。今回はイメージ化したplumberの環境を、ECSハンズオンの構成で動かしてみました。
参考
やったこと
作業はCloud9で行いました。
ディレクトリ・ファイル作成
まずは各種準備です。
# プロジェクトのディレクトリ作成
mkdir test-plumber && cd test-plumber
# イメージプル
docker pull r-base
# 必要なファイルを作成
touch Dockerfile
touch plumber.R
touch sample.R
Dockerfileは以下になります。参考にしたページとは、インストールするパッケージがあったり、ポート番号が異なったりしています。
FROM r-base
COPY sample.R /usr/local/src/
COPY plumber.R /usr/local/src/
WORKDIR /usr/local/src/
# install the linux libraries needed for plumber
RUN apt-get update -qq && apt-get install -y \
libsodium-dev \
libcurl4-gnutls-dev
RUN R -e 'install.packages("plumber")'
EXPOSE 80
ENTRYPOINT ["Rscript", "plumber.R"]
以下はRになります。
library(plumber)
api <- plumber::plumb("sample.R")
api$run(host = "0.0.0.0", port=80)
#* @get /hello
hw <- function() {
return("Hello, world!")
}
#* @get /hello/<name>/<age:int>
hw <- function(name, age) {
return(paste("Hello", name, "You're", age, "years old", seq=" "))
}
#* @get /fn
hw <- function(x) {
x <- as.numeric(x)
y <- 2 * x + 1
return(y)
}
#irisを読み込み
df <- iris
#* @get /plot
#* @png
hw <- function() {
p <- plot(df$Sepal.Length, df$Sepal.Width,
main="Sample plot", xlab="Sepal.Length", ylab="Sepal.Width")
print(p)
}
イメージのBuild
ファイルに記述できたらbuildしていきます。
# よく使う文字列を環境変数にセット
REGION="ap-northeast-1"
ACCOUNTID=$(aws sts get-caller-identity --output text --query Account)
IMAGENAME="test-plumber"
# build 5分強
docker build -t ${IMAGENAME} .
# テストで起動
docker run --rm -p 8080:80 ${IMAGENAME}
# 別コンソールから
curl localhost:8080/hello
curl localhost:8080/hello/jiro/22
コンテナイメージを、ECR にアップロードする
リポジトリ作成
CLIでやっていくため、CFnで作成します。
# ECRリポジトリ作成CFn
touch createECRRepository.yaml
AWSTemplateFormatVersion: "2010-09-09"
Resources:
########################################################
### ECR Repository
########################################################
TestEcrPoc:
Type: AWS::ECR::Repository
Properties:
RepositoryName: test-plumber-ecs
Outputs:
RepositoryUri:
Value: !GetAtt TestEcrPoc.RepositoryUri
ECRを作成して、PUSHします。
# ECRにレポジトリ作成
STACKNAME="create-ecrrepo"
aws cloudformation create-stack --stack-name ${STACKNAME} --template-body file://createECRRepository.yaml --region ${REGION}
# イメージにタグ付与
TAGNAME=`aws cloudformation describe-stacks --stack-name ${STACKNAME} --query "Stacks[].Outputs[?OutputKey=='RepositoryUri'].[OutputValue]" --output text`:latest
docker tag ${IMAGENAME}:latest ${TAGNAME}
# 認証
aws ecr get-login-password --region ${REGION} | docker login --username AWS --password-stdin ${ACCOUNTID}.dkr.ecr.${REGION}.amazonaws.com
# 作ったイメージをPUSH
docker push ${TAGNAME}
VPC作成
ハンズオンにあるように作ります。詳細はハンズオンを確認ください。
セキュリティグループを修正し、インバウンドルールにHTTPをすべてのIPから有効にする。
クラスターの作成
ECSにてクラスター名とVPCのみ指定して作成します。こちらも詳細はハンズオン資料にあります。
タスク定義
タスク定義ファイミリーと、コンテナ名、イメージURIを設定します。イメージURIは、以下のコマンドの結果を使うと楽かと思います。
echo `aws cloudformation describe-stacks --stack-name ${STACKNAME} --query "Stacks[].Outputs[?OutputKey=='RepositoryUri'].[OutputValue]" --output text`:latest
サービス作成
作成したクラスターでサービスを作成します。ハンズオン資料は「デプロイ」とありますが、コンソールの表示が異なるようです。
"ロードバランシング -オプション"を開いて、ロードバランサーも設定します。
ヘルスチェックパスは/hello
と設定。
作成されるまで待ちます。
正常に作成されると以下のようになりました
接続
ネットワーキングのタブのDNS名でアクセスします。
URLの最後に/hello
を付けて再アクセスです。
その他、/hello/jiro/21
の場合。
/fn?x=2
の場合。
/plot
の場合。
削除
ハンズオン資料にありますが、今はある程度まとめて消してくれるようです。
-
ALB(後でまとめて削除される) -
TargetGroup(後でまとめて削除される) -
ECS Service の Task 数を 0 に変更(後でまとめて削除される) - ECS Service の削除
- クラスターの削除
- タスク定義の削除
- VPC の削除
- ECR の削除
- Cloud9 の削除
ALBとTargetGroupは、ECS Service作成時に実行されるCloudformationのスタックにて定義されており、コンソールからの削除で、そのスタックで作成されたリソースはすべて消えます。
また削除時のメッセージを見る限り、0にスケールダウンしなくてもOKな模様です。
タスク定義は手動で削除する必要があります。対象のタスク定義の登録解除を行います。
その後、"非アクティブなタスク"にして削除します。DELETE_IN_PROGRESS
から消えるまで、30分程度かかる模様です。
ECRはCloudformationで作成したので、スタックを削除すればOKです。削除前にイメージを削除しておいてください。
おわりに
今回はECSのハンズオンを少し変えて、自作のイメージとしてR(plumber)を用いてみました。
簡単にスケーリングするRのスクリプト環境を作れるのが大変魅力的に感じました。