AppSyncのデプロイについてまとめてみた
はじめに
ある案件でAppSyncを使うことになったが、商用利用の事例が少なくデプロイ方法がわからなかった。
自動でデプロイできる仕組みを探したところ、Serverless FrameworkのAppSyncプラグインがあったので使ってみた。
AppSyncとは
AppSyncはAWSで利用できるGraphQLベースのマネージドサービスである。
特徴として
- バックエンドサービスを自由に切り替えることができる
- GraphQLベースのため、フロントエンドに必要なデータを定義できる
などがある。
特にバックエンドにはLambdaやDynamoDB、HTTPなど多様なリソースを選択できる。
前提
今回の案件では以下の条件があった。
- AppSyncをLambdaバックエンドとHTTPバックエンドの二種類を実装
- フロントエンドはアプリ(iOS, Android) とWebアプリ(JavaScript)
- 環境は開発環境・検証環境・本番環境の3つ
- CloudFormation経験は薄く、Sceptreを使ってECS(Fargate)を作成した経験のみ
デプロイ方法の選定
現状AppSyncを商用利用して、デプロイするためには以下の手段が考えられた。
- CloudFormationを書く
- Amplify CLIを使う
CloudFormationを使ってデプロイするためにはYaml地獄と戦い、トライアンドエラーを繰り返す必要がある。 時間的猶予がなかったため却下した。
Amplify CLIはコマンド一つでAWSリソースを作ることができる強者である。 しかし、以下の懸念点があった。
- 開発当初は
env
機能がなかったため、環境を複数設定できない - 複数のフロントエンドで共有することが難しい
そのため、リソースの作成にAmplify CLIを使用しなかった。
他に良いデプロイ方法はないか探していたら、以下の記事に遭遇し、ServerlessFrameworkのAppSyncプラグインを知った。
read.acloud.guru
Serverless Frameworkを使う予定があったので、試してみたら思いのほか手軽だった。
ここからは実際にデプロイした手順を記録していく。
Serverless FrameworkでAppSyncデプロイ
今回はAppSyncのバックエンドにLambdaを使用する。 GraphQL SchemaにはブログWebアプリケーションを想定に実装する。
サンプルはGitHubにもあげているので併せてみていただきたい。
CLIインストール
NPMでインストールする。
$ npm install -g serverless
プロジェクト初期化
プロジェクトを初期化する。
このタイミングでは package.json
は作成されていない。
$ serverless create --template aws-nodejs --path appsync-deploy $ cd appsync-deploy $ ls -a .gitignore handler.js serverless.yml
create
コマンドを実行するには template
オプションが必要である。
template
の種類は以下に詳細が記載されている。
成果物のうち serverless.yml
はCloudFormationのもとになるYaml定義。
handler.js
はAWS Lambdaを使用する場合の実行ファイルのため、AppSyncのデプロイだけでは不要である。
プラグインのインストール
ServerlessFrameworkのプラグインはNPMパッケージでまとめられているため、 package.json
でプラグインを管理していく。
Node環境がまだないので、改めてNPM初期化を実施する
$ git init $ npm init This utility will walk you through creating a package.json file. It only covers the most common items, and tries to guess sensible defaults. See `npm help json` for definitive documentation on these fields and exactly what they do. Use `npm install <pkg>` afterwards to install a package and save it as a dependency in the package.json file. Press ^C at any time to quit. package name: (appsync-deploy) version: (1.0.0) description: entry point: (handler.js) test command: git repository: keywords: author: license: (ISC) About to write to appsync-deploy/package.json: { "name": "appsync-deploy", "version": "1.0.0", "description": "", "main": "handler.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC" }
AppSyncプラグインをインストールする。
$ npm i serverless serverless-appsync-plugin
デプロイコマンドをNPMの scripts
に定義する。
"scripts": { "deploy": "serverless deploy -v" },
これでデプロイを実行する準備が整った。
serverless.yml
を整えながら、AppSyncの設定を加えていく。
Serverless Framework共通設定
はじめに基本設定を記述していく。
serverless.yml
を開くと例が記載されているが、今回必要な部分は少ないので消す。
service: appsync-deploy provider: name: aws region: ap-northeast-1 plugins: - serverless-appsync-plugin
service
はCloudFormationのStack Nameに使用される部分であり、
デプロイ環境の総称となる。今回はプロジェクトのディレクトリ名を使用する。
provider
はCloud Providers(AWS)およびリージョンの設定をする。
plugins
にはインストールしたAppSyncのプラグインを記述する。
AppSyncの基本設定
このサンプルではAppSyncの認証に Amazon Cognitoを選択する。
Schemaは簡易的にするために Query
と Mutation
を一つずつにした。
Schemaの詳細を以下に記載する。
schema { query: Query mutation: Mutation } type Query { listArticle: ArticlesResponse } type Mutation { createArticle(title: String, content: String): ArticlesResponse } type Article { id: Int title: String content: String } type ArticlesResponse { errorCode: String articles: [Article] }
Schemaと認証設定を serverless.yml
に追記する。
custom: accountId: ${env:AWS_ACCOUNT_ID} appSync: name: BlogApp # AppSyncのAPI名 authenticationType: AMAZON_COGNITO_USER_POOLS # API Keyなど選択 userPoolConfig: # Cognitoの設定 awsRegion: ap-northeast-1 defaultAction: ALLOW userPoolId: ap-northeast-1_XXXXX schema: schema.graphql
Data Sources
バックエンドにはLambdaを使用するため、二つのARNが必要になる。
- LambdaそのもののARN
- AppSyncがLambdaを実行するRoleのARN
Roleはデフォルトの設定で作成されないため、事前にコンソールから作るか、
Serverless Frameworkの resources
機能で作る。
DataSourcesを serverless.yml
に反映すると以下になる。
custom: accountId: ${env:AWS_ACCOUNT_ID} appSync: name: BlogApp # AppSyncのAPI名 authenticationType: AMAZON_COGNITO_USER_POOLS # API Keyなど選択 userPoolConfig: # Cognitoの設定 awsRegion: ap-northeast-1 defaultAction: ALLOW userPoolId: ap-northeast-1_XXXXX schema: schema.graphql dataSources: - type: AWS_LAMBDA name: BlogAppResolver config: functionName: blog-app-resolver lambdaFunctionArn: "arn:aws:lambda:ap-northeast-1:${env:AWS_ACCOUNT_ID}:function:blog-app-resolver" serviceRoleArn: "arn:aws:iam::${env:AWS_ACCOUNT_ID}:role/service-role/appsync-ds-lam-xxxxxxxxxxxxx
Mapping Templates
最後にMapping Templatesを整える。
Mapping Templatesのリクエストとレスポンスそれぞれをファイル化し、 mapping-templates
ディレクトリに格納することでAppSyncに反映する仕組みになっている。
レスポンスのMapping Templatesは共通化させて設定した。
レスポンス
common-response.vtl
$util.toJson($context.result)
Queryのリクエスト
query-list-blog-request.vtl
{ "version" : "2017-02-28", "operation": "Invoke", "payload": { "path": "list_blog", "data": $util.toJson($context.args) } }
Mutationのリクエスト
mutation-create-blog-request.vtl
{ "version" : "2017-02-28", "operation": "Invoke", "payload": { "path": "create_blog", "data": $util.toJson($context.args) } }
これらを mapping-templates
ディレクトリ以下に格納する。ディレクトリ名は変更することもできる。
Mapping Templatesの設定を serverless.yml
に反映すると以下のようになる。
custom: accountId: ${env:AWS_ACCOUNT_ID} appSync: name: BlogApp # AppSyncのAPI名 authenticationType: AMAZON_COGNITO_USER_POOLS # API Keyなど選択 userPoolConfig: # Cognitoの設定 awsRegion: ap-northeast-1 defaultAction: ALLOW userPoolId: ap-northeast-1_H8OHxpYAa schema: schema.graphql dataSources: - type: AWS_LAMBDA name: BlogAppResolber config: functionName: blog-app-resolver lambdaFunctionArn: "arn:aws:lambda:ap-northeast-1:${env:AWS_ACCOUNT_ID}:function:blog-app-resolver" serviceRoleArn: "arn:aws:iam::${env:AWS_ACCOUNT_ID}:role/service-role/appsync-ds-lam-ln4jdz-blog-app-resolver" mappingTemplates: - dataSources: BlogAppResolber type: Query # Query, Mutation, Subscription field: listArticle # Schema内のフィールド名 request: "query-list-blog-request.vtl" response: "common-response.vtl" - dataSources: BlogAppResolber type: Mutation field: createArticle request: "mutation-create-blog-request.vtl" response: "common-response.vtl"
デプロイ実行
package.json
に登録したコマンドでデプロイを実行する。
サンプルはCognitoやRole ARNを仮で記載しているので、編集してから実行する。
$ npm run deploy
エラーが出る場合は環境変数に SLS_DEBUG
を追加することで、実行の詳細を確認することができる。
$ export SLS_DEBUG=*
Serverless Frameworkは最初に、 serverless.yml
ファイルをコンパイルして、CloudFormationに変換し、S3バケットに格納する。
成果物は .serverless
ディレクトリにも保存される。
S3に格納されたら、CloudFormationが実行され、定義したAWSリソースが生成される。
まとめ
- AppSyncの情報は少ない
- デプロイはServerless Frameworkが便利