こんにちは!エンジニアの久保です。
2021/9 より AWS Lambda の動作環境として、Arm/Graviton2 プロセッサが選択できるようになりました。
これまでは X86 プロセッサだけだったのですが、Arm/Graviton2 を選択することで低コストで高パフォーマンスを実現できます。弊社でも現在 X86 で動作していた Lambda を Arm での動作へ置き換えを進めています。
今回は Lambda を Arm プロセッサで動作させる場合の SAM テンプレートをご紹介します。
SAMテンプレートを書き換え Arm プロセッサで動作可能にする
SAM テンプレートの template.yml を次のように書き換えて Arm プロセッサで動作するようにします。
具体的には2点を変更しています。
- Architectures を X86_64 から arm64 へ変更する
- Lambda Insights を有効にしている場合は、Arm に対応したものへ変更する
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
sam-app
Sample SAM Template for sam-app
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
Function:
Timeout: 3
Tracing: Active
Layers:
# - !Sub "arn:aws:lambda:${AWS::Region}:580247275435:layer:LambdaInsightsExtension:25"
- !Sub "arn:aws:lambda:${AWS::Region}:580247275435:layer:LambdaInsightsExtension-Arm64:2"
Api:
TracingEnabled: True
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
CodeUri: hello-world/
Handler: app.lambdaHandler
Runtime: nodejs16.x
Architectures:
# - x86_64
- arm64
Events:
HelloWorld:
Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
Properties:
Path: /hello
Method: get
Outputs:
# ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
# Find out more about other implicit resources you can reference within SAM
# https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
HelloWorldApi:
Description: "API Gateway endpoint URL for Prod stage for Hello World function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
HelloWorldFunction:
Description: "Hello World Lambda Function ARN"
Value: !GetAtt HelloWorldFunction.Arn
HelloWorldFunctionIamRole:
Description: "Implicit IAM Role created for Hello World function"
Value: !GetAtt HelloWorldFunctionRole.Arn
必要に応じて CI を書き換えます。
Lambda 関数内で使っているライブラリがアーキテクチャに依存しない場合は、CI を変更する必要なく動きます。
一方で、アーキテクチャに依存するライブラリを使っている場合(たとえば、libvips を使う node.js の sharp など)は、次の対応が必要です。
- CI の実行環境を Arm へ変更する
- 異なるアーキテクチャでもビルドできるようにする
一般的には前者の方法が選ばれますが、場合によっては CI は X86 の環境環境しか用意していない場合もあるでしょう。
今回はこのケースに該当したため、X86 の CI でビルドを試します。
異なるアーキテクチャ(ArmをX86)でビルドできるようにする
X86 の環境で Arm 向けのビルドを行うには sam build --use-container を使って、Dockerコンテナでビルドする方法が一般的です。しかしながら --use-container オプションが使えない場合があります。
例えば、セルフホストで動作させている GitLab CI などの場合です。設定によっては、Pipeline を Docker コンテナ上で実行していたりします。この場合 Docker コンテナ内で Docker build するには dind (Docker in Docker)とよばれる仕組みを使います。
ところが、今回の環境では dind で sam build --use-container を動かすことができませんでした。
そもそも Arm 用のビルドが必要なのは、npm の sharp で使われている libvips を Arm でビルドされたバイナリにする必要があるためです。SAM を使わずに npm で install する場合、公式では npm install --arch=arm64 --platform=linux sharp でインストールせよ、と紹介されています。
そこで SAM を使った場合に内部で実行されている npm install でこれらのパラメータを指定してみました。
具体的には環境変数を設定してから sam build を実行します。
export npm_config_arch: "arm64" export npm_config_platform: "linux" sam build
補足事項として、環境変数に npm_config_xxx と設定した場合、 npm install --xxx のパラメータとして渡されます。
まとめ
今回は Lambda を Arm プロセッサで動作させる場合の SAM テンプレートをご紹介しました。
Arm プロセッサを利用することでコストを抑えた Lambda の利用が可能になります。ぜひご活用ください。