Ansible

作者:JunLan 发布时间: 2025-12-19 阅读量:10 评论数:0

Ansible

Ansible

Ansible is a radically simple IT automation system. It handles configuration management, application deployment, cloud provisioning, ad-hoc task execution, network automation, and multi-node orchestration. Ansible makes complex changes like zero-downtime rolling updates with load balancers easy. More information on the Ansible website.

Ansible 是一套软件工具,其可实现基础架构即程式码。它是开源软件,并且该套件包括软件供应、组态管理和应用程序部署等功能。
Ansible 是无代理的,借由透过 SSH 或允许 PowerShell 执行的 Windows 远端管理机制来建立临时远端连线。 Ansible 的控制节点在大多数已安装 Python 的类 Unix 系统上执行。系统组态部分是透过使用它自己的宣告式语言来定义的。

项目介绍说明

发展史

Ansible 最初由 Michael DeHaan 编写,于 2012-03-09 发布 0.0.1 版;并于 2015-10-17 年被 Red Hat(红帽)公司以 1.5 亿美元收购,其旨在自动化设定类 Unix 系统和 Microsoft Windows 的环境。

"ansible"一词是由 Ursula K. Le Guin(厄休拉・克罗伯・勒古恩)在她 1966 年的小说 Rocannon’s World(罗坎农的世界)中所创造的,指的是虚构的即时通讯系统。

特性

  • 模块化:调用特定的模块完成特定任务,支持自定义模块,可使用任何编程语言写模块
  • Paramiko(python 对 ssh 的实现)模块,PyYAML,Jinja2(模板语言)三个关键模块
  • 基于 Python 语言实现
  • 部署简单,基于 python 和 SSH (默认已安装),agentless,无需代理不依赖 PKI (无需ssl)
  • 基于 OpenSSH
  • 暴等性:一个任务执行 1 遍和执行 n 遍效果一样,不因重复执行带来意外情况
  • 支持 playbook 编排任务,YAML 格式,编排任务,支持丰富的数据结构
  • 较强大的多层解决方案 role

Ansible 主要组成

  • PLAYBOOKS:任务剧本(任务集),编排定义 Ansible 任务集的配置文件,由 Ansible 顺序依次执行,通常是 JSON 格式的 YML 文件
  • INVENTORY:Ansible 管理主机的清单 /etc/anaible/hosts
  • MODULES:Ansible 执行命令的功能模块,多数为内置核心模块,也可自定义
  • PLUGINS:模块功能的补充,如连接类型插件、循环插件、变量插件、过滤插件等,该功能不常用
  • API:供第三方程序调用的应用程序编程接口

官网

源代码库
官网
官方文档

安装部署

准备工作

# 安装 epel (Fedora项目)维护的一个社区软件包仓库
[root@localhost ~]# dnf install epel-release -y

[root@localhost ~]# dnf info ansible
上次元数据过期检查:0:00:18 前,执行于 2025年06月21日 星期六 13时31分09秒。
可安装的软件包
名称         : ansible
时期         : 1
版本         : 7.7.0  # 精选集合的 ansible 软件包版本,不是 ansible-core 的版本
发布         : 1.el9
架构         : noarch
大小         : 34 M
源           : ansible-7.7.0-1.el9.src.rpm
仓库         : epel
概况         : Curated set of Ansible collections included in addition to ansible-core
URL          : https://ansible.com
协议         : GPL-3.0-or-later AND Apache-2.0 AND BSD-2-Clause AND BSD-3-Clause AND MIT AND MPL-2.0 AND PSF-2.0
描述         : Ansible is a radically simple model-driven configuration management,
             : multi-node deployment, and remote task execution system. Ansible works
             : over SSH and does not require any software or daemons to be installed
             : on remote nodes. Extension modules can be written in any language and
             : are transferred to managed machines automatically.
             :
             : This package provides a curated set of Ansible collections included in addition
             : to ansible-core.

安装 Ansible 软件包

dnf install ansible -y

验证成功安装

2025-06-21 目前 Github 最新版本是 v2.18.6,epel 源中用的是 2.14.18 版本

[root@localhost ~]# ansible --version
ansible [core 2.14.18]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.9/site-packages/ansible
  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.9.19 (main, Sep 11 2024, 00:00:00) [GCC 11.5.0 20240719 (Red Hat 11.5.0-2)] (/usr/bin/python3)
  jinja version = 3.1.2
  libyaml = True
  
[root@localhost ~]# which ansible
/usr/bin/ansible

# 查看可用的模块
[root@localhost ~]# ansible-doc -l | wc -l
7736

相关文件

配置文件

  1. /etc/ansible/ansible.cfg 主配置文件,配置 ansible 工作特性
  2. /etc/ansible/hosts 主机清单
  3. /etc/ansible/roles/ 存放角色的目录

ansible.cfg 主配置文件

Ansible 的配置文件 /etc/ansible/ansible.cfg,其中大部分的配置内容无需进行修改

# 生成 example 配置文件模板
[root@localhost ~]# ansible-config init --disabled > /etc/ansible/ansible.cfg

[root@localhost ~]# grep -v '^#' /etc/ansible/ansible.cfg | grep -v '^;' | grep -v '^$'
[defaults]
log_path=/var/log/ansible.log  # # 设置日志文件保存位置,默认不保存日志
host_key_checking = False  # 取消对 ssh key 的验证(免去首次ssh连接时输入yes的操作)

或:
# 将 ssh 配置文件中 33 行 StrictHostKeyChecking 的 ask 改成 no 即可
[root@localhost ~]# vim /etc/ssh/ssh_config
#   StrictHostKeyChecking ask

hosts 主机配置文件

[root@localhost ~]# grep -v '^#' /etc/ansible/hosts | grep -v '^;' | grep -v '^$'
[centos]
192.168.110.136
[rocky]
192.168.110.129
192.168.110.132

相关工具

  • /usr/bin/ansible:主程序,临时命令执行工具
  • /usr/bin/ansible-doc:查看配置文档,模块功能查看工具,相当于 man 命令
  • /usr/bin/ansible-playbook:定制自动化任务,编排剧本工具,相当于脚本
  • /usr/bin/ansible-pull:远程执行命令的工具
  • /usr/bin/ansible-vault:文件加密工具
  • /usr/bin/ansible-console:基于 Console 界面与用户交互的执行工具
  • /usr/bin/ansible-galaxy:下载/上传优秀代码或 Roles 模块的官网平台

利用 ansible 实现管理的主要方式:

  • Ad-Hoc:即利用 ansible 命令,主要用于临时命令使用场景
  • Ansible-playbook:主要用于长期规划好的大型项目的场景,需要有前期的规划过程

工具使用方式

ansible-doc

# -s 查看 ping 的关键用法
[root@localhost ~]# ansible-doc -s ping
- name: Try to connect to host, verify a usable python and return `pong' on success
  ping:
      data:                  # Data to return for the `ping' return value. If this parameter is set to `crash', the module will cause an exception.

ansible

ansible 命令执行过程
  1. 加载配置文件,默认 /etc/ansible/ansible.cfg
  2. 加载自己对应的模块文件,如:command
  3. 通过 ansible 将模块或命令生成对应的临时 py 文件,并将该文件传输至远程服务器的对应执行用户$HOME/.ansible/tmp/ansible-tmp-数字/XXX.PY 文件
  4. 给文件 +x 执行权限
  5. 执行并返回结果
  6. 删除临时 py 文件,退出
ansible <host-pattern> [-m module_name] [-a args]

选项说明:

--version  #显示版本
-m module  #指定模块,默认为command
-V  #详细过程-VV-VVV更详细
--1ist-hosts  #显示主机列表,可简写--list
-k,--ask-pass  #提示输入ssh连接密码,默认Key验证
-C,--check #检查,并不执行
-T,--timeout=TIMEOUT  #执行命令的超时时间,默认10s
-u,--user=REMOTE_USER  #执行远程执行的用户
-b,--become #代替旧版的sudo切换
--become-user=USERNAME #指定sudo的runas用户,默认为root
-K,--ask-become-pass  #提示输入sudo时的口令
基于密码验证连接主机使用 Ansible ping
# 列出管理的主机地址
[root@localhost ~]# ansible all --list
  hosts (3):
    192.168.110.136
    192.168.110.129
    192.168.110.132
[root@localhost ~]# ansible rocky --list
  hosts (2):
    192.168.110.129
    192.168.110.132

# -k 使用密码验证
[root@localhost ~]# ansible all -k -m ping
SSH password:  # 此处输入密码,每台被管理的主机密码必须相同
192.168.110.136 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
192.168.110.129 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
192.168.110.132 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
基于 Key 验证的脚步案例
push_ssh_key.sh 脚本
#!/bin/bash
# push_ssh_key.sh

# 使用数组定义 IP 地址,避免换行符问题
IPLIST=(
    192.168.110.129
    192.168.110.132
    192.168.110.136
)

# 检查并安装 sshpass
rpm -q sshpass &> /dev/null || yum install sshpass -y

# 生成 SSH 密钥,如果不存在
[ -f /root/.ssh/id_rsa ] || ssh-keygen -t rsa -f /root/.ssh/id_rsa -N ''

# 设置 SSHPASS 环境变量
export SSHPASS=Root@2020

# 循环遍历 IP 地址列表
for IP in "${IPLIST[@]}"; do
    # 使用 sshpass 和 ssh-copy-id 推送 SSH 密钥
    sshpass -e /usr/bin/ssh-copy-id root@$IP
done

echo "SSH keys pushed to the following hosts:"
printf "%s\n" "${IPLIST[@]}"

执行脚本推送公钥到服务器
[root@localhost ~]# bash push_ssh_key.sh
Generating public/private rsa key pair.
Your identification has been saved in /root/.ssh/id_rsa
Your public key has been saved in /root/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:pi3i+wqqsHw8M0B+f7rDbdQ2nzrBtQHnnTFkw7nCi+M root@localhost.localdomain
The key's randomart image is:
+---[RSA 3072]----+
|            o+.  |
|         . ..=.  |
|          = . =  |
| .         * +   |
|o       S o =    |
| o .   = O o     |
|. = + = + = .    |
|oo O = = E o     |
|=.. B*B  .o      |
+----[SHA256]-----+
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'root@192.168.110.129'"
and check to make sure that only the key(s) you wanted were added.

/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'root@192.168.110.132'"
and check to make sure that only the key(s) you wanted were added.

/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'root@192.168.110.136'"
and check to make sure that only the key(s) you wanted were added.

SSH keys pushed to the following hosts:
192.168.110.129
192.168.110.132
192.168.110.136

[root@localhost ~]# cat .ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDL1hmqIssxT5xm/Pb5SLtwmOqgpAIQkRzAWxhMYcENtcAGDqqcov/6vHsf4oYzmKBS5s5eA4U7X6WEfUacujur383F9ANZC8tP9p1hjEc3v5qBtyusMAhLawDBSe7aS3KGtz1TQBEwu+WDtmaaCE5Y81RfHS7s0PdCNAAf6GD9EILgFgJy4l3Y7TuNbilHE2AI+7T57SOFDjDQ7b+nP0X8bal9WZqXwsgx/8buwzTst/GT1FrNbXI0VApcRFLJPQXmGgqsBkzUMqZjFbZAuNyU93STc0pNQINMFNC0rjYzFR0FOVIN75Q8sLJe6tLIWjaEBK0RMw+T7SG6lhAnj5M3/1FN0EOAxfRWC2pZQjVzHZlpyukhB9YXuKKbqTN1Qzv1HjEpJZN/AMGZ6wYtZC2osm3/ZDt2V1Hl/RGHelTjFGYOcEfW4GWt+es7WmFKkEuQrsyYX06X3QF4ZMVoNoUrVzgJEDigRNq+lJMYrQPmcajsgmISF1oGrX7wQS63rMM= root@localhost.localdomain
无需输入密码连接主机
[root@ansible ~]# ansible all -m ping
192.168.110.136 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
192.168.110.132 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
192.168.110.129 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}

# 重启除了 192.168.110.129 以外的所有主机
[root@ansible ~]# ansible 'all:!192.168.110.129' -a reboot

ansible-playbook

hello.yaml

# hello.yaml
- hosts: rocky
  remote_user: root
  tasks:
    - name: hello world
      command: /usr/bin/wall hello world!
[root@ansible ~]# ansible-playbook hello.yaml

PLAY [rocky] ************************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************
ok: [192.168.110.132]
ok: [192.168.110.129]

TASK [hello world] ******************************************************************************************************************************************

来自 root@ansible (somewhere) (Sat Jun 21 15:50:46 2025) 的广播消息:

hello world!

changed: [192.168.110.132]
changed: [192.168.110.129]

PLAY RECAP **************************************************************************************************************************************************
192.168.110.129            : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
192.168.110.132            : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

ansible-vault

格式:

ansible-vault [--version] {create,decrypt,edit,view,encrypt,encrypt_string,rekey}

范例:

[root@ansible ~]# ansible-vault --version
ansible-vault [core 2.14.18]

#加密
[root@ansible ~]# ansible-vault encrypt hello.yaml
New Vault password:
Confirm New Vault password:
Encryption successful

#解密
[root@ansible ~]# ansible-vault decrypt hello.yaml
Vault password:
Decryption successful

#查看
[root@ansible ~]# ansible-vault view hello.yaml

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

#修改口令
ansible-vault rekey hello.yaml

#创建新文件
ansible-vault create hello.yaml

ansible-console

此工具可交互执行命令,支持 tab,ansible2.0+ 新增
提示符格式:

执行用户@当前操作的主机组(当前组的主机数量)[f:并发数]$

常用子命令:

  • 设置并发数:forks n 例如:forks 10
  • 切换组:cd 主机组 例如:cd centos
  • 列出当前组主机列表:list
  • 列出所有的内置命令:? 或 help

范例

[root@ansible ~]# ansible-console
Welcome to the ansible console. Type help or ? to list commands.

root@all (3)[f:5]$ list
192.168.110.136
192.168.110.129
192.168.110.132
root@all (3)[f:5]$ centos
root@all (3)[f:5]$ cd centos
root@centos (1)[f:5]$ list
192.168.110.136
root@centos (1)[f:5]$ ping
192.168.110.136 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"

ansible-galaxy

此工具会连接 https://galaxy.ansible.com 下载相应的roles
范例:

#列出所有已安装的galaxy
ansible-galaxy list
#安装galaxy
ansible-galaxy install geerlingguy.mysq1
ansible-galaxy install geerlingguy.redis
#删除galaxy
ansible-galaxy remove geerlingguy.redis

常用模块

2015年底270多个模块,2016年达到540个,2018年01月12日有1378个模块,2018年07月15日1852个模块,2019年05月25日(ansible2.7.10)时2080个模块,2020年03月02日有3387个模块,2025年06月21日有7736个,虽然模块众多,但最常用的模块也就2,30个而已,针对特定业务只用10几个模块
常用模块帮助文档参考:https://docs.ansible.com/ansible/latest/module_plugin_guide/index.html

Command

功能:在远程主机执行命令,为 ansible 的默认模块,可省略 -m 选项
注意:此命令不支持$VARNAME <> | ; & 等,用 shell 模块实现
范例:

# 查看 ansible 使用的默认模块
[root@ansible ~]# cat /etc/ansible/ansible.cfg | grep 'module_name'
;module_name=command

[root@ansible ~]# ansible all -m command -a 'hostname'
192.168.110.136 | CHANGED | rc=0 >>
host2
192.168.110.132 | CHANGED | rc=0 >>
host1
192.168.110.129 | CHANGED | rc=0 >>
ansible
或:
[root@ansible ~]# ansible all -a 'hostname'

Shell

功能:和 command 相似,用 shell 执行命令(完美适配 Linux 命令)
范例:

[root@ansible ~]# ansible all -m shell -a "mkdir /data && echo Hellow World! > /data/hello.txt"
192.168.110.136 | CHANGED | rc=0 >>

192.168.110.129 | CHANGED | rc=0 >>

192.168.110.132 | CHANGED | rc=0 >>

[root@ansible ~]# ansible all -m shell -a "cat /data/hello.txt"
192.168.110.136 | CHANGED | rc=0 >>
Hellow World!
192.168.110.132 | CHANGED | rc=0 >>
Hellow World!
192.168.110.129 | CHANGED | rc=0 >>
Hellow World!

[root@ansible ~]# ansible all -m shell -a 'echo $HOSTNAME'
192.168.110.136 | CHANGED | rc=0 >>
host2
192.168.110.132 | CHANGED | rc=0 >>
host1
192.168.110.129 | CHANGED | rc=0 >>
ansible

# -vvv 显示执行的详细信息
[root@ansible ~]# ansible all -vvv -m shell -a 'pwd' > ansible.log
# 查看执行的信息中,最后 ansible 会删除/root/.ansible/tmp/目录中执行时的文件
[root@ansible ~]# cat ansible.log | grep 'rm -f -r'
<192.168.110.136> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o 'ControlPath="/root/.ansible/cp/7708d1067a"' 192.168.110.136 '/bin/sh -c '"'"'rm -f -r /root/.ansible/tmp/ansible-tmp-1750516555.2640955-231392-54371291020814/ > /dev/null 2>&1 && sleep 0'"'"''
<192.168.110.129> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o 'ControlPath="/root/.ansible/cp/6d9303b522"' 192.168.110.129 '/bin/sh -c '"'"'rm -f -r /root/.ansible/tmp/ansible-tmp-1750516555.355576-231393-47609501383121/ > /dev/null 2>&1 && sleep 0'"'"''
<192.168.110.132> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o 'ControlPath="/root/.ansible/cp/0d0972515f"' 192.168.110.132 '/bin/sh -c '"'"'rm -f -r /root/.ansible/tmp/ansible-tmp-1750516555.3586736-231396-183365063470160/ > /dev/null 2>&1 && sleep 0'"'"''

Script

功能:在远程主机上运行 ansible 服务器上的脚本(无需拷贝脚本到远端主机、无需单独配置脚本权限)
范例:

[root@ansible ~]# echo "uname -a" > test.sh

[root@ansible ~]# ansible all -m script -a 'test.sh'
192.168.110.136 | CHANGED => {
    "changed": true,
    "rc": 0,
    "stderr": "Shared connection to 192.168.110.136 closed.\r\n",
    "stderr_lines": [
        "Shared connection to 192.168.110.136 closed."
    ],
    "stdout": "Linux host2 3.10.0-1160.el7.x86_64 #1 SMP Mon Oct 19 16:18:59 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux\r\n",
    "stdout_lines": [
        "Linux host2 3.10.0-1160.el7.x86_64 #1 SMP Mon Oct 19 16:18:59 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux"
    ]
}
192.168.110.129 | CHANGED => {
    "changed": true,
    "rc": 0,
    "stderr": "Shared connection to 192.168.110.129 closed.\r\n",
    "stderr_lines": [
        "Shared connection to 192.168.110.129 closed."
    ],
    "stdout": "Linux ansible 5.14.0-503.14.1.el9_5.x86_64 #1 SMP PREEMPT_DYNAMIC Fri Nov 15 12:04:32 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux\r\n",
    "stdout_lines": [
        "Linux ansible 5.14.0-503.14.1.el9_5.x86_64 #1 SMP PREEMPT_DYNAMIC Fri Nov 15 12:04:32 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux"
    ]
}
192.168.110.132 | CHANGED => {
    "changed": true,
    "rc": 0,
    "stderr": "Shared connection to 192.168.110.132 closed.\r\n",
    "stderr_lines": [
        "Shared connection to 192.168.110.132 closed."
    ],
    "stdout": "Linux host1 5.14.0-503.14.1.el9_5.x86_64 #1 SMP PREEMPT_DYNAMIC Fri Nov 15 12:04:32 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux\r\n",
    "stdout_lines": [
        "Linux host1 5.14.0-503.14.1.el9_5.x86_64 #1 SMP PREEMPT_DYNAMIC Fri Nov 15 12:04:32 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux"
    ]
}

Copy

功能:从 ansible 服务器主控端复制文件到 远程主机

# 如目标存在,默认覆盖,此处指定先备份
ansible all -m copy -a "src=/root/test.sh dest=/tmp/test1.sh owner=junlan mode=600 backup=yes"

# 指定内容,直接生成目标文件
ansible all -m copy -a "content='Hello World\nHello World2' dest=/tmp/test.txt"

# 将/data 目录一起复制,注意 /data 后面没有/
ansible all -m copy -a "src=/data dest=/backup"

# 只复制 /data 下的文件,不包括 /root 目录自身,注意 /data 后面有/
ansible websrvs -m copy -a "src=/etc/ dest=/backup"

Fetch

功能:从 远程主机 提取文件至 ansible 的主控端,和 copy 相反(不支持目录)
范例:

ansible all -m fetch -a "src=/etc/os-release dest=/backup/"
[root@ansible ~]# tree /backup
/backup
├── 192.168.110.129
│   └── etc
│       └── os-release
├── 192.168.110.132
│   └── etc
│       └── os-release
├── 192.168.110.136
│   └── etc
│       └── os-release
└── data
    └── hello.txt

File

功能:设置文件属性,对文件的操作

# 创建文件
ansible all -m file -a "path=/data/file.log state=touch mode=000 owner=junlan"

# 创建目录
ansible all -m file -a "path=/data/folder state=directory"

# 删除目录
ansible all -m file -a "path=/data/folder state=absent"

# 创建软链接
ansible all -m file -a "src=/data/hello.txt state=link dest=/data/hello.txt.link"
[root@ansible ~]# ansible all -m shell -a "ls -l /data/"
192.168.110.136 | CHANGED | rc=0 >>
总用量 4
----------. 1 junlan root  0 6月  21 23:22 file.log
drwxr-xr-x. 2 root   root  6 6月  21 23:25 folder
-rw-r--r--. 1 root   root 14 6月  21 22:29 hello.txt
192.168.110.129 | CHANGED | rc=0 >>
总用量 4
----------. 1 junlan root  0  6月 21 23:22 file.log
drwxr-xr-x. 2 root   root  6  6月 21 23:25 folder
-rw-r--r--. 1 root   root 14  6月 21 22:29 hello.txt
192.168.110.132 | CHANGED | rc=0 >>
总用量 4
----------. 1 junlan root  0  6月 21 23:22 file.log
drwxr-xr-x. 2 root   root  6  6月 21 23:25 folder
-rw-r--r--. 1 root   root 14  6月 21 22:29 hello.txt

unarchive

功能:解包解压缩工
实现有两种用法:
1、将ansible主机上的压缩包传到远程主机后解压缩至特定目录,设置copy=yes
2、将远程主机上的某个压缩包解压缩到指定路径下,设置copy=no
常用参数:

  • copy:默认为 yes,当 copy=yes,拷贝的文件是从 ansible 主机复制到远程主机上,如果设置为copy=no,则在远程主机上寻找 src 源文件
  • remote_src:和 copy 功能一样且互斥,yes 表示在远程主机,不在 ansible 主机,no 表示文件在ansible 主机上
  • src:源路径,可以是 ansible 主机上的路径,也可以是远程主机上的路径,如果是远程主机上的路径,则需要设置 copy=no
  • dest:远程主机上的目标路径
  • mode:设置解压缩后的文件权限
# 创建压缩包
tar Jcvf data.xz /data
# 将 ansible 主机上的 data.xz 文件解压到目标主机的 /tmp 目录
ansible all -m unarchive -a 'src=data.xz dest=/tmp owner=junlan'

# 将文件拷贝到远程主机
ansible all -m copy -a 'src=/root/data.xz dest=/tmp'
# 在远程主机上将 /tmp/data.xz 解压到 /tmp 目录
ansible all -m unarchive -a 'src=/tmp/data.xz dest=/tmp owner=junlan copy=no'

# 原路径也可以是互联网路径
ansible all -m unarchive -a src=https://example.com/example.zip dest=/data copy=no'

Archive

功能:打包压缩保存到被管理节点
范例:

ansible all -m archive -a 'path=/var/log/ dest=/data/log.tar.bz2 format=bz2 owner=junlan mode=0600'

Hostname

功能:管理主机名
范例:

ansible node1 -m hostname-a "name=websrv"
ansible 10.0.0.18 -m hostname -a 'name=node18.magedu.com'

DNF/YUM

功能:管理软件包,只支持 RHEL,CentOS,Fedora;Ubuntu 需要用 apt 模块

# 安装 iotop 和 cowsay 软件
ansible all -m dnf -a 'name=iotop,cowsay'

# 卸载 iotop 和 cowsay 软件
ansible all -m dnf -a 'name=iotop,cowsay state=absent'
# cowsay 软件包在 epel 有
[root@ansible ~]# cowsay I Love You!
 _____________
< I Love You! >
 -------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

Service

功能:管理服务
范例:

ansible all -m service -a 'name=httpd state=started enabled=yes'
ansible all -m service -a ' name=httpd state=stopped'
ansible all -m service -a 'name=httpd state=reloaded'
ansible all -m shell -a "sed -i's/AListen 80/Listen 8080/' /etc/httpd/conf/httpd. conf"
ansible all -m service -a 'name=httpd state=restarted'

User

功能:管理用户
范例:

#创建用户
ansible all -m user -a 'name=user1 comment="test user" uid=2048 home=/app/user1
group=root'
ansible all -m user -a 'name=nginx comment=nginx uid=88 group=nginx groups="root, daemon"
she11=/sbin/nologin system=yes create_home=no home=/data/nginx non_unique=yes'
#remove=yes表示删除用户及家目录等数据,默认remove=no
ansible all-m user -a 'name=nginx state=absent remove=yes'

Group

功能:管理组
范例:

#创建组
ansible all -m group -a 'name=nginx gid=88 s system=yes'
#删除组
ansible all -m group -a 'name=nginx state=absent'

Lineinfile

ansible在使用 sed 进行替换时,经常会遇到需要转义的问题,而且 ansible 在遇到特殊符号进行替换时,存在问题,无法正常进行替换。在 ansible 自身提供了两个模块:lineinfile 和 replace 模块,可以方便的进行替换

功能:相当于sed,可以修改文件内容

ansible 192.168.110.132 -m lineinfile -a "path=/etc/selinux/config regexp='^SELINUX=' line='SELINUX=disable'"

Setup

setup 模块来收集主机的系统信息,这些 facts 信息可以直接以变量的形式使用,但是如果主机较多,会影
响执行速度,可以使用 gather_facts: no 来禁止 Ansible 收集 facts 信息
范例:

# 输出所有信息
ansible all -m setup

# 只输出主机名 
ansible all -m setup -a "filter=ansible_hostname"

# 只输出python版本
ansible all -m setup -a "filter=ansible_python_version"

ansible all-m setup-a"filter=ansible_domain"
ansible all -m setup -a "filter=ansible_memtotal_mb"
ansible all -m setup -a "filter=ansible_memory_mb"
ansible all -m setup -a "filter=ansible_memfree_mb"
ansible all -m setup -a "filter=ansible_os_family"
ansible all -m setup -a "filter=ansible_distribution_major_version"
ansible all -m setup -a "filter=ansible_distribution_version"
ansible all-m setup-a"filter=ansible_processor_vcpus"
ansible all-m setup -a "filter=ansible_all_ipv4_addresses"
ansible all -m setup -a "filter=ansible_architecture"
ansible all -m setup -a "filter=ansible_processor*"

Playbook

playbook 剧本是由一个或多个 “play” 组成的列表,采用YAML语言编写

play的主要功能在于将预定义的一组主机,装扮成事先通过 ansible 中的 task 定义好的角色。Task实际是调用 ansible 的一个 module,将多个 play 组织在一个playbook中,即可以让它们联合起来,按事先编排的机制执行预定义的动作。

YAMI

YAML(Yet Another Markup Language,仍是一种标记语言)是一个可读性高的用来表达资料序列的格式。

YAML参考了其他多种语言,包括:XML、C、Python、Perl 以及电子邮件格式 RFC2822 等。Clark Evans 在2001 年在首次发表了这种语言,另外 Ingy dot Net 与 Oren Ben-Kiki 也是这语言的共同设计者,目前很多软件中采有此格式的文件,如:ubuntu,anisble,docker,k8s等。YAML:YAML Ain’t Markup Language,即 YAML不是XML。YAML 官方网站:https://yaml.org/

YAML语言特性

  • 可读性好
  • 脚本语言的交互性好
  • 使用实现语言的数据类型
  • 有一个一致的信息模型
  • 易于实现
  • 可以基于流来处理
  • 表达能力强,扩展性好

语法简介

YAML 的语法和其他高阶语言类似,并且可以简单表达清单、散列表、标量等数据结构。其结构(Structure)通过空格来展示,序列(Sequence)里的项用“-“来代表,Map里的键值对用”:"分隔。

  • 在单一文件第一行,用连续三个连字号 “-” 开始,还有选择性的连续三个点号“…” 用来表示文件的结尾
  • 次行开始正常写 Playbook 的内容,一般建议写明该 Playbook 的功能
  • 使用 # 号注释代码
  • 缩进必须是统一的,不能空格和 tab 混用
  • 缩进的级别必须是一致,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行来实现
  • 内容区别大小写,key/value 的值均大小写敏感
  • 多个 key/value 可同行写也可换行写,同行使用 , 分隔
  • 一个 name 只能包括一个 task
List 列表

列表由多个元素组成,每个元素放在不同行,且元素前均使用“-"打头,或者将所有元素用[]括起来放在同一行
范例:

#不同行,行以-开头,后面有一个空格
#A list of tasty fruitsI
- Apple
- Orange
- strawberry
- Mango

#同一行
[Apple, orange, strawberry, Mango]
Dictionary 字典

字典由多个key与value构成,key和value之间用:分隔,所有k/v可以放在一行,或者每个k/v分别放在不同行
范例:

#不同行
# An employee record
name:ExampleDeveloper
job:Developer
ski11:Elite

#同一行,也可以将key:value放置于花括号中进行表示,用,分隔多个key:value
# An employee record
{name:"Example Developer", job: "Developer", ski11:"Elite"}}

三种常见的数据格式

  1. XML(Extensible Markup Language):可扩展标记语言,可用于数据交换和配置
  2. JSON(JavaScript Object Notation):JavaScript 对象表记法,主要用来数据交换或配置,不支持注释,常用于网络传输
  3. YAML(YAML Ain’t Markup Language YAML):不是一种标记语言,大小写敏感,不支持 tab,常用于配置文件

可以用工具互相转换,参考网站:
https://www.json2yaml.com/
http://www.bejson.com/json/json2yaml/

Playbook核心元素

一个 playbook 中由一个列表组成,到表的元素类型如下:

  • Hosts 执行的远程主机列表
  • Tasks 任务集,由多个 task 的元素组成的列表实现,每个 task 是一个字典
  • Variables 内置变量或自定义变量在 playbook 中调用
  • Templates 模板,可替换模板文件中的变量并实现一些简单逻辑的文件
  • Handlers 和 notify 结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
  • tags 标签指定某条任务执行,用于选择运行 playbook 中的部分代码。ansible 具有幕等性,因此会自动跳过;没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地长。此时,如果确信其没有变化,就可以通过 tags 跳过此些代码片断
  • 一个完整的代码块功能需最少元素需包括name和task,一个name只能包括一个task

hosts 组件

Hosts:playbook 中的每一个play的目的都是为了让特定主机以某个指定的用户身份执行任务。hosts用于指定要执行指定任务的主机,须事先定义在主机清单中。写法如下:

one.example.com
one.example.com:two.example.com
192.168.1.50
192.168.1.*
Websrvs:dbsrvs  #或者,两个组的并集
Websrvs:&dbsrvs  #与,两个组的交集
webservers:!phoenix  #在websrvs组,但不在dbsrvs组
- hosts: websrvs:appsrvs

remote_user组件

remote_user:可用于Host和task中。也可以通过指定其通过sudo的方式在远程主机上执行任务,其可用于play全局或某任务;此外,甚至可以在sudo时使用sudo_user指定sudo时切换的用户

- hosts: websrvs
  remote_user: root

  tasks:
    - name: test connection
  ping:
  remote_user:magedu
  sudo:yes    #默认sudo为root
  sudo_user:junlan    #sudo为junlan

task列表和action组件

play 的主体部分是task list,task list 中有一个或多个 task,各个 task 按次序逐个在 hosts 中指定的所有主机上执行,即在所有主机上完成第一个 task 后,再开始第二个task

task 目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致

每个 task 都应该有其 name,用于 playbook 的执行结果输出,建议其内容能清晰地描述任务执行步骤。如果未提供name,则 action 的结果将用于输出

task两种格式

(1) action:module arguments

(2) module:arguments 建议使用
注意:shell 和 command 模块后面跟命令,而非 key=value

playbook基本用法案例

yaml 文件

# install_http.yaml
---
- hosts: rocky
  remote_user: root

  tasks:
    - name: 安装 nginx
      dnf: name=nginx
    - name : start nginx
      service: name=nginx state=started enabled=yes

执行文件

# 检测 yaml 文件语法是否正确
ansible-playbook -C install_http.yaml

# 执行 playbook
ansible-playbook -C install_http.yaml

playbook命令

格式

ansible-playbook <filename.yml>... [options]

# 例:
ansible-playbook --list-hosts install_http.yaml

常见选项

-C--check  #只检测可能会发生的改变,但不真正执行操作
--1ist-hosts  #列出运行任务的主机
--list-tags  #列出tag
--1ist-tasks  #列出task
--1imit 主机列表  #只针对主机列表中的特定主机执行
-V-VV-VVV  #显示过程

handlers和notify用法

Handlers 本质是task list,类似于MySQL中的触发器触发的行为,其中的 task 与前述的 task 并没有本质上的不同,主要用于当关注的资源发生变化时,才会采取一定的操作。而 Notify 对应的 action 可用于在每个 play 的最后被触发,这样可避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作。在 notify 中列出的操作称为 handler,即 notify 中调用 handler 中定义的操作

案例:

# install_httpd.yaml
- hosts: rocky
  remote_user: root
  gather_facts: no 
  
  tasks:
    - name: 安装Apache
      dnf: name=httpd state=present
    #- name: 修改配置文件
    #  copy: src=files/httpd.conf dest=/etc/httpd/conf/
    - name : modify config
      Lineinfile: path=/etc/httpd/conf/httpd.conf regexp='^Listen' Line='Listen 8080'
    #- name: mkdir website dir
    #  file:path=/data/html state=directory
    #- name: web html
    #  copy:src=files/index.html dest=/data/html/
    - name: start service
      service: name=httpd state=started enabled=yes

变量用法

使用已有的变量
# var1.yaml
- hosts: rocky
  remote_user: root
  gather_facts: yes

  tasks:
    - name: create log file
      file: name=/data/{{ ansible_nodename }}-{{ ansible_distribution_major_version  }}.log state=touch owner=junlan mode=600
使用自定义变量

案例1:通过-e 参数传递变量

[root@ansible ~]# cat var2.yaml
- hosts: rocky
  remote_user: root
  tasks:
    - name: 安装指定的软件包
      dnf: name={{ pkname }} state=present
ansible-playbook -e pkname=cowsay var2.yaml
[root@ansible ~]# cat var3.yaml
- hosts: rocky
  remote_user: root
  vars:
    - username: user1
    - groupname: group1

  tasks:
    - name: create group
      group: name={{ groupname }}
    - name: create user
      user: name={{ username }} group={{ groupname }}
ansible-playbook var3.yaml

案例3:将变量存放在单独配置文件中

# vars.yaml
---
package_name: mariadb-server
service_name: mariadb

# cat var4.yaml
---
- hosts: rocky
  remote_user: root
  vars_files:
     - /root/vars.yaml

  tasks:
    - name: install package
      dnf: name={{ package_name }}
      tags: install
    - name: start service
      service: name={{ service_name }} state=started enabled=yes
ansible-playbook var4.yaml

4.6.5主机清单文件中定义变量
4.6.5.1主机变量
在inventory主机清单文件中为指定的主机定义变量以便于在playbook中使用
范例:

[websrvs]
www1.magedu.com http_port=80 maxRequestsperchi1d=808
www2.magedu.com http_port=8080 maxRequestsperchild=909

4.6.5.2组(公共)变量
在inventory主机清单文件中赋予给指定组内所有主机上的在playbook中可用的变量,如果和主机变是同名,优
级低于主机变量
范例:

[websrvs]
www1.magedu.com
www2.magedu.com
[websrvs:vars] I
ntp_server=ntp.magedu.com
nfs_server=nfs.magedu.com

Template(模板)模块

jinja2语言

jinjia2

jinja2 语言使用字面量,有下面形式:

  • 字符串:使用单引号或双引号
  • 数字:整数,浮点数
  • 列表:[item1,item2,…]
  • 元组:(item1,item2,…)
  • 字典:{key1:value1,key2:value2,…}
  • 布尔型:true/false
  • 算术运算:+,-,*,/,//,%,**
  • 比较操作:==,!=,>,>,<,<=
  • 逻辑运算:and,or,not
  • 流表达式:For,If,When

字面量:

表达式最简单的形式就是字面量。字面量表示诸如字符串和数值的 Python 对象。如"Hello World" 双引号或单引号中间的一切都是字符串。无论何时你需要在模板中使用一个字符串(比如函数调用、过滤器或只是包含或继承一个模板的参数),如42,42.23数值可以为整数和浮点数。如果有小数点,则为浮点数,否则为整数。在Python 里,42和42.0是不一样的

算术运算:
Jinja允许用计算值。支持下面的运算符
十:把两个对象加到一起。通常对象是素质,但是如果两者是字符串或列表,你可以用这种方式来衔接它们。无论
如何这不是首选的连接字符串的方式!连接字符串见~运算符。{1+1}等于2
-:用第一个数减去第二个数。{3-2}等于1
/:对两个数做除法。返回值会是一个浮点数。{1/2}等于{0.5}
//:对两个数做除法,返回整数商。{20//7}等于2
%:计算整数除法的余数。{11%7}等于4工
:用右边的数乘左边的操作数。{22}会返回4。也可以用于重复一个字符串多次。{一*80}会打印80
个等号的横条
** : 取左操作数的右操作数次雾。{[2**3}}会返回8

逻辑运算符
对于if语句,在for过滤或if表达式中,它可以用于联合多个表达式
and如果左操作数和右操作数同为真,返回true
or 如果左操作数和右操作数有一个为真,返回true
not对一个表达式取反
(expr)表达式组
true/false true永远是true,而false始终是false

template

template 可以根据和参考模块文件,动态生成相类似的配置文件;template 文件必须存放于 templates 目录下,且命名为 .j2 结尾,yaml/yml 文件需和 templates 目录平级,目录结构如下示例:

[root@localhost ansible_data]# tree /ansible_data/
/ansible_data/
├── templates
│   └── nginx.conf.j2
└── temp_nginx.yaml
案例1:

根据机器的CPU数量,批量修改nginx配置文件 worker_processes 的值

# 获取机器的 cpu 核数
[root@localhost ansible_data]# ansible all -m setup -a "filter=ansible_processor_vcpus"
192.168.110.136 | SUCCESS => {
    "ansible_facts": {
        "ansible_processor_vcpus": 1,
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false
}
192.168.110.129 | SUCCESS => {
    "ansible_facts": {
        "ansible_processor_vcpus": 2,
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false
}
192.168.110.132 | SUCCESS => {
    "ansible_facts": {
        "ansible_processor_vcpus": 2,
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false
}

# 生成 nginx 配置文件
[root@localhost ansible_data]# dnf install nginx -y
# 创建 templates 目录
[root@localhost ansible_data]# mkdir templates
# 将配置文件拷贝到 templates 目录,并重名为 .j2 结尾的文件
[root@localhost ansible_data]# cp /etc/nginx/nginx.conf templates/nginx.conf.j2
# 修改配置文件,将 worker_processes 的 auto  改为:{{ ansible_processor_vcpus**2 }}
[root@localhost ansible_data]# vim templates/nginx.conf.j2
user nginx;
#worker_processes auto;
worker_processes {{ ansible_processor_vcpus**2 }};
......

temp_nginx.yaml

---
# temp_nginx.yaml
- hosts: rocky
  remote_user: root

  tasks:
    - name: install nginx
      dnf: name=nginx
    - name: template config to remote hosts
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
    - name: start service
      service: name=nginx state=started enabled=yes
# 执行
[root@localhost ansible_data]# ansible-playbook temp_nginx.yaml

PLAY [rocky] ************************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************
ok: [192.168.110.129]
ok: [192.168.110.132]

TASK [install nginx] ****************************************************************************************************************************************
ok: [192.168.110.129]
changed: [192.168.110.132]

TASK [template config to remote hosts] **********************************************************************************************************************
changed: [192.168.110.129]
changed: [192.168.110.132]

TASK [start service] ****************************************************************************************************************************************
changed: [192.168.110.129]
changed: [192.168.110.132]

PLAY RECAP **************************************************************************************************************************************************
192.168.110.129            : ok=4    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
192.168.110.132            : ok=4    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0


# 查看配置文件 worker_processes 为 4(2个cpu*2=4)
[root@localhost ansible_data]# ansible rocky -m shell -a 'cat /etc/nginx/nginx.conf | grep worker_processe'
192.168.110.129 | CHANGED | rc=0 >>
#worker_processes auto;
worker_processes 4;
192.168.110.132 | CHANGED | rc=0 >>
#worker_processes auto;
worker_processes 4;

# 查看确实是创建了 4 个 worker 进程
[root@localhost ansible_data]# ansible rocky -m shell -a 'ps -aux | grep nginx'
192.168.110.129 | CHANGED | rc=0 >>
root       47180  0.0  0.0  11236  1596 ?        Ss   20:53   0:00 nginx: master process /usr/sbin/nginx
nginx      47181  0.0  0.2  15560  5052 ?        S    20:53   0:00 nginx: worker process
nginx      47182  0.0  0.2  15560  5052 ?        S    20:53   0:00 nginx: worker process
nginx      47183  0.0  0.2  15560  5052 ?        S    20:53   0:00 nginx: worker process
nginx      47184  0.0  0.2  15560  5052 ?        S    20:53   0:00 nginx: worker process

192.168.110.132 | CHANGED | rc=0 >>
root        9867  0.0  0.0  11236  1468 ?        Ss   20:53   0:00 nginx: master process /usr/sbin/nginx
nginx       9868  0.0  0.2  15560  5052 ?        S    20:53   0:00 nginx: worker process
nginx       9869  0.0  0.2  15560  5052 ?        S    20:53   0:00 nginx: worker process
nginx       9870  0.0  0.2  15560  5052 ?        S    20:53   0:00 nginx: worker process
nginx       9871  0.0  0.2  15560  5052 ?        S    20:53   0:00 nginx: worker process


案例2:

when 语句,可以实现条件测试。如果需要根据变量、facts 或此前任务的执行结果来做为某 task 执行与否的前提时要用到条件测试,通过在 task 后添加 when 子句即可使用条件测试,jinja2 的语法格式

批量重启 Centos 系统

# temp_when.yaml
---
- hosts: all
  remote_user: root
  tasks:
    - name: "Reboot Centos System"
      command: reboot
      when: ansible_distribution == "CentOS"
# 执行playbook
[root@localhost ansible_data]# ansible-playbook temp_when.yaml

PLAY [all] **************************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************
ok: [192.168.110.136]
ok: [192.168.110.132]
ok: [192.168.110.129]

TASK [Reboot Centos System] *********************************************************************************************************************************
skipping: [192.168.110.129]
skipping: [192.168.110.132]
fatal: [192.168.110.136]: FAILED! => {"msg": "Failed to connect to the host via ssh: kex_exchange_identification: read: Connection reset by peer\r\nConnection reset by 192.168.110.136 port 22"}

PLAY RECAP **************************************************************************************************************************************************
192.168.110.129            : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
192.168.110.132            : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
192.168.110.136            : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

# 验证 centos 7 系统确实被重启了
[root@localhost ~]# hostnamectl | grep System
  Operating System: CentOS Linux 7 (Core)
[root@localhost ~]# uptime
 21:21:02 up 0 min,  1 user,  load average: 3.18, 0.77, 0.25

解决管理节点过多导致的超时问题

默认情况下,Ansible 将尝试并行管理 playbook中所有的机器。对于滚动更新用例,可以使用 serial 关键字定义 Ansible 一次要管理多少主机,还可以将 serial 关键字指定为百分比,表示每次并行执行的主机数占总数的比例。
范例:

vim test_serial.ym7
- hosts:a11
  serial:2 # 每次只同时处理 2 个主机
  #serial:"20%" #每次只同时处理20%的主机
  gather_facts:FaTse
  
  tasks :
    - name : task one
      comand:hostname
	- name : task two
  	  command:hostname

roles 角色

角色是 ansible 自 1.2 版本引入的新特性,用于层次性、结构化地组织 playbook。roles 能够根据层次型结构自动装载变量文件、tasks 以及 handlers 等。要使用 roles 只需要在 playbook 中使用 include 指令即可。

简单来讲,roles 就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷地include 它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中
运维复杂的场景:建议使用roles,代码复用度高
roles:多个角色的集合,可以将多个的 role,分别放至 roles 目录下的独立子目录中

roles/
mysql/
httpd/
nginx/
redis/

galaxy

https://galaxy.ansible.com/

[root@localhost ansible_data]# ansible-galaxy list
# /usr/share/ansible/roles
# /etc/ansible/roles
[WARNING]: - the configured path /root/.ansible/roles does not exist.

http://ansible.com.cn/ # 中文站点

http://galaxy.ansible.com
https://galaxy.ansible.com/explore#/
http://github.com/
https://github.com/ansible/ansible
https://github.com/ansible/ansible-examples

评论