构建面向生产的 CI/CD 流水线:使用 Terraform、GitHub Actions 和 Ansible 自动化基础设施

发布: (2025年12月10日 GMT+8 05:15)
5 min read
原文: Dev.to

Source: Dev.to

项目目标与概述

本项目的主要目标是为一个多服务的 TODO 应用创建一个全自动化的部署流水线,实现完整的基础设施自动化。解决方案需要满足以下关键需求:

核心需求

  • 从代码提交到生产部署的全流程自动化
  • 使用声明式配置进行基础设施供应
  • 自动化配置管理,确保服务器设置一致
  • 零停机部署并实现 SSL/TLS 终止
  • 漂移检测,保持基础设施一致性
  • 分布式追踪,用于调试微服务交互
  • 以安全为先,使用加密的密钥并最小化攻击面

选用技术栈

  • 基础设施即代码:Terraform,用于 AWS 资源供应
  • 配置管理:Ansible,用于服务器配置和应用部署
  • CI/CD 编排:GitHub Actions,用于工作流自动化
  • 容器化:Docker 与 Docker Compose,实现服务隔离
  • 反向代理:Traefik,用于路由、负载均衡和自动 SSL
  • 可观测性:Zipkin,用于分布式请求追踪
  • 消息队列:Redis,用于异步日志处理

最终目标是实现一个系统,能够通过一次 git push 同时部署基础设施变更和应用更新,并内置漂移检测、邮件通知以及生产环境的手动审批门等安全机制。

系统架构与设计

该应用采用微服务模式,共有七个不同的服务,每个服务使用最适合其职责的语言实现。

架构图

Microservice Architecture

图 1:完整的微服务架构,展示所有服务、技术栈以及数据流向。

服务职责

#服务语言 / 平台关键职责
1Frontend ServiceVue.jsSPA UI,调用后端 API,Zipkin 客户端,提供静态资源
2Auth APIGo认证与授权,JWT 处理,通过 Users API 验证凭证
3Todos APINode.jsTODO 项目的增删改查,向 Redis 发布事件,进行 JWT 验证
4Users APISpring Boot (Java)用户资料管理,为 Auth 服务提供只读查询
5Log Message ProcessorPython消费 Redis 消息,记录事件以供监控
6Redis内存消息队列(pub/sub)
7Zipkin分布式追踪收集器与 UI
8Traefik反向代理,自动服务发现,Let’s Encrypt SSL,路由与仪表盘

网络架构

Docker Network Architecture

图 2:Docker 网络示意图,展示隔离的 app-network,Traefik 为唯一的外部网关。

所有服务通过名为 app-network 的专用 Docker 桥接网络进行通信,提供以下优势:

  • 与宿主机系统隔离
  • 通过容器名称(DNS)实现服务间通信
  • 除 Traefik 外不暴露端口
  • 外部客户端与 Traefik 之间的流量已加密

使用 Terraform 的基础设施即代码

Terraform 之所以被选中,是因为其声明式配置、状态管理以及成熟的 AWS 提供程序。

供应的 AWS 资源

1. EC2 实例

# Data source ensures we always use the latest Ubuntu AMI
data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"] # Canonical's AWS account

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
}

# EC2 Instance resource definition
resource "aws_instance" "todo_app" {
  ami                    = data.aws_ami.ubuntu.id
  instance_type          = var.instance_type
  key_name               = aws_key_pair.deployer.key_name
  vpc_security_group_ids = [aws_security_group.todo_app.id]

  tags = {
    Name        = "todo-app-server-v2"
    Environment = "production"
    Project     = "hngi13-stage6"
  }
}

2. 安全组

resource "aws_security_group" "todo_app" {
  name        = "todo-app-sg"
  description = "Security group for TODO application"

  # HTTP access for initial Let's Encrypt challenges
  ingress {
    description = "HTTP"
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  # HTTPS access
  ingress {
    description = "HTTPS"
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  # SSH access (restricted)
  ingress {
    description = "SSH"
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["YOUR.TRUSTED.IP/32"]
  }

  # Allow all outbound traffic
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
Back to Blog

相关文章

阅读更多 »

什么是 DevOps?

引言 如果在网上搜索“什么是 DevOps?”,你会找到许多复杂的定义。在本文中,我们将从基础解释 DevOps。DevOps = De...