Elastic File System
AWS 彈性檔案系統 (Amazon Elastic File System,Amazon EFS) 是 AWS 提供的一種雲端儲存服務,提供無伺服器、完全彈性和加密的檔案儲存,供 AWS 運算服務和企業內部使用。
Amazon EFS 支援網路檔案系統 (NFS) 版本 4.0 和 4.1 (NFSv4) 協定,並通過可移植作業系統介面 (POSIX) 權限控制使用者對檔案的訪問。
EFS 可以同時被多個系統或是 AWS 服務掛載。目前 EC2、ECS 與 Lambda 等計算服務皆可以掛載 EFS。
在 EC2 上掛載 EFS
EC2 需要手動掛載 EFS。以 Amazon Linux 2023 為例,首先安裝 Amazon EFS 客戶端。
sudo yum install -y amazon-efs-utils
然後在跟目錄底下新建一個 /efs 資料夾。
cd /
sudo mkdir efs
接下來就能透過下面的指令掛載 EFS。
# sudo mount -t efs <FILE-SYSTEM-ID> <EFS-MOUNT-POINT>
# 範例如下
sudo mount -t efs fs-abcd123456789ef0 efs/
[!NOTE]
EC2 掛載 EFS 不需要任何 Policy。
在 Lambda 上掛載 EFS
Lambda 上也能掛載 EFS。 但是 Lambda 必須放在 VPC 底下,並透過 Access Point 來存取 EFS。 下面以 Terraform 為例,建立一個 EFS 並掛載到 Lambda。
以 Terraform 為例。首先建立一個 EFS 與 Access Point。
resource "aws_efs_file_system" "for_lambda" {
performance_mode = "generalPurpose"
encrypted = true
tags = {
Name = "efs_for_lambda"
}
}
resource "aws_efs_backup_policy" "policy" {
file_system_id = aws_efs_file_system.for_lambda.id
backup_policy {
status = "ENABLED"
}
}
resource "aws_efs_mount_target" "for_lambda" {
file_system_id = aws_efs_file_system.for_lambda.id
subnet_id = data.aws_subnet.private.id
security_groups = [aws_security_group.allow_internal_access_to_efs.id]
}
resource "aws_efs_access_point" "for_lambda" {
file_system_id = aws_efs_file_system.for_lambda.id
root_directory {
path = var.root_directory
creation_info {
owner_gid = 1000
owner_uid = 1000
permissions = "755"
}
}
posix_user {
gid = 1000
uid = 1000
}
}
Lambda 在存取 EFS 中的檔案時,會以 Access Point 設定的 UID (User ID) 與 GID (Group ID) 來判斷是否擁有對檔案的權限。
For Amazon EFS, file system objects (that is, files, directories, and so on) are owned by a single owner and a single group. Amazon EFS uses the mapped numeric IDs to check permissions when a user attempts to access a file system object.
所以如果你想用 Lambda 存取 EFS 中用 EC2 建立的檔案, 可以將 UID 與 GID 都設定為 1000,即 EC2 預設使用者的 UID 與 GID。
接下來在 Lambda 中掛載 EFS。
resource "aws_lambda_function" "web_lambda_function" {
depends_on = [aws_efs_mount_target.alpha]
filename = var.filename
source_code_hash = filesha256(var.filename)
handler = "Bref\\LaravelBridge\\Http\\OctaneHandler"
runtime = var.lambda_runtime
function_name = "${var.app_name}-web"
memory_size = 1024
timeout = 28
architectures = ["arm64"]
role = aws_iam_role.lambda_execution.arn
layers = [var.php_lambda_layer_arn]
environment {
variables = merge(local.lambda_function_environment_variables, {
BREF_LOOP_MAX = "250"
OCTANE_PERSIST_DATABASE_SESSIONS = "1"
})
}
# 要掛載 EFS,Lambda 必須放在 VPC 底下
vpc_config {
subnet_ids = [aws_subnet.private.id]
security_group_ids = [aws_security_group.egress_only.id]
}
# 掛載 EFS,注意掛載路徑必須是 /mnt 開頭
file_system_config {
arn = aws_efs_access_point.for_lambda.arn
local_mount_path = "/mnt/efs"
}
}
這樣 Lambda 中的 /mnt/efs 就會掛載到 EFS 中的 /lambda。
EFS 支援 SQLite
因為 EFS 支援 NFSv4,所以可以在上面使用 SQLite。 讀多寫少的小網站完全可以考慮 EFS + SQLite 的方式來代替一般的資料庫。