4. 自动化环境部署:使用 Terraform 与 Ansible 实现服务目录平台的一键部署与配置

服务目录平台的上线往往涉及多云基础设施、中间件集群、应用配置与安全策略的协同。手动部署不仅耗时且极易出错,尤其在环境晋级(开发→测试→预发→生产)过程中,配置漂移是导致故障的首要原因。本章将演示如何通过 Terraform 完成基础设施即代码(IaC)的声明式编排,再通过 Ansible 完成配置管理与应用交付,最终实现从裸云资源到可用服务目录平台的“一键部署”。

核心目标: 一次编写,环境无关;版本控制,可审计;幂等执行,消除漂移。

4.1 工具选型与分工矩阵

Terraform 与 Ansible 并非竞争关系,而是互补工具。下表明确了二者在自动化流水线中的职责边界:

维度 Terraform Ansible
核心定位 基础设施编排(IaC) 配置管理与应用部署
状态管理 有状态(.tfstate 文件) 无状态(幂等执行)
执行模型 声明式(期望状态) 过程式(Playbook 步骤)
主要操作对象 云资源(VPC、ECS、RDS、SLB) 操作系统、中间件、应用文件
变更粒度 资源级(创建/销毁/替换) 包/服务/文件/模板级
典型交付物 基础设施拓扑 可运行的应用系统
最佳实践: 使用 Terraform 输出(Output)将云资源 IP、连接串等动态信息直接注入 Ansible 的 Inventory 或 Extra Vars,实现两阶段无缝衔接。

4.2 整体自动化流程架构

下图展示了从代码提交到服务目录平台可用的完整自动化链路。Terraform 负责“建楼”,Ansible 负责“精装”。

Terraform + Ansible 自动化部署流程 阶段一:Terraform 基础设施编排 VPC / 子网 ECS 云服务器 RDS 数据库 SLB 负载均衡 Output 动态 Inventory 阶段二:Ansible 配置部署 JDK / Nginx Tomcat / Redis 应用包部署 配置注入 服务目录平台(可用状态) 说明: Terraform 通过 Provider 与云 API 交互,创建资源并输出 IP/端口;Ansible 通过动态 Inventory 插件或 Extra Vars 接收这些信息, 无需人工填写任何地址,实现从基础设施到应用配置的完全自动化闭环。

4.3 Terraform 核心配置示例

以下是一个精简的 Terraform 配置,用于创建服务目录平台所需的 VPC、ECS 实例和 RDS 数据库。所有资源通过变量(Variable)实现环境差异化。

# main.tf - 服务目录平台基础设施定义
terraform {
  required_version = ">= 1.5"
  backend "s3" {
    bucket = "catalog-tfstate-${var.env}"
    key    = "catalog-platform/terraform.tfstate"
    region = "cn-north-1"
  }
}

provider "aws" {
  region = var.region
}

# 1. 网络层
resource "aws_vpc" "catalog_vpc" {
  cidr_block = var.vpc_cidr
  tags = { Name = "catalog-vpc-${var.env}" }
}

resource "aws_subnet" "public" {
  count             = 2
  vpc_id            = aws_vpc.catalog_vpc.id
  cidr_block        = cidrsubnet(var.vpc_cidr, 8, count.index)
  availability_zone = data.aws_availability_zones.available.names[count.index]
  tags = { Name = "catalog-public-${var.env}-${count.index}" }
}

# 2. 计算层 - ECS 实例
resource "aws_instance" "catalog_app" {
  count         = var.app_instance_count
  ami           = data.aws_ami.centos8.id
  instance_type = var.app_instance_type
  subnet_id     = aws_subnet.public[count.index % 2].id
  tags = { Name = "catalog-app-${var.env}-${count.index}" }
}

# 3. 数据层 - RDS
resource "aws_db_instance" "catalog_db" {
  engine         = "mysql"
  engine_version = "8.0"
  instance_class = var.db_instance_class
  db_name        = "catalogdb"
  username       = var.db_username
  password       = var.db_password
  skip_final_snapshot = true
  tags = { Name = "catalog-db-${var.env}" }
}

# 4. 输出 - 供 Ansible 使用
output "app_server_ips" {
  value = aws_instance.catalog_app[*].public_ip
}

output "db_endpoint" {
  value = aws_db_instance.catalog_db.endpoint
}
环境晋级技巧: 通过 terraform workspace 管理 dev/staging/prod 环境,每个工作区拥有独立的 state 文件和变量值,避免资源冲突。

4.4 Ansible Playbook 配置与部署

在 Terraform 完成资源创建后,Ansible 接管剩余工作。以下 Playbook 演示了如何安装 Java 环境、部署应用包并修改数据库连接配置。

---
# deploy-catalog.yml - 服务目录平台应用部署
- name: 部署服务目录平台应用
  hosts: catalog_servers
  gather_facts: yes
  vars:
    app_version: "{{ lookup('env', 'APP_VERSION') | default('1.2.0', true) }}"
    db_host: "{{ hostvars['localhost']['db_endpoint'] }}"

  tasks:
    - name: 安装 JDK 11
      yum:
        name: java-11-openjdk-devel
        state: present

    - name: 创建应用目录
      file:
        path: /opt/catalog
        state: directory
        mode: '0755'

    - name: 从制品库下载应用包
      get_url:
        url: "http://artifactory.example.com/catalog/{{ app_version }}/catalog.war"
        dest: /opt/catalog/catalog.war
        checksum: "sha256:{{ lookup('url', 'http://artifactory.example.com/catalog/{{ app_version }}/catalog.war.sha256') }}"

    - name: 注入数据库连接配置
      template:
        src: application-prod.properties.j2
        dest: /opt/catalog/application-prod.properties
      notify: restart catalog service

    - name: 启动服务目录平台
      systemd:
        name: catalog
        state: started
        enabled: yes

  handlers:
    - name: restart catalog service
      systemd:
        name: catalog
        state: restarted

4.5 一键部署执行流程

将上述两个工具串联后,运维人员只需执行一条命令即可完成全流程部署。下表列出了标准执行步骤与关键检查点:

步骤 命令/操作 关键检查点
1. 初始化 Terraform terraform init 后端存储连接正常,Provider 版本锁定
2. 预览基础设施变更 terraform plan -out=tfplan 确认资源增删改与预期一致
3. 应用基础设施 terraform apply tfplan 资源创建成功,Output 输出 IP 与连接串
4. 生成 Ansible Inventory terraform output -json | jq ... > inventory.json Inventory 包含正确的 IP 列表与变量
5. 执行 Ansible Playbook ansible-playbook -i inventory.json deploy-catalog.yml 所有 Task 显示 OK,无 Failed 任务
6. 健康检查 curl http://<slb_dns>/catalog/health 返回 HTTP 200 及 JSON 状态
常见陷阱: Terraform state 文件必须远程存储(如 S3 + DynamoDB 锁),避免多人操作时 state 冲突导致资源被意外删除。Ansible Playbook 应始终使用 --check 模式在预发环境验证后再执行生产部署。

4.6 环境晋级差异化配置

不同环境(开发、测试、预发、生产)在资源规格、副本数、数据库密码等方面存在差异。通过 Terraform 变量文件与 Ansible 的 Group Vars 实现环境隔离:

环境晋级差异化配置映射 Terraform 变量文件 dev.tfvars staging.tfvars prod.tfvars 输出 动态注入 Ansible Group Vars group_vars/dev.yml group_vars/staging.yml group_vars/prod.yml 环境差异示例: • 开发:1 台 t2.micro • 测试:2 台 t2.medium • 预发:2 台 t2.large • 生产:4 台 c5.xlarge + 独立 DB 实例规格 + 独立密码与密钥

4.7 幂等性与故障回滚

自动化部署的核心要求是幂等性——无论执行多少次,结果一致。Terraform 通过 state 文件确保资源状态收敛;Ansible 通过模块的幂等设计(如 yum、template、systemd)保证重复执行不产生副作用。

  • Terraform 回滚: 执行 terraform destroy 销毁当前环境资源,或通过 terraform apply 恢复上一个 state 版本。
  • Ansible 回滚: 在 Playbook 中定义 rollback 标签,通过 --tags rollback 触发回滚操作,如替换旧版本包、恢复配置文件。
  • 版本控制: 所有 Terraform 配置、Ansible Playbook 和变量文件均纳入 Git 仓库,每次部署对应一个 Git Commit,支持快速回溯。
生产级建议: 在 CI/CD 流水线中集成 terraform plan 与 ansible-playbook --syntax-check 作为门禁,只有通过静态检查的代码才能进入部署阶段。同时,为每个环境保留最近 5 次部署的 state 备份,用于紧急恢复。