Ansible运行原理揭秘:如何用YAML脚本掌控数服务器?

1 Ansible基本架构

1.1 Ansible工作模式

Ansible是基于模块工作的,本身没有批量部署的能力,真正具有批量部署能力的是Ansible所运行的模块,Ansible只是提供一种框架。

1.2 Ansible组件

  • Ansible:Ansible核心程序
  • Play books:任务剧本(任务集),编排定义Ansible任务集的配置文件,由Ansible依次执行多个任务,通常是JSON格式的YML文件
  • Host inventory:Ansible管理主机的清单,记录由Ansible管理的主机信息,包括端口、密码、IP等
  • Modules:核心模块,主要操作是通过调用核心模块来完成管理任务
  • CustomModules:自定义模块,完成核心模块无法完成的功能,支持多种语言
  • Connection plugins:基于连接插件连接到各个主机上,即Ansible和Host通信使用,默认是使用SSH
  • Plugins:模块功能的补充,如连接类型插件、循环插件、变量插件等,可借助于插件完成更丰富的功能
  • Playbooks:批量的命令文件
    用户请求发送给Ansible核心模块,Ansible核心模块通过Host inventory模块寻找需要运行的主机,然后通过Connection plugins连接远程的主机,并发送命令。Ansible使用插件来连接每一个被控制端Host,此外,也通过插件来记录日志等信息。

1.3 Ansible生成的主要文件

/etc/ansible

  • /etc/ansible/ansible.cfg :配置文件
  • /etc/ansible/hosts :主机库(host inventory),管理被监控的主机
  • /usr/bin/ansible:主程序
  • /usr/bin/ansible-doc:文档
  • /usr/bin/ansible-playbook:剧本

2 Ansible任务执行模式

2.1 Ansible任务执行模式

Ansible任务执行模式分为2种:

  • ad-hoc模式(点对点模块):使用单个模块,支持批量执行单条命令,相当与在bash中执行一句Shell命
  • playbook模式(剧本模式):Ansible主要的管理方式,通过多个task的集合完成一类功能,可以理解为多个ad-hoc的配置文件

2.2 Ansible任务执行流程

3 Ansible应用

3.1 定义主机列表(Inventory)

Ansible主要功能在于批量主机操作,为了便捷地使用其中的部分主机,可以在inventory中将主机进行分组命名。默认的inventory file为/etc/ansible/hosts。inventory文件可以有多个,也可以通过Dynamic Inventory来动态生成。
Inventory文件格式:

  • Inventory文件遵循ini文件风格,中括号[]中的字符为组名
  • 可以将同一个主机同时放到不同的组当中
  • 如果主机采用的是非ssh默认端口时,可以在主机名称之后采用冒号加具体端口号来注明
  • 如果主机名遵循相似的命名模式,可以使用列表的形式来表示主机名
  • 主机变量可以在Inventory中定义主机时进行添加,便于在playbook中进行使用
复制代码
示例:
1.Inventory文件遵循ini文件风格,中括号[]中的字符为组名可以将同一个主机同时放到不同的组当中
[webservers]
node1



[dbservers]
node1

2.如果主机采用的是非ssh默认端口时,可以在主机名称之后采用冒号加具体端口号来注明
[webservers]
node1:2022



[dbservers]
node1

2.如果主机名遵循相似的命名模式,可以使用列表的形式来表示主机名
[webservers]
node[1:3]



[dbservers]
node[1:2]

3.主机变量可以在Inventory中定义主机时进行添加,便于在playbook中进行使用
[webservers]
node1 http_port=80 maxRequestsPerChild=808
node2 http_port=8080 maxRequestsPerChild=909

**Inventory参数:**Ansible在基于ssh连接Inventory中指定的远程主机时,可以通过指定参数来指定其交互方式,常用参数如下:

  • ansible_ssh_host:远程主机
  • ansible_ssh_user:指定远程主机ssh端口
  • ansible_ssh_pass:连接远程主机使用的密码
  • ansible_sudo_pass:sudo密码,建议使用--ask-sudo-pass命令
  • ansible_connection:指定连接类型,类型包括:local、ssh、paramiko
  • ansible_shell_type:指定连接对端的shell类型,默认支持sh
  • ansible_ssh_private_key_file:ssh连接使用的私钥
  • ansible_python_interpreter:指定对端使用的python编译器路径
复制代码
示例:
根据定义的Inventory调用ping检测网络是否可达:
检测Inventory中定义的所有主机:ansible all -m ping

[root@node2 ~]# ansible all -m ping
192.168.10.32 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
192.168.10.30 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
192.168.10.31 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
[root@node2 ~]# 


检测Inventory中定义的dbservers组的主机:ansible dbservers -m ping
[root@node2 ~]# ansible dbservers -m ping
192.168.10.30 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
[root@node2 ~]# 

检测指定单台主机:ansible 192.168.10.30 -m ping
[root@node2 ~]# ansible 192.168.10.30 -m ping
192.168.10.30 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
[root@node2 ~]# 

3.2 基于ad-hoc模式运行

Ansible通过ssh实现目标主机的配置管理、应用部署、任务执行等操作,故而需要事先配置Ansible端能基于秘钥认证的方式连接各被管理节点。

复制代码
基本语法:
ansible <pattern> -m <module_name> -a <module_arguments> [options]

解释:
<pattern>:目标主机或主机组,可以是Inventory中的主机名、IP地址、主机组或关键字(如all)
-m <module_name>:指定要使用的模块(如ping、shell、copy等)
-a <module_arguments>:传递给模块的参数
[options]:可选参数,用于控制Ansible行为

3.2.1 常用选项

|---------------|------------------------------------------------|
| 模块 | 描述 |
| -i | 指定自定义的Inventory文件 |
| --private-key | 指定SSH私钥文件 |
| -u | 指定SSH用户 |
| -k | 提示输入SSH密码 |
| -K | 提示输入become(提权)密码(如sudo密码) |
| -b | 使用become(提权)执行任务(如sudo) |
| --become-user | 指定提权后的用户(默认为root) |
| -v | 输出详细信息(-vvv或-vvvv可增加调试信息) |
| --check | 模拟运行(不实际执行任何更改) |
| --diff | 显示文件的差异(适用于文件相关模块,如copy、template) |
| --ask-pass | 提示输入SSH密码 |
| --limit | 限制运行的主机范围(如limit webservers只对webservers组的主机生效) |

复制代码
示例:使用shell模块检查/etc/passwd文件中是否包含 root
ansible all -m shell -a 'grep root /etc/passwd'

[root@node2 ~]# ansible all -m shell -a 'grep root /etc/passwd'
192.168.10.30 | CHANGED | rc=0 >>
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
192.168.10.32 | CHANGED | rc=0 >>
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
192.168.10.31 | CHANGED | rc=0 >>
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@node2 ~]# 

3.2.2 常用模块

|---------|-----------------------------|
| 选项 | 解释 |
| ping | 目标主机连通性测试 |
| command | 在远程主机上执行命令,不支持管道 |
| shell | 在目标远程主机上调用shell解释器,支持管道命令 |
| copy | 复制文件到目标远程服务器主机上,支持设定内容和修改权限 |
| file | 创建文件、链接文件以及删除文件等操作 |
| yum | 服务安装 |
| fetch | 从远程目标主机复制文件到本地 |
| cron | crontab计划任务管理 |
| service | 服务管理 |
| user | 用户管理 |
| group | 用户组管理 |
| setup | 主要是收集信息 |
| script | 将本地脚本在目标远端服务器主机上运行 |

复制代码
示例:使用file模块在目标远程主机上创建文件
ansible all -m file -a "path=/tmp/tmp.txt state=touch"

[root@node2 ~]# ansible all -m file -a "path=/tmp/tmp.txt state=touch"
192.168.10.31 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/tmp/tmp.txt", 
    "gid": 0, 
    "group": "root", 
    "mode": "0644", 
    "owner": "root", 
    "secontext": "unconfined_u:object_r:user_tmp_t:s0", 
    "size": 0, 
    "state": "file", 
    "uid": 0
}
192.168.10.32 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/tmp/tmp.txt", 
    "gid": 0, 
    "group": "root", 
    "mode": "0644", 
    "owner": "root", 
    "size": 0, 
    "state": "file", 
    "uid": 0
}
192.168.10.30 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/tmp/tmp.txt", 
    "gid": 0, 
    "group": "root", 
    "mode": "0644", 
    "owner": "root", 
    "size": 0, 
    "state": "file", 
    "uid": 0
}

3.3 基于playbook模式执行

Playbook模式是一种通过编写YAML格式的脚本文件(称为 playbook)来定义和执行自动化任务的方式,playbook是由一个或者多个play组成的列表,play主要功能是将事先归并为一组的主机装扮成事先通过task定义好角色,task就是调用的AnsiBle的一个模块(module)。
playbook的组成部分:

  • hosts:用于指定要执行的指定任务的主机组,其可以是一个或者多个由冒号组成的主机组
  • user:指定远程主机上执行任务的用户,也可以自定sudo的用户
  • variable:用于定义playbook运行时使用的变量
  • tasks:用于定义在远程目标主机上执行的任务列表,包括
    1)name:任务的名称,建议描述任务执行步骤
    2)module:options:调用Ansible的模块module和传入的参数
  • handler:用于定义task完成后需要调用的任务,包括
    1)notify:在每个paly的最后触发,调用在handler中定义的操作
    2)handler:task的列表
复制代码
playbook示例:
---
- hosts: web  # 目标主机组
  become: yes  # 使用提权(如 sudo)
  tasks:
    - name: Ensure Apache is installed
      yum:
        name: httpd
        state: present

    - name: Ensure Apache is running
      service:
        name: httpd
        state: started

3.3.1 playbook核心组件

  1. hosts

    作用:指定目标主机或主机组(在Inventory)中定义
    示例:
    hosts: webserver

  2. tasks

    作用:定义要执行的任务列表
    每个任务包含内容:
    name:任务描述(可选,推荐使用)
    模块名称(如yum、copy、service等)
    模块参数

    示例:
    tasks:

    • name: Ensure Apache is installed
      yum:
      name: httpd
      state: present
  3. vars

    作用:定义变量
    示例:
    vars:
    http_port: 80

  4. handlers

    作用:定义处理器,通常用于重启服务
    示例:
    handlers:

    • name: Restart Apache
      service:
      name: httpd
      state: restarted
  5. become

    作用:是否使用提权(如sudo)
    示例:
    become: yes

3.3.2 playbook的执行

复制代码
ansible-playbook playbook.yml

常用选项:

|-------------|-----------------------------------|
| 选项 | 描述 |
| -i | 指定自定义的Inventory文件 |
| --limit | 限制运行的主机范围 |
| --check | 模拟运行(不实际执行任何更改) |
| --diff | 显示文件的差异(适用于文件相关模块,如copy、template) |
| --tags | 只运行指定标签的任务 |
| --skip-tags | 跳过指定标签的任务 |
| -v | 输出详细信息(-vvv或-vvvv可增加调试信息) |

3.3.3 playbook高级用法

1.条件判断

复制代码
使用when关键字根据条件执行任务
示例:
tasks:
  - name: Install Apache on CentOS
    yum:
      name: httpd
      state: present
    when: ansible_os_family == "RedHat"
  1. 循环

    使用loop关键字实现循环
    示例:
    tasks:

    • name: Ensure users are present
      user:
      name: "{{ item }}"
      state: present
      loop:
      • alice
  2. 模版

    使用template模块生成动态配置文件
    示例:
    tasks:

    • name: Configure Apache
      template:
      src: templates/httpd.conf.j2
      dest: /etc/httpd/httpd.conf
  3. 角色

    将Playbook分解为可重用的角色
    示例:
    roles:

    • common
    • webserver

3.3.4 案例:安装httpd

1.创建playbook相关目录

复制代码
[root@node2 ansible]# mkdir apache-playbook
[root@node2 ansible]# cd apache-playbook
[root@node2 ansible]# mkdir files
[root@node2 ansible]# mkdir templates

2.编辑Inventory文件,增加主机组web

复制代码
[root@node2 ansible]# echo "[web]" >>/etc/ansible/hosts

[root@node2 ansible]# echo "192.168.10.32" >>/etc/ansible/hosts
[root@node2 ansible]# 

3.创建plalybook.yml文件,增加如下内容

复制代码
---
- hosts: web  # 目标主机组
  become: yes  # 使用提权(如 sudo)
  vars:
    http_port: 80  # 定义 HTTP 端口
    html_content: "Hello, Ansible!"  # 定义 HTML 页面内容

  tasks:
    # 1. 安装 Apache
    - name: Ensure Apache is installed
      yum:
        name: httpd
        state: present

    # 2. 配置 Apache
    - name: Configure Apache
      template:
        src: templates/httpd.conf.j2  # 模板文件
        dest: /etc/httpd/conf/httpd.conf  # 目标配置文件
      notify: Restart Apache  # 触发处理器

    # 3. 部署 HTML 页面
    - name: Deploy HTML page
      copy:
        content: "{{ html_content }}"
        dest: /var/www/html/index.html

    # 4. 启动 Apache 并设置开机自启
    - name: Ensure Apache is running and enabled
      service:
        name: httpd
        state: started
        enabled: yes

  handlers:
    # 定义处理器,用于重启 Apache
    - name: Restart Apache
      service:
        name: httpd
        state: restarted

4.创建模版文件,在templates目录下创建httpd.conf.j2文件,并增加如下内容

复制代码
# {{ ansible_managed }} - DO NOT EDIT MANUALLY

Listen {{ http_port }}

<VirtualHost *:{{ http_port }}>
    DocumentRoot "/var/www/html"
    ServerAdmin webmaster@localhost
    ErrorLog /var/log/httpd/error.log
    CustomLog /var/log/httpd/access.log combined
</VirtualHost>

5.运行playbook

复制代码
ansible-playbook -i /etc/ansible/hosts playbook.yml

[root@node2 apache-playbook]# ansible-playbook -i /etc/ansible/hosts playbook.yml

PLAY [web] **********************************************************************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************************************************************
ok: [192.168.10.32]

TASK [Ensure Apache is installed] ***********************************************************************************************************************************************
ok: [192.168.10.32]

TASK [Configure Apache] *********************************************************************************************************************************************************
ok: [192.168.10.32]

TASK [Deploy HTML page] *********************************************************************************************************************************************************
ok: [192.168.10.32]

TASK [Ensure Apache is running and enabled] *************************************************************************************************************************************
ok: [192.168.10.32]

PLAY RECAP **********************************************************************************************************************************************************************
192.168.10.32              : ok=5    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[root@node2 apache-playbook]# 

6.验证结果

复制代码
[root@node2 apache-playbook]# curl http://192.168.10.30
Hello, Ansible!
[root@node2 apache-playbook]# 
相关推荐
weixin_430750931 小时前
OpenMediaVault debian Linux安装配置企业私有网盘(三) 静态ip地址配置
linux·服务器·debian·nas·网络存储系统
403240731 小时前
[Jetson/Ubuntu 22.04] 解决挂载 exFAT 硬盘报错 “unknown filesystem type“ 及只读权限问题的终极指南
linux·运维·ubuntu
零意@2 小时前
debian如何把新编译的内核镜像替换原来的内核
运维·debian·更新内核版本·linux内核版本更新·debian更新内核
Love丶伊卡洛斯2 小时前
Ubuntu 部署 STUN服务端
linux·运维·ubuntu
有毒的教程3 小时前
SaltStack 开源自动化运维工具详细介绍
运维·开源·saltstack
大房身镇、王师傅3 小时前
【VirtualBox】VirtualBox 7.1.6 RockyLinux10 配置增强功能 设置共享目录
运维·服务器·virtualbox·rockylinux10
betazhou3 小时前
rsync使用案例分析
linux·运维·服务器·rsync·同步数据
SmartBrain4 小时前
Agent 知识总结
服务器·数据库·笔记
QQ__17646198244 小时前
为Windows系统安装Codex(保姆级教程)
服务器·大模型·codex
minglie15 小时前
谷歌浏览器搜索技巧
运维