Lambda で awscli を利用する

# はじめに
Lambda でAWS のインスタンスを管理をさせたいとき awscli のインストールが必要になるので、これを利用できるようにする。

# 概要
1. awscli を利用する EC2 のインスタンスと同じ OS を用意する (docker)
1. docker container でawscli をインストールして zip でかためる
1. zip にしたファイルを S3 に置く
1. S3 に置いたファイルをLambda のレイヤーで 指定する
1. Lamda の関数を用意して レイヤーを指定
1. bootstrap, hello.sh を用意(編集)


# awscli を利用して EC2 に接続する Access キーを用意する
```bash
# cat /var/lib/aws/aws_cli.key
アクセスキー
シークレットキー
ap-northeast-1 (ゾーン)
text
```

# awscli をインストールする環境 (docker コンテナ) の用意
Amazon Linux 2023 でawscli を動作させたいので、このOSのdocker イメージで用意する。

### インストール
```bash
# yum -y install docker
```

### docker デーモン起動

```bash
# systemctl start docker
````

### Amazon Linux 2023 のイメージをダウンロードしてコンテナを用意

```bash
# docker run -it --rm -v ./volume:/volume amazonlinux:2023 bash
bash-5.2# uname -a
Linux 4c1bfd43594e 6.1.109-118.189.amzn2023.x86_64 #1 SMP PREEMPT_DYNAMIC Tue Sep 10 08:59:12 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
```

# awscli コマンドの用意

### docker コンテナで作業で必要なコマンドをインストール

```bash
bash-5.2# dnf -y install which zip
Amazon Linux 2023 repository                                                               30 MB/s |  28 MB     00:00
Last metadata expiration check: 0:00:07 ago on Thu Oct  3 23:20:53 2024.
Dependencies resolved.
==========================================================================================================================
 Package                Architecture            Version                                Repository                    Size
==========================================================================================================================
Installing:
 which                  x86_64                  2.21-26.amzn2023.0.2                   amazonlinux                   42 k
 zip                    x86_64                  3.0-28.amzn2023.0.2                    amazonlinux                  257 k
Installing dependencies:
 unzip                  x86_64                  6.0-57.amzn2023.0.2                    amazonlinux                  182 k

Transaction Summary
==========================================================================================================================
Install  3 Packages

Total download size: 481 k
Installed size: 1.1 M
Downloading Packages:
(1/3): which-2.21-26.amzn2023.0.2.x86_64.rpm                                              773 kB/s |  42 kB     00:00
(2/3): unzip-6.0-57.amzn2023.0.2.x86_64.rpm                                               2.7 MB/s | 182 kB     00:00
(3/3): zip-3.0-28.amzn2023.0.2.x86_64.rpm                                                 3.6 MB/s | 257 kB     00:00
--------------------------------------------------------------------------------------------------------------------------
Total                                                                                     920 kB/s | 481 kB     00:00
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Preparing        :                                                                                                  1/1
  Installing       : unzip-6.0-57.amzn2023.0.2.x86_64                                                                 1/3
  Installing       : zip-3.0-28.amzn2023.0.2.x86_64                                                                   2/3
  Installing       : which-2.21-26.amzn2023.0.2.x86_64                                                                3/3
  Running scriptlet: which-2.21-26.amzn2023.0.2.x86_64                                                                3/3
  Verifying        : unzip-6.0-57.amzn2023.0.2.x86_64                                                                 1/3
  Verifying        : which-2.21-26.amzn2023.0.2.x86_64                                                                2/3
  Verifying        : zip-3.0-28.amzn2023.0.2.x86_64                                                                   3/3

Installed:
  unzip-6.0-57.amzn2023.0.2.x86_64        which-2.21-26.amzn2023.0.2.x86_64        zip-3.0-28.amzn2023.0.2.x86_64
  
Complete!
```



### awscli のインストール

docker コンテナに awscli をインストール

```bash
bash-5.2# curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 62.9M  100 62.9M    0     0   113M      0 --:--:-- --:--:-- --:--:--  113M

bash-5.2# unzip awscliv2.zip
   :
   :
  inflating: aws/dist/docutils/parsers/rst/include/isocyr1.txt
  inflating: aws/dist/docutils/parsers/rst/include/isotech.txt
  inflating: aws/dist/docutils/parsers/rst/include/isomscr-wide.txt
  inflating: aws/dist/docutils/parsers/rst/include/isoamsb.txt
  inflating: aws/dist/docutils/parsers/rst/include/isolat2.txt

bash-5.2# ./aws/install
You can now run: /usr/local/bin/aws --version

bash-5.2# /usr/local/bin/aws --version
aws-cli/2.17.65 Python/3.12.6 Linux/6.1.109-118.189.amzn2023.x86_64 exe/x86_64.amzn.2023

```


### EC2 にアクセスするキーを docker コンテナにコピー
docker コンテナでディレクトリを作成

```bash
bash-5.2# mkdir -p  /var/lib/aws
```

他のターミナルなどから EC2 にアクセスするキー (/var/lib/aws/aws_cli.key) を docker コンテナにコピー
(ヒアドキュメントで読み込む)

```bash
# cat /var/lib/aws/aws_cli.key
アクセスキー
シークレットキー
ap-northeast-1
text
```

```bash
# docker ps
CONTAINER ID   IMAGE              COMMAND   CREATED          STATUS          PORTS     NAMES
4c1bfd43594e   amazonlinux:2023   "bash"    26 minutes ago   Up 26 minutes             intelligent_stonebraker

# docker cp  /var/lib/aws/aws_cli.key 4c1bfd43594e:/var/lib/aws
Successfully copied 2.05kB to 4c1bfd43594e:/var/lib/aws
```


### awscli コマンドをかためる
aws コマンドの実体を探す

```bash
bash-5.2# ls -al /usr/local/bin/aws
lrwxrwxrwx. 1 root root 37 Oct  3 23:27 /usr/local/bin/aws -> /usr/local/aws-cli/v2/current/bin/aws

bash-5.2# ls -al  /usr/local/aws-cli/v2/current/bin/aws
lrwxrwxrwx. 1 root root 11 Oct  3 23:27 /usr/local/aws-cli/v2/current/bin/aws -> ../dist/aws

bash-5.2# ls -al /usr/local/aws-cli/v2/current/dist/aws
-rwxr-xr-x. 1 root root 6525544 Oct  3 23:27 /usr/local/aws-cli/v2/current/dist/aws
```

awscli コマンドを Lambda の動作ディレクトリ (bin) に合わせてから、かためる

```bash
bash-5.2#  cp -r /usr/local/aws-cli/v2/current/dist /volume/bin

bash-5.2#  cd /volume

bash-5.2# zip -r awscli.zip bin
    :
    :
  adding: bin/docutils/parsers/rst/include/isomscr-wide.txt (deflated 80%)
  adding: bin/docutils/parsers/rst/include/isoamsb.txt (deflated 72%)
  adding: bin/docutils/parsers/rst/include/isolat2.txt (deflated 84%)
  adding: var/lib/aws/aws_cli.key (stored 0%)

bash-5.2# ls -al awscli.zip
-rw-r--r--. 1 root root 67580649 Oct  3 23:33 awscli.zip
```

### docker コンテナから awscli.zip をコピー
S3 に置くファイルをホストOS にコピーする

```bash
# docker cp 4c1bfd43594e:/volume/awscli.zip ./awscli.zip
Successfully copied 67.6MB to /home/ec2-user/awscli.zip

# ls -al awscli.zip
-rw-r--r--. 1 root root 67580905 Oct  4 08:46 awscli.zip
```


# awscli コマンドのファイル (awscli.zip) を S3 にアップロード 
[バケットの作成] をクリックをして、新しいバケットを用意する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/f5fd5074-329a-940a-940a-0552be1a448b.png)

[バケット名] に適当な名前を入れる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/1089fea1-e3af-c174-7303-222e67f1a7ff.png)


他の項目は特に変更せずに [バケットの作成] をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/57b500ce-03d4-5031-741f-66e193d654e5.png)


汎用バケットが作成されるので、バケットの名前のリンクをクリックする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/3ee0ece6-2276-b210-1559-358cc01ff015.png)

[アップロード] をクリックしてアップロードページを表示する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/73f44cb0-9a77-544a-9083-269eb90bcb02.png)

アップロードページで [ファイルを追加] で awscli.zip を選択する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/d438936f-4182-d9b6-73a7-de16f9581631.png)

アップロードすると、進行中画面が出て、アップロード完了画面となる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/1c08deac-bb43-dded-a503-6b7124ad13ec.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/91a5c420-dd17-8aae-01e6-5fef30b44436.png)


[オブジェクト] に awscli.zip が入る。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/a52cbada-9adc-a81c-bd8e-39648b6c736b.png)

[オブジェクト] の awscli.zip をインクをすると詳細が出てくるので、この [オブジェクトURL] を覚えておく(どこかコピーしておく)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/dd2e06cb-ae34-10cb-94e5-48c7322eaa2e.png)




# Lambda レイヤーを用意

Lambda の左メニューから [レイヤー] を選択をして [レイヤーの作成] をクリックする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/5ba79af1-f250-24bd-0fab-a8424138c15b.png)

以下のレイヤーの設定をして、[作成] をする。

* [名前] は適当
* [Amazon S3 からファイルをアップロードする]を選択し、awscli.zip のオブジェクトURL を入力(コピペ)する
* 互換性のあるアーキテクチャは、awscli を用意した環境と同じ (だいたいは x86_64 だとは思うが)
* 互換性のあるランタイムのリストから、awscli を用意した OS (ここでは Amazon Linux 2023)
* 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/8bfd46e5-fb1c-208d-308f-2b6a53dbce78.png)


レイヤーが作成される

* 詳細画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/bc3928ce-755a-4c95-d9cf-711b626ffffa.png)

* 一覧画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/d16097d4-2cb4-d860-210c-a835b1f94e43.png)


# Lambda 関数を用意

左のメニューから [関数] をクリックして [関数の作成] をクリックする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/c613e4ad-4d80-7542-9fd7-69d5735c8750.png)

以下の関数の設定をして [関数の作成] をクリックする。

* [名前] は適当に入れる
* 互換性のあるアーキテクチャは、awscli を用意した環境と同じ (だいたいは x86_64 だとは思うが)
* [ランタイム]は動作させたい環境 (awscli を動作させたい環境なので Amazon Linux 2023)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/3ef14904-00e8-6a32-92f2-5f949e38fdd6.png)

関数が作成されるので、レイヤーを設定する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/708d07b4-d3ec-e69d-87c6-b4d035ec469b.png)

画面の下に行き [レイヤー] にある [レイヤーの追加] をクリックする。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/94e24f00-b641-5fba-b10a-1bc265175c8d.png)


関数にレイヤーを設定して [追加] をクリックする

自分で作ったレイヤーを選択する。
バージョンは利用するバージョンを選択する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/154ddb33-2454-0b71-9366-bb029d2e3c9d.png)

コードソードが出てくる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/d636eab1-8e06-7812-fbde-57f37227b0a0.png)


# 関数のコードを修正

ソースコードで以下の変更をして [deploy] をクリックする。

* bootstrap.sh.sample を bootstrap に名前を変更
* hello.sh.sample を hello.sh に名前を変更し aws --version と追加し実行してみる


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/54fa6359-e163-8d88-e047-f665888f5f42.png)


# Lambda 関数の実行タイムアウトを変更

デフォルトだと3秒なので、タイムアウト時間を延ばす

[設定] の [一般設定] にある [編集] をクリックする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/9b15b3f6-75bb-1834-d5c3-ebc312b8a1e9.png)

[タイムアウト] の設定でとりあえず5分にして [保存] をクリックする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/f79ddf22-a59d-9db8-7600-9f5a0d17f160.png)


# 関数の実行

[テスト] をクリックする。

以下の画面で、[名前]を適当に入力し、他は変更せずに [保存] をクリックする。
　
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/0ef7755e-4572-ca1e-0ad9-eba24d0f376e.png)

[テスト] で [テスト] をクリックすると実行する。
だいたい20秒ぐらいで終了する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/b614cc51-d7b1-f3c1-5aaa-7449a90a5220.png)



# Lambda でawscli を利用してEC2 のインスタンス一覧を表示する

### EC2 へのアクセス権追加

実行ロールに EC2 の読み込み権限を付与しないと以下のようなエラーになる。

```
An error occurred (UnauthorizedOperation) when calling the DescribeInstances operation: You are not authorized to perform this operation.
```


実行ロールの [ロール名]のリンクをクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/36bd24c1-6b16-4a5a-1102-f84915d5dbae.png)

IAM の [ロール]設定画面に移動するので、[許可ポリシー]で [許可を追加]をクリックする。

※)以下の設定ではすでに AmazonEC2ReadOnlyAccess の許可がされている

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/a10be738-89a2-5341-7969-caaf66fced61.png)


[ポリシーをアタッチ]を選択する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/8d8030b2-f506-f6e4-9d16-27fe19812095.png)

ポリシーのなかから「AmazonEC2ReadOnlyAccess」を選択して[許可を追加]をクリックする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/b6faf9db-a399-2806-c4d9-9f3bffe96cdf.png)


### awscli のコマンドを設定

[設定] の環境変数で以下の設定をしておく。
AWS の接続キーはホームディレクトリ (/home/xxxxx) に保存しようとするが、Lambda は /tmp 以外はリードオンリーのため、保存するキーのファイル位置を変更する。

* キー
** AWS_CONFIG_FILE
* 値
** /tmp/.aws/config

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/f0ed08b3-9a6b-41c3-0b28-84ead04e617b.png)

[コード] に以下のように記載する

```bash
function handler () {
    EVENT_DATA=$1

    aws --version
    

    echo AWS_CONFIG_FILE=$AWS_CONFIG_FILE

    aws configure set アクセスキー シークレットキー
    ls -al /tmp/.aws/
    
    echo Display INstance ID List
    aws ec2 describe-instances --query 'Reservations[].Instances[].{InstanceId:InstanceId}'


    RESPONSE="{\"statusCode\": 200, \"body\": \"Hello from Lambda!\"}"
    echo $RESPONSE
    


}

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/42e04bd0-dfee-bac7-6e24-63cbc007b393.png)


[テスト] で実行すると以下のようにインスタンスの一覧が出てくる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/4da7f237-c9b4-2169-6e90-aa64c79f70c2.png)