Ansible部署、核心概念与操作指南

Ansible部署、核心概念与操作指南

一、Ansible 简介

Ansible 是一款开源的自动化运维工具,基于 Python 开发,无需在受管节点安装客户端,通过 SSH 协议实现远程控制。其核心优势包括:

  • 无代理架构:受管节点无需部署额外软件
  • 模块化设计:通过丰富的模块实现各类运维任务
  • 支持 declarative 语法:Playbook 采用 YAML 格式,易读易写
  • 幂等性:重复执行同一操作不会产生意外结果

二、Ansible 部署过程

2.1 环境要求

  • 控制节点(Ansible 主机):Python 3.6+、SSH 客户端
  • 受管节点:SSH 服务开启、Python 2.7 或 3.5+、sudo 权限(可选)
  • 网络:控制节点与受管节点网络互通,支持 SSH 连接

2.2 控制节点安装(以 CentOS 为例)

方式 1:YUM 安装(推荐)
bash 复制代码
# 安装 EPEL 源(CentOS 默认无 Ansible 仓库)
sudo yum install -y epel-release

# 安装 Ansible
sudo yum install -y ansible

# 验证安装
ansible --version
方式 2:pip 安装
bash 复制代码
# 安装 pip
sudo yum install -y python3-pip

# 安装 Ansible
pip3 install ansible

# 添加环境变量(若未自动添加)
echo "export PATH=\$PATH:/usr/local/bin" >> ~/.bashrc
source ~/.bashrc

# 验证安装
ansible --version

2.3 免密登录配置(可选但推荐)

Ansible 默认使用 SSH 连接受管节点,配置免密登录可避免重复输入密码:

bash 复制代码
# 控制节点生成 SSH 密钥对(若已存在可跳过)
ssh-keygen -t rsa -b 2048 -N "" -f ~/.ssh/id_rsa

# 分发公钥到受管节点(替换为实际主机名/IP)
ssh-copy-id root@node1
ssh-copy-id root@node2

2.4 目录结构说明

安装完成后,Ansible 核心目录如下:

bash 复制代码
# 查看 Ansible 安装文件分布
rpm -ql ansible

关键目录说明:

  • /etc/ansible/:主配置目录(默认配置文件、主机清单)
  • /usr/bin/:执行文件(ansible、ansible-playbook 等)
  • /usr/lib/pythonX.X/site-packages/ansible/:依赖库与模块
  • /usr/share/ansible/plugins/:插件目录
  • /usr/share/doc/ansible/:帮助文档

三、核心概念

3.1 主机清单(Inventory)

定义 Ansible 管理的主机集合,支持静态清单(文本文件)和动态清单(脚本生成)。

3.1.1 静态清单格式(INI 格式)

创建清单文件 inventory

ini 复制代码
# 单个主机(IP 或主机名)
web1.example.com
192.0.2.42

# 主机组定义
[webservers]
web1.example.com
web2.example.com
192.168.3.7

[dbservers]
db1.example.com
db2.example.com
192.0.2.42
192.0.2.43

# 地理位置分组
[eastdc]
web1.example.com
db1.example.com

[westdc]
web2.example.com
db2.example.com

# 组嵌套(子组必须已定义)
[dc:children]
eastdc
westdc

# 范围简写(支持数字/字母范围)
[priv]
192.168.[4:7].[0:255]  # 192.168.4.0-192.168.7.255

[hosts]
host[01:20].example.com  # host01 ~ host20

[servers]
server[a:c].example.com  # servera ~ serverc
3.1.2 内置主机组
  • all:包含所有主机
  • ungrouped:未归属任何组的主机
3.1.3 清单验证命令
bash 复制代码
# 查看单个主机
ansible --list-hosts -i inventory web1.example.com

# 查看主机组
ansible --list-hosts -i inventory webservers

# 查看所有主机
ansible --list-hosts -i inventory all

# 树形结构显示清单
ansible-inventory -i inventory --graph

# YAML 格式导出清单
ansible-inventory -i inventory --list -y

3.2 配置文件(ansible.cfg)

控制 Ansible 行为的配置文件,支持多级别优先级(从高到低):

  1. 环境变量 ANSIBLE_CONFIG 指定的文件
  2. 当前目录下的 ./ansible.cfg
  3. 用户家目录下的 ~/.ansible.cfg
  4. 系统默认配置 /etc/ansible/ansible.cfg
常用配置示例(./ansible.cfg
ini 复制代码
[defaults]
# 清单文件路径
inventory = ./inventory
# 远程登录用户
remote_user = laogao
# 并发执行主机数
forks = 10
# 禁用 SSH 主机密钥检查
host_key_checking = False
# 日志文件路径
log_path = /var/log/ansible.log
# 默认模块
module_name = command

[privilege_escalation]
# 启用权限提升(sudo)
become = True
# 提升到 root 用户
become_user = root
# 提权方式
become_method = sudo
# 不提示输入 sudo 密码
become_ask_pass = False
配置验证命令
bash 复制代码
# 查看当前生效的配置文件
ansible --version | grep 'config file'

# 查看所有配置项
ansible-config list

# 查看生效的配置
ansible-config dump

# 查看配置文件内容
ansible-config view

3.3 模块(Modules)

Ansible 的最小功能单元,用于执行具体任务(如文件操作、软件安装、服务管理等)。

常用模块分类
模块类型 代表模块 功能描述
文件操作 copy、file、lineinfile 复制文件、设置文件属性、修改文件内容
软件包 yum、apt、pip 管理系统软件包
服务管理 service、systemd 启动 / 停止 / 重启服务
系统管理 user、group、reboot 管理用户组、重启系统
命令执行 command、shell、raw 执行命令(command 不支持管道 / 重定向)
模块文档查询
bash 复制代码
# 查看模块列表
ansible-doc -l

# 查看指定模块详情(如 copy 模块)
ansible-doc copy

# 查看模块使用示例
ansible-doc -s copy

3.4 Ad-Hoc 命令

临时执行的单个任务命令,无需编写 Playbook,适用于快速测试或简单操作。

命令语法
bash 复制代码
ansible <host-pattern> -m <module> [-a <module-arguments>] [-i <inventory>]
  • <host-pattern>:主机 / 主机组(如 allwebservers
  • -m:指定模块(默认 command 模块)
  • -a:模块参数
  • -i:指定清单文件
常用示例
bash 复制代码
# 1. 查看所有受管节点主机名(默认 command 模块)
ansible all -a "hostname"

# 2. 检查操作系统版本
ansible all -a "cat /etc/os-release"

# 3. 查看内存使用情况
ansible all -a "free -h"

# 4. 统计 /etc 目录文件数(需 shell 模块支持管道)
ansible all -m shell -a "ls -l /etc | wc -l"

# 5. 安装 httpd 软件(yum 模块)
ansible webservers -m yum -a "name=httpd state=present"

# 6. 启动并设置 httpd 开机自启(service 模块)
ansible webservers -m service -a "name=httpd state=started enabled=yes"

# 7. 复制本地文件到远程(copy 模块)
ansible all -m copy -a "src=/tmp/local.txt dest=/opt/remote.txt mode=0644"

# 8. 创建用户(user 模块)
ansible all -m user -a "name=newuser uid=1001 state=present"
执行结果颜色说明
  • 绿色:目标主机已为预期状态,无需修改
  • 黄色:命令执行后状态变更,已设置为预期状态
  • 红色:执行过程出错,任务中止

3.5 Playbook

Ansible 的核心功能,用于编排多个任务,支持复杂的运维流程自动化。Playbook 采用 YAML 格式,具有可读性强、可复用的特点。

YAML 语法规则
  1. 缩进敏感:同一级别元素缩进一致(推荐 2 个空格)
  2. 键值对:key: value(冒号后必须加空格)
  3. 列表:用 - 开头表示
  4. 注释:# 开头
  5. 字符串:可不用引号,特殊字符(如空格、换行)需用引号包裹
  6. 多行字符串:| 保留换行,> 折叠换行
Playbook 基本结构
yaml 复制代码
# 示例:部署 Web 服务
- name: 部署 HTTP 服务  # Play 名称
  hosts: webservers     # 目标主机组
  become: True          # 启用权限提升
  tasks:                # 任务列表
    - name: 安装 httpd 和 firewalld  # 任务 1 名称
      yum:               # 模块名
        name:            # 模块参数
          - httpd
          - firewalld
        state: latest    # 确保为最新版本

    - name: 创建测试页面  # 任务 2 名称
      copy:
        content: "Welcome to Ansible Web!\n"
        dest: /var/www/html/index.html

    - name: 启动 firewalld 并放行 HTTP 服务  # 任务 3 名称
      firewalld:
        service: http
        permanent: yes
        state: enabled
        immediate: yes

    - name: 启动 httpd 并设置开机自启  # 任务 4 名称
      service:
        name: httpd
        state: started
        enabled: yes
Playbook 执行命令
bash 复制代码
# 1. 直接执行
ansible-playbook playbook.yaml

# 2. 语法检查(不执行任务)
ansible-playbook --syntax-check playbook.yaml

# 3. 空运行(模拟执行,不修改系统)
ansible-playbook -C playbook.yaml

# 4. 提高输出详细程度(-v 到 -vvvv)
ansible-playbook -v playbook.yaml

# 5. 指定清单文件
ansible-playbook -i inventory playbook.yaml

3.6 变量(Variables)

用于存储可复用数据,简化 Playbook 维护。变量支持多级别定义,优先级从高到低为:

  1. 命令行变量(-e 参数)
  2. Playbook 任务级变量
  3. Playbook Play 级变量
  4. 主机变量(host_vars)
  5. 主机组变量(group_vars)
  6. 清单文件变量
变量定义方式
方式 1:命令行定义
bash 复制代码
# 传递变量 package=httpd 并安装
ansible all -e "package=httpd" -m yum -a "name={{ package }} state=present"
方式 2:Play 级变量(vars 关键字)
yaml 复制代码
- name: 测试变量
  hosts: node1
  vars:
    user: joe
    home_dir: /home/joe
  tasks:
    - name: 创建用户 {{ user }}
      user:
        name: "{{ user }}"
        home: "{{ home_dir }}"
        state: present
方式 3:变量文件(vars_files 关键字)

创建变量文件 vars/user.yaml

yaml 复制代码
user: laowang
home_dir: /home/laowang

在 Playbook 中引用:

yaml 复制代码
- name: 测试变量文件
  hosts: node1
  vars_files:
    - vars/user.yaml
  tasks:
    - name: 创建用户 {{ user }}
      user:
        name: "{{ user }}"
        home: "{{ home_dir }}"
        state: present
方式 4:主机 / 组变量(目录结构)

推荐方式,在项目目录下创建 host_varsgroup_vars 目录:

plaintext 复制代码
project/
├── ansible.cfg
├── inventory
├── group_vars/
│   └── webservers.yaml  # 主机组变量
├── host_vars/
│   └── node1.yaml       # 主机变量
└── playbook.yaml

group_vars/webservers.yaml

yaml 复制代码
package: httpd
service: httpd

host_vars/node1.yaml

yaml 复制代码
package: mariadb-server  # 覆盖组变量
变量引用规则
  • 变量用 {``{ 变量名 }} 引用

  • 若变量作为值的第一个元素,需用引号包裹:

    yaml 复制代码
    # 错误示例
    name: {{ user }}
    # 正确示例
    name: "{{ user }}"
数组变量
yaml 复制代码
- name: 测试数组变量
  hosts: node1
  vars:
    users:
      - name: joe
        uid: 1001
        home: /home/joe
      - name: jane
        uid: 1002
        home: /home/jane
  tasks:
    - name: 创建用户 {{ item.name }}
      user:
        name: "{{ item.name }}"
        uid: "{{ item.uid }}"
        home: "{{ item.home }}"
        state: present
      loop: "{{ users }}"  # 循环数组

3.7 事实(Facts)

Ansible 自动从受管节点收集的系统信息(如主机名、IP 地址、内核版本等),可作为变量直接使用。

查看 Facts
bash 复制代码
# 查看所有 Facts
ansible node1 -m setup

# 过滤特定 Facts(如默认 IPv4 地址)
ansible node1 -m setup -a "filter=ansible_default_ipv4"
常用 Facts 示例
Facts 变量 描述
ansible_facts['hostname'] 短主机名
ansible_facts['fqdn'] 完全限定域名
ansible_facts['default_ipv4']['address'] 默认 IPv4 地址
ansible_facts['kernel'] 内核版本
ansible_facts['memory_mb']['total'] 总内存(MB)
ansible_facts['distribution'] 操作系统发行版
在 Playbook 中使用 Facts
yaml 复制代码
- name: 使用 Facts 配置 Nginx
  hosts: webservers
  tasks:
    - name: 配置 Nginx 监听地址
      lineinfile:
        path: /etc/nginx/nginx.conf
        regexp: '^listen'
        line: "listen {{ ansible_facts['default_ipv4']['address'] }}:80;"
关闭 Facts 收集(加快执行速度)
yaml 复制代码
- name: 关闭 Facts 收集
  hosts: webservers
  gather_facts: no  # 关闭自动收集
  tasks:
    # 手动收集特定 Facts(如需)
    - name: 收集网络相关 Facts
      setup:
        gather_subset: network

3.8 敏感数据管理(Ansible Vault)

用于加密存储敏感数据(如密码、API 密钥),避免明文泄露。

常用命令
bash 复制代码
# 1. 创建加密文件
ansible-vault create secret.yaml
# 输入密码后,编辑文件内容(YAML 格式):
# password: Huawei@123
# db_user: root

# 2. 查看加密文件
ansible-vault view secret.yaml
# 或通过密码文件自动输入密码
ansible-vault view --vault-password-file=pass.txt secret.yaml

# 3. 编辑加密文件
ansible-vault edit secret.yaml

# 4. 加密现有文件
ansible-vault encrypt plain.yaml

# 5. 解密文件
ansible-vault decrypt secret.yaml

# 6. 修改加密文件密码
ansible-vault rekey secret.yaml
在 Playbook 中使用加密文件
yaml 复制代码
- name: 部署数据库并配置密码
  hosts: dbservers
  vars_files:
    - secret.yaml  # 引用加密文件
  tasks:
    - name: 安装 mariadb-server
      yum:
        name: mariadb-server
        state: present

    - name: 设置数据库 root 密码
      mysql_user:
        name: root
        password: "{{ password }}"  # 引用加密变量
        host: '%'
        priv: '*.*:ALL'
        state: present
执行带加密文件的 Playbook
bash 复制代码
# 交互输入密码
ansible-playbook playbook.yaml --ask-vault-pass

# 通过密码文件输入
ansible-playbook playbook.yaml --vault-password-file=pass.txt

# 在 ansible.cfg 中配置密码文件路径(永久生效)
echo "vault_password_file = ./pass.txt" >> ansible.cfg
ansible-playbook playbook.yaml

四、常用文件操作模块实战

4.1 file 模块(文件 / 目录管理)

yaml 复制代码
- name: 文件操作示例
  hosts: all
  tasks:
    # 1. 创建文件并设置权限
    - name: 创建测试文件
      file:
        path: /tmp/testfile
        owner: root
        group: root
        mode: 0644  # 权限(必须带前导 0)
        state: touch

    # 2. 创建目录(递归)
    - name: 创建 /webdev 目录
      file:
        path: /webdev
        owner: apache
        group: apache
        mode: 0755
        state: directory

    # 3. 删除文件
    - name: 删除测试文件
      file:
        path: /tmp/testfile
        state: absent

4.2 copy 模块(文件复制)

yaml 复制代码
- name: 复制文件示例
  hosts: webservers
  tasks:
    # 1. 复制本地文件到远程
    - name: 复制 Nginx 配置文件
      copy:
        src: /etc/nginx/nginx.conf  # 本地文件路径
        dest: /etc/nginx/nginx.conf  # 远程文件路径
        owner: root
        group: root
        mode: 0644
        backup: yes  # 覆盖前备份原文件(后缀为时间戳)

    # 2. 直接写入内容到远程文件
    - name: 创建自定义 index.html
      copy:
        content: |
          <html>
            <head><title>Ansible Test</title></head>
            <body><h1>Hello from {{ ansible_facts['hostname'] }}</h1></body>
          </html>
        dest: /var/www/html/index.html

4.3 lineinfile 模块(单行文本修改)

yaml 复制代码
- name: 单行文本操作示例
  hosts: webservers
  tasks:
    # 1. 确保文件中存在特定行
    - name: 添加时区配置
      lineinfile:
        path: /etc/profile
        line: "export TZ=Asia/Shanghai"
        state: present

    # 2. 在指定行前插入
    - name: 在 Listen 80 前插入 Listen 8080
      lineinfile:
        path: /etc/httpd/conf/httpd.conf
        line: "Listen 8080"
        insertbefore: '^Listen 80'
        state: present

    # 3. 替换匹配的行
    - name: 注释掉 Listen 80
      lineinfile:
        path: /etc/httpd/conf/httpd.conf
        regexp: '^Listen 80'
        line: '#Listen 80'
        state: present

4.4 blockinfile 模块(多行文本块操作)

yaml 复制代码
- name: 多行文本操作示例
  hosts: webservers
  tasks:
    # 1. 向文件添加多行文本块
    - name: 配置 Apache 虚拟主机
      blockinfile:
        path: /etc/httpd/conf/httpd.conf
        block: |
          <VirtualHost *:80>
              ServerName web.example.com
              DocumentRoot /var/www/example
              ErrorLog /var/log/httpd/example_error.log
              CustomLog /var/log/httpd/example_access.log combined
          </VirtualHost>
        state: present
        marker: "# {mark} ANSIBLE MANAGED BLOCK - VirtualHost"  # 标记注释

4.5 fetch 模块(从远程获取文件)

yaml 复制代码
- name: 从远程获取文件示例
  hosts: dbservers
  tasks:
    # 收集远程主机的日志文件到控制节点
    - name: 获取 MariaDB 日志
      fetch:
        src: /var/log/mariadb/mariadb.log  # 远程文件路径(必须是文件)
        dest: /tmp/backup/  # 控制节点存储路径(会自动创建主机名子目录)
        flat: no  # 保留目录结构(默认 no)
相关推荐
逆风水手13 小时前
Ansible自动化运维入门指南
linux·运维·自动化·ansible
2301_767902641 天前
Ansible 自动化运维入门到实战
运维·自动化·ansible
忍冬行者1 天前
通过ansible分发免密公钥、清理不再使用的公钥及验证公钥状态
linux·服务器·ansible
Lynnxiaowen1 天前
今天我们利用Jenkins插件调用ansible
linux·运维·ansible·jenkins
linweidong4 天前
顺丰运维面试题及参考答案
运维·nginx·容器·ansible·运维开发·防火墙·python面试
不想画图4 天前
Ansible自动化运维工具及基础用法
运维·自动化·ansible
不想画图4 天前
Ansible-Inventory和playbook编写
ansible
m0_488777655 天前
Ansible-Playbook 剧本编写
ansible·playbook·剧本编写
hanyi_qwe5 天前
Ansible-Playbook 剧本编写
ansible