Ansible剧本1

有时候一个任务需要大量的操作,继续执行ad-hoc命令不合适,这个时候用剧本(playbook)。

playbook:批处理任务,但是他有自己的语法格式。

playbook文件格式

  • YAML语言编写。
  • YAML是一个类似XML、JSON的标记性语言,YAML强调以数据为中心。
  • YAML本身定义比较简单,号称"一种人性化的数据格式语言"

YAML语言规范:

  1. 大小写敏感
  2. 使用空格作为嵌套缩进工具,缩进时不允许使用Tab键。
  3. 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可。
  4. 使用"-"(横线)+单个空格:表示单个列表项。
  5. 使用":"+空格:表示单个键值对。
  6. 使用"{}"表示一个键值表。

playbook文件执行

通过ansible-playbook命令进行解析的,ansible-playbook命令会根据自上而下的顺序依次执行playbook文件中的内容。

它允许传输某个命令的状态到后面的指令,也可以从一台机器的文件中抓取内容并附为变量,然后在另外一台机器中使用,这样可以实现一些复杂的部署机制。

解释:

传输命令的状态到后面的指令

含义:执行一个命令,根据它的执行结果(成功/失败/输出内容),决定后续指令是否执行或如何执行。

复制代码
- name: 根据服务状态决定操作
  hosts: web_servers
  tasks:
    # 1. 检查 nginx 是否运行
    - name: 获取 nginx 状态
      command: systemctl is-active nginx
      register: nginx_status   # 将命令的状态(输出/返回码)保存到变量
      ignore_errors: yes       # 即使服务未运行也不停止

    # 2. 根据状态执行不同操作
    - name: 如果 nginx 正在运行,则重载配置
      command: systemctl reload nginx
      when: nginx_status.stdout == "active"   # 只有状态为 active 才执行

    - name: 如果 nginx 未运行,则启动它
      command: systemctl start nginx
      when: nginx_status.stdout != "active"

从一台机器的文件中抓取内容作为变量,在另一台机器使用

含义:在机器 A 读取文件内容 → 保存为变量 → 在机器 B 使用这个变量(比如部署时保持配置一致性)。

复制代码
- name: 跨主机传递变量
  hosts: master_server
  tasks:
    # 1. 从 master 机器读取版本号文件
    - name: 抓取当前部署版本
      slurp:                    # slurp 模块用于抓取文件内容(base64编码)
        src: /app/version.txt
      register: version_file

    - name: 解码文件内容
      set_fact:
        current_version: "{{ version_file.content | b64decode | trim }}"

    # 2. 将版本号写入一个变量(便于其他主机使用)
    - name: 设置全局变量
      set_fact:
        deploy_version: "{{ current_version }}"
      delegate_to: localhost   # 暂存在控制机

- name: 在目标服务器上使用该变量
  hosts: app_servers
  tasks:
    - name: 根据版本号拉取对应镜像
      command: "docker pull myapp:{{ hostvars['master_server']['deploy_version'] }}"
      # hostvars['master_server']['deploy_version'] 访问另一台机器的变量

    - name: 部署指定版本
      command: "docker run -d myapp:{{ hostvars['master_server']['deploy_version'] }}"

playbook文件的构成

playbook是由一个或者多个"play"组成的列表。play的主要功能在于,将事先合并为一组的主机封装成事先通过ansible定义好的角色。将多个play组织在一个playbook中就可以让他们连同起来按照事先安排好的机制完成一些列复杂的任务。

解释:

实际场景:部署一个完整的 Web 应用 (包含负载均衡、应用服务器、数据库)。

概念图:

具体实现:

复制代码
---
# 这是一个 Playbook,包含 3 个 Play

# ============================================
# Play 1: 配置负载均衡器
# ============================================
- name: 配置负载均衡服务器
  hosts: lb_servers          # 作用于负载均衡器主机组
  become: yes                # 使用 sudo 权限
  
  tasks:
    - name: 安装 Nginx
      apt:
        name: nginx
        state: present
        
    - name: 配置 Nginx 上游服务器
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
      notify: reload nginx    # 配置变更时触发 handler
      
    - name: 启动 Nginx 服务
      systemd:
        name: nginx
        state: started
        enabled: yes
        
  handlers:
    - name: reload nginx
      systemd:
        name: nginx
        state: reloaded


# ============================================
# Play 2: 部署应用服务器
# ============================================
- name: 部署应用服务器
  hosts: app_servers         # 作用于应用服务器主机组
  become: yes
  
  tasks:
    - name: 安装 Java 11
      apt:
        name: openjdk-11-jdk
        state: present
        
    - name: 创建应用目录
      file:
        path: /opt/myapp
        state: directory
        mode: '0755'
        
    - name: 复制应用 JAR 包
      copy:
        src: /jenkins/workspace/myapp.jar
        dest: /opt/myapp/myapp.jar
        
    - name: 配置应用启动参数
      template:
        src: application.yml.j2
        dest: /opt/myapp/application.yml
        
    - name: 启动应用
      systemd:
        name: myapp
        state: started
        enabled: yes
        daemon_reload: yes


# ============================================
# Play 3: 配置数据库服务器
# ============================================
- name: 配置数据库服务器
  hosts: db_servers          # 作用于数据库服务器主机组
  become: yes
  
  tasks:
    - name: 安装 MySQL
      apt:
        name: mysql-server
        state: present
        
    - name: 创建应用数据库
      mysql_db:
        name: myapp_production
        state: present
        
    - name: 创建数据库用户
      mysql_user:
        name: myapp_user
        password: "{{ db_password }}"
        priv: 'myapp_production.*:ALL'
        state: present
        
    - name: 导入初始数据
      mysql_db:
        name: myapp_production
        state: import
        target: /opt/sql/init.sql

5个核心组件:

target部分:定义将要执行playbook的远程主机。

variable部分:定义playbook运行时需要使用的变量

task部分:定义将要在远程主机上将要执行的任务列表

handler部分:定义task执行完成以后需要调用的任务

复制代码
#部署一个完整的 Web 应用
# 假设我们需要部署一个 Nginx + PHP + MySQL 的 Web 应用,通过 Role 来组织。
---
# site.yml - 主 Playbook
- name: 部署完整的 Web 应用
  hosts: web_servers          # 1️⃣ target:目标主机
  become: yes
  vars:                        # 2️⃣ variable:变量定义
    app_name: mywebapp
    app_port: 8080
    db_host: 192.168.1.100
    db_name: webapp_db
    db_user: webapp_user
    
  tasks:                       # 3️⃣ task:任务列表
    - name: 确保 Nginx 已安装
      apt:
        name: nginx
        state: present
        
    - name: 复制配置文件
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
      notify: restart nginx    # 4️⃣ handler:触发条件
        
    - name: 启动 Nginx
      systemd:
        name: nginx
        state: started
        
  handlers:                    # 4️⃣ handler:任务完成后调用的任务
    - name: restart nginx
      systemd:
        name: nginx
        state: restarted

Roles:角色

对应的5个层目录:

vars变量层

task任务层

handlers触发条件

files文件

template模板

复制代码
roles/
├── common/                     # 通用基础角色
│   ├── defaults/               # 1️⃣ vars变量层(默认变量)
│   │   └── main.yml
│   ├── vars/                   # 1️⃣ vars变量层(高优先级变量)
│   │   └── main.yml
│   ├── tasks/                  # 2️⃣ task任务层
│   │   └── main.yml
│   ├── handlers/               # 3️⃣ handlers触发条件层
│   │   └── main.yml
│   ├── files/                  # 4️⃣ files文件层(静态文件)
│   │   ├── sshd_config
│   │   └── hosts
│   ├── templates/              # 5️⃣ template模板层(Jinja2模板)
│   │   ├── nginx.conf.j2
│   │   └── app.yml.j2
│   └── meta/                   # 元数据(依赖关系)
│       └── main.yml
│
├── nginx/                      # Nginx 角色
│   ├── defaults/
│   │   └── main.yml            # 默认配置
│   ├── tasks/
│   │   └── main.yml
│   ├── handlers/
│   │   └── main.yml
│   ├── templates/
│   │   └── nginx.conf.j2
│   └── files/
│       └── nginx_logrotate
│
└── mysql/                      # MySQL 角色
    ├── defaults/
    ├── tasks/
    ├── handlers/
    ├── templates/
    │   ├── my.cnf.j2
    │   └── init.sql.j2
    └── files/
        └── mysql_secure.sql

playbook组件

playbook中的每一个play的目的都是为了让特定主机以某个指定的用户身份执行任务。

hosts用于指定要执行指定任务的主机,需要事先定义在主机清单。

host

复制代码
vim /etc/ansible/hosts

# hosts 文件
[all]
192.168.79.139
192.168.79.140
192.168.79.141
192.168.79.142
192.168.79.143
192.168.79.144
192.168.79.145

[all:vars]
ansible_user=root
ansible_ssh_pass=root
ansible_ssh_common_args='-o StrictHostKeyChecking=no'

[webservers]
192.168.79.139
192.168.79.140

[db]
192.168.79.141
192.168.79.142
192.168.79.143
192.168.79.144
192.168.79.145

[docker:children]
webservers
db

---
- name: 基础服务器信息收集
  hosts: all
  gather_facts: yes
  
  tasks:
    # 1. 基础连接测试
    - name: 测试连接
      ping:
      
    # 2. 系统信息
    - name: 收集系统信息
      debug:
        msg: |
          ====================================
          主机名: {{ ansible_hostname }}
          系统: {{ ansible_system }} {{ ansible_kernel }}
          发行版: {{ ansible_distribution }} {{ ansible_distribution_version }}
          CPU: {{ ansible_processor_cores }} 核心
          内存: {{ ansible_memtotal_mb }} MB
          架构: {{ ansible_architecture }}
          ====================================
          
    # 3. 网络信息
    - name: 显示网络接口
      debug:
        var: ansible_interfaces
        
    - name: 显示默认网关
      debug:
        msg: "默认网关: {{ ansible_default_ipv4.gateway }}"
      when: ansible_default_ipv4.gateway is defined
      
    # 4. 时间信息
    - name: 显示系统时间
      debug:
        msg: "当前时间: {{ ansible_date_time.date }} {{ ansible_date_time.time }}"
        
    # 5. 用户信息
    - name: 显示当前用户
      debug:
        msg: "执行用户: {{ ansible_user_id }}"
        
    # 6. 简单命令执行
    - name: 执行 uptime 命令
      command: uptime
      register: uptime_result
      
    - name: 显示 uptime 输出
      debug:
        var: uptime_result.stdout

# 1. 列出将要执行的主机(不实际执行)
ansible-playbook -i hosts first.yml --list-host

task:

复制代码
# 2. 查看所有任务(不执行)
ansible-playbook -i hosts first.yml --list-task
复制代码
# 3. 试运行(检查语法和逻辑)
ansible-playbook -i hosts first.yml --check
复制代码
# 4. 实际执行(详细输出)
ansible-playbook -i hosts first.yml -v
复制代码
# 5. 只对特定主机执行
ansible-playbook -i hosts first.yml --limit webservers
复制代码
# 6. 执行并询问确认
ansible-playbook -i hosts first.yml --step
相关推荐
科技牛牛2 小时前
平台该怎么设计更低误伤的 IP 风控策略?
服务器·网络·tcp/ip
一颗青果2 小时前
如何加速TCP传输大文件
网络·网络协议·tcp/ip
heRs BART2 小时前
Ubuntu 20.04配置网络
网络·ubuntu·php
要做一个小太阳2 小时前
blockbox配置文件详解与优化
运维·网络·prometheus
pupudawang2 小时前
Spring Boot 热部署
java·spring boot·后端
我登哥MVP2 小时前
【SpringMVC笔记】 - 9 - 异常处理器
java·spring boot·spring·servlet·tomcat·maven
DianSan_ERP2 小时前
淘宝订单接口集成中如何正确处理消费者敏感信息的安全与合规问题?
大数据·运维·网络·人工智能·安全·servlet
下地种菜小叶2 小时前
Spring Boot 2.x 升级 3.x / 4.x 怎么做?一次讲清 JDK、Jakarta、依赖兼容与上线策略
java·spring boot·后端
iiiiyu2 小时前
常用API(StringJoiner类 & Math类 & System类)
java·大数据·开发语言·数据结构·编程语言