AWS lambda (arm) Python3.10.xにライブラリをLayerで追加する方法

## 目的

`aws:lambda(arm)`にランタイム`Python3.10`で好きなライブラリを追加する

例として`pandas`を`lambda`で使えるようにする

## 前提

- 手元のPCのCPUが`intel製`の`x86`
- `aws`のアクセスキーを発行が手元にある状況
- 使用するのは`Python3.10.11`

## 方針

1. `EC2`インスタンスを`AmazonLinux2(arm)`で立てる
1. `EC2`にSSHで接続
1. `OpenSSL 1.1.1` をインストール
1. `EC2`に`Python3.10.11`をインストール
1. `pip`で`pandas`をインストールし`zip`化
1. 作成した`zip`を`S3`にアップロード
1. `S3`にアップした`zip`から`lambda`のレイヤーを作成
1. `lambda`にレイヤーを追加
1. `lambda`でバージョン確認

##  1.`EC2`インスタンスを`AmazonLinux2(arm)`で立てる

`EC2`インスタンスのAMIを`AmazonLinux2`で作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1262857/ced92bd9-557e-eb49-af3a-2949fa90d466.png)

アーキテクチャを`64ビット(arm)`に変更します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1262857/c803e47b-d623-6e41-13fc-f6309e457c13.png)

適当なインスタンスタイプを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1262857/2233d045-183f-06f2-df14-4ac879a5a167.png)

ログイン用のキーペアを作成または選択します。
今回は`ec2-lambda-layer-creation-instance-key`というキーペアを作成してキーペアをダウンロードします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1262857/460388fa-788a-fc36-4388-ac01e719b50d.png)

キーペアを作成後、`インスタンスを起動`します。

## 2.`EC2`にSSHで接続

手元のPCで先ほど作成してダウンロードしたキーペアがある場所まで`cd`コマンドで移動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1262857/91f2cd0a-0541-0861-8ce5-7f47c815113e.png)

`EC2`インスタンスを選択後インスタンスに接続の`SSHクライアント`のタブからSSH接続するためのコマンド類をコピーして順番にターミナルで実行していきます。

:::note
基本的に黄色でハイライトしてある箇所をターミナルにコピペすればよいです
:::


![ssh.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1262857/6901a2f9-6e06-8434-a982-a3061d0eeb3c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1262857/740aa6bb-a54d-0ef7-69d3-9ed22e957c8e.png)

## 3.`OpenSSL 1.1.1` をインストール

1. `OpenSSL`のバージョンを確認
    ```bash
    $ openssl version
    OpenSSL 1.0.2k-fips  26 Jan 2017
    ```
1. `OpenSSL 1.1.1`をインストール
    ```bash
    $ sudo yum install -y openssl11 openssl11-devel
    ```
    インストールに成功すると最後に`Complete!`と表示されます。

1. `OpenSSL 1.1.1`のインストールを確認
    ```bash
    $ openssl11 version
    OpenSSL 1.1.1g FIPS  21 Apr 2020
    ```
    これで`OpenSSL 1.1.1`のインストールを確認できました。

## 4.`EC2`に`Python3.10.11`をインストール

1. pyenv 公式推奨ビルド環境の構築
    ```bash
    $ sudo yum install -y gcc zlib-devel bzip2 bzip2-devel readline-devel sqlite sqlite-devel tk-devel libffi-devel xz-devel
    ```
2.  pyenv のインストール

    次のコマンドを順番に実行します
    ```bash
    $ sudo yum install -y git
    $ curl https://pyenv.run | bash
    ```
    
    以下のコマンドで環境変数を設定します。
    ```bash
    $ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
    $ echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
    $ echo 'eval "$(pyenv init -)"' >> ~/.bashrc
    ```
    
    シェルを再起動します。
    ```bash
    $ exec $SHELL -l
    ```
    
    pyenvのインストールの確認
    
    ```bash
    $ pyenv --version
    pyenv 2.3.21
    ```

1. `Python3.10.x`のインストール

    インストールできるPythonのバージョンを確認します。
    ```bash
    $ pyenv install -l 
    ```
    
    今回は`Python3.10.11`をインストールします。
    
    ```bash
    $ pyenv install 3.10.11
    ```

1. Python3.10.xのインストールを確認します。

    次のコマンドで先ほどインストールしたPythonのバージョンが表示されたらインストール成功です。
    
    ```bash
    $ pyenv versions
    ```

1. `Python`のバージョンの切り替え
    
    pyenvでPythonのバージョンを変更します。**今回は`global`でバージョンを変更します。**
    ```bash
    # 全体でバージョン変更
    $ pyenv global 3.10.11
    $ python --version
    Python 3.10.11
    
    # カレントディレクトリのみバージョン変更
    $ pyenv local 3.10.11
    $ python --version
    Python 3.10.11
    ```

## 5.`pip`で`pandas`をインストールし`zip`化

次のコマンドを順番に実行して`pandas`をインストールします。

```bash
$ pip install --upgrade pip
$ mkdir python
$ cd python
$ pip install pandas -t .
$ cd ../
$ zip -r python.zip python
```
- `-t`オプションで指定したディレクトリにインストール
- `python.zip`という名前の`zip`を作成する必要があります。

## 6.作成した`zip`を`S3`にアップロード

1. アップロードするS3のバケットを作成

    適当な名前のバケットを作成します。今回は`s3-lambda-layers-bucket`というバケット名で作成しました。
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1262857/7c09987b-70d6-5571-189f-1023f7067fc0.png)

2. zipをS3にアップロード

    今回は、IAMのアクセスキーを使用して`S3`にファイルをアップロードするプログラムを使用してアップロードします。
    
    `EC2`インスタンスから次のコマンドでクローンして`READMD.md`に従いインストールしてください。
    
    ```bash
    $ git clone https://github.com/kkml4220/file-upload-to-S3
    $ cd file-upload-to-S3
    $ pip install -r requirements.txt
    $ python setup.py
    AWS_ACCESS_KEY_IDを入力してください：************
    AWS_SECRET_ACCESS_KEYを入力してください：*********
    AWS_S3_BUCKET_NAMEを入力してください：s3-lambda-layers-bucket # 先ほど作成したバケット名
    AWS_DEFAULT_REGIONを入力してください：************
    $ python main.py ../python.zip # 先ほど作成したzipへの相対パス
    ```

    詳しくは[README.md](https://github.com/kkml4220/file-upload-to-S3/blob/master/README.md)をご覧ください。

1. S3にアップロードされたか確認

    ![s3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1262857/321dc384-e315-04ed-34d4-091bac033256.png)

## 7.`S3`にアップした`zip`から`lambda`のレイヤーを作成

`lambda`のサイドメニューから`レイヤー`を選択してレイヤーを作成します。

![スクリーンショット 2023-06-28 23.29.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1262857/1c440e2a-9314-5b92-20a5-eb920bbb4e17.png)

- Amazon S3からファイルをアップロードを選択して先ほどアップロードした`zip`ファイルのパスを貼り付けます
- アーキテクチャとランタイムを指定します

## 8.`lambda`にレイヤーを追加

テスト用に適当な`lambda`関数を作成します。

![スクリーンショット 2023-06-28 23.26.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1262857/5e864e11-3704-3823-1ad3-61abfbafd76d.png)
- ランタイムとアーキテクチャが先ほど作成したレイヤーと合っていることを確認してください。

作成した関数にレイヤーを追加する方法は作成した関数の名前の下にあるレイヤーをクリックするとページ下部に遷移します。そこでレイヤーを追加をクリックすると次のような画面に遷移します。

![スクリーンショット 2023-06-28 23.27.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1262857/fa192d74-7b86-a6b2-bc21-bd82cd130f37.png)

ここでカスタムレイヤーから先ほど作成したレイヤーをプルダウンで選択します。
これでレイヤーの追加が完了です。

## 9.`lambda`でバージョン確認

作成した`lambda`の関数を仮置きで次のように書き換えて`Deploy`します。

```python
import json
import pandas

def lambda_handler(event, context):
    # TODO implement
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!'),
        "version": f"pandas: {pandas.__version__}"
    }
```

適当なテストイベントを作成してレスポンスで次のように表示されれば成功です。
- `event`の名前を適当に決めてテストを実行するだけで良いです。

![スクリーンショット 2023-06-28 23.39.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1262857/81ec1e8c-72e4-7fb2-0754-ddcdfdac46e1.png)


## 参考リンク

- [OpenSSL 1.1.1 が必須なPython 3.10.x をAmazon Linux 2 にインストールする](https://blog.serverworks.co.jp/install-python3-with-openssl11)