~ 最高境界,無伺服器勝有伺服器 ~
相關程式碼:https://github.com/slindevel/modern-aws-marathon
AWS Lambda 是一項運算服務,可讓您執行程式碼,無需佈建或管理伺服器。
Lambda 在高可用性的運算基礎設施上執行您的程式碼,並執行所有運算資源的管理,包括伺服器與作業系統維護、容量佈建與自動擴展以及記錄。使用 Lambda,您唯一需要做的就是在 Lambda 支援的其中一種語言執行期中提供您的程式碼。 ~ by AWS ~
這段話說明得很精確,但如果初學的人還是不知道他在說什麼吧
在計算機科學和程式領域,Lambda常常用來表示匿名函數或Lambda函數,也稱為函數字面量或函數值。 Lambda函數是一種無需定義名稱的函數,通常用於「編寫簡短而緊湊的程式碼」。
AWS Lambda 服務就是可以讓你跑簡短而緊湊的程式碼的服務。
所謂「簡短而緊湊的代碼」,是指相對於模組而言,舉個例來說,我們今天想完成一件事情需要10個步驟,雲服務會希望你把這「10個步驟」包上去,而不是把「完成一件事」包上去,未來在完成另一件相關的事情的時候,很大機會會用到這「10個步驟」,設計可重用簡短的程式碼讓服務得以重用我認為是雲端原生工程師一個很重要的課題。往後可能還有機會介紹到 API Gateway 的服務應該就更有感覺了,他可以掛上一個 HTTP Restful API 對外服務,後面接著一個 lambda service(更精確的說法:lambda handler),一個 HTTP Get 端點,對應到一個 lambda function。
我們先從一個簡單的 Python lambda handler 開始吧,
先準備 python 3.11 的環境,因為我們後面幾天會用到 AI 的東西,裝上 anaconda 管理 python 版本會比較方便,不過我們 lambda 上執行的話,必須要把整個 python project folder 封裝成 zip 檔案,這會需要這個 project folder 是完全獨立的,筆者是**使用 conda 管理 python 版本後再使用此版本建立 virtual env **的做法,建立 python virtual env 指令:進入專案目錄下 python -m venv .venv
使用 Python 建置 Lambda 函數
網路上有很多 step-by-step 的教學,都有附圖很好上手,我們都是武林高手,自然要用 AWS CLI 做啦
# create the role for execution of lambda
$ aws iam create-role --role-name marathon-lambda-ex \
--assume-role-policy-document file://trust-policy.json
# add lambda execution permissions to the role
$ aws iam attach-role-policy \
--role-name marathon-lambda-ex \
--policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
# get role info
$ aws iam get-role --role-name marathon-lambda-ex
$ aws iam list-role-policies --role-name marathon-lambda-ex
$ aws iam list-attached-role-policies --role-name marathon-lambda-ex
$ mkdir MarathonLambdaFunction && cd MarathonLambdaFunction
$ python -m venv .venv
$ vi lambda_function.py
# lambda_function.py
import json
def lambda_handler(event, context):
# TODO implement
return {
'statusCode': 200,
'body': json.dumps('Hello from Marathon Lambda!')
}
# package it to zip format
$ zip function.zip lambda_function.py
# aws cli create-function
# query 'marathon-lambda-ex' role ARN first
$ aws iam get-role --role-name marathon-lambda-ex
$ aws lambda create-function \
--function-name marathon-function \
--zip-file fileb://function.zip \
--handler lambda_function.lambda_handler --runtime python3.11 \
--role <marathon-lambda-ex arn>
# then testing it, will output to out.log file
$ aws lambda invoke --function-name marathon-function out.log --log-type Tail
# update function to response new body 'Hello from New Marathon Lambda!'
$ zip function.zip lambda_function.py && \
aws lambda update-function-code \
--function-name marathon-function \
--zip-file fileb://function.zip
不知道 role 的 ARN 也可以進 web console 查詢
然後我們加一些 python package 進去我們的專案,只有一種最陽春的形式:python package folder
# lambda_function.py
import json
import boto3
import requests
def lambda_handler(event, context):
return {
'statusCode': 200,
'body': json.dumps('Hello from New Marathon Lambda!')
}
def lambda_handler_2(event, context):
bucket_list = ""
s3 = boto3.resource('s3')
for bucket in s3.buckets.all():
bucket_list = bucket_list + ', ' + bucket.name
return {
'statusCode': 200,
'body': json.dumps('all buckets: ' + bucket_list)
}
def lambda_handler_3(event, context):
r = requests.get('https://www.google.com.tw/')
return {
'statusCode': 200,
'body': json.dumps('all buckets: ' + str(r.status_code))
}
$ zip function.zip lambda_function.py && \
aws lambda update-function-code \
--function-name marathon-function \
--zip-file fileb://function.zip
# need to update lambda configuration to use lambda_handler_2
$ aws lambda update-function-configuration --function-name marathon-function \
--handler lambda_function.lambda_handler_2
# fail becaouse lambda no permission to s3
$ aws lambda invoke --function-name marathon-function out.log --log-type Tail
# attach policy to lambda execution role & invoke again
$ aws iam attach-role-policy --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess --role-name marathon-lambda-ex
$ aws lambda invoke --function-name marathon-function out.log --log-type Tail
# use python virtual env
$ python -m venv .venv
$ . .venv/bin/activate
$ pip install requests
$ pip install boto3
$ pip show pip # find where is the package installed, here is '.venv/lib/python3.11/site-packages'
$ pushd .venv/lib/python3.11/site-packages && zip -r ../../../../function.zip . && popd
$ zip function.zip lambda_function.py
$ aws lambda update-function-code \
--function-name marathon-function \
--zip-file fileb://function.zip
$ aws lambda update-function-configuration --function-name marathon-function \
--handler lambda_function.lambda_handler_3
$ aws lambda invoke --function-name marathon-function out.log --log-type Tail
# 執行以下指令移除一些不必要的檔案
$ find . | grep -E "(/__pycache__$|\.pyc$|\.pyo$)" | xargs rm -rf
上面的 lambda_handler_3 大家會發現一個小秘密,預設 lambda 是可以連外的,一般說來建立 lambda 會建議需要設定 vpc ,才能決定你的 lambda 住哪邊吧,之後才能由 vpc 掌握可以連線的 resouces,包含外網,這部分我們會在明天 lambda 進階探討
最後我們看看 function.zip 的內容吧
├── function (folder)
├── lambda_function.py (file)
├ ├── requests (folder)
├ ├── boto3 (folder)
使用 credentials 在本機端執行
上面的取得 S3 bucket list 的 handler 也可以在本機端執行唷,記得我們在之前瘋狂使用本機端的 AWS CLI 執行一堆指令吧,關鍵在於我們有設定本機端的Credential,同樣地,我們也可以使用 Python 程式碼取得本機端的 Credential 來執行 AWS 服務相關的程式碼,直接來看範例吧(AWS_PROFILE_NAME可以在 ~/.aws/credentials 裡面找到
# Can be execution on local environment
def lambda_handler_3(event, context):
session = boto3.Session(profile_name='{YOUR_AWS_PROFILE_NAME}')
s3_client = session.client('s3')
response = s3_client.list_buckets()
bucket_list = ""
for bucket in response['Buckets']:
bucket_list = bucket_list + ', ' + bucket['Name']
return {
'statusCode': 200,
'body': json.dumps('all buckets: ' + bucket_list)
}
Lambda 這個概念的出現,讓我們重新思考**何謂架構**,說到底其實我們**其實不需要架構**,**只需要**有人可以幫我們執行我們要的指令**完成我們要的功能**而已,因為要**快速、穩定、正確**大量執行我們的指令,數十年的資訊架構演進都是**為了實現這一件事情**,執行者需要處理租用機房,採購設備,部署指令,維持運作等等工作,而今天 AWS Lambda **只需要我們提供指令**以及**足夠的執行資訊(環境變數)**給他就行了,**有需要的時候幫忙找環境執行,不需要的時候不佔用資源**,多麽優雅美妙!
Cloud Native 意指雲端原生應用,強調原生的背後很有可能是呼籲回歸本質? Native 一詞我認為相當有趣,資訊的進步腳步太快,項目五花八門,今日我們似乎看到了應用的終點,用程式寫個人出來做事 — AI,但我們仍然在創造一堆困難艱澀的名詞,回歸 Native,邁向收斂看起來才像是個終點,另一方面 Cloud,應該是因為實現 Native的解答在雲端上面的意思吧,而 Lambda 是我認為最能闡述體會出這個概念的服務!
https://aws.amazon.com/tw/blogs/compute/introducing-aws-lambda-destinations/
https://boto3.amazonaws.com/v1/documentation/api/latest/index.html
https://dev.to/aws-builders/simple-aws-20-advanced-tips-for-lambda-1oif
https://awstip.com/how-to-add-external-python-libraries-to-aws-lambda-baa8cb8dd7e1
https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html