Operations 10 min read

Build a Zero‑Downtime Enterprise Deployment Pipeline with Ansible

This guide walks you through designing and implementing a complete Ansible‑based deployment pipeline—including inventory setup, role definitions, rolling and blue‑green deployments, rollback mechanisms, performance tweaks, debugging, and best‑practice recommendations—to achieve reliable, automated, zero‑downtime releases for web applications.

Raymond Ops
Raymond Ops
Raymond Ops
Build a Zero‑Downtime Enterprise Deployment Pipeline with Ansible

Project Architecture

项目结构
├── inventories/          # 环境清单
│   ├── dev/
│   ├── staging/
│   └── production/
├── group_vars/          # 组变量
├── roles/               # 角色目录
│   ├── common/          # 基础环境
│   ├── nginx/           # Web 服务器
│   ├── app/             # 应用部署
│   └── monitoring/      # 监控配置
├── playbooks/           # 剧本文件
└── deploy.yml           # 主部署文件

Core Component Implementation

1. Inventory Configuration

all:
  children:
    webservers:
      hosts:
        web-01:
          ansible_host: 10.0.1.10
        web-02:
          ansible_host: 10.0.1.11
    databases:
      hosts:
        db-01:
          ansible_host: 10.0.2.10
    loadbalancers:
      hosts:
        lb-01:
          ansible_host: 10.0.3.10

2. Application Deployment Role (roles/app/tasks/main.yml)

---
- name: "创建应用目录"
  file:
    path: "{{ app_path }}"
    state: directory
    owner: "{{ app_user }}"
    group: "{{ app_group }}"
    mode: '0755'

- name: "从 Git 仓库拉取代码"
  git:
    repo: "{{ git_repo }}"
    dest: "{{ app_path }}/releases/{{ deployment_id }}"
    version: "{{ git_branch | default('main') }}"
    force: yes
  register: git_result

- name: "安装依赖包"
  pip:
    requirements: "{{ app_path }}/releases/{{ deployment_id }}/requirements.txt"
    virtualenv: "{{ app_path }}/venv"
    virtualenv_python: python3
  when: git_result.changed

- name: "配置应用参数"
  template:
    src: config.j2
    dest: "{{ app_path }}/releases/{{ deployment_id }}/config.py"
    backup: yes
  notify: restart_application

- name: "创建软链接指向当前版本"
  file:
    src: "{{ app_path }}/releases/{{ deployment_id }}"
    dest: "{{ app_path }}/current"
    state: link
    force: yes
  notify: restart_application

3. Rolling Deployment Strategy (playbooks/rolling_deploy.yml)

---
- name: "滚动部署应用"
  hosts: webservers
  serial: 1               # 一台一台部署
  max_fail_percentage: 0

  pre_tasks:
    - name: "从负载均衡器移除节点"
      uri:
        url: "http://{{ lb_host }}/remove/{{ inventory_hostname }}"
        method: POST
      delegate_to: localhost
    - name: "等待连接断开"
      wait_for:
        port: 80
        state: stopped
        timeout: 60

  tasks:
    - name: "部署应用"
      include_role:
        name: app
    - name: "健康检查"
      uri:
        url: "http://{{ inventory_hostname }}/health"
        method: GET
        status_code: 200
      retries: 10
      delay: 5

  post_tasks:
    - name: "添加节点到负载均衡器"
      uri:
        url: "http://{{ lb_host }}/add/{{ inventory_hostname }}"
        method: POST
      delegate_to: localhost

4. Rollback Mechanism (roles/app/tasks/rollback.yml)

---
- name: "获取历史版本列表"
  find:
    paths: "{{ app_path }}/releases"
    file_type: directory
  register: releases

- name: "排序并获取上一版本"
  set_fact:
    previous_release: "{{ (releases.files | sort(attribute='mtime', reverse=true))[1].path | basename }}"
  when: releases.files | length > 1

- name: "回滚到上一版本"
  file:
    src: "{{ app_path }}/releases/{{ previous_release }}"
    dest: "{{ app_path }}/current"
    state: link
    force: yes
  when: previous_release is defined
  notify: restart_application

Advanced Feature Implementations

Blue‑Green Deployment

- name: "蓝绿部署切换"
  block:
    - name: "部署到绿色环境"
      include_role:
        name: app
      vars:
        app_env: green
    - name: "验证绿色环境"
      uri:
        url: "http://{{ inventory_hostname }}:{{ green_port }}/health"
        status_code: 200
    - name: "切换流量到绿色环境"
      replace:
        path: /etc/nginx/sites-enabled/app.conf
        regexp: 'proxy_pass http://blue'
        replace: 'proxy_pass http://green'
      notify: reload_nginx
  rescue:
    - name: "部署失败,保持蓝色环境"
      debug:
        msg: "部署失败,自动保持当前蓝色环境运行"

Configuration Management & Vault

Encrypted vault file (group_vars/all/vault.yml) can be decrypted with:

ansible-playbook deploy.yml --ask-vault-pass

Monitoring Integration (roles/monitoring/tasks/main.yml)

- name: "部署 Prometheus 监控配置"
  template:
    src: prometheus.yml.j2
    dest: "/etc/prometheus/targets/{{ inventory_hostname }}.yml"
  delegate_to: "{{ monitoring_server }}"
  notify: reload_prometheus

- name: "发送部署通知到 Slack"
  uri:
    url: "{{ slack_webhook_url }}"
    method: POST
    body_format: json
    body:
      text: "🚀 {{ inventory_hostname }} 部署完成 - 版本: {{ git_branch }}"
  delegate_to: localhost

Performance Optimization Techniques

Parallel Execution

- name: "并行安装软件包"
  package:
    name: "{{ item }}"
    state: present
  loop: "{{ packages }}"
  async: 300   # 5 分钟超时
  poll: 0      # 立即返回
  register: package_install

- name: "等待所有包安装完成"
  async_status:
    jid: "{{ item.ansible_job_id }}"
  loop: "{{ package_install.results }}"
  register: job_result
  until: job_result.finished
  retries: 30

Conditional Execution

- name: "检查应用是否需要更新"
  stat:
    path: "{{ app_path }}/current"
  register: current_version

- name: "部署新版本"
  include_tasks: deploy.yml
  when: not current_version.stat.exists or git_result.after != (current_version.stat.lnk_target | basename)

Debugging & Logging

Debug Mode Activation

# 详细输出
ansible-playbook deploy.yml -vvv

# 检查模式(不实际执行)
ansible-playbook deploy.yml --check --diff

# 逐步执行
ansible-playbook deploy.yml --step

Log Recording Configuration

- name: "记录部署日志"
  lineinfile:
    path: /var/log/deployment.log
    line: "{{ ansible_date_time.iso8601 }} - {{ inventory_hostname }} - {{ deploy_action }}"
    create: yes

One‑Click Deployment Script (deploy.sh)

#!/bin/bash
set -e

ENVIRONMENT=${1:-staging}
BRANCH=${2:-main}
DEPLOYMENT_ID=$(date +%Y%m%d_%H%M%S)

echo "🚀 开始部署到 $ENVIRONMENT 环境"
echo "📦 分支: $BRANCH"
echo "🆔 部署ID: $DEPLOYMENT_ID"

# 预检查
ansible-playbook -i inventories/$ENVIRONMENT playbooks/precheck.yml

# 执行部署
ansible-playbook -i inventories/$ENVIRONMENT deploy.yml \
  -e "git_branch=$BRANCH" \
  -e "deployment_id=$DEPLOYMENT_ID" \
  --vault-password-file .vault_pass

# 部署后验证
ansible-playbook -i inventories/$ENVIRONMENT playbooks/verify.yml

echo "✅ 部署完成!"

Best‑Practice Summary

版本管理 :所有 Ansible 代码均使用 Git 进行版本控制。

环境隔离 :为 dev、staging、production 等不同环境维护独立的 inventory 文件。

密钥安全 :使用 Ansible Vault 加密敏感变量,如数据库密码、API token。

幂等性 :确保任务可安全重复执行,避免重复操作。

错误处理 :关键任务使用 block/rescue 结构捕获异常并回滚。

监控告警 :部署完成后自动推送至 Prometheus 与 Slack,实现实时可观测性。

文档维护 :保持清晰的 README、变量说明和运行手册,便于团队协作。

References

GitHub repository: https://github.com/raymond999999 Gitee repository:

https://gitee.com/raymond9
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

ci/cdAutomationDeploymentDevOpsrollbackAnsibleBlue-Green
Raymond Ops
Written by

Raymond Ops

Linux ops automation, cloud-native, Kubernetes, SRE, DevOps, Python, Golang and related tech discussions.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.