Serverless Framework v2で作った古いプロジェクトを深く考えずにv3に移行してみる


※ 当ページには【広告/PR】を含む場合があります。
2023/03/13
【Angularユーザーのための認証API自作講座②】Serverless FrameworkでCognitoオーソライザー付きRestAPIを構築する
蛸壺の技術ブログ|Serverless Frameworkでv2の古いプロジェクトを深く考えずにv3に移行してみる

気づくと
「Serverless Framework」v3系になって久しいですが、先日、だいぶ前に放置していたv2時代のプロジェクトもメンテナンスして復活させて使いたい、という話になりました。

Serverless Framework v2からv3への移行のポイントは公式でも説明されています。

Upgrading to Serverless Framework v3|serverless framework

このドキュメントにはなんだか細々しい内容が詳しく記載してありますが、割と関係ないオプションにも触れられているので、全てに目を通すのも億劫です。

「何も考えずにv2をv3にそのまま引き上げることはできないのか...」

という消極的なモチベーションのもとで、ここではserverlessのパッケージバージョンをv3にとりあえず引き上げてから、警告の内容を一つ一つ潰していくスタイルで移行していくときのメモ記事です。

先にこの記事での内容を先取りしておくと、

            
            1. Serverless Framework v2からv3への移行はさほど難しくない
2. AWSへのデプロイの場合にCloudFormation用のアクセスポリシーが新たに必要
3. Serverless Frameworkプラグインはv3移行後もほぼそのまま使える(と思って良い)
4. doctorサブコマンドを使ってserverless.ymlの非推奨項目を診断する
        
ということを以降で細かく説明していきます。


Serverless Framework v2からv3へのバージョン引き上げ

過去のServerless Framework v2の開発時期や状況・開発目標によっても状況が異なります。

今回は
AWS LambdaにExpressアプリをデプロイするときの使っていたプロジェクトを例に、v3への引き上げを行ってみましょう。

例えば手元のだいぶご無沙汰のプロジェクトで作成して放置していたv3引き上げ前の
package.jsonは以下のようになっていました。

            
            {
    //...
    "dependencies": {
        //...
        "aws-serverless-express": "^3.4.0",
        //...
    },
    "devDependencies": {
        //...
        "serverless": "^2.53.1",
        "serverless-apigw-binary": "^0.4.4",
        "serverless-domain-manager": "^6.0.0",
        //...
        
久しぶりすぎて、どのバージョンで使っていたのか思い出せません。

参考までにどのバージョンのslsが入っていたか確認してみます。

            
            $ npx sls --version
Framework Core: 2.72.3 (local)
Plugin: 5.5.4
SDK: 4.3.2
Components: 3.18.2
        
ではnpmjsなどの情報を元に、package.jsonを直接全てのパッケージを最新のものに手動引き上げを敢行します。

            
            {
    //...
    "devDependencies": {
        //...
        "serverless": "^3.28.1",
        //....
        
npmで最新のバージョンを確認していった限りでは、オプションプラグインの類はバージョンを上げる必要がないようだったので、ここではserverless本体だけのバージョンを上げることになりそうです。

この時点では、v3での既存のプラグインの扱いがどのようになっているかは深く考えずに、Serverlessをアップグレードしてみます。

            
            $ yarn install
$ npx sls --version
Framework Core: 3.28.1 (local)
Plugin: 6.2.3
SDK: 4.3.2
        
v3をアップグレードした限りでは、ここではCoreが2.72 -> 3.28に上がっています。

Pluginも同時に引き上げられて、
5.5 -> 6.2になっています。

対してSDKのバージョンは変わらずですが、Componentsに至ってはなくなっています。

さて、このままデプロイできれば何の問題もないのですが、おそらくは色々と失敗してしまうでしょう。

何も考えずv2時代の
serverless.ymlのままおもむろにデプロイコマンドを試してみます。

            
            $ npx sls deploy -v
Framework Core: 3.28.1 (local)
Plugin: 6.2.3
SDK: 4.3.2
        
...verbose指定でデプロイしたつもりが「バージョン表示」!?

どうやらショートカットオプションの
-v--verboseではなくて、--versionへ統合されたようですね。

このようにv3ではCLIコマンド操作も異なるようです。

つまり
--verboseはショートカットとして省略できないオプションになっているので、デプロイは以下のようになります。

            
            $ npx sls deploy --verbose
Environment: linux, node 16.17.1, framework 3.28.1 (local), plugin 6.2.3, SDK 4.3.2
Docs:        docs.serverless.com
Support:     forum.serverless.com
Bugs:        github.com/serverless/serverless/issues

Error:
The Serverless version (3.28.1) does not satisfy the "frameworkVersion" (2) in serverless.yml
        
当然、古いserverless.ymlのままではダメだと怒られました。

というわけで、以降では
serverless.ymlの大幅な改修工事を一つ一つ執り行っていきましょう。


Serverless Frameworkのv3対応

まずは「serverless cli」のヘルプを呼び出してみます。

            
            $ npx serverless --help
Serverless Framework v3.28.1

Usage
serverless <command> <options>
sls <command> <options>

Get started
Run serverless to interactively setup a project.
Use --help-interactive to display the interactive setup help.

Monitoring
Enable performance and error monitoring with the Serverless Dashboard.
Learn more: https://serverless.com/monitoring

Plugins
Extend the Serverless Framework with plugins.
Explore plugins: https://serverless.com/plugins

Options
--help / -h                     Show this message
--version / -v                  Show version info
--verbose                       Show verbose logs
--debug                         Namespace of debug logs to expose (use "*" to display all)

Main commands
deploy                          Deploy a Serverless service
deploy function                 Deploy a single function from the service
info                            Display information about the service
invoke                          Invoke a deployed function
invoke local                    Invoke function locally
logs                            Output the logs of a deployed function

Other commands
deploy list                     List deployed version of your Serverless Service
deploy list functions           List all the deployed functions and their versions
metrics                         Show metrics for a specific function
remove                          Remove Serverless service and all resources
rollback                        Rollback the Serverless service to a specific deployment
rollback function               Rollback the function to the previous version
test                            Run HTTP tests
package                         Packages a Serverless service
plugin install                  Install and add a plugin to your service
plugin uninstall                Uninstall and remove a plugin from your service
print                           Print your compiled and resolved config file
config                          Configure Serverless
config credentials              Configures a new provider profile for the Serverless Framework
create                          Create new Serverless service
dashboard                       Open the Serverless dashboard
doctor                          Print status on reported deprecations triggered in the last command run
generate-event                  Generate event
help                            Show this help
install                         Install a Serverless service from GitHub or a plugin from the Serverless registry
login                           Login or sign up for Serverless
logout                          Logout from Serverless
output get                      Get value of dashboard deployment profile parameter
output list                     List all dashboard deployment profile parameters
param get                       Get value of dashboard service output
param list                      List all dashboard deployment profile parameters
plugin list                     Lists all available plugins
plugin search                   Search for plugins
slstats                         Enable or disable stats
        
また以下はv2時代の古いserverless.ymlの内容です。

"古い"とは言っても、v2末期の「もうすぐv3がリリースするので〇〇が非推奨になるよー」と言うアナウンスがあった時期に少しだけ書き直したので、割と"v3"寄りの設定にはなっています。

            
            service: hoge
frameworkVersion: "2"

plugins:
  - serverless-apigw-binary
  - serverless-domain-manager

provider:
  name: aws
  runtime: nodejs12.x
  lambdaHashingVersion: 20201221
  memorySize: 192
  timeout: 10
  stage: ${opt:stage,"dev"}
  region: ap-northeast-1
  apiGateway:
    disableDefaultEndpoint: true

package:
  exclude:
    - '**'
  include:
    - 'dist/**'
    - 'lambda.js'
    - 'package.json'
    - 'node_modules/@vendia/**'
    - 'node_modules/aws-serverless-express/**'
    - 'node_modules/binary-case/**'
    - 'node_modules/type-is/**'
    - 'node_modules/media-typer/**'
    - 'node_modules/mime-types/**'
    - 'node_modules/mime-db/**'

custom:
  apigwBinary:
    types:
      - '*/*'
  customDomain:
    domainName: 'hoge.hoge.com'
    basePath: ''
    stage: ${self:provider.stage}
    createRoute53Record: true

functions:
  api:
    handler: lambda.universal
    events:
      - http:
          path: /
          method: GET
          cors:
            origin: '*'
            headers:
              - Content-Type
              - X-Amz-Date
              - Authorization
              - X-Api-Key
              - X-Amz-Security-Token
              - X-Amz-User-Agent
            allowCredentials: false
        
見ての通り、簡単なAWS APIGatewayAWS Lambdaを紐付けするための設計になっています。

この
serverless.ymlを起点に、v3で正常に継続的なデプロイができることを確認していきます。

frameworkVersionタグ

まずは大前提として
serverless.ymlのファイルバージョンを上げます。

            
            #...

#frameworkVersion: "2"
frameworkVersion: "3"

#...
        
バージョンを変えて見ただけですが、ここでデプロイに再チャレンジしてみましょう。

            
            $ npx sls deploy --verbose

Deploying hoge to stage dev (ap-northeast-1)

Packaging
Excluding development dependencies for service package
Retrieving CloudFormation stack
Uploading
Uploading CloudFormation file to S3
Uploading State file to S3
Uploading service hoge.zip file to S3 (26.74 MB)
Updating CloudFormation stack
Creating new change set
Waiting for new change set to be created
Change Set did not reach desired state, retrying
Executing created change set
  UPDATE_IN_PROGRESS - AWS::CloudFormation::Stack - hoge-dev
  UPDATE_IN_PROGRESS - AWS::IAM::Role - IamRoleLambdaExecution
  UPDATE_COMPLETE - AWS::IAM::Role - IamRoleLambdaExecution
  UPDATE_IN_PROGRESS - AWS::Lambda::Function - ApiLambdaFunction
  UPDATE_COMPLETE - AWS::Lambda::Function - ApiLambdaFunction
  CREATE_IN_PROGRESS - AWS::Lambda::Version - ApiLambdaVersionJxxxxxxxxxxxxxxxxxxxxxxxxxxxx4
  CREATE_IN_PROGRESS - AWS::Lambda::Version - ApiLambdaVersionJxxxxxxxxxxxxxxxxxxxxxxxxxxxx4
  CREATE_COMPLETE - AWS::Lambda::Version - ApiLambdaVersionJxxxxxxxxxxxxxxxxxxxxxxxxxxxx4
  CREATE_IN_PROGRESS - AWS::ApiGateway::Deployment - ApiGatewayDeployment1000000000004
  CREATE_IN_PROGRESS - AWS::ApiGateway::Deployment - ApiGatewayDeployment1000000000004
  CREATE_COMPLETE - AWS::ApiGateway::Deployment - ApiGatewayDeployment1000000000004
  UPDATE_COMPLETE_CLEANUP_IN_PROGRESS - AWS::CloudFormation::Stack - hoge-dev
  DELETE_IN_PROGRESS - AWS::ApiGateway::Deployment - ApiGatewayDeployment1000000000005
  DELETE_SKIPPED - AWS::Lambda::Version - ApiLambdaVersionoerJxxxxxxxxxxxxxxxxxxxxxxxk
  DELETE_COMPLETE - AWS::ApiGateway::Deployment - ApiGatewayDeployment1000000000005
  UPDATE_COMPLETE - AWS::CloudFormation::Stack - hoge-dev
Retrieving CloudFormation stack
V1 - Updated API mapping from '(none)'
                    to '(none)' for 'hoge.hoge.com'
Removing old service artifacts from S3

✔ Service deployed to stack hoge-dev (140s)

endpoints:
  GET - https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/
  GET - https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/{proxy+}
functions:
  api: hoge-dev-api (27 MB)

Stack Outputs:
  DomainName: hoge.hoge.com
  HostedZoneId: XXXXXXXXXXXXXX
  ApiLambdaFunctionQualifiedArn: arn:aws:lambda:ap-northeast-1:000000000000:function:hoge-dev-api:18
  DistributionDomainName: xxxxxxxxxxxxxx.cloudfront.net
  ServiceEndpoint: https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev
  ServerlessDeploymentBucketName: hoge-dev-serverlessdeploymentbucket-xxxxxxxxxxxx
Serverless Domain Manager:
  Domain Name: hoge.hoge.com
  Target Domain: xxxxxxxxxxxxxx.cloudfront.net
  Hosted Zone Id: XXXXXXXXXXXXXX

2 deprecations found: run 'serverless doctor' for more details

Improve API performance – monitor it with the Serverless Console: run "serverless --console"
        
ん...2つくらい"非推奨"の項目が見つかったものの、デプロイはそのままいけた?

「なんだ、バージョンを返るだけで動くじゃん」と一瞬期待しましたが、実は全然そうは動きません。

デモ用に作ってみたドメインを使ったSPAにアクセスしてみると、

合同会社タコスキングダム|蛸壺の技術ブログ

というようにCORS設定のエラーだったり、バックエンドがきちんと動作していなかったり、AWS APIgatewayやAWS Lambdaへの"なにか"が致命的にコケているようです。

【AWSの場合】ポリシーの追加

AWS上にデプロイする場合は、Cloudformationへのスタックに対するアクションの権限が新たに必要になりました。

            
            - cloudformation:CreateChangeSet
- cloudformation:DeleteChangeSet
- cloudformation:DescribeChangeSet
- cloudformation:ExecuteChangeSet
        
ということで、現在のIAMユーザーにCloudformationのChangeSetのポリシーを付けましょう。

ルートユーザーでAWSのIAMダッシュボードへログインし、開発時に作業を行っているIAMユーザーに先程のアクセス権限を付与します。

合同会社タコスキングダム|蛸壺の技術ブログ

再びデプロイすると、今度はうまくSPAが表示されていることが分かります。

合同会社タコスキングダム|蛸壺の技術ブログ

拍子抜けかもしれませんが、今回のサーバレスの構成は主にAWS APIGatewayだけがターゲットで大したことはなかったので、v2からv3の移行はほぼそのままの設定で動くようです。

また結局、プラグインに関してもv2からv3への移行で、大きな影響は受けないような設計のようです。

v2はもうサポートされていないので、時間に余裕があれば恐れることなくv3に移行していきましょう。

serverless.ymlの非推奨項目を診断する・「sls doctor」コマンド

v3に以降したあとで、何かCLIコマンドを使うと、serverless.yml中の非推奨項目があれば、コマンドの実行結果の最後に情報として表示されるようになります。

            
            $ npx sls deploy list --verbose
2023-03-12 03:29:31 UTC
Timestamp: 1678591771043
Files:
  - compiled-cloudformation-template.json

#...中略

2 deprecations found: run 'serverless doctor' for more details
        
この非推奨項目の詳細が知りたい場合に、「serverless doctor」サブコマンドを利用し、どこを更新すると良いのかヒントをもらえるようになります。

            
            $ npx sls doctor --verbose
2 deprecations triggered in the last command:

Support for "package.include" and "package.exclude" will be removed in the next major release. Please use "package.patterns" instead
More info: https://serverless.com/framework/docs/deprecations/#PACKAGE_PATTERNS
Setting "20201221" for "provider.lambdaHashingVersion" is no longer effective as new hashing algorithm is now used by default. You can safely remove this property from your configuration.
More info: https://serverless.com/framework/docs/deprecations/#LAMBDA_HASHING_VERSION_PROPERTY
        
見てのように結構具体的な書き換え情報がもらえるので、公式のドキュメントを読み込むことなく効率よく修正することができそうです。


まとめ

ということで、この記事では以下のことについて解説していきました。

            
            1. Serverless Framework v2からv3への移行はさほど難しくない
2. AWSへのデプロイの場合にCloudFormation用のアクセスポリシーが新たに必要
3. Serverless Frameworkプラグインはv3移行後もほぼそのまま使える(と思って良い)
4. doctorサブコマンドを使ってserverless.ymlの非推奨項目を診断する
        
仕事で普段からサーバーレスアーキテクチャを採用したサービスを取り入れているだけに、大幅な移行作業が無いのは有り難いことです。