こんにちは!エンジニアの久保です。

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 の利用が可能になります。ぜひご活用ください。

Join Us !

ウエディングパークでは、一緒に働く仲間を募集しています!
ご興味ある方は、お気軽にお問合せください(カジュアル面談から可)

採用情報を見る