本篇教程,我们将共同了解如何将AWS Lambda函数(Node.js)迁移至OpenFaaS。
云函数服务确实优点很多,不仅成本低廉,而且适合大部分用例的实际需求。但在另一方面,OpenFaaS相较于云函数服务也拥有不少独特优势。
下面,我先聊聊自己在使用OpenFaaS中的具体感受:
根据实际体验,我之前已经建立起一套Docker Swarm集群,其中的资源由云服务供应商管理,同时拥有监控、高可用性以及自我修复机制。
现在,我可以在这套集群设置之上使用OpenFaaS,而且完美匹配实际用例。
终极目标是将AWS Lambda Function迁移至OpenFaaS:
我们在AWS中的无服务器应用程序包含API网关、DynamoDB以及Lambda(Node.js)。
在示例中,我会尽量控制应用程序的复杂度,因此其功能非常简单:当我在API网关资源上发出GET请求时,在DynamoDB表上执行GetItem。
在这种情况下,我将哈希键值硬编码至 ruan.bekker中。
整个流程如下所示:
-> API: /dev/person,
-> Lambda calls DynamoDB: {"id": "ruan.bekker"},
-> Response: {"id": "ruan.bekker", "name": "ruan", ...}
为了完全透明,我将使用无服务器方式设置整个AWS栈:
$ mkdir -p ~/dev/aws-node-get-dynamodb \
&& cd ~/dev/aws-node-get-dynamodb
$ npm install -g serverless
$ serverless create --template aws-nodejs
创建Lambda函数:
$ mkdir function/handler.js
$ cat function/handler.js
'use strict';
const AWS = require('aws-sdk');
const dynamoDb = new AWS.DynamoDB.DocumentClient();
module.exports.identity = (event, context, callback) => {
const params = {
TableName: process.env.DYNAMODB_TABLE,
Key: {
id: 'ruan.bekker',
},
};
dynamoDb.get(params, (error, result) => {
if (error) {
console.error(error);
callback(null, {
statusCode: error.statusCode || 501,
headers: { 'Content-Type': 'text/plain' },
body: 'GetItem Failed',
});
return;
}
const response = {
statusCode: 200,
body: JSON.stringify(result.Item),
};
callback(null, response);
});
};
无服务器定义文件:
$ cat serverless.yml
service: aws-node-get-dynamodb
frameworkVersion: ">=1.1.0 <2.0.0"
provider:
name: aws
runtime: nodejs10.x
environment:
DYNAMODB_TABLE: my-dynamodb-table
iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:GetItem
Resource: "arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:provider.environment.DYNAMODB_TABLE}"
functions:
get:
handler: functions/handler.identity
events:
- http:
path: person
method: get
cors: true
resources:
Resources:
TodosDynamoDbTable:
Type: 'AWS::DynamoDB::Table'
DeletionPolicy: Retain
Properties:
AttributeDefinitions:
-
AttributeName: id
AttributeType: S
KeySchema:
-
AttributeName: id
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
TableName: ${self:provider.environment.DYNAMODB_TABLE}
部署该栈:
$ serverless deploy --region eu-west-1
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service aws-node-get-dynamodb.zip file to S3 (7.38 MB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
..............
Serverless: Stack update finished...
Service Information
service: aws-node-get-dynamodb
stage: dev
region: eu-west-1
stack: aws-node-get-dynamodb-dev
resources: 12
api keys:
None
endpoints:
GET - https://xx.execute-api.eu-west-1.amazonaws.com/dev/person
functions:
get: aws-node-get-dynamodb-dev-get
layers:
None
Serverless: Run the "serverless" command to setup monitoring, troubleshooting and testing.
现在我们的技术栈已经部署完成,接下来就是向DynamoDB中写入一个条目。
由于本文的重点在于迁移,因此我将哈希键硬编码至ruan.bekker当中,下面在DynamoDB中创建该条目:
$ aws dynamodb put-item \
--table-name my-dynamodb-table --item \
'
{
"id": {"S": "ruan.bekker"},
"name": {"S": "ruan"},
"surname": {"S": "bekker"},
"country": {"S": "south africa"},
"age": {"N": "32"}
}
发送一条指向该API网关URL的GET请求:
$ curl https://xx.execute-api.eu-west-1.amazonaws.com/dev/person
{"id":"ruan.bekker","surname":"bekker","name":"ruan","country":"south africa","age":32}
可以看到,现在我们已经能够在DynamoDB中检索到该条目。
创建一个新的Node.js OpenFaaS函数(请注意,设置当中使用了镜像前缀与网关url,如下所示):
$ mkdir -p ~/dev/lambda-to-openfaas-migration \
&& cd ~/dev/lambda-to-openfaas-migration
$ faas-cli new \
--lang node person \
--prefix=ruanbekker \
--gateway https://openfaas.ruan.dev
$ mv person.yml stack.yml
在本示例中,我会将AWS Access Keys与Secret Keys创建为OpenFaaS secrets:
$ faas-cli secret create my-aws-secret-key --from-literal="your-access-key"
$ faas-cli secret create my-aws-access-key --from-literal="your-secret-key"
在我们的package.json当中提供aws-sdk依赖项,并借此与AWS进行交互:
$ cat person/package.json
{
"name": "function",
"version": "1.0.0",
"description": "",
"main": "handler.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"aws-sdk": "latest"
}
}
我们的栈定义:
$ cat stack.yml
provider:
name: openfaas
gateway: https://openfaas.ruan.dev
functions:
person:
lang: node
handler: ./person
image: ruanbekker/person:latest
environment:
content_type: application/json
DYNAMODB_TABLE: my-dynamodb-table
AWS_REGION: eu-west-1
secrets:
- my-aws-access-key
- my-aws-secret-key
我们的初始设置中仍包含AWS Lambda函数代码,但到这里的栈已经设置完成,而且无需任何本地复本。
下面,我们需要下载Lambda部署软件包:
$ mkdir aws-lambda \
&& cd aws-lambda
$ lambda_url=$(aws lambda get-function --function-name serverless-rest-api-with-dynamodb-dev-get | jq -r .Code.Location)
$ curl -o deployment_package.zip "${lambda_url}"
提取该部署软件包并利用由此得到的OpenFaaS处理程序替换原Lambda函数处理程序:
$ unzip deployment_package.zip
$ cd ..
$ mv aws-lambda/function/handler.js person/handler.js
接下来,我们需要修改处理程序以纳入各secrets与环境变量:
$ cat person/handler.js
'use strict';
const fs = require('fs');
const secretAK = "/var/openfaas/secrets/my-aws-access-key";
const secretSK = "/var/openfaas/secrets/my-aws-secret-key";
const accessKey = fs.readFileSync(secretAK, "utf-8");
const secretKey = fs.readFileSync(secretSK, "utf-8");
const AWS = require('aws-sdk');
AWS.config.update({
credentials: new AWS.Credentials ({
region: process.env.AWS_REGION,
accessKeyId: accessKey,
secretAccessKey: secretKey
})
})
const dynamoDb = new AWS.DynamoDB.DocumentClient();
module.exports = (context, callback) => {
const params = {
TableName: process.env.DYNAMODB_TABLE,
Key: {
id: 'ruan.bekker',
},
};
dynamoDb.get(params, (error, result) => {
if (error) {
console.error(error);
callback(null, {
statusCode: error.statusCode || 501,
headers: { 'Content-Type': 'text/plain' },
body: 'GetItem Failed',
});
return;
}
const response = result.Item;
callback(null, response);
});
};
部署OpenFaaS函数:
$ export OPENFAAS_URL=https://openfaas.ruan.dev
$ faas-cli up
Deploying: person.
Deployed. 202 Accepted.
URL: https://openfaas.ruan.dev/function/person
现在,我们需要在OpenFaaS API网关URL上通过GET请求测试新创建的函数:
$ curl https://openfaas.ruan.dev/function/person
{"id":"ruan.bekker","surname":"bekker","name":"ruan","country":"south africa","age":32}
搞定,现在我们已经将AWS Lambda Function迁移至OpenFaaS。
原文链接:
https://sysadmins.co.za/migrate-your-aws-node-js-lambda-function-to-openfaas/
领取专属 10元无门槛券
私享最新 技术干货