BeeX Tech blog

BeeXではクラウドネイティブアプリ開発、企業の基幹クラウド基盤構築、システム移行、運用保守を行っています。

Azure ReposからAWS Lambdaへのデプロイ構成(Python)

はじめに

こんにちは、半田(@handy)です。

 

以前、Azure ReposからAWS Beanstalkへのデプロイを行った記事を書きましたが、今回はAWS Lambdaへのデプロイを試してみました。

Azure ReposからAWS Beanstalkにデプロイする構成を構築する(Pythonアプリ使用)

 

構築構成

実際に構築した構成は以下になります。

Azure Reposリポジトリで管理されているコードを修正すると、デプロイが実行されてLambda関数のコードのみ更新されるシンプルな構成になります。



 

構築方法

今回はAzureのIaCには慣れていないので、ポータルから手動で構築を行いました。

 

前提

以下の作業は既に実施済みになります。

AWS側

  • Lambda関数作成済み(Python)
  • Azure Pipelinede利用するIAMユーザーの作成

 

Azure側

  • Azure DevOps OrganizationとProjectの作成
  • 「AWS Toolkit for Azure DevOps」Extentionsのインストール
  • Azure Reposにlambda-functionsリポジトリとreleaseブランチの作成

 

事前準備

AWS側

  • デプロイ先のLambda関数のファイル名とコードをローカルにメモしておきます。

※今回はLambda関数作成時点のものを利用します。



 

Azure側

  • Lambdaへのデプロイに使用するIAMユーザーのアクセスキーとシークレットアクセスキーを「lambda-deploy-iam-user」という名前で登録しておきます。

※[Project Settings]の[Service connections]から登録可能できます



 

実作業

デプロイコード作成

AzureからLambda関数のデプロイを行う場合、Azure PipelineのJob内で関数コードをZip圧縮して、Zipファイルを指定してデプロイAPIを実行する必要があります。
そのため、Zip圧縮を行う単位となるmyfunctionフォルダを作成し、その中にデプロイするlambda_function.pyファイルを作成します。

中央上部を見てmainブランチであることを確認し、"事前準備"手順で確認したファイル名とコードをコピーしてファイルをlambda_function.py作成します。



 

※一応使用したコードを以下に貼っておきます

import json


def lambda_handler(event, context):
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

 

パイプライン作成

デプロイするコードが作成できたら、Azure Pipelineでパイプラインを作成します。



 

[Azure Repos Git]を選択します。



[lambda-functions]リポジトリを選択します。



 

ここの一覧ではExtentionsのAWS関連の設定項目は出てこないので、適当に選択しておきます。



 

設定内容を元にしたazure-pipelines.ymlファイルが表示されるので、中身を手動でLambda関数デプロイ用に書き換えます。



 

ymlファイル内を全選択して、以下の内容に書き換えます。
内容としては、「ArchiveFiles@2」タスクでmyfunctionフォルダ配下をZip圧縮し、「LambdaDeployFunction@1」タスクで指定したLambda関数にデプロイを行っています。

trigger:
- release


pool:
  vmImage: ubuntu-latest


resources:
- repo: self


steps:
- task: ArchiveFiles@2
  inputs:
    rootFolderOrFile: 'myfunction/'
    includeRootFolder: false
    archiveType: 'zip'
    archiveFile: '$(Build.ArtifactStagingDirectory)/myfunction.zip'

- task: LambdaDeployFunction@1
  inputs:
    awsCredentials: 'lambda-deploy-iam-user'
    regionName: 'ap-northeast-1'
    deploymentMode: 'codeonly'
    functionName: 'azure-deploy-func1'
    codeLocation: 'localfile'
    localZipFile: '$(Build.ArtifactStagingDirectory)/myfunction.zip'

 

Zip圧縮ですが、適当にフォルダ/ファイルを作成して圧縮すればよいというわけではなく、以下のドキュメントに記載されているものと同じ構成となるようにしています。

Working with .zip file archives for Python Lambda functions

ルート直下に関数コードを配置するよう記載されているので、今回はmyfunctionフォルダ直下にPythonファイルを配置しています。



 

LambdaDeployFunction@1」タスクには2つのデプロイモードがあり、コードのみデプロイするものと、Lambda関数全体をデプロイするものがあります。
今回はコードのみとするため事前にLambda関数を作成しましたが、モードによっては関数を新規作成することも可能です。



 

※Lambda関数から作成する場合は必須となる設定項目が増えます
 具体的なパラメータの詳細についてはこちらを参考にするとよいでしょう



 

ymlファイルの中身が書き換え出来たら、実行せずに保存します。



 

関数コード更新

ここまでできたらデプロイできるか確認してみます。
lambda-functionsリポジトリのlambda_function.pyファイルを以下のように修正してCommitします。



 import json


def lambda_handler(event, context):
    print('first deploy')
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

 

mainブランチからパイプラインのトリガーに設定したreleaseブランチにマージします。





 

正常にマージできたことを確認します。



 

パイプライン実行確認

Azure Pipelineから作成したパイプラインを見るとjobが実行されていることが確認できます。



 

Lambda関数を確認してみるとコードの4行目に先ほど修正した「print('first deploy')」が含まれていることが確認できました。



 

おまけ

Lambda関数では外部ライブラリを使用することがあると思います。
もし本記事のようにAzureからデプロイする対象がコードだけの場合、パイプライン上でLayerをデプロイできないため、Lambda関数側に手動でLayerを追加する必要があります。
その時にどうしても手動操作を減らしたいということであれば、以下のようにmyfunctionフォルダ内に外部ライブラリをインストールすることで、LayerをLambda関数に追加せずに利用することができます。
以下例ではrequestsパッケージとしていますが、コマンドオプションを「-r requirements.txt」とかに指定しておけばファイルをリポジトリ上のrequirements.txtファイルを修正するだけでライブラリのインストールが可能です。
※ただし、ファイルサイズがLambda関数のクォータに引っかからないように注意は必要です

 trigger:
- release


pool:
  vmImage: ubuntu-latest


resources:
- repo: self


strategy:
  matrix:
    Python311:
      python.version: '3.11'


steps:
- task: UsePythonVersion@0
  inputs:
    versionSpec: '$(python.version)'
  displayName: 'Use Python $(python.version)'


- script: |
    python -m pip install --upgrade pip
    pip install --target ./myfunction requests
  displayName: 'Install dependencies'


- task: ArchiveFiles@2
  inputs:
    rootFolderOrFile: 'myfunction/'
    includeRootFolder: false
    archiveType: 'zip'
    archiveFile: '$(Build.ArtifactStagingDirectory)/myfunction.zip'

- task: LambdaDeployFunction@1
  inputs:
    awsCredentials: 'lambda-deploy-iam-user'
    regionName: 'ap-northeast-1'
    deploymentMode: 'codeonly'
    functionName: 'azure-deploy-func1'
    codeLocation: 'localfile'
    localZipFile: '$(Build.ArtifactStagingDirectory)/myfunction.zip'

 

requestsパッケージをインストールしてデプロイした例は以下です。



 

おわりに

本記事の構成ではAzure上にあるコードをマスターとしてAWSにデプロイするため、コード管理をAzureに集約できるというメリットがあります。

ただ、この構成では1つのリポジトリで複数のLambda関数のコードを管理するのには向かないので、その場合はServerless Framework等を併用することになるかと思います。
(まぁそうするとGitHub ActionsやCircleCIでデプロイするのと大差はなくなるのですが...)

 

Azure-AWS間の連携構成は調べても記事があまり出てこないので、せっかくなので書いてみました。

この記事がどなたかの参考になれば幸いです。