使用 Terraform 构建云原生博客平台

目录

  • 为什么要构建另一个博客平台?
  • 架构决策 核心基础设施组件 基础设施管理
  • 真正的挑战跨账户问题 CI/CD 管道设置
  • 主要学习内容
  • 期待
  • 代码示例和文档

    Next.js + AWS(CloudFront、S3、Route53、ACM)+ Terraform + GitHub Actions CI/CD

    Github 代码

    完整的 Terraform 配置、GitHub Actions 工作流程和详细的设置说明可在存储库中找到。您可以随意将其用作您自己的项目的参考或提出改进建议。

    记住:有时最长的道路会教给你最宝贵的经验。

    为什么要构建另一个博客平台?

    他们说:“只要使用 WordPress 就可以了。几分钟就可以搞定。”

    作为一名 AWS 解决方案架构师,我知道我可以在一小时内在控制台中启动一个简单的博客。但问题是 - 我已经构建了保持 99.9% 正常运行时间的生产系统。我已经无数次点击控制台。这个项目不是关于博客的最快路径;而是关于突破我的极限。

    我需要一个能够:

  • 强迫我将控制台知识转化为代码
  • 挑战我对 AWS 服务交互的理解
  • 为复杂的云架构创建真实世界的测试场
  • 为面临类似挑战的其他工程师提供文档
  • 真正的价值是什么?知道如何在控制台中执行某项操作和在 Terraform 中实现它之间的差距。这就是学习发生的地方。这就是工程师成长的地方。

    架构决策

    核心基础设施组件

    我在设计架构时考虑了几个关键要求:

  • 高可用性:使用 CloudFront 进行边缘分发
  • 安全性:实施适当的 IAM 角色和 OIDC 联合
  • 可扩展性:S3 用于静态内容和版本控制
  • 自动化:使用 GitHub Actions 完成 CI/CD 管道
  • 每个部分的组合方式如下:

    内容交付和安全

  • CloudFront Distribution:处理 HTTPS 终止、缓存和低延迟交付
  • ACM(AWS 证书管理器):管理 SSL 证书以实现安全通信
  • 源访问身份 (OAI):将 S3 访问限制为仅对 CloudFront 进行访问
  • S3 存储桶:托管启用了版本控制的静态文件
  • 基础设施管理

  • 私有 S3 后端:安全地维护 Terraform 状态文件
  • IAM 角色:以最小权限实现长期自动化
  • OIDC Web Identity:保护 GitHub Actions 的 AWS 访问
  • 这种设置不仅遵循了 AWS 精心构建的框架的六大支柱,还让我了解了网络和 IaC 的复杂性。

    真正的挑战:连续的旅程

    纸面上看似简单的架构变成了复杂的故障排除之旅。以下是每个挑战如何导致下一个挑战:

    1. 托管区域之谜

    最初,Terraform 无法通过名称访问托管区域。虽然 AWS CLI 可以找到它,但 Terraform 一直失败。这是我第一次意识到更深层次的问题,尽管我还没有意识到。

    # Initial attempt that failed`
    resource "zone_name" "primary" {
      name = var.domain_name
    }
    
    # Solution: Use zone ID directly`
    data "zone_id" "primary" {
      zone_id = var.zone_id
    }

    2. 多账户迷宫

    托管区域问题揭示了一个复杂的问题:我在不知情的情况下尝试跨多个 AWS 账户访问资源,但没有适当的跨账户权限。具体表现如下:

  • 第一个迹象:Terraform 尝试访问托管区域等资源时出现权限错误
  • 第二个迹象:未在预期帐户中找到用户
  • 最终启示:S3 存储桶 403 错误表明跨账户访问尝试
  • 在尝试修复权限多次后,我疲惫不堪,打开了无数个 Chrome 标签,于是我离开了电脑。有时,最好的调试工具就是全新的视角。当我回来时,我系统地检查了每个环境变量,发现它们配置不正确。

    最初,我为默认帐户设置了环境变量:

    # Checking current identity
    aws sts get-caller-identity
    
    # Setting up environment variables
    export AWS_ACCESS_KEY_ID="new_access_key"
    export AWS_SECRET_ACCESS_KEY="new_secret_key"
    export AWS_DEFAULT_REGION="us-east-1"
    
    # Profile
    export AWS_PROFILE=default

    但这在尝试切换账户时会产生冲突。真正的问题是什么?Terraform 角色缺乏跨账户访问权限。

    3.跨账户资源管理

    情况变得清晰起来:

  • 托管区域:位于主账户中,但由于备份账户中的资源而无法访问
  • S3 存储桶:在备份账户中,但主要角色缺乏跨账户访问权限
  • Terraform:能够创建资源,因为我从备份账户而不是主账户授予了权限。
  • 头脑清醒后,我看清了事情的真相。我采取了系统的方法:

    解决方案需要系统清理:

  • 配置文件配置:我专门为备份账户配置了一个配置文件,该账户最初已被删除。通过设置 export AWS_PROFILE=backup,我将 Terraform 操作与正确的账户对齐。
  • 环境变量调整:我取消设置了导致冲突的先前环境变量并重新配置了 AWS CLI,以确保操作在适当的账户下正确验证和执行。
  • 验证和清理:我运行了 aws sts get-caller-identity 来验证 CLI 现在使用的是正确的账户。随后,我使用 terraform init 重新初始化 Terraform,并使用 terraform destroy --auto-approve 删除备份中错误创建的资源。
  • 这些问题的解决标志着该项目的一个重要转折点。我不仅设法通过确保资源与各自的账户正确对齐来简化 AWS 架构,而且还强化了 AWS 管理和 Terraform 使用的最佳实践。这个过程强调了警惕的账户管理的重要性,并为在云环境中保持清晰度和组织性提供了宝贵的经验教训。

    4. CI/CD 管道优化

    最后的挑战出现在 CI/CD 管道中。虽然 YAML 在语法上是正确的,但 Terraform 操作却挂在 Terraform Plan 上。根本原因是什么?环境变量需要单独传递给每个 Terraform 命令:

    - name: Terraform Init
      run: |
        cd ./terraform-config
        terraform init
      env:
        TF_VAR_domain_name: ${{ secrets.DOMAIN_NAME }}
        TF_VAR_aws_region: ${{ secrets.AWS_REGION}}
        TF_VAR_zone_id: ${{ secrets.ZONE_ID }}
    
    - name: Terraform
      id: plan
      run: |
        cd ./terraform-config
        terraform plan -out=tfplan
    
    - name: Terraform Apply
      id: apply
      run: |
        cd ./terraform-config
        terraform apply -auto-approve tfplan

    工作解决方案

    - name: Terraform Init
      run: |
        cd ./terraform-config
        terraform init
      env:
        TF_VAR_domain_name: ${{ secrets.DOMAIN_NAME }}
        TF_VAR_aws_region: ${{ secrets.AWS_REGION}}
        TF_VAR_zone_id: ${{ secrets.ZONE_ID }}
    
    - name: Terraform
      id: plan
      run: |
        cd ./terraform-config
        terraform plan -out=tfplan
      env:
        TF_VAR_domain_name: ${{ secrets.DOMAIN_NAME }}
        TF_VAR_aws_region: ${{ secrets.AWS_REGION}}
        TF_VAR_zone_id: ${{ secrets.ZONE_ID }}
    
    - name: Terraform Apply
      id: apply
      run: |
        cd ./terraform-config
        terraform apply -auto-approve tfplan 
      env:
        TF_VAR_domain_name: ${{ secrets.DOMAIN_NAME }}
        TF_VAR_aws_region: ${{ secrets.AWS_REGION}}
        TF_VAR_zone_id: ${{ secrets.ZONE_ID }}

    我花了两个小时才解决了这个难题,这凸显了理解 CI/CD 管道中 Terraform 命令的细微差别的重要性,并强调了细致配置以确保顺利实现自动化的必要性。

    主要学习内容

  • 账户管理至关重要
  • - Always verify which account you're operating in
    - Set up proper profile management early
    - Use `aws sts get-caller-identity` frequently
  • 基础设施即代码需要不同的思维
  • - What works in the console might need different approaches in Terraform
    - Resource relationships need explicit definition
    - State management is crucial
  • 身份验证流程理解
  • - OIDC federation setup requires careful configuration
    - Environment variables affect different tools differently
    - Multiple authentication methods need careful management
  • 最佳实践的出现
  • - Always verify account context before operations
    
    
    
    
    Implement clear naming conventions
    
    
    Maintain separation of concerns between accounts
    
    
    Document environment variable requirements

    拥抱艰难之路

    一年前,我做出了一个选择:不再满足于简单的道路。我已经建立了多个 AWS 项目。已经维护了 Linux 服务器。已经获得了 AWS 解决方案架构师认证。但 Terraform?那是我要攀登的下一座山。

    控制台很舒服。它是可视化的。它是即时的。但是代码呢?代码要求精确。每个资源关系都必须明确。每个权限都必须定义。每个交互都必须计划好。

    这个项目迫使我以不同的方式思考基础设施:

  • 不再需要点击选项
  • 不再依赖 AWS 的默认设置
  • 不再需要通过视觉确认变更
  • 相反,我必须:

  • 在代码中定义每个资源关系
  • 深入了解每一次服务交互
  • 从一开始就规划自动化
  • 从状态管理和漂移检测的角度思考
  • 是不是更难了?当然。

    是不是花了更长时间?毫无疑问。

    这值得吗?每一分钟都令人沮丧。

    期待

    这个平台不仅仅是一个博客——它证明了现代云架构的复杂性和学习机会。每一个挑战都迫使我更深入地研究 AWS 服务、Terraform 行为和云实践。

    最终架构遵循 AWS 完善架构框架原则:

  • 安全性:适当的 IAM 角色、OIDC 联合和访问控制
  • 可靠性:CloudFront 分发和 S3 版本控制
  • 性能效率:边缘缓存和优化
  • 成本优化:几乎免费
  • 卓越运营:全自动部署