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]# 
相关推荐
大小科圣8 分钟前
Tomcat介绍及部署
运维·服务器
好多知识都想学34 分钟前
第二章Linux 命令概述
linux·运维·服务器
wo32586614536 分钟前
浪潮英政服务器CS5420H2配置阵列时报错The reguested command has inualid arguments.解决方法
运维·服务器
熊峰峰43 分钟前
Linux第0节:Linux环境的搭建
linux·运维·服务器
一点多余.44 分钟前
nginx的使用
运维·nginx
鸭梨山大。1 小时前
linux命令-iptables与firewalld 命令详解
linux·运维·网络
半夏知半秋1 小时前
linux下的网络抓包(tcpdump)介绍
linux·运维·服务器·网络·笔记·学习·tcpdump
o0o_-_1 小时前
【瞎折腾/ragflow】构建docker镜像并部署使用ragflow
运维·docker·容器
深思慎考1 小时前
Linux——进程间通信初解(匿名管道与命名管道)
java·linux·服务器
深思慎考2 小时前
Linux——进程间通信(system V共享内存)
linux·服务器·算法