使用 S3、Libvips 和 Ruby 的 AWS Lambda 微服务研讨会
有兴趣使用 Ruby 从头学习 AWS 和 Lambda 吗?本次研讨会利用 Docker 和AWS SAM Cookiecutter 模板,提供快速且配置简单的课程。您将学习以下内容,并学习如何编写一个响应 S3 事件以调整源镜像大小的 Lambda。
- AWS Lambda的入门概念。
- 使用AWS SAM CLI在本地开发和部署 Lambda。
- 通过CloudFormation实践基础设施即代码 (IaC) 。
研讨会步骤
想快速学习,稍后再阅读?在每个部分中,找到以⚡️⏩⚡️符号开头的代码框,输入或应用它们,即可轻松完成整个工作坊。不过,请务必抽出时间跟进并稍后阅读笔记。以下是今天工作坊的步骤。
准备
🚢 安装 Docker
AWS SAM 使用 Docker 来模拟 Ruby Lambda 运行时环境。我们还使用 Docker 来避免同时安装 AWS CLI 和 SAM CLI。由于两者都使用 Python,安装起来可能会比较麻烦。不用担心,Docker 也能帮您解决这个问题。如果您还没有安装Docker,请立即安装。它能正常工作吗?
$ docker --version
Docker version 19.03.8, build afacb8b
⛅️ AWS 账户
毕竟,从现在开始,我们就在云端了——所以你需要一个 AWS 账户。创建账户非常简单。之后,你需要使用账户的AWS_ACCESS_KEY_ID
和 来配置程序访问权限。如果你还没有这些权限,可以在AWS 管理控制台AWS_SECRET_ACCESS_KEY
中执行以下操作来创建它们。
- 点击工具栏中的“服务”。
- 在查找服务字段中输入“IAM”,然后选择。
- 单击左侧导航中的“用户”,选择您的用户名。
- 单击“安全凭证”选项卡。
- 单击“创建访问密钥”按钮。
- 将您的密钥 ID 和秘密复制到安全的地方。
从这里开始,您需要配置 CLI 程序访问。使用 AWS CLI Docker 容器可以轻松完成此操作。
$ docker run \
--interactive \
--tty \
--rm \
--volume "${HOME}/.aws:/root/.aws" \
"amazon/aws-cli" \
configure
出现提示时,请粘贴上述步骤中生成的密钥 ID 和密钥。我建议使用us-east-1
默认区域和json
输出格式。为了aws
简化所有 CLI 命令,我建议使用以下别名。
alias aws='docker run --rm -it --tty -v "${HOME}/.aws:/root/.aws" -v "${PWD}:/aws" "amazon/aws-cli"'
或者,您可以通过 Homebrew 安装 AWS CLI 和 SAM。
$ brew install awscli
$ brew tap aws/tap
$ brew install aws-sam-cli
假设您已运行configure
并设置了别名。它能正常工作吗?此命令应该会列出您 AWS 账户中的所有 S3 存储桶。
$ aws s3 ls
🚀 CI/CD
这部分是可选的。但是,如果您已经git
安装并使用 GitHub,那么提交我们的工作不仅有趣,还能确保代码探索的安全。如果您两者都没有,也没关系,您可以放心地跳过这些步骤。
但是,如果您有 GitHub 帐户,我们的入门项目包含一个GitHub Action Workflow,可以帮助您以完全自动化的方式实践持续集成和持续交付 (CI/CD)。稍后会详细介绍。
步骤 1:使用 SAM Init 新建项目
自从Serverless框架首次出现以来,大多数开发者都对其非常熟悉。可以将其视为每个云提供商“无服务器”产品的 ActiveRecord 适配器。它是一个由社区插件支持的高阶抽象。
为了简化其 Lambda 产品的开发周期,AWS 开发了一款名为 🐿 SAM 的工具,它是无服务器应用程序模型 (Serverless Application Model)的缩写。SAM 包含用于表达函数的 YAML 语法名称,以及用于运行、构建和部署该函数的命令行工具。
❓为什么要使用 SAM 而不是无服务器?这两个工具都是开源的。但是,如果您是无服务器新手并且正在使用 AWS,我建议您使用 SAM。学习太多抽象层可能会令人沮丧。所以,在升级之前(如果有需要的话),请坚持使用 SAM 并学习它。
SAM初始化
要启动一个新的 SAM 项目,我们将使用一个 Docker 容器来运行,sam init
该容器利用这个自定义 Ink Cookiecutter 项目模板为您启动一个新的项目文件夹。
⚡️⏩⚡️
$ docker run \
--interactive \
--volume "${PWD}:/var/task:delegated" \
lambci/lambda:build-ruby2.7 \
sam init --location "gh:customink/cookiecutter-ruby"
它会提示您输入项目名称,并询问您的 Lambda 是否需要 HTTP API。请使用“image_service”作为此名称。此外,我们不希望此 Lambda 产生 HTTP 事件,因此在第二个问题中输入“2” 。
- 项目名称 [my_awesome_lambda]: image_service
- 选择 http_api 1 - 是 2 - 否:2️⃣
现在切换到你新创建的项目目录。所有其他命令都假定你位于此工作目录中。
⚡️⏩⚡️
$ cd image_service
🚀 CI/CD
假设您正在使用 git,并且在处理此项目时创建了一个 GitHub 仓库,请创建您的第一个提交并推送。请记住,首先在 GitHub 上创建一个新的仓库。
⚡️⏩⚡️
$ git init && git add .
$ git commit -m "Initial commit"
$ git remote add origin git@github.com:YOURUSERNAME/image_service.git
$ git push -u origin master
❗️YOURUSERNAME
用你自己的 GitHub 用户名替换。
发生了什么?
您的新 SAM 项目文件夹包含您新 Ruby Lambda 所需的一切。请花些时间浏览其内容。特别是template.yaml
描述您的 Lambda 函数的 SAM 文件。该文件指定了一个用于lib/image_service.rb
接收事件的处理程序方法。从更高层次来看,以下是新项目中生成的内容。
Dockerfile
使用和来进行 Docker 设置docker-compose
。- 一个具有 lib 目录、捆绑器和测试的工作 Ruby 项目。
- SAM 完全集成到所有设置和测试脚本中。
在整个研讨会期间,您将有机会熟悉所有这些内容。
第 2 步:设置和部署
在当前状态下,Lambda 唯一会做的事情就是记录触发它的事件。与其等待重大版本发布,不如趁着首次部署熟悉流程的好时机。首先,我们需要设置项目的依赖项并运行测试。这些命令类似于标准脚本,用于执行一次性引导或可重复的设置。例如,如果您在 Gemfile 中更改了依赖项。
⚡️⏩⚡️
$ ./bin/bootstrap
$ ./bin/setup
$ ./bin/test
如果您的测试运行良好,您应该会看到类似这样的输出。
# Running:
.
Finished in 0.000992s, 1008.4712 runs/s, 1008.4712 assertions/s.
1 runs, 1 assertions, 0 failures, 0 errors, 0 skips
您的第一次部署
⚡️⏩⚡️
$ STAGE_ENV=production ./bin/deploy
这将使用 AWS SAM 的构建、打包和部署 CLI 命令。假设一切顺利,您应该会看到 SAM 的 CloudFormation 部署任务的输出以类似以下内容结尾。请花点时间查看完整输出。
CloudFormation outputs from deployed stack
---------------------------------------------------------------------------------------------
Outputs
---------------------------------------------------------------------------------------------
Key ImageServiceLambdaArn
Description Lambda Function Arn
Value arn:aws:lambda:us-east-1:012345678912:function:image-service-production
---------------------------------------------------------------------------------------------
Successfully created/updated stack - image-service-production in us-east-1
💥有问题吗?你确定运行了bin/bootstrap
脚本吗?它应该会创建一个 S3 存储桶来存储你打包的工件。请检查.bucket-name
你的 AWS 账户中是否存在该文件以及该存储桶。
调用您的 Lambda
即使没有任何事件处理程序,我们仍然可以调用并测试您的 Lambda 是否已成功部署。登录AWS 管理控制台:
- 点击工具栏中的“服务”。
- 在查找服务字段中输入“CloudFormation”,然后选择。
在此页面中,您将看到新部署的镜像服务 Lambda 被列为“堆栈”。堆栈是项目的 AWS 资源集合。
点击您的堆栈,然后点击“资源选项卡”。您的 Lambda 项目只有两个资源:Lambda 本身以及它所执行的 IAM 角色。
- 点击“物理 ID”列下的“image-service-productions”Lambda 资源。这将带您进入 AWS 控制台中的 Lambda。
- 点击右上角的“测试”按钮。
- 使用“Hello World”事件模板。
- 将其命名为“HelloWorld”。
- 单击“创建”按钮。
- 现在单击“测试”按钮来调用您的 Lambda
🎉 恭喜!
您的新 Lambda 已运行。从我们刚刚执行的测试调用中,您可以看到返回值:一个包含状态码的 Ruby 哈希、一个标头数组以及一个响应正文。在本例中,Lambda 只是以 JSON 字符串的形式返回了它收到的相同事件。这就是您项目中的处理程序方法。
def handler(event:, context:)
puts event
{ statusCode: 200,
headers: [{'Content-Type' => 'application/json'}],
body: JSON.dump(event) }
end
CloudWatch 日志
那么,Ruby 处理程序中的调用怎么办puts
?标准输出又写到哪里了?日志记录到文件又怎么样?除了有限的存储空间外/tmp
,Lambda 无法写入文件系统。所有标准输出(日志)都会被 CloudWatch 捕获并写入日志组。该服务完全托管。查看我们测试调用的日志。
- 点击工具栏中的“服务”。
- 在查找服务字段中输入“CloudWatch”,然后选择。
- 单击左侧菜单中的“日志组”。
- 找到名为“/aws/lambda/image-service-production”的日志组并选择它。
从这里开始,CloudWatch 将日志按日期整理成流。点击其中一个即可查看测试调用的日志。
START RequestId: 0d6c34b2-42f0-439f-9f65-c35050e8da3e Version: $LATEST
{"key1"=>"value1", "key2"=>"value2", "key3"=>"value3"}
END RequestId: 0d6c34b2-42f0-439f-9f65-c35050e8da3e
REPORT RequestId: 0d6c34b2-42f0-439f-9f65-c35050e8da3e Duration: 2.93 ms Billed Duration: 100 ms Memory Size: 512 MB Max Memory Used: 49 MB Init Duration: 255.06 ms
❗️当出现问题时,深入研究 CloudWatch 日志是您应该首先查看发生了什么的地方之一。
🚀 CI/CD
由于 SAM 已捆绑并打包了我们的 Lambda,因此Gemfile.lock
我们的项目中新增了一个功能,确保我们的 gem 已锁定。我们可以在继续下一步之前提交此更改。
⚡️⏩⚡️
$ git add .
$ git commit -m "Add Gemfile.lock"
$ git push
步骤 3:将 Lambda 连接到 S3
现在该熟悉一下 AWS SAM 项目中的文件了。它们的组织方式通常与 Ruby Gem 类似。有一个lib
目录,其中包含与您的项目名称匹配的文件和文件夹。Ruby 文件是同名目录中所有必需文件的入口点。此外,还包含Gemfile
任何其他 Gem 依赖项的入口。
但是在部署过程中,我们如何在 AWS 中创建资源?此外,Lambda 如何知道在哪里调用你的 Ruby 代码?
模板.yaml
这是CloudFormation的 SAM 规范,用于指导如何构建项目所需的一切。您可以将其视为简化 AWS Lambda 开发的语法糖。
❗️需要记住的是,SAM 规范是 CloudFormation 的子集。任何有效的 CloudFormation 都可以在此模板中使用。
部署脚本运行时,SAM 会检查您的模板文件,找到您的代码,将其打包成一个压缩文件,上传到 S3 存储桶,然后使用新打包的 template.yaml 文件指示 CloudFormation 为您构建所需的 AWS 资源。请花些时间检查您的template.yaml
文件。请注意以下几点:
- 该
Resources
部分包含您需要在 AWS 中为此项目创建的所有内容。 - 您的函数的资源
Runtime
属性已设置为 Ruby 2.7。它还具有内存和超时设置。 - 函数部分
Handler
是 SAM 了解代码所在位置的方式。它会查找lib/image_service.rb
包含调用方法的文件handler
。 - CloudFormation 实际上是一种半动态语言。它通过称为伪参数的概念支持运行时反射,以及称为内部函数的行为。
❓SAM 把我的代码上传到哪个存储桶了?好问题!在上传过程中bin/bootstrap
,我们为您创建了一个随机存储桶名称。该名称存储在一个.bucket-name
文件中。
添加您的 S3 资源
上面有很多信息,SAM/CloudFormation 确实有很多功能。但让我们慢慢开始,创建 Lambda 的 S3 存储桶,以便它可以监听事件并最终调整图像大小。将以下内容添加ImageServiceS3Bucket
到template.yaml
文件中的Resources
部分下。由于缩进很重要,我们已显示了相对于 的位置ImageServiceLambda
。不过顺序并不重要。
⚡️⏩⚡️
Resources:
ImageServiceLambda:
# ...
ImageServiceS3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub image-service-SOMEUNIQNAME-${StageEnv}
❗️S3 bucket 名称是全局的。因此请将SOMEUNIQNAME
上面的内容替换为您自己的唯一名称。
触发 Lambda 事件
还记得我们的 Lambda 之前没有关联任何事件,需要我们手动触发测试吗?现在我们已经声明了 S3 存储桶资源,可以指示 SAM/CloudFormation 从任何S3 通知触发我们的 Lambda 。我们将选择任何ObjectCreated
事件。SAM 允许我们提供Events
属性,而这正是我们要添加属性的地方。请参阅下面的示例,了解如何在本ImageServiceLambda
Properties
节下添加属性。
⚡️⏩⚡️
ImageServiceLambda:
Type: AWS::Serverless::Function
Properties:
# ...
Events:
ImageServiceS3BucketEvent:
Type: S3
Properties:
Bucket: !Ref ImageServiceS3Bucket
Events: s3:ObjectCreated:*
这ImageServiceS3BucketEvent
被称为逻辑ID。它由我们定义,可以是任何我们想要的值,就像ImageServiceS3Bucket
上面一样。
我们的 S3 事件确实需要两样东西:存储桶的名称以及我们想要触发 Lambda 的事件。其!Ref
语法是我之前提到的内部函数之一。在本例中,我们赋予它上一步模板中存储桶资源的逻辑 ID。之所以能够成功,是因为 S3 存储桶的 Ref 返回值就是其名称。
部署更新的堆栈
又到了部署的时间了。部署时,请仔细观察 SAM 的输出。它展示了 CloudFormation 如何检测堆栈的变更,注意到新增资源以及哪些资源需要修改。它愉快地整理了所有这些,甚至确定了事件需要按什么顺序发生才能获得所需的结果。简直太神奇了!✨
⚡️⏩⚡️
$ STAGE_ENV=production ./bin/deploy
测试 S3 上传触发器 Lambda
现在,我们的存储桶已通过堆栈部署创建完成,接下来我们来上传一个镜像,看看它是否能触发 Lambda 函数。这里有一个有趣的文件,名为RubyForGood.png
,我们可以通过 AWS 控制台上传它。
- 点击工具栏中的“服务”。
- 在查找服务字段中输入“S3”,然后选择。
- 单击名为 的 S3 存储桶
image-service-SOMEUNIQNAME-production
。 其中SOMEUNIQNAME
是您之前选择的名称。 - 将此文件拖放到浏览器窗口即可启动上传对话框。
- 单击“下一步”3次,使用权限等的默认值。最后单击“上传”开始上传。
之后,您应该会看到文件已上传到 S3 存储桶。但是我们的 Lambda 是否收到了该事件?使用上一章中的CloudWatch 步骤,导航到您的日志组,查看您的 Lambda 是否收到了该事件并记录了它。您应该看到类似这样的内容。
{
"Records": [
{
"eventVersion": "2.1",
"eventSource": "aws:s3",
"awsRegion": "us-east-1",
"eventTime": "2020-04-26T23:40:00.273Z",
"eventName": "ObjectCreated:Put",
"userIdentity": {
"principalId": "AWS:AIDAJIS4TINW4H5GRI3LG"
},
"requestParameters": {
"sourceIPAddress": "72.228.219.152"
},
"responseElements": {
"x-amz-request-id": "B1C967507AE19561",
"x-amz-id-2": "CwSljyyyFADdm1Cyf06BsYkfWfoojX5CX7ezcT1Y9uWSF/L4mWGjz01cnPpGg+W+fiWEiCj2oQjTkELtfJFny5DlbB80UXkz"
},
"s3": {
"s3SchemaVersion": "1.0",
"configurationId": "8fe91e68-1782-47d8-93a1-470f89531673",
"bucket": {
"name": "image-service-SOMEUNIQNAME-production",
"ownerIdentity": {
"principalId": "A4ILFJ7OF8X06"
},
"arn": "arn:aws:s3:::image-service-SOMEUNIQNAME-production"
},
"object": {
"key": "RubyForGood.png",
"size": 659624,
"eTag": "a2028b43a11dd778720371ceaf53dde5",
"sequencer": "005EA59B740BD1E80F"
}
}
}
]
}
事实上,这个事件对我们最终的测试套件可能很有用。我建议把它添加到你的项目中test/events/s3-put.json
。稍后我们可以用它来进行一些最终的测试驱动开发。
🚀 CI/CD
这似乎是拯救我们工作成果的另一个好时机。
⚡️⏩⚡️
$ git add .
$ git commit -m "Connecting Lambda to S3"
$ git push
步骤4:图像处理和Lambda层
为了调整图像大小,我们需要选择一个 Ruby 库来帮我们完成这项工作。值得庆幸的是,Rails ActiveStorage提供了一个很棒的库,名为ImageProcessing,它可以利用 ImageMagick 或 Libvips 来调整图像大小。
将其添加到您的Gemfile
。
⚡️⏩⚡️
gem 'image_processing'
添加 Libvips
谈到 Lambda 时,我们通常称之为“无服务器”,但实际上,从技术角度来看,它确实涉及服务器。具体来说,它们是执行代码的微型虚拟机。您可以将它们视为托管容器,我们称之为“运行时”。如果您查看项目template.yaml
文件,您会发现我们函数的资源Runtime
属性设置为ruby2.7
。顾名思义,这些微型虚拟机仅包含执行所需任务所需的极简软件,例如,安装了 Ruby。这确保了它们体积小巧,并且能够快速执行代码。
通常,带有原生 C 扩展的 Ruby 库需要头文件或共享对象来编译或链接。ImageMagick 和 Libvips 都需要其他共享对象。AWS Lambda 的现代运行时并未预装这些共享对象。您可以使用一种名为Lambda Layers的技术来完成这项工作。Layers 工作原理最简单的解释是,它们会将代码添加到运行时的/opt
目录中。我们将使用一个 Lambda 层,将Libvips添加到我们的运行时中,以便 ImageProcessing gem 能够使用它。
在文件的功能部分下添加此公共 Libvips 层资源ARN。Properties
template.yaml
⚡️⏩⚡️
ImageServiceLambda:
Type: AWS::Serverless::Function
Properties:
# ...
Layers:
- arn:aws:lambda:us-east-1:589405201853:layer:rubyvips892-27:13
❓我可以了解更多关于这个 Libvips 层是如何构建的吗?是的,这里是用于构建该层的ruby-vips-lambda项目。此外, Yumda项目对于其他常见的层用例也是一个很好的选择。
权限
还记得我们第一次部署Lambda 并在 AWS 控制台中查看 CloudFormation 堆栈时吗?在“资源”选项卡中有一个 类型AWS::IAM::Role
。SAM 自动为我们创建了这个角色。调用时,我们的 Lambda 将使用附加到此角色的任何托管或内联策略执行。如果我们的 Lambda 要读写 S3 存储桶,则需要权限。幸运的是,借助 AWS SAM 框架,使用Policies
属性可以非常轻松地完成此操作。
任何有效的 AWS Identity & Access Management语句都可以在本节中以集合的形式表示。每个语句都将附加到您的 Lambda 函数的角色。以下是一个简单的示例,它声明此 Lambda 可以对其拥有的 S3 存储桶执行任何操作。
⚡️⏩⚡️
ImageServiceLambda:
Type: AWS::Serverless::Function
Properties:
# ...
Policies:
- Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- s3:*
Resource:
- !Sub arn:aws:s3:::image-service-SOMEUNIQNAME-${StageEnv}
- !Sub arn:aws:s3:::image-service-SOMEUNIQNAME-${StageEnv}/*
❗️S3 bucket 名称是全局的。因此,请将SOMEUNIQNAME
上面的名称替换为您自己的唯一名称。确保它与您在资源中使用的名称匹配ImageServiceS3Bucket
。
🚀 CI/CD
我们尚未完成读写 S3 bucket 所需的全部代码。所以现在无需提交工作。
步骤 5:Resizer 代码和权限
在本节中,我们将响应“将 Lambda 连接到 S3”部分中的新 S3 事件。以下是我们的代码将执行的步骤:
- 从我们的 S3 存储桶中读取图像文件。
- 将图像调整为 200px 宽作为新图像。
- 将该图像以新名称上传回同一个 S3 存储桶。
Resizer 类
我编写了这个简单的 Ruby 对象(PORO)类来帮我们完成这项工作。请花点时间仔细阅读一下。以下是一些高阶调用:
- 需要 ImageProcessing gem 的Vips实现。
- 创建一个
Aws::S3::Client
要使用的客户端。 - 使用 S3 键和可选的所需大小进行初始化。
- 如果图像尚未调整大小,则调整其大小。
- 利用 S3 元数据避免递归调整大小事件。
- 所有工作都是使用缓冲区在内存中完成还是写入磁盘?
使用以下代码在项目中lib/image_service
名为resizer.rb
file 的目录中创建一个新文件。💥请将常量更改SOMEUNIQNAME
为BUCKET
与您的实际存储桶名称匹配。💥
⚡️⏩⚡️
require 'aws-sdk-s3'
require 'image_processing/vips'
module ImageService
class Resizer
CLIENT = Aws::S3::Client.new region: Env.region
BUCKET = "image-service-SOMEUNIQNAME-#{Env.stage}"
attr_reader :key, :size
def initialize(key, size = 200)
@key = key
@size = size
end
def resize!
return if resized?
resized = ImageProcessing::Vips
.source(source)
.resize_to_limit(size, nil)
.call(save: false)
.write_to_buffer(File.extname(key))
put_object resized, new_key
end
def source
if File.extname(key) == '.png'
Vips::Image.pngload_buffer(get_object)
else
Vips::Image.new_from_buffer(get_object, File.extname(key))
end
end
def new_key
"#{File.basename(key, File.extname(key))}-#{size}#{File.extname(key)}"
end
def get_object
CLIENT.get_object(bucket: BUCKET, key: key).body.read
end
def put_object(object, put_key)
CLIENT.put_object bucket: BUCKET, key: put_key, body: object,
metadata: { 'resized' => '1' }
end
def resized?
metadata['resized'] == '1'
end
def metadata
response = CLIENT.head_object bucket: BUCKET, key: key
response.metadata || {}
rescue Aws::S3::Errors::NotFound
{}
end
end
end
❓我注意到你确实需要了,aws-sdk-s3
但它并没有添加到你的 中Gemfile
,这是怎么回事?每个 Lambda 运行时都预装了 SDK 包,以便于执行常见任务。在本例中,Aws::S3 SDK 就是其中之一。
❓我注意到你没有将 anAWS_ACCESS_KEY_ID
或 a传递AWS_SECRET_ACCESS_KEY
给客户端?这是怎么回事?由于我们的 Lambda 是通过上一步中添加的执行角色调用的,所以我们无需管理密钥或机密。所有客户端 SDK 都会自动使用该角色。欢迎来到未来!
处理程序变更
现在我们有了可以调整 S3 对象大小的 Ruby 对象,我们需要将它连接到 Lambda 的处理函数中。以下代码已更改为:
- 为我们的新文件添加了要求。
- 从事件中获取 S3 密钥。
- 创建一个新的 Resizer 实例。调整文件大小。
- 返回一些有意义的响应。S3 键。
更新您的image_service.rb
文件以使用此代码。
⚡️⏩⚡️
require 'json'
require 'dotenv'
require_relative './image_service/env'
require_relative './image_service/resizer'
def handler(event:, context:)
key = event['Records'][0].dig('s3','object','key')
resizer = ImageService::Resizer.new(key, 200)
resizer.resize!
{ statusCode: 200,
headers: [{'Content-Type' => 'application/json'}],
body: JSON.dump({key: key}) }
end
部署更新的堆栈
需要改变的事情有很多,但现在我们已准备好部署并看到我们的努力取得成效。
⚡️⏩⚡️
$ STAGE_ENV=production ./bin/deploy
看看它是如何工作的
就像在将 Lambda 连接到 S3步骤中一样,我们将上传我们的测试图像,RubyForGood.png
如右图所示。
- 点击工具栏中的“服务”。
- 在查找服务字段中输入“S3”,然后选择。
- 单击名为 的 S3 存储桶
image-service-SOMEUNIQNAME-production
。其中 SOMEUNIQNAME 是您之前选择的名称。 - 删除我们之前上传的文件。
现在将我们的文件拖放RubyForGood.png
到 S3 浏览器窗口中,点击三次“下一步”,使用权限等默认值。最后点击“上传”开始上传。上传完成后,点击几次♻️按钮,直到看到新文件出现。
💥 你没看到新文件吗?去检查一下你的 CloudWatch 日志,看看发生了什么。如果你有任何问题或遇到困难,可以通过GitHub Issues寻求帮助,我很乐意为你提供帮助。
🚀 CI/CD
如果一切顺利,现在是提交代码的好时机。
后续步骤和资源
以下是我建议做的一些事情,以继续学习或深入研究 AWS 生态系统。
🚀 自动化 CI/CD - 你是否厌倦了无休止bin/deploy
地重复工作?想使用 GitHub Actions 实现自动化流程?本项目包含一个工作流程,助你快速上手。打开项目的 README 文件,了解具体操作步骤。
HTTP Web 服务- 使用 cookie 模板的 HTTP 选项创建一个小型 Web 服务。这将帮助你学习 API 网关HTTP API
使 CloudWatch 日志过期- 设置您的 CloudWatch 日志过期。没错,您需要为它们付费,直到永远。您可以根据需要设置它们的过期时间。
S3 CloudFormation 存储桶- 在此bin/bootstrap
过程中,我们为您创建了一个动态存储桶名称,并将其存储在.bucket-name
文件中。通常,建议在不同项目中使用相同的 S3 存储桶。
资源
找到下一步行动并知道在哪里寻求帮助可能会很困难。以下是我在使用 SAM 编写 AWS Lambda 代码时参考的一些地方。
AWS 无服务器应用程序模型 (AWS SAM) 规范- 从属性引用到内部函数,涵盖您需要了解的所有内容template.yaml
。请记住,无服务器应用程序模型 (SAM) 规范是 CloudFormation 的一个更专注、更简洁的子集,旨在简化 Lambda 开发。
AWS 资源和属性类型参考在模板中传递 AWS 资源时,了解内部函数的返回值会很有帮助Ref
。每个资源都不同。有时是名称,有时是 ARN。