使用 Pulumi 在 AWS 上安全快速地部署静态网站
使用 Pulumi 在 AWS 上安全快速地部署静态网站
这是Pulumi 部署和文档挑战赛 的提交内容 :快速静态网站部署
我建造了什么
在这个项目中,我使用 Pulumi 作为基础设施即代码 (IaC) 工具,在 AWS 上创建了一个安全且可扩展的静态网站基础设施。该解决方案设置了一个 Amazon S3 存储桶来托管静态站点文件,并将其与 Amazon CloudFront 集成,以实现快速的全球内容交付。为了确保安全的 HTTPS 访问,我将权限限制为仅限 CloudFront,使用 AWS 证书管理器 (ACM) 获取 SSL 证书,并使用 Route 53 设置了一个自定义域。
所有代码均使用 Pulumi 的 Python SDK 以 Python 编写,这使得代码库易于阅读和维护。最终构建了一个现代化的 React 静态网站,可立即投入生产,经济高效且安全可靠,所有操作均由 Pulumi 完全自动化完成。
现场演示链接
CloudFront 链接 https://d8fuic0sibn8l.cloudfront.net/ https://d8fuic0sibn8l.cloudfront.net/nonexistent-page 自定义域链接 https://challenge.drintech.online https://challenge.drintech.online/nonexistent-page
项目回购
使用 Pulumi 在 AWS 上安全快速地部署静态网站
这是一个使用 pulumi 建立安全、快速的静态网站部署的存储库。
目录
概述
该项目使用 Pulumi 作为 IAC 工具来设置安全快速的静态网站部署。Pulumi 是一款独特的 IAC 工具,可让您使用自己喜欢的编程语言定义基础架构。借助 Pulumi,我们将在 AWS 上设置基础架构(S3 存储桶、CloudFront 和 Route 53),并使用 Python 将静态网站文件安全地部署到此基础架构。
技术
我的旅程
由于这是我第一次使用 Pulumi,所以我从研究 Pulumi 文档开始这个项目。事实证明,这是一次非常棒的体验,因为 Pulumi 文档对开发者友好且易于理解。作为 Python 的爱好者,并且对它非常熟悉,我选择使用 Pulumi Python SDK 来搭建静态网站基础架构,并在其中部署一个静态 React 网站。
我的开发之旅收获颇丰,因为我对技术有了更深入的理解,但也充满了意想不到的挑战。有一次,我甚至以为我的电脑上下载了恶意软件,哈哈。我使用 Pulumi 文档提供的静态网站模板开始了这段旅程。让我们回顾一下我在开发过程中的步骤和遇到的挑战。
使用的技术摘要
Pulumi :一种使用 Python 配置和管理云资源的基础设施即代码 (IaC) 工具。
Python :一种提供与 Pulumi 和 AWS 资源交互的模块的编程语言。
S3 Bucket :一种存储静态网站文件和资产的对象存储服务,作为 CloudFront 的起源。
CloudFront :一种内容分发网络 (CDN),可缓存网站内容,并以低延迟的方式在全球范围内安全分发。这些内容缓存在距离用户较近的边缘站点。
Route 53 :管理 DNS 记录的服务,允许网站使用自定义域。
建筑学
先决条件
首先,需要满足以下条件:
步骤1:Pulumi安装
下面的命令在 Linux 机器上安装 pulumi,刷新 shell 以便反映更改,并确认安装。
curl -fsSL https://get.pulumi.com | sh
source ~/.bashrc
pulumi version
Enter fullscreen mode
Exit fullscreen mode
步骤2:设置项目模板
接下来,我创建了一个新文件夹 website/
并设置了静态网站模板。该静态网站模板捆绑了示例文件和配置,以便使用 S3 和 CloudFront 部署静态网站。
mkdir website && cd website
pulumi new static-website-aws-python
Enter fullscreen mode
Exit fullscreen mode
由于这是我 pulumi new
第一次使用该命令,因此我需要登录 Pulumi Cloud 来验证我的 CLI。我发现这一点很有意思,因为验证后,我就可以立即开始构建基础设施。Pulumi 会自动远程管理状态文件,而不像其他 IaC 工具那样,我必须手动设置后端文件来远程管理状态文件,然后再专注于自动化。
完成配置后,pulumi 继续安装 中定义的依赖项, requirements.txt
但由于 python 环境变量错误而失败。我没有安装 python3-venv。幸运的是,python 提供了正确的命令,让我能够安装错误消息中提到的正确版本。
Pulumi 将基础架构设置作为项目和堆栈进行管理。项目代表整个基础架构定义。它们包含元数据、运行时以及一些用于管理和执行基础架构代码的配置。项目在 pulumi.yaml
文件中定义。
堆栈是项目的一个实例,具有其自身的配置和状态。堆栈包含特定于环境的配置,允许我们将基础架构部署到不同的环境,例如开发、预发布和生产环境。堆栈在 中定义 pulumi.dev.yaml
。
设置项目和堆栈后,pulumi 为我生成了以下文件。
pulumi.yaml
:这代表项目。它包含元数据、运行时和用于管理基础架构代码的配置。
name : website
description : A Python program to deploy a static website on AWS
runtime :
name : python
options :
toolchain : pip
virtualenv : venv
config :
pulumi:tags :
value :
pulumi:template : static-website-aws-python
Enter fullscreen mode
Exit fullscreen mode
pulumi.dev.yaml
:此文件代表开发环境的堆栈。它包含特定于环境的配置,例如 AWS 区域、静态文件路径和 HTML 文档。
config :
aws:region : us-east-1
website:indexDocument : index.html
website:errorDocument : error.html
website:path : ./www
Enter fullscreen mode
Exit fullscreen mode
pulumi>=3.0.0,<4.0.0
pulumi-aws>=6.0.2,<7.0.0
pulumi-synced-folder>=0.0.0,<1.0.0
Enter fullscreen mode
Exit fullscreen mode
venv/
:此文件夹在隔离的虚拟环境中管理该项目的 Python 依赖项。
www/
:此文件夹包含示例静态 Web 文件,包括 index.html
和 error.html
。
.gitignore
:此处列出的文件不会被 Git 跟踪。这导致我们无法将依赖项推送到我们的仓库。
细分 __main__.py
所有主要操作都在这个文件中进行。本文将重点介绍代码中协同工作以构建静态网站基础架构的各个部分,以及我如何处理代码中已弃用的部分。在进行详细分析后,我将调整这些组件,以部署更安全、更个性化、更快速的静态网站基础架构。
import pulumi
import pulumi_aws as aws
import pulumi_synced_folder as synced_folder
Enter fullscreen mode
Exit fullscreen mode
这将导入必要的模块来创建 AWS 资源并将文件同步到 S3 存储桶。
config = pulumi . Config ()
path = config . get ( " path " ) or " ./www "
index_document = config . get ( " indexDocument " ) or " index.html "
error_document = config . get ( " errorDocument " ) or " error.html "
Enter fullscreen mode
Exit fullscreen mode
这将从堆栈中读取特定于环境的设置 pulumi.Config
并将它们作为变量传递。
bucket = aws . s3 . BucketV2 (
" bucket " ,
# website={
# "index_document": index_document,
# "error_document": error_document,
# },
)
bucket_website = aws . s3 . BucketWebsiteConfigurationV2 (
" bucket " ,
bucket = bucket . bucket ,
index_document = { " suffix " : index_document },
error_document = { " key " : error_document },
)
Enter fullscreen mode
Exit fullscreen mode
这会创建一个 S3 存储桶并将其设置为静态网站托管。它还指定了索引文档和错误文档。该类 bucketV2
不再接受 website
将存储桶配置为网站的参数,因为这会导致错误。相反,该类 BucketWebsiteConfigurationV2
用于将存储桶配置为网站托管。
ownership_controls = aws . s3 . BucketOwnershipControls (
" ownership-controls " ,
bucket = bucket . bucket ,
rule = {
" object_ownership " : " ObjectWriter " ,
},
)
Enter fullscreen mode
Exit fullscreen mode
这将设置权限,定义新上传对象的所有者。“ObjectWriter”表示上传者保留所有权。我稍后会修改此设置以增强安全性。
public_access_block = aws . s3 . BucketPublicAccessBlock (
" public-access-block " ,
bucket = bucket . bucket ,
block_public_acls = False ,
)
Enter fullscreen mode
Exit fullscreen mode
通过关闭存储桶的公共 ACL 阻止功能,可以公开读取对象。换句话说,它将存储桶公开,以便任何人都可以访问它。但是,出于安全最佳实践的考虑,我们不建议这样做,并且稍后会进行调整,因为它允许任何人通过 HTTP 不安全地访问我们的静态文件。
bucket_folder = synced_folder . S3BucketFolder (
" bucket-folder " ,
acl = " public-read " ,
bucket_name = bucket . bucket ,
path = path ,
opts = pulumi . ResourceOptions ( depends_on = [ ownership_controls , public_access_block ]),
)
Enter fullscreen mode
Exit fullscreen mode
这用于 pulumi_synced_folder
将位于 的静态文件上传 path
到 S3 存储桶。它将公共读取 ACL 设置应用于上传的对象,允许公共用户访问网站文件。它确保 ownership_controls
和 public_access_block
优先设置。此顺序非常重要,可以避免权限冲突,并确保对象 ACL 与存储桶所有权设置一致。
创建 CloudFront CDN 用于缓存和分发
cdn = aws . cloudfront . Distribution (
" cdn " ,
enabled = True ,
origins = [
{
" origin_id " : bucket . arn ,
" domain_name " : bucket_website . website_endpoint ,
" custom_origin_config " : {
" origin_protocol_policy " : " http-only " ,
" http_port " : 80 ,
" https_port " : 443 ,
" origin_ssl_protocols " : [ " TLSv1.2 " ],
},
}
],
Enter fullscreen mode
Exit fullscreen mode
这将创建一个 CloudFront 分发版,使用 CDN 为网站提供服务。 源 设置为 S3 存储桶的网站端点 ,并使用“仅 http”协议,因为 S3 网站托管本身不支持 HTTPS。这意味着 CloudFront 将在内部通过 HTTP 从 S3 获取静态文件。
default_cache_behavior = {
" target_origin_id " : bucket . arn ,
" viewer_protocol_policy " : " redirect-to-https " ,
" allowed_methods " : [
" GET " ,
" HEAD " ,
" OPTIONS " ,
],
" cached_methods " : [
" GET " ,
" HEAD " ,
" OPTIONS " ,
],
" default_ttl " : 600 ,
" max_ttl " : 600 ,
" min_ttl " : 600 ,
" forwarded_values " : {
" query_string " : True ,
" cookies " : {
" forward " : " all " ,
},
},
},
Enter fullscreen mode
Exit fullscreen mode
此设置强制用户始终使用 HTTPS(重定向到 https)通过 CloudFront 访问网站。它还包含请求方法、Cookie、缓存规则和 TTL(缓存时间)设置。默认 TTL 会将静态文件缓存 600 秒(10 分钟),适用于经常更改的内容。
例如,如果您的静态网站仍处于开发的早期阶段,并且您每天发布多个版本,则此设置效果很好。如果您的静态网站更稳定且很少更新,则请使用 3600 秒(1 小时)或 86400 秒(24 小时)。
如果您使用较长的 TTL 并更新存储桶中的任意或所有对象,CloudFront 会提供使特定或所有对象的缓存失效的选项。这可确保您的最新更改对用户可见。
price_class = " PriceClass_100 " ,
custom_error_responses = [
{
" error_code " : 404 ,
" response_code " : 404 ,
" response_page_path " : f " / { error_document } " ,
}
],
restrictions = {
" geo_restriction " : {
" restriction_type " : " none " ,
},
},
viewer_certificate = {
" cloudfront_default_certificate " : True ,
},
Enter fullscreen mode
Exit fullscreen mode
PriceClass_100
限制 CloudFront 发行版使用美国、加拿大和欧洲的边缘站点,以节省成本。如果您需要为用户提供更广泛的覆盖范围,可以考虑其他 CloudFront 价格等级。
S3 存储桶中的 404 错误通过提供 errorDocument
(error.html) 进行管理。您可以使用 geo_restriction 来控制区域访问,或确保您的内容在全球范围内可用。CloudFront 使用其默认 SSL 证书,允许公共用户通过 HTTPS 安全地访问您的内容。
pulumi . export ( " originURL " , pulumi . Output . concat ( " http:// " , bucket_website . website_endpoint ))
pulumi . export ( " originHostname " , bucket . website_endpoint )
pulumi . export ( " cdnURL " , pulumi . Output . concat ( " https:// " , cdn . domain_name ))
pulumi . export ( " cdnHostname " , cdn . domain_name )
Enter fullscreen mode
Exit fullscreen mode
这将导出 S3 和 CloudFront 访问新部署的静态网站所需的 URL 和主机名。
步骤 3:部署静态网站
现在我们了解了基础设施代码的工作原理,让我们部署基础设施并访问示例静态网站。
运行 pulumi up
。此命令用于验证并设置基础架构。验证成功后,它会确认我是否要部署基础架构。
选择“是”后,Pulumi 会部署基础架构。我可以在 Pulumi 控制台上跟踪已部署的堆栈。控制台提供了一个易于使用的仪表板,我可以在其中监控部署、查看日志(更新)以及查看已部署到堆栈的资源。
CloudFront 发行版的创建耗时最长。部署完成后,我将能够使用 S3 通过 HTTP 访问示例静态网站, originURL
并使用 CloudFront 通过 HTTPS 访问示例静态网站 cdnURL
。
通过在 URL 中添加不存在的路径来查看错误页面,例如 https://cloudfronturl.net/nonexistent-page
。
在部署过程中,Pulumi 显示一条警告:“website_endpoint 已弃用”。这 website_endpoint
是一个不再受支持的输出属性。控制台上的 Pulumi Co-Pilot 有助于修复此警告。
为了解决这个问题,我 按照 Pulumi Co-Pilot 的建议,在代码底部的 CDN 配置和导出部分中,将 website_endpoint
属性替换为属性。然后,我使用 命令确认警告已解决。 bucket_regional_domain_name
pulumi preview
要将任何自定义网站部署到 S3,您需要更新堆栈文件 () 中的路径 pulumi.dev.yaml
以指向静态网站文件的位置。
我想通过将自己构建的 React 应用程序部署到 S3 存储桶来让事情变得更有趣。我将 react_website/
文件夹移动到了代码库的根目录。包含静态文件的生产版本位于该 react_website/build/
目录中。开发栈中的配置已更新,用于部署 React 应用程序。
config :
aws:region : us-east-1
website:indexDocument : index.html
website:errorDocument : error.html
website:path : ./react_website/build
Enter fullscreen mode
Exit fullscreen mode
pulumi up
命令部署了 React 应用程序。新部署的静态网站可以通过任何提供的 URL 链接访问。我通过在 URL 中添加一个不存在的路径来测试错误页面,结果一切正常。接下来的阶段就变得棘手,甚至有点混乱了。
步骤 4:确保网站部署安全
这一步最具挑战性,需要进行最多的故障排除。我频繁在 Pulumi 文档和 AWS 控制台之间切换,以解决意外问题。
目前,该网站可以通过 HTTP 方式使用存储桶端点访问,也可以通过 HTTPS 方式使用 cdnURL 访问。禁用此功能 BucketPublicAccessBlock
会使存储桶及其对象公开访问,从而带来安全风险。我设置了一个安全部署,以确保用户只能通过 CloudFront URL 安全地访问静态网站。
为了增强安全性,我限制了存储桶的权限,以便只有 CloudFront 可以从存储桶中获取对象。我修改了 public_access_block
设置,阻止了所有对 S3 存储桶的公开访问。这确保了除非获得明确许可,否则任何人都无法访问 S3 存储桶或读取其中的对象。换句话说,该存储桶现在是私有的。
public_access_block = aws . s3 . BucketPublicAccessBlock (
" public-access-block " ,
bucket = bucket . bucket ,
block_public_acls = True ,
block_public_policy = True ,
ignore_public_acls = True ,
restrict_public_buckets = True ,
)
Enter fullscreen mode
Exit fullscreen mode
接下来,我将其设置 object_ownership
为 BucketOwnerEnforced
。此设置将禁用 ACL,并确保存储桶拥有者是所有对象的所有者。使用此配置,只能使用存储桶策略明确授予对对象的访问权限。
ownership_controls = aws . s3 . BucketOwnershipControls (
" ownership-controls " ,
bucket = bucket . bucket ,
rule = {
" object_ownership " : " BucketOwnerEnforced " ,
},
)
Enter fullscreen mode
Exit fullscreen mode
我创建了 CloudFront 源访问身份 (OAI)。OAI 是一种虚拟身份,可以与 CloudFront 发行版关联,以保护对私有 S3 存储桶的访问。
oai = aws . cloudfront . OriginAccessIdentity ( " oai " )
Enter fullscreen mode
Exit fullscreen mode
custom_origin_config
然后,我通过从 切换到 将 OAI 连接到 CloudFront 发行版 s3_origin_config
。这 s3_origin_config
将设置 CloudFront 通过 OAI 访问 S3 存储桶。
cdn = aws . cloudfront . Distribution (
...
origins = [
{
" origin_id " : bucket . arn ,
" domain_name " : bucket . bucket_regional_domain_name ,
" s3_origin_config " : {
" origin_access_identity " : oai . cloudfront_access_identity_path ,
},
}
],
...
)
Enter fullscreen mode
Exit fullscreen mode
我创建了一个 S3 存储桶策略,仅允许 CloudFront OAI 访问该 S3 存储桶。该策略授予有限的权限,仅允许 CloudFront 从存储桶中获取对象。以下代码创建了该策略并将其附加到存储桶。
bucket_policy = aws . s3 . BucketPolicy (
" bucketPolicy " ,
bucket = bucket . id ,
policy = pulumi . Output . all ( bucket . arn , oai . iam_arn ). apply ( lambda args : f """ {{
" Version " : " 2012-10-17 " ,
" Statement " : [
{{
" Effect " : " Allow " ,
" Principal " : {{ " AWS " : " { args [ 1 ] } " }},
" Action " : " s3:GetObject " ,
" Resource " : " { args [ 0 ] } /* "
}}
]
}} """ )
)
Enter fullscreen mode
Exit fullscreen mode
当我运行 pulumi up
测试新的安全更改时, 所有对象都出现了“ AccessControlListNotSupported: The bucket does not allow ACLs synced_folder
”错误。出现此错误的原因是,模块将 ACL 附加到对象并将其上传到 S3 存储桶。然而,该 BucketOwnerEnforced
设置禁用了 ACL,这与 冲突 synced_folder
。
尽管 Pulumi 文档明确指出 synced_folder
ACL 属性可以设置为 None
,但我在执行代码时仍然遇到了要求输入值的错误。我手动编写了代码,使用 bucketObject
S3 子模块中的类将对象上传到 S3 存储桶,并使用嵌套 for
循环遍历所有文件。Pulumi Co-Pilot 对此很有帮助。
然后我 synced_folder
用新生成的代码替换了该代码。
for root , _ , files in os . walk ( path ):
for file in files :
file_path = os . path . join ( root , file )
key = os . path . relpath ( file_path , path )
aws . s3 . BucketObject (
key ,
bucket = bucket . bucket ,
source = pulumi . FileAsset ( file_path ),
opts = pulumi . ResourceOptions ( depends_on = [ ownership_controls , public_access_block ]),
)
Enter fullscreen mode
Exit fullscreen mode
在上面的代码中,我使用 os
模块获取了我机器上静态文件的路径。我在代码开头导入了该模块。
import os
Enter fullscreen mode
Exit fullscreen mode
现在,当我运行 pulumi up
并尝试访问该网站时,出现了拒绝访问错误。检查我的 S3 存储桶后,发现好像发生了灾难——什么都没有了。于是,我决定 pulumi destroy && pulumi up
从头开始重建基础设施。虽然这样可以恢复对象,但拒绝访问错误仍然存在。
我检查了代码中的所有配置,并在控制台中仔细检查了 CloudFront 和 S3 存储桶的设置,但一切似乎都正确无误。在第三次查看 CloudFront 分发控制面板时,我注意到该 default root object
选项尚未设置。这似乎不是什么问题,因为它是可选的,而且即使没有它,设置也能正常工作,直到我设置了 OAI。设置 OAI 后,一些可选设置就会变成必需的。
告诉 default root object
CloudFront 当用户访问 CloudFront URL 时返回哪个对象,在本例中是 index.html
。我向 Pulumi Copilot 询问了正确的参数,以便在 CDN 配置中进行设置。
cdn = aws . cloudfront . Distribution (
" cdn " ,
enabled = True ,
default_root_object = " index.html " ,
...
)
Enter fullscreen mode
Exit fullscreen mode
我部署了新的更改,希望一切顺利。但是,当我尝试使用 CloudFront URL 访问网站时,一个名为“download”且没有扩展名的奇怪文件被下载到我的电脑上。我立即删除了它。一时间,我担心自己下载了恶意软件,担心我的安全网站在刚刚设置了增强安全措施后就受到了攻击。
我意识到我需要了解基础设施中发生的情况,以便回答诸如此类的问题:我的请求是否到达了 CloudFront 分发版?它成功了吗?它是否返回了错误?如果是,错误是什么?
我切换到 CloudFront 仪表板,导航到日志记录选项卡,并为 CloudFront 设置一个日志记录目标,以将日志发送到我在上一个项目中为 Lambda 函数创建的 CloudWatch 日志组。
然后,我尝试再次访问该链接,以便记录请求和响应,从而收集信息来排查此意外行为。我从 CloudWatch 访问了日志,但无法立即理解其中的含义。我将其粘贴到 Pulumi Copilot 中进行分析。
通过 Pulumi Copilot 的回复,我意识到我用于上传对象的代码没有为它们设置正确的文件类型。相反,它将所有对象的文件类型都设置为 , application/octet-stream
而不是 text/html
,而这正是显示 index.html 所必需的。
这就解释了为什么会下载一个奇怪的文件,我怀疑这是我的index.html,我可以自信地打开它来确认。
我再次向 Pulumi Copilot 询问解决方案,以在 for
上传对象的嵌套循环代码中设置文件类型。
import mimetypes
...
for root , _ , files in os . walk ( path ):
for file in files :
file_path = os . path . join ( root , file )
key = os . path . relpath ( file_path , path )
content_type , _ = mimetypes . guess_type ( file_path )
print ( f " Uploading: { file_path } as { key } " )
aws . s3 . BucketObject (
key ,
bucket = bucket . bucket ,
source = pulumi . FileAsset ( file_path ),
content_type = content_type or " application/octet-stream " ,
opts = pulumi . ResourceOptions ( depends_on = [ ownership_controls , public_access_block ]),
)
Enter fullscreen mode
Exit fullscreen mode
嵌套循环现在使用 mimetypes
模块为每个上传的对象设置正确的文件类型。我运行了 pulumi up
,它终于成功了,或者说我以为如此。我的 React 静态网站现在可以通过 CloudFront URL 链接安全访问。当我尝试访问源 URL 时,它返回了访问被拒绝的错误,这是意料之中的。然而,当我尝试使用 CloudFront URL 访问错误页面时,我也收到了访问被拒绝的错误,这出乎意料。
因此,我求助于值得信赖的旧版故障排除库(Stack Overflow)。我发现,由于 CloudFront 和 S3 存储桶都受 OAI 保护,因此当页面不存在时,S3 存储桶会向 CloudFront 发送 403 错误代码,而不是 404。我调整了 CloudFront 设置,使其在从 S3 存储桶收到 403 错误代码时显示错误页面并向用户发送 404 错误响应。
...
custom_error_responses = [
{
" error_code " : 403 ,
" response_code " : 404 ,
" response_page_path " : f " / { error_document } " ,
}
]
...
Enter fullscreen mode
Exit fullscreen mode
我部署了最新的更改,现在可以访问静态网站的主页和错误页面了。下一步是使用自定义域名进行个性化设置。
设置自定义域
我和朋友们分享 CloudFront URL 来访问我安全、快速、美观的静态网站,感觉很无聊。我想要一个自定义域名,能够体现我的个人特色和网站的主题。我按照 Pulumi 文档中的步骤为静态网站设置了一个自定义域名。
步骤包括:
将域和子域配置添加到堆栈。
将新配置导入我的代码。
使用 ACM 创建并验证新的 SSL/TLS 证书。我使用了 DNS 验证方法,该方法涉及在托管区域中创建 DNS 记录以确认域所有权。
调整 CloudFront 代码以使用参数处理自定义域的请求 aliases
。
创建 Route 53 别名 A 记录,将我们的子域映射到 CloudFront 域。
您可能想知道为什么我们使用别名 A 记录而不是 CNAME 记录(后者通常用于将一个域映射到另一个域)。建议使用 Route 53 别名 A 记录将域映射到 CloudFront 等 AWS 服务。使用别名 A 记录,DNS 查询将在内部解析,从而提高速度和效率。
设置自定义域名后,我就能使用个性化域名访问我的静态网站了。当我为 React 应用程序创建新的生产版本时,只需运行 即可 pulumi up
。Pulumi 会通过自动部署到安全的 S3 存储桶来处理剩下的工作。
使用 Pulumi
这是我第一次使用 Pulumi 作为 IAC 工具,我发现它非常棒。Pulumi 允许我使用 Python,这是我最喜欢的编程语言。这让我感觉 Pulumi 很熟悉,就像是我工作流程的一部分一样。与其他 IAC 工具一样,Pulumi 省去了我点击 AWS 控制台设置基础设施的麻烦,并允许我开发可重复使用的基础设施。但与其他 IAC 工具不同的是,Pulumi 允许我立即实现自动化,而无需先手动配置远程状态文件。
Pulumi 控制台和 Pulumi Copilot(我在这个项目中的个人助理)在故障排除、参考和成功完成这个项目方面非常有帮助。Pulumi 控制台提供了我所做更改的更新(日志),让我可以轻松跟踪更改并参考过去的执行结果。Pulumi Copilot,我的智能个人助理,帮助我修复了已弃用的参数,生成了存储桶策略,分析了日志,并提供了可能的解决方案。
事实上,当我想保护我的静态网站基础设施时,我复制了模板提供的全部代码,并向 Pulumi Copilot 发出提示,要求设置一个安全的网站基础设施。这简化了流程,让我可以专注于使用 Pulumi 文档调整和审查代码,并进行一些调整。拥有一个能够理解我正在使用的基础设施工具的 AI 助手真是太棒了。它让基础设施的配置变得轻而易举。
以下是我的一些关键提示:
提示 1
can you adjust this code to set the content type for each file uploaded ?
for root , _ , files in os . walk ( path ):
for file in files :
file_path = os . path . join ( root , file )
key = os . path . relpath ( file_path , path )
aws . s3 . BucketObject (
key ,
bucket = bucket . bucket ,
source = pulumi . FileAsset ( file_path ),
)
Enter fullscreen mode
Exit fullscreen mode
提示 2
The option acl = None is not working . It still ask for acl value on runtime . Is there any good alternative to S3BucketFolder ?
bucket_folder = synced_folder . S3BucketFolder (
" bucket-folder " ,
acl = None ,
bucket_name = bucket . bucket ,
path = path ,
opts = pulumi . ResourceOptions ( depends_on = [ ownership_controls , public_access_block ]),
)
Enter fullscreen mode
Exit fullscreen mode
提示 3
this is the cloudfront log I got from cloudwatch . Any reason why I can ' t access my static files via cloudfront URL after using OAI?
{
" date " : " 2025-04-02 " ,
" time " : " 18:01:10 " ,
" x-edge-location " : " LOS50-P2 " ,
" sc-bytes " : " 594 " ,
" c-ip " : " 102.89.44.119 " ,
" cs-method " : " GET " ,
" cs(Host) " : " d39ymmysanotpr.cloudfront.net " ,
" cs-uri-stem " : " / " ,
" sc-status " : " 200 " ,
" cs(Referer) " : " - " ,
" cs(User-Agent) " : " Mozilla/5.0%20(Windows%20NT%2010.0;%20Win64;%20x64)%20AppleWebKit/537.36%20(KHTML,%20like%20Gecko)%20Chrome/135.0.0.0%20Safari/537.36 " ,
" cs-uri-query " : " - " ,
" cs(Cookie) " : " - " ,
" x-edge-result-type " : " Miss " ,
" x-edge-request-id " : " -lB3Ff7SJ8HEdpSZeS8d8AwV8kjflOVlQdgaI_-yqDYQ-TenMjY2nA== " ,
" x-host-header " : " d39ymmysanotpr.cloudfront.net " ,
" cs-protocol " : " https " ,
" cs-bytes " : " 486 " ,
" time-taken " : " 0.480 " ,
" x-forwarded-for " : " - " ,
" ssl-protocol " : " TLSv1.3 " ,
" ssl-cipher " : " TLS_AES_128_GCM_SHA256 " ,
" x-edge-response-result-type " : " Miss " ,
" cs-protocol-version " : " HTTP/2.0 " ,
" fle-status " : " - " ,
" fle-encrypted-fields " : " - " ,
" c-port " : " 17055 " ,
" time-to-first-byte " : " 0.480 " ,
" x-edge-detailed-result-type " : " Miss " ,
" sc-content-type " : " application/octet-stream " ,
" sc-content-len " : " 238 " ,
" sc-range-start " : " - " ,
" sc-range-end " : " - "
}
Enter fullscreen mode
Exit fullscreen mode
请注意,此提交于 4 月 6 日太平洋夏令时间晚上 8 点 42 分发布。
参考链接
感谢您的阅读。我们非常欢迎您提出建议和反馈,请在评论区留言。
鏂囩珷鏉ユ簮锛�https://dev.to/drintech/secure-and-fast-static-website-deployment-on-aws-using-pulumi-3bi5