長期間使用していない AWS Lambda の inactive 状態を active 状態にする方法を備忘録として残しておく

事象

関数が数週間アイドルのままの場合、Inactive 状態になり、その状態で関数を呼び出すとエラーになる

詳細は以下を参照

対象の洗い出し

以下のスクリプトを AWS CLI にて使用することで対象の洗い出しが行える

#!/bin/sh

aws --profile <<プロフィール名>> lambda list-functions --region <<リージョン名>> --query 'Functions[?starts_with(FunctionName, `<<関数名プレフィックス>>`) == `true`].FunctionName' > lambda_list.json
lambda_names=`jq -r .[] lambda_list.json`

for lambda_name in $lambda_names; do
  aws --profile <<プロフィール名>> lambda get-function --output text --function-name $lambda_name --query 'Configuration.[FunctionName, State, LastUpdateStatus]' | sort -k 1 | column -t -s "`printf '\t'`"
done

解消方法

inactive の状態で lambda を実行するとエラーになるがしばらくすると active 状態となり実行可能となる
もしくは、以下のスクリプトを AWS Console 上で実行することで inactive => active に状態を更新できる

#!/bin/bash -eu

all_lambda_name_list=()
inactive_lambda_name_list=()

# 最初にアカウント上のすべての関数名を取得
function get_all_lambda_name_list() {
    echo "【Start get_all_lambda_name_list】$(date "+%Y/%m/%d %H:%M:%S")"
    readonly lambda_list=$(aws lambda list-functions \
        | jq -r '.Functions')

    len=$(echo $lambda_list | jq length)
    for i in $( seq 0 $(($len - 1)) ); do
        all_lambda_name_list+=($(echo $lambda_list | jq -r .[$i].FunctionName))
    done
    echo "【End get_all_lambda_name_list】$(date "+%Y/%m/%d %H:%M:%S")"
}

# 関数が state = Active かどうかの判定
function is_lambda_active() {
    local lambda_name=$1
    local state=$(aws lambda get-function-configuration \
        --function-name $lambda_name \
        | jq -r '.State')
    
    if [ $state = "Active" ]; then
        echo "true"
    else
        echo "false"
    fi
}

# Active でない関数のみを抽出
function filter_inactive_resources() {
    echo "【Start filter_inactive_resources】$(date "+%Y/%m/%d %H:%M:%S")"
    for lambda_name in ${all_lambda_name_list[@]}; do
        is_active=$(is_lambda_active $lambda_name)
        if [ "${is_active}" = "false" ]; then
            echo $lambda_name
            inactive_lambda_name_list+=($lambda_name)
        fi
    done
    echo "【End filter_inactive_resources】$(date "+%Y/%m/%d %H:%M:%S")"
}

# Active でない関数に対して publish-version を実行する
function publish_lambda() {
    echo "【Start publish_lambda】$(date "+%Y/%m/%d %H:%M:%S")"
    if [ ${#inactive_lambda_name_list[@]} -eq 0 ]; then
        echo "there is no lambda to publish"
        return 0
    fi
    for lambda_name in ${inactive_lambda_name_list[@]}; do
        echo "now publishing ${lambda_name}"
        aws lambda publish-version --function-name $lambda_name
        aws lambda wait function-active --function-name $lambda_name # 関数が Active になるまで待機
    done
    echo "【End publish_lambda】$(date "+%Y/%m/%d %H:%M:%S")"
}

echo "【Start Processing】$(date "+%Y/%m/%d %H:%M:%S")"
get_all_lambda_name_list
filter_inactive_resources
publish_lambda
echo "【End Processing】$(date "+%Y/%m/%d %H:%M:%S")"

AWS CLI で実行する場合は以下を参考にする

#!/bin/sh

# Shared
AWS_PROFILE_PREFIX={AWS プロファイルのプレフィックス} #自分の設定に書き換える
LOG_FILE=log/make_active_all_lambda.log

all_lambda_name_list=()
inactive_lambda_name_list=()

read -p "Which environment connect to? (dev/stg/prd): " input_environment

# Check the environment
case "${input_environment}" in
  "dev" | "stg" | "prd")
    echo "Connecting to ${environment} environment..." >> ${LOG_FILE} 2>&1

    if [ $input_environment = "prd" ]; then
        # AWS MFA Authentication
        aws-mfa --profile=${AWS_PROFILE_PREFIX}-${input_environment}
    fi;;
  *)
    echo "Please enter the correct environment." >> ${LOG_FILE} 2>&1
    echo "【End Processing】$(date "+%Y/%m/%d %H:%M:%S")" >> ${LOG_FILE} 2>&1
    exit;;
esac

# アカウント内全ての関数名を取得
function get_all_lambda_name_list() {

    readonly lambda_list=$(aws lambda --profile=${AWS_PROFILE_PREFIX}-${input_environment} list-functions \
        | jq -r '.Functions')

    len=$(echo $lambda_list | jq length)
    for i in $( seq 0 $(($len - 1)) ); do
        all_lambda_name_list+=($(echo $lambda_list | jq -r .[$i].FunctionName))
    done
}

# 関数の state == Active かどうかを返す
function is_lambda_active() {
    local lambda_name=$1
    local state=$(aws lambda --profile=${AWS_PROFILE_PREFIX}-${input_environment} get-function-configuration \
        --function-name $lambda_name \
        | jq -r '.State')

    if [ $state = "Active" ]; then
        echo "true"
    else
        echo "false"
    fi
}

# 関数の state == Active でないものを抽出
function filter_inactive_resources() {
    echo "== following lambda is inactive ==" >> ${LOG_FILE} 2>&1
    for lambda_name in ${all_lambda_name_list[@]}; do
        is_active=$(is_lambda_active $lambda_name)
        if [ "${is_active}" = "false" ]; then
            echo $lambda_name
            inactive_lambda_name_list+=($lambda_name)
        fi
    done
    echo "== that's all ==" >> ${LOG_FILE} 2>&1
}

# 関数を Active にする
function publish_lambda() {
    if [ ${#inactive_lambda_name_list[@]} -eq 0 ]; then
        echo "there is no lambda to publish" >> ${LOG_FILE} 2>&1
        return 0
    fi
    for lambda_name in ${inactive_lambda_name_list[@]}; do
        echo "now publishing ${lambda_name}" >> ${LOG_FILE} 2>&1
        aws lambda --profile=${AWS_PROFILE_PREFIX}-${input_environment} publish-version --function-name $lambda_name
        aws lambda --profile=${AWS_PROFILE_PREFIX}-${input_environment} wait function-active --function-name $lambda_name # 関数が Active になるまで待つ
    done
}

echo "【Start Processing】$(date "+%Y/%m/%d %H:%M:%S")" >> ${LOG_FILE} 2>&1
get_all_lambda_name_list
filter_inactive_resources
publish_lambda
echo "【End Processing】$(date "+%Y/%m/%d %H:%M:%S")" >> ${LOG_FILE} 2>&1