こんにちは!エンジニアの久保です。
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 の利用が可能になります。ぜひご活用ください。