使用AWS EFS文件系统加载lambda python函数依赖
使用AWS EFS文件系统加载lambda python函数依赖
1. 文档目的
通常在部署AWS lambda python函数时,函数的依赖包通常会通过加载层来挂载,但是lambda 函数层的大小是有限制的,其限制如下:
函数层:最大五层
部署程序包(.zip 文件存档)大小:
50 MB(已压缩,可直接上载)
250 MB(已解压缩)此配额适用于您上载的所有文件,包括层和自定义运行时。
3 MB(控制台编辑器)
更多的限制,可查阅AWS 官方文档:Lambda 配额 - Amazon Lambda (amazonaws.cn)
如果函数依赖包解压后大于250MB, 那么可以使用以下方法突破限制:
- 使用EFS文件系统挂载依赖包;
- 使用container方式部署lambda函数;
本文讨论使用EFS文件系统加载python依赖包。以下是具体的创建步骤:
2. 创建过程
2.1.创建EFS文件系统
- 创建文件系统
- 打开 Amazon EFS 管理控制台:https://console.aws.amazon.com/efs/
- 选择创建文件系统以打开创建文件系统对话框对话框。
- 输入名称您的文件系统的。
- 选择VPC。
- 存储类选择默认的标准,如果是测试,可以考虑选择单区,以节约费用。
- 选择创建完成文件系统的创建。
- 创建接入点
- 在文件系统页面选择已经创建的文件系统
- 在文件系统详细页面选择接入点标签,
- 点击创建接入点
- 在创建页面,输入接入点名称和根目录路径:
- 输入用户ID 和组 ID:
- 输入拥有者用户ID , 拥有者组 ID 和文件权限:
- 选择 创建接入点,完成创建。
2.2.实例上挂载EFS,安装依赖包
- 启动EC2实例
- 打开 Amazon EC2 控制台
- 选择 Launch Instance(启动实例)
选择Amazon Linux 2 AMI 镜像,然后选择Select.。
- 选择一个实例类型、配置实例详细信息、添加存储.、添加标签、配置安全组
- 选择 Review and Launch
- 选择启动。
- 选中密钥对复选框,然后选择启动实例。
- 2)挂载EFS文件系统
- 在文件系统详细页面选择连接,查看连接命令:
(如果实例和FES在相同的子网,可选择通过DNS挂载,如果不在相同的子网,则要通过ip挂载)
- 登录EC2实例,安装efs 客户端:
# yum install -y amazon-efs-utils
- 挂载efs:
# mount -t nfs4 \
-o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport 10.100.15.94:/ /mnt
- 安装python依赖包(以cx_Oracle为例),将依赖包安装到挂载目录下:
# mkdir -p /mnt/oracle/{python,lib}
# cd /mnt/oracle
# wget \
# unzip -j instantclient-basic-linux.x64-19.3.0.0.0dbru.zip -d lib
# yum -y install libaio
# cp /lib64/libaio.so.1 lib/
# pip3 install cx_Oracle -t python/
2.3.创建lambda函数
- 1)创建函数:
- 在 Lamba 控制台选择 Create function。
- 在 Basic information中,执行以下操作:
输入Name: python_oracle
对于运行时,选择: python 3.7
对于更改默认执行角色,选择创建具有基本 Lambda 权限的新角色。
- 高级设置里选择启用VPC:
对于 VPC:选择EFS文件系统所在的VPC。
对于子网:选择EFS文件系统关联的子网。
对于安全组:选择已经存在的安全组或在VCP下新建一个安全组,VPC内放行所有流量,然后刷新选择安全组。
- 选择 Create function
- 2)修改函数配置
- 函数页面选择配置选项
常规配置:修改超时时间为适当的值,如1分钟,最大不超过15分钟。否则默认的3秒可能会在运行函数时报超时的错误。
文件系统:选择添加文件系统:
下拉选择EFS文件系统;
下拉选择接入点;
输入本地挂载路径:以/mnt开头,如: /mnt/efs
权限:点击角色名称,进入角色详细界面,添加权限,添加对EC2的操作策略:AmazonEC2FullAccess(也可按最小访问原则创建策略然后添加到角色权限中)
环境变量:(因为cx_Oracle要用到自己的lib库,所以至少要添加一个环境变量,指定lib库的路径) 添加环境变:LD_LIBRARY_PATH (系统库路径)在路径值的末尾加上库依赖库的路径,本例为:/mnt/efs/lib
Key: LD_LIBRARY_PATH
Value:/lib64:/usr/lib64:$LAMBDA_RUNTIME_DIR:$LAMBDA_RUNTIME_DIR/lib:$LAMBDA_TASK_ROOT:$LAMBDA_TASK_ROOT/lib:/opt/lib: /mnt/efs/lib
- 3)编写代码
在代码定义部分加入依赖包和路径:
import sys
sys.path.append('/mnt/efs/python')
sys.path.append('/mnt/efs/lib')
import cx_Oracle
测试代码如下:
import json
import os
import sys
sys.path.append('/mnt/efs/python')
sys.path.append('/mnt/efs/lib')
import cx_Oracle
def lambda_handler(event, context):
#print(sys.path)
#print('Before: ',os.listdir('/mnt/efs/lib'))
host1 = os.getenv('host1')
port = os.getenv('port')
sid = os.getenv('sid')
db_user = os.getenv('db_user')
db_password = os.getenv('db_password')
dsn_tns = cx_Oracle.makedsn(host1, port, service_name = sid)
conn = cx_Oracle.connect(user = db_user, password = db_password, dsn = dsn_tns, encoding = 'UTF-8')
return "successfully connected to oracle server"
2.4.调用 Lambda 函数
- 选择函数后,选择 Test(测试)选项卡。
- 在 Test event(测试事件)部分中,选择 New event(新事件)。在 Template(模板)中,保留默认的 hello-world 选项。输入此测试的 Name(名称):test
- 选择 Save changes(保存更改),然后选择 Test(测试)
- 返回代码选项,在代码源框里选择Deploy选项
- 部署完成后选择Test选项调用函数:
- 成功完成后,在控制台中查看结果:
- 默认情况下,lambda会调用cloudwatch,生成一个以lambda名称为名的日志组:
- 选择日志组,在日志流选项里选择日志,可查看lambda的执行日志:
3. 结论
- 在使用EFS 文件系统时如果文件大小超过2G, 则需要使用容器的方式部署lambda 函数,或是将函数拆分成多个类函数部署;
- 在部署函数时,可添加配置函数的VPC,并文件系统所在的VPC相同;
- 默认lambda的系统环境变量不会自动添加自定义文件的路径,需要手动添加环境变量;
- 如果EFS文件系统网络可达,可以本地挂载文件系统安装依赖包,而不用创建新实例挂载文件系统。
附:添加lambda层
如果python依赖包不超过250M,可使用添加层的式加载python依赖。步骤如下:
- EC2上安装python依赖包:
# mkdir boto3
# pip install boto3 –target boto3
- 2)压缩依赖包并上传至S3:
# zip -y -r boto3.zip boto3
# aws s3 cp boto3.zip s3://qdoraclelayer/oraclelayer/
- 3)创建lambda 层:
- 打开 Lambda 控制台的 Layers page
- 选择 Create layer
- 在 Layer configuration下,在 Name中,输入层的名称:boto3layer
- 选择 Upload a file from Amazon S3,输入zip文件的S3地址
- 对于 Compatible runtimes(兼容的运行时)选择7
- 选择 Create
- 4)添加层:
- 在函数页面的层选项选择添加层:
- 在添加层页面选择自定义屋
- 在下拉框选择需要的层的名称
- 选择添加
- 添加后可在函数概述中看到layer 为 (1):