Fool's blog Fool's blog
首页
  • Ansible
  • Jenkins
  • Docker
  • Kubernetes
  • Linux常用命令
  • Git
  • Nginx
  • PVE
  • Samaba
  • Python
  • Go
GitHub (opens new window)

The Fool

运维萌新
首页
  • Ansible
  • Jenkins
  • Docker
  • Kubernetes
  • Linux常用命令
  • Git
  • Nginx
  • PVE
  • Samaba
  • Python
  • Go
GitHub (opens new window)
  • Ansible

    • Ansible基础
      • 安装
      • 模块
        • Command
        • Shell
        • File
        • Cron
        • Script
        • Copy
        • Apt/Yum
        • Systemd
        • Mount
        • Archive/Unarchive
        • Template
      • playbook
        • 变量
        • 全局变量
        • 剧本变量
        • 资产变量
        • 主机组变量
        • Facts变量
        • 循环-loop
        • register
        • when
        • handlers
        • Tags
      • Roles
      • 配置文件--ansible.cfg
        • 增加forks值
        • 修改执行策略
        • 开启ssh长连接
        • 开启pipeling
        • 关闭gather_facts
        • Facts缓存
        • 动态资产
      • 统计服务器基本信息
    • Ansible实践
  • Jenkins

  • DevOps
  • Ansible
The Fool
2025-11-02
目录

Ansible基础

# Ansible基础

Ansible是一个非常强大的自动化运维工具,它基于SSH,Ansible 不需要在目标主机上安装任何客户端代理,它直接利用 SSH 来远程执行命令和配置管理。

# 安装

apt update -y
apt install ansible -y
apt install sshpass
1
2
3

验证是否安装成功

ansible --version
1
ansible [core 2.14.18]
  config file = None
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] (/usr/bin/python3)
  jinja version = 3.1.2
  libyaml = True
1
2
3
4
5
6
7
8
9

默认配置文件

/etc/ansible/ansible.cfg
1

编辑/etc/ansible/hosts, 如果没有则创建。

vim /etc/ansible/hosts
1

如果配置免密后还要输入密码认证,可以查看/etc/ssh/sshd_config文件以下参数是否设置为:yes

PubkeyAuthentication yes
1
ansible all -i inventory.ini -m ping # 参数可以指定自定义文件
1

hosts 文件内容如下———因为ansible基于ssh,所以可以使用密码或密钥,我这里使用密码

先安装

apt install sshpass -y
1
[nodes]
ip ansible_user=root ansible_ssh_pass=pass ansible_port=2222
[web]
ip ansible_user=root ansible_ssh_pass=pass ansible_port=2222
[db]
ip ansible_user=root ansible_ssh_pass=pass ansible_port=2222
1
2
3
4
5
6

密钥

ssh-keygen -t rsa #中间一路按enter键即可
ssh-copy-id root@IP
1
2
[nodes]
ip ansible_user=root 
[web]
ip ansible_user=root 
[db]
ip ansible_user=root 
1
2
3
4
5
6

all 指所有主机,当然你可以指定部分主机

ansible all -m ping
ansible web,db -m ping
1
2

成功执行后应有这样的提示

node02 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
node01 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
node03 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 模块

ansible:ad-hoc命令结构如下:

ansible 主机 -m 模块名 -a 操作
1
ansible-doc -s 模块名 # 可以列出模块的具体用法和参数
1
ansible-doc -l # 列出所有模块
1
ansible-playbook --syntax-check site.yml #语法检测
1

# Command

Command:不会通过 shell 解释器运行命令,只能执行一些简单的指令。默认模块不指定默认command。

ansible nodes -m  command -a "uptime"
1
ip | CHANGED | rc=0 >>
 20:51:34 up 26 days, 17:49,  3 users,  load average: 0.01, 0.08, 0.06
1
2

# Shell

Shell:通过 shell 解释器运行命令,可以使用 shell 特性,如管道、重定向、环境变量等。

从以下列子可以明显看出command 不支持管道。

root@master:/etc/ansible# ansible nodes -m shell -a "netstat -tunlp | grep 22"
IP | CHANGED | rc=0 >>
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      16355/sshd: /usr/sb 
tcp6       0      0 :::22                   :::*                    LISTEN      16355/sshd: /usr/sb 
root@master:/etc/ansible# ansible nodes -m command -a "netstat -tunlp | grep 22"
IP | CHANGED | rc=0 >>
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      16355/sshd: /usr/sb 
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      61011/docker-proxy  
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      61025/docker-proxy  
tcp        0      0 127.0.0.1:1514          0.0.0.0:*               LISTEN      60398/docker-proxy  
tcp6       0      0 :::22                   :::*                    LISTEN      16355/sshd: /usr/sb 
tcp6       0      0 :::80                   :::*                    LISTEN      61018/docker-proxy  
tcp6       0      0 :::443                  :::*                    LISTEN      61034/docker-proxy  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# File

File: 用于管理文件和目录的属性,可以创建、删除文件或目录,设置文件或目录的权限、拥有者和组等属性

文件/目录操作常用参数:

  1. owner: 定义文件/目录的属主
  2. group: 定义文件/目录的属组
  3. mode: 定义文件/目录的权限
  4. path: 必选项,定义文件/目录的路径
  5. recurse: 递归的设置文件的属性,只对目录有效
  6. src: 要被链接(软/硬)的源文件的路径,只应用于state=link的情况
  7. dest: 被链接到的路径,只应用于state=link的情况
  8. state:
  • directory: 如果目录不存在,创建目录
  • file: 文件不存在,则不会被创建,存在则返回文件的信息,常用于检查文件是否存在。
  • link: 创建软链接
  • hard: 创建硬链接
  • touch: 如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间
  • absent: 删除目录、文件或者取消链接文件

创建目录并设置权限

ansible nodes -m file -a "path=/etc/ansible/test state=directory mode=0755"
1
root@master:/etc/ansible# ls -l
total 4
-rw-r--r-- 1 root root 78 Mar 18 21:29 hosts
drwxr-xr-x 2 root root 39 Mar 18 21:38 playbook
drwxr-xr-x 2 root root  6 Mar 27 21:10 test
1
2
3
4
5
ansible nodes -m file -a "path=/etc/ansible/test state=touch" # 创建文件
ansible nodes -m file -a "path=/etc/ansible/test state=absent" # 删除文件或目录
1
2

更多操作可以通过以下命令查看

ansible-doc -s 模块名
1

# Cron

Cron:用于在远程主机上管理定时任务

注意:使用 Ansible 创建的计划任务,是不能使用本地 crontab -e 去编辑,否则 Ansible 无法再次操作他。

常用参数:

  • name: 指定一个 cron job 的名字。一定要指定,便于日后删除。
  • minute: 指定分钟,可以设置成 (0-59,,/2 等) 格式。默认是 *,也就是每分钟。
  • hour: 指定小时,可以设置成 (0-23,,/2 等) 格式。默认是 *,也就是每小时。
  • day: 指定天,可以设置成 (1-31,,/2 等) 格式。默认是 *,也就是每天。
  • month: 指定月份,可以设置成 (1-12,,/2 等) 格式。默认是 *,也就是每月。
  • weekday: 指定星期,可以设置成 (0-6 for Sunday-Saturday,* 等) 格式。默认是 *,也就是每星期。
  • job: 指定要执行的内容,通常可以写个脚本,或者一段内容。
  • state: 指定这个 job 的状态,可以是新增 (present) 或者是删除 (absent)。默认为新增 (present)。

创建一个每5分钟执行一次的任务

ansible all -m cron -a "name='job1' job='/usr/local/bin/check_service.sh' minute='*/5' state=present"
1

删除一个任务

ansible all -m cron -a "name='job1' state=absent"
1

查看创建的任务

ansible all -m shell -a "crontab -l"
1

# Script

Script:允许你在远程主机上执行本地脚本

创建一个简单的shell 脚本

vim test_script.sh
1
#!/bin/bash
echo "Current hostname: $(hostname)"
echo "Current date: $(date)"
echo "Script arguments: $@"
1
2
3
4
chmod +x test_script.sh
1
ansible nodes -m script -a "./test_script.sh hello ansible"
1
IP | CHANGED => {
    "changed": true,
    "rc": 0,
    "stderr": "Shared connection to 154.23.243.49 closed.\r\n",
    "stderr_lines": [
        "Shared connection to 154.23.243.49 closed."
    ],
    "stdout": "Current hostname: master\r\nCurrent date: Sun Mar 30 08:55:14 PM CST 2025\r\nScript arguments: hello ansible\r\n",
    "stdout_lines": [
        "Current hostname: master",
        "Current date: Sun Mar 30 08:55:14 PM CST 2025",
        "Script arguments: hello ansible"
    ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# Copy

常用参数:

  • src: 指定拷贝文件的源地址
  • dest: 指定拷贝文件的目标地址
  • backup: 拷贝文件前,若原始文件发生变化,则对目标文件进行备份
  • owner: 指定新拷贝文件的所有者
  • group: 指定新拷贝文件的所有组
  • mode: 指定新拷贝文件的权限
root@node01:~# ansible web -m copy -a "src=./get_helm.sh dest=/root/"
node02 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": true,
    "checksum": "3b4ee4bce486825ac1e35c595b676296d1892677",
    "dest": "/root/get_helm.sh",
    "gid": 0,
    "group": "root",
    "md5sum": "6b90dff0367e198cd2e46bd569114557",
    "mode": "0644",
    "owner": "root",
    "size": 11913,
    "src": "/root/.ansible/tmp/ansible-tmp-1760083316.1165833-3219920-162983002986822/source",
    "state": "file",
    "uid": 0
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
root@node02:~# ls -l
total 504856
-rwxr-xr-x 1 root root      5332 Jun  8 20:44 agent.sh
-rw-r--r-- 1 root root  10562552 Apr  1  2025 cri-dockerd_0.3.17.3-0.debian-bookworm_amd64.deb
-rw-r--r-- 1 root root     11913 Oct 10 16:01 get_helm.sh
-rw-r--r-- 1 root root 505623040 Feb 19  2025 hpav1.tar
-rw-r--r-- 1 root root       254 Sep 21 15:17 nginx.conf
-rw-r--r-- 1 root root    754176 Feb 19  2025 pause.tar
1
2
3
4
5
6
7
8

# Apt/Yum

常用参数: name: 要安装的软件包名,多个软件包以逗号(,)隔开。 state: 对当前指定的软件进行安装或移除操作。 state参数支持的值:

  • present: 确认已经安装,但不升级。
  • installed: 确认已经安装。
  • latest: 确保安装,且升级为最新。
  • absent: 确认已移除。
  • removed: 确认已移除。

Apt/Yum:系统上管理软件包

安装软件包

ansible all -m apt -a "name=vim,curl state=present"
1

删除软件包

ansible all -m apt -a "name=curl state=absent"
1

# Systemd

常用参数:

  • daemon_reload: 重新载入 systemd,扫描新的或有变动的单元。
  • enabled: 是否开机自启动 (yes/no)。
  • name: 必选项,服务名称,例如 httpd, vsftpd。
  • state: 对当前服务执行启动、停止、重启、重新加载等操作 (started, stopped, restarted, reloaded)。

服务状态管理:

ansible all -m systemd -a "name=nginx state=started"
1

启用/禁用服务开机自启:

ansible all -m systemd -a "name=nginx enabled=yes"

ansible all -m systemd -a "name=nginx enabled=no"
1
2
3

重新加载 systemd 配置:

ansible all -m systemd -a "daemon_reload=yes"      # systemctl daemon-reload
1

# Mount

Mount:用于管理文件系统的挂载点

挂载一个标准的 ext4 文件系统

ansible all -m mount -a "path=/mnt/data src=/dev/sdb1 fstype=ext4 state=mounted"
1

完全移除挂载(卸载并从 fstab 中删除)

ansible all -m mount -a "path=/mnt/data state=absent"
1

# Archive/Unarchive

Archive/Unarchive:用于处理文件的压缩和解压缩操作

压缩多个文件/目录

ansible all -m archive -a "path=/path/to/dir1,/path/to/dir2 dest=/path/to/archive.tar.gz"
1

解压控制主机的文件到被控主机

ansible all -m unarchive -a "src=/local/path/archive.tar.gz dest=/remote/path/"
1

解压被控主机的文件(需要被控主机需要相同的路径和名字)

ansible all -m unarchive -a "src=/remote/path/archive.tar.gz dest=/remote/path/ remote_src=yes"
1

# Template

使用了 Jinja2 格式作为文件模版,可以进行文档内变量的替换。

它的每次使用都会被 Ansible 标记为 "changed" 状态。文件以 .j2结尾。

常用参数:

  • src: 指定 Ansible 控制端的文件路径。
  • dest: 指定 Ansible 被控端的文件路径。
  • owner: 指定文件的属主。
  • group: 指定文件的属组。
  • mode: 指定文件的权限。
  • backup: 创建一个包含时间戳信息的备份文件,这样如果您以某种方式错误地破坏了原始文件,就可以将其恢复原状。(yes/no)
vim hello_ansible.j2
 hello {{ name }}!!!!!
ansible db -m template -a "src=./hello_ansible.j2 dest=/tmp/hello_ansible.txt" -e "name=ansible"
root@node03:/etc# cat /tmp/hello_ansible.txt 
hello ansible!!!!!
1
2
3
4
5

# playbook

常见属性:

  • name属性:每个play的名字。
  • hosts属性:每个play涉及的被管理服务器,同ad-hoc中的资产选择器。
  • tasks属性:每个play中具体要完成的任务,以列表的形式表达。
  • become属性:如果需要提权,则加上become相关属性。
  • become_user属性:若提权的话,提权到哪个用户上。
  • remote_user属性:指定连接用户。若不指定,则默认使用当前执行ansible Playbook的用户。

hosts: 可以写一个主机组,也可以写IP--------hosts: 192.168.1.12,192.168.1.13

---
- name: Here is a playbook to install node_exporter.
  hosts: nodes  # 指定要安装的主机组
  #become: yes # 相当于sudo
  #become_user: zsan # 指定用户运行
  vars:
    node_exporter_url: "https://github.com/prometheus/node_exporter/releases/download/v1.9.0/node_exporter-1.9.0.linux-amd64.tar.gz"

  tasks:
  - name: Download node_exporter
    get_url: 
      url: "{{ node_exporter_url }}"
      dest: "/opt/node_exporter.tar.gz"
      mode: "0644"
1
2
3
4
5
6
7
8
9
10
11
12
13
14

测试一个playbook 是否正确,并不会真正执行

ansible-playbook -C install_node-exporter.yml
1

检查剧本

ansible-playbook  install_node-exporter.yml --syntax-check
1

运行一个剧本

ansible-playbook  install_node-exporter.yml
1

# 变量

变量优先级:命令行 > Playbook > Inventory > Role 默认

# 全局变量

全局变量,是我们使用 ansible 或使用 ansible-playbook 时,手动通过 -e 参数传递给 Ansible 的变量。

ansible db -m template -a "src=./hello_ansible.j2 dest=/tmp/hello_ansible.txt" -e "name=ansible"
1

# 剧本变量

此种变量和 PlayBook 有关,定义在 PlayBook 中。它的定义方式有多种,我们这里介绍两种最常用的定义方式。

通过PLAY属性vars定义

- name: Here is a playbook to install node_exporter.
  hosts: nodes  # 指定要安装的主机组
  #become: yes # 相当于sudo
  #become_user: zsan # 指定用户运行
  vars:
    node_exporter_url: "https://github.com/prometheus/node_exporter/releases/download/v1.9.0/node_exporter-1.9.0.linux-amd64.tar.gz"

  tasks:
  - name: Download node_exporter
    get_url: 
      url: "{{ node_exporter_url }}"
      dest: "/opt/node_exporter.tar.gz"
      mode: "0644"
1
2
3
4
5
6
7
8
9
10
11
12
13

通过PLAY属性vars_files定义

- name: Here is a playbook to install node_exporter.
  hosts: nodes  # 指定要安装的主机组
  #become: yes # 相当于sudo
  #become_user: zsan # 指定用户运行
  vars:
    - vars/url.yaml

  tasks:
  - name: Download node_exporter
    get_url: 
      url: "{{ node_exporter_url }}"
      dest: "/opt/node_exporter.tar.gz"
      mode: "0644"
1
2
3
4
5
6
7
8
9
10
11
12
13
# cat vars/url.yaml
node_exporter_url: "https://github.com/prometheus/node_exporter/releases/download/v1.9.0/node_exporter-1.9.0.linux-amd64.tar.gz"
1
2

引用变量使用**""**

# 资产变量

root@node01:/opt/ansible# cat /etc/ansible/hosts 
[nodes]
node01 ansible_user=root age=18
node02 ansible_user=root 
node03 ansible_user=root 
[web]
node02 ansible_user=root 
[db]
node03 ansible_user=root 
1
2
3
4
5
6
7
8
9

此时age就是node01的变量只有node01能访问

root@node01:/opt/ansible# ansible node01 -m debug -a "msg='{{age}}'"
node01 | SUCCESS => {
    "msg": 18
}
1
2
3
4

此时,node02访问会提示未定义

root@node01:/opt/ansible# ansible node02 -m debug -a "msg='{{age}}'"
node02 | FAILED! => {
    "msg": "The task includes an option with an undefined variable. The error was: 'age' is undefined. 'age' is undefined. 'age' is undefined. 'age' is undefined"
}
1
2
3
4

# 主机组变量

如果主机组变量与主机变量重复,优先使用主机变量

[nodes]
node01 ansible_user=root age=18
node02 ansible_user=root 
node03 ansible_user=root 
[web]
node02 ansible_user=root 
[db]
node03 ansible_user=root 
[nodes:vars]
age=20
1
2
3
4
5
6
7
8
9
10
root@node01:/opt/ansible# ansible nodes -m debug -a "msg='{{age}}'"
node01 | SUCCESS => {
    "msg": 18
}
node02 | SUCCESS => {
    "msg": 20
}
node03 | SUCCESS => {
    "msg": 20
}
1
2
3
4
5
6
7
8
9
10

# Facts变量

Facts变量不包含在前文中介绍的全局变量、剧本变量及资产变量之内。 Facts变量不需要我们人为去声明变量名及赋值。 它的声明和赋值完全由Ansible中的setup模块帮我们完成。 它收集了有关被管理服务器的操作系统版本、服务器IP地址、主机名,磁盘的使用情况、CPU个数、内存大小等等有关被管理服务器的私有信息。 在每次PlayBook运行的时候都会发现在PlayBook执行前都会有一个Gathering Facts的过程。这个过程就是收集被管理服务器的Facts信息过程。

root@node01:/opt/ansible# ansible db -m setup -a "filter=*mem*"
node03 | SUCCESS => {
    "ansible_facts": {
        "ansible_memfree_mb": 2677,
        "ansible_memory_mb": {
            "nocache": {
                "free": 6765,
                "used": 1175
            },
            "real": {
                "free": 2677,
                "total": 7940,
                "used": 5263
            },
            "swap": {
                "cached": 0,
                "free": 0,
                "total": 0,
                "used": 0
            }
        },
        "ansible_memtotal_mb": 7940,
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

在playblook

加上gather_facts : no关闭facts变量获取

- name: Here is a playbook to install node_exporter.
  hosts: nodes  # 指定要安装的主机组
  gather_facts: no
  #become: yes # 相当于sudo
  #become_user: zsan # 指定用户运行
  vars:
    - vars/url.yaml

  tasks:
  - name: Download node_exporter
    get_url: 
      url: "{{ node_exporter_url }}"
      dest: "/opt/node_exporter.tar.gz"
      mode: "0644"
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 循环-loop

---
- name: create users
  hosts: nodes
  tasks:
  - name: create user
    user:
      name: "{{ item }}" # item 并不是必须得,可以自定义
      state: present
    loop:
      - "user01"
      - "user02"
      - "user03"
1
2
3
4
5
6
7
8
9
10
11
12

自定义循环变量名

---
- name: create users
  hosts: nodes
  tasks:
    - name: create user
      user:
        name: "{{ user_name }}"  # 使用自定义的循环变量名
        state: present
      loop:
        - "user01"
        - "user02"
        - "user03"
      loop_control:
        loop_var: user_name  # 将默认的 item 改为 user_name
1
2
3
4
5
6
7
8
9
10
11
12
13
14

另一种list定义--------建议, 方便变量得重复利用

---
- name: create users
  hosts: nodes
  vars: 
    users_list:
      - "user01"
      - "user02"
      - "user03"
  tasks:
  - name: create user
    user:
      name: "{{ item }}" # item 并不是必须得,可以自定义
      state: present
    loop: "{{ users_list }}"
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# register

在 Ansible 中,register 用于:保存任务执行的结果到变量中,以便在后续任务中使用。

可以理解为:把任务的输出结果保存下来,供后续任务条件判断或输出使用。

---
- hosts: nodes
  tasks:
  - name: echo ip address
    shell: "echo {{ ansible_default_ipv4.address }} >> /tmp/ip.log"  #当Ansible连接目标主机执行任务时,默认会先执行一个"Gathering Facts"阶段,自动收集主机的各种系统信息
  - name: cat /tmp/ip.log
    shell: "cat /tmp/ip.log"
    register: ip_log_result  # 将上条命令执行的结果注册到这个变量中
  - name: debug ip_log_result
    debug:
      msg: "{{ ip_log_result.stdout_lines }}"
1
2
3
4
5
6
7
8
9
10
11
root@node01:/opt/ansible# ansible-playbook register.yaml 

PLAY [nodes] ************************************************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************************************ok: [node02]
ok: [node01]
ok: [node03]

TASK [echo ip address] **************************************************************************************************************************************changed: [node01]
changed: [node02]
changed: [node03]

TASK [cat /tmp/ip.log] **************************************************************************************************************************************changed: [node02]
changed: [node01]
changed: [node03]

TASK [debug ip_log_result] **********************************************************************************************************************************ok: [node01] => {
    "msg": [
        "192.168.187.111"
    ]
}
ok: [node02] => {
    "msg": [
        "192.168.187.112"
    ]
}
ok: [node03] => {
    "msg": [
        "192.168.187.113"
    ]
}

PLAY RECAP **************************************************************************************************************************************************node01                     : ok=4    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
node02                     : ok=4    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
node03                     : ok=4    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

# when

---
- hosts: nodes
  tasks:
  - name: copy file
    copy:
      src: /opt/test.log
      dest: /etc/
    register: file_status
    
  - name: Display success message if file was changed
    debug: 
      msg: "File was successfully copied"
    when: file_status.changed
1
2
3
4
5
6
7
8
9
10
11
12
13

# handlers

handlers和notify是实现任务触发机制的重要组件,通常用于管理服务的重启、配置文件重载等需要条件触发的操作。

---
- hosts: nodes
  vars:
    app_name: myapp
  tasks: 
  - name: Copy nginx config
    template:    # 动态渲染Jinja2模板后分发文件,copy是直接复制静态文件
      src: nginx.conf.j2   # 只需在主控机器上即可
      dest: /etc/nginx/nginx.conf
    notify:      # 可以同时触发多个handler,调用相关名字即可
      - Restart nginx
      - Reload logs
  
  handlers:
    - name: Restart nginx
      service:
        name: nginx
        state: restarted
    
    - name: Reload logs
      command: /usr/sbin/nginx -s reload
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

nginx.conf.j2

server {
    listen 80;
    server_name {{ ansible_hostname }};  # ansible 内置模块获取setup,可以用这个命令查看都有哪些内容: ansible nodes -m setup
    root /var/www/{{ app_name }};
}
1
2
3
4
5

# Tags

---
- hosts: nodes
  vars:
    network_tools: ['rsync', 'iperf3']  # 使用变量管理软件列表

  tasks:
    - name: Install network tools
      apt:
        name: "{{ item }}"
        state: present
        update_cache: yes  # 等同于 apt update 确定安装的软件为最新的
      loop: "{{ network_tools }}"
      tags:          # 可以指定多个或多个tag,运行是满足一个即可运行
        - install
        - network_setup
        - step_01 

    - name: Remove iperf3 (cleanup)
      apt:
        name: iperf3
        state: absent
      tags:
        - uninstall
        - cleanup
        - step_02
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
ansible-playbook playbook.yml --tags "install"  # 执行install tag
ansible-playbook playbook.yml --tags "step_01"  # 执行step_01 tag
ansible-playbook playbook.yml --skip-tags "install"    # 跳过带有install tags 执行其它tags
1
2
3

# Roles

Role(角色) 是 Ansible 中的一种分层结构化组织 Playbook 的方式,它能让配置更清晰、可重用、易维护。

# 初始化一个roles
ansible-galaxy init network_tools
1
2
├── defaults
│   └── main.yml         # 用于定义默认变量,这些变量的优先级低于其他变量
├── files                # 存储静态文件,这些文件可以通过 copy 或 template 模块复制到目标主机
├── handlers
│   └── main.yml         # 定义处理程序(handlers),这些处理程序可以由任务触发
├── meta
│   └── main.yml         # 定义角色的元数据,包括依赖关系等
├── README.md            # 角色的说明文档,描述角色的用途和使用方法
├── tasks
│   └── main.yml         # 定义角色的主要任务列表,这是角色的核心部分
├── templates            # 存储 Jinja2 模板文件,这些模板文件可以动态生成配置文件
├── tests
│   ├── inventory        # 测试库存文件,用于定义测试环境中的主机
│   └── test.yml         # 测试 playbook,用于测试角色的功能
└── vars
    └── main.yml         # 定义角色的变量,这些变量的优先级高于 defaults 变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

把Tags案例改为roles

network_tools/tasks/main.yml

---
- name: Install network tools
  apt:
    name: "{{ item }}"
    state: present
    update_cache: yes
  loop: "{{ network_tools }}"
  tags:
    - install
    - network_setup
    - step_01

- name: Remove iperf3 (cleanup)
  apt:
    name: iperf3
    state: absent
  tags:
    - uninstall
    - cleanup
    - step_02
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

network_tools/vars/main.yml

---
network_tools:
  - rsync
  - iperf3
1
2
3
4

site.yml

---
- hosts: nodes
  roles:
    - network_tools
1
2
3
4

执行

ansible-playbook site.yml
1

调试

# 根据v数量,输出详细信息
ansible-playbook  register.yaml -v
ansible-playbook  register.yaml -vv
ansible-playbook  register.yaml -vvv
1
2
3
4

# 配置文件--ansible.cfg

  • ANSIBLE_CONFIG(如果设置了环境变量)
  • ansible.cfg(在当前目录中)
  • ~/.ansible.cfg(在主目录中)
  • /etc/ansible/ansible.cfg

生成示例ansible.cfg文件 您可以生成一个完全注释掉的示例ansible.cfg文件,例如:

ansible-config init --disabled > ansible.cfg
1

您还可以拥有一个包含现有插件的更完整的文件:

ansible-config init --disabled -t all > ansible.cfg
1

# 增加forks值

forks决定了Ansible 并发执行任务的数量,即Ansible 在执行 Playbook 时,最多同时并发连接 5 台主机。

forks值默认是5个

1760183531441.png

[nodes]
node01
node02
node03
node04
node05
node06
node07
node08
node09
node10
1
2
3
4
5
6
7
8
9
10
11

如果,forks=5,Ansible 先启动 5 个并行进程,分别连接 node01~node05,等这些主机任务完成后,再执行 node06~node10;

值得注意的是同一批必须5个都执行完,才会执行下一批。

# 修改执行策略

上面已经说过,ansible默认执行策略是同一批必须执行完,才会执行下一批。

在配置文件中默认为 strategy=linear即顺序执行模式一步一步执行,每个 task 同步运行

1760183846233.png

修改为strategy=free即异步执行模式每台主机独立执行,不必等其他主机

但是要注意,有些场景下要小心使用free策略,特别是节点依赖时。比如,某些节点运行服务A,另一些节点运行服务B,而服务B是依赖于服务A的,那么必须不能让运行B服务的节点先执行。

# 开启ssh长连接

开启ssh长连接 ,要求ssh为5.6版本,查看版本ssh -v

1760185166324.png

ControlPersist 只影响 空闲连接的保持时间,而不会干扰 正在运行的任务即

  • 当最后一个 SSH 子连接(Ansible 的任务)执行完后,主控制连接仍然保持 5 天不关闭。
  • 如果 5 天内再次执行 Ansible,它会直接复用这个连接;
  • 超过 5 天没用,就会关闭,下次再执行会重新建立新的连接。

修改为5天

ssh_args = -C -o ControlMaster=auto -o ControlPersist=5d 
1

# 开启pipeling

默认为Falsen,如果需要开启修改为True即可。

1760185447227.png

# 关闭gather_facts

方法1

在 playbook 文件开头写上:

- hosts: all
  gather_facts: no
  tasks:
    - name: Disable facts gathering
      debug:
        msg: "No facts gathered"
1
2
3
4
5
6

方法2:全局修改

修改参数gather_facts为explicit即可

1760184775883.png

# Facts缓存

默认情况下,Ansible 每次执行 Playbook 都会重新收集 facts。这在大规模集群中非常耗时。Facts 缓存(Facts Cache) 就是让 Ansible 把上次收集的 facts 保存下来,下次直接读取,不再重新扫描主机。

文件缓存

fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_facts_cache
fact_caching_timeout = 86400
1
2
3

内存缓存

fact_caching = memory
fact_caching_timeout = 3600
1
2

Redis缓存

fact_caching = redis
fact_caching_connection = localhost:6379:0
fact_caching_timeout = 86400
1
2
3
# 强制刷新缓存
ansible-playbook site.yml --flush-cache
1
2

# 动态资产

你可以在命令行同时指定多个 inventory 文件,比如:

ansible-playbook -i hosts01.yaml -i hosts02.yaml site.yml
1

待补.............................

# 统计服务器基本信息

vim basic.yaml
1

粘贴如下内容

---
- name: Collect system info
  hosts: Test
  gather_facts: yes

  tasks:
    - name: Save system info header to local file
      delegate_to: localhost
      run_once: true
      copy:
        dest: ./system_info.csv
        content: "IP,CPU,Memory(GB),DiskTotal(GB),OS\n"

    - name: Calculate total disk size (GB)
      set_fact:
        total_disk_gb: "{{ ansible_devices | dict2items | map(attribute='value.size') | map('regex_replace', 'GB','') | map('float') | sum | round(0) }}"

    - name: Append each host's info
      delegate_to: localhost
      lineinfile:
        path: ./system_info.csv
        line: "{{ inventory_hostname }},{{ ansible_processor_vcpus }},{{ (ansible_memtotal_mb / 1024) | round(0) }},{{ total_disk_gb }},{{ ansible_distribution }} {{ ansible_distribution_version }}"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ansible-playbook basic.yaml #会在当前目录生成一个system_info.csv文件
1
IP,CPU,Memory(GB),DiskTotal(GB),OS
IP,10,23.0,215.0,Debian 12
IP,8,16.0,120.0,Debian 12
1
2
3
#DevOps
Ansible实践

Ansible实践→

最近更新
01
viper
12-20
02
Jenkins基础
12-19
03
Jenkins实践
12-19
更多文章>
Theme by Vdoing | Copyright © 2024-2025 The Fool
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式