Ansible学习
0、常见的自动化运维工具
- Anaible:python,Agentless,中小型环境
- Saltstack:python 一般需要部署agent,执行效率比较高
- Puppet:ruby,功能强大、配置复杂、重型、适合大型环境
- Fabric: python,agentless
- Chef:ruby,国内应用少
- Cfengine
- func
一、概述
Ansible
是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。
Ansible特点:
- 部署简单,只需要在主控端部署Ansible环境,被控端无需作任何操作
- 默认使用SSH协议对设备进行管理
- 主从集中化管理
- 配置简单、功能强大、扩展性强
- 支持API及自定义模块、可以通过Python轻松扩展
- 通过Playbooks来定制强大的配置、状态管理
- 对云计算平台、大数据都有很好的支持
官方文档:https://docs.ansible.com/ansible/latest/
GitHub地址:https://github.com/ansible/ansible
二、Ansible 架构
上图为ansible的基本架构,从上图可以了解到其由以下部分组成:
- 核心:ansible
- 核心模块(Core Modules):这些都是ansible自带的模块
- 扩展模块(Custom Modules):如果核心模块不足以完成某种功能,可以添加扩展模块
- 插件(Plugins):完成模块功能的补充
- 剧本(Playbooks):ansible的任务配置文件,将多个任务定义在剧本中,由ansible自动执行
- 连接插件(Connectior Plugins):ansible基于连接插件连接到各个主机上,虽然ansible是使用ssh连接到各个主机的,但是它还支持其他的连接方法,所以需要有连接插件
- 主机清单(Host Inventory):定义ansible管理的主机
三、Ansible 工作原理
-
在ANSIBLE管理体系中,存在"管理节点"和"被管理节点"两种角色。
-
被管理节点通常被称为"资产" 。
-
在管理节点上,Ansible将AdHoc或PlayBook转换为Python脚本并通过SSH将这些Python脚本传递到被管理服务器上,在被管理服务器上一次执行,并实时的将结果返回。
从上面的图上可以了解到:
- 管理端支持
local 、ssh、zeromq
三种方式连接被管理端,默认使用基于ssh的连接,这部分对应上面架构图中的连接模块; - 可以按应用类型等方式进行
Host Inventory(主机清单)
分类,管理节点通过各类模块实现相应的操作,单个模块,单条命令的批量执行,我们可以称之为ad-hoc; - 管理节点可以通过playbooks 实现多个task的集合实现一类功能,如web服务的安装部署、数据库服务器的批量备份等。playbooks我们可以简单的理解为,系统通过组合多条ad-hoc操作的配置文件 。
四、Ansible安装与配置
环境示例图
先决条件
管理节点
确保存在OpenSSH
确保Python版本 >= 2.6
确保安装Ansible
被管理节点
确保存在OpenSSH
确保Python版本 >= 2.4 //若为2.4版本,确保安装了python-samplesjson扩展
不需要安装Ansible
安装命令
-
yum方式
yum install epel-release # 第三方的yum源 yum install ansible
-
pip方式
这里使用系统自带的python2的环境
如果系统安装的是pip3,可以直接使用pip3安装Ansible
yum install epel-release # 第三方的yum源 yum install python2-pip pip install ansible
-
查看版本
[root@test44 ~]# ansible --version ansible 2.9.27 config file = /etc/ansible/ansible.cfg configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules'] ansible python module location = /usr/lib/python2.7/site-packages/ansible executable location = /usr/bin/ansible python version = 2.7.5 (default, Oct 30 2018, 23:45:53) [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)]
-
开启日志记录
配置文件:
/etc/ansible/ansible.cfg
去掉注释 #log_path = /var/log/ansible.log
-
去掉第一次连接ssh ask确认
# 第一种(推荐) vi /etc/ansible/ansible.cfg # host_key_checking = False # 第二种 vi /etc/ssh/ssh_config StrictHostKeyChecking ask ==> StrictHostKeyChecking no
建立SSH信任关系
-
管理节点(ansible)中创建密钥对
ssh-keygen -t rsa
-
本地的公钥传输到被管理节点
每个被管理节点都需要传递
过程中被管理节点可以是在
/etc/hosts
配置的主机名或者是IP地址ssh-copy-id root@192.168.1.1
主机连通性测试
修改默认配置文件在/etc/ansible/hosts
,格式为ini,添加主机地址,同时定义一个webservers组,其中包含主机地址,如下
sun25
sun48
sun38
[webservers]
sun48
sun38
用ping模块对单台主机进行ping操作
[root@sun25 ~]# ansible sun25 -m ping
sun25 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
对webserver组进行ping操作
[root@sun25 ~]# ansible webservers -m ping
sun48 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
sun38 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
出现上述结果表示Ansible正确工作,主机连通测试成功
提示
这里测试时在控制主机与被管节点之间配置了SSH证书信任。如果没有用证书认证,则需要在执行Ansible命令时添加-k参数,在提示“SSH password:”时输入root(默认)账号密码
比如,在/etc/ansible/hosts 添加一个没有配置免密的主机IP,然后执行ping
[root@sun25 ~]# ansible 192.168.2.191 -m ping
192.168.2.191 | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: Warning: Permanently added '192.168.2.191' (ECDSA) to the list of known hosts.\r\nPermission denied (publickey,gssapi-keyex,gssapi-with-mic,password).",
"unreachable": true
}
[root@sun25 ~]# ansible 192.168.2.191 -m ping -k
SSH password:
192.168.2.191 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
实际生产环境中,大多倾向于使用Linux普通用户账号进行连接并通过sudo命令实现root权限。
在远程主机创建用户 ansible
,并设置sudo
useradd ansible
passwd ansible # 密码为ansible
echo ansible ALL=(ALL) NOPASSWD:ALL >>/etc/sudoers
在控制端执行
Ansible首先提示您键入SSH密码(
-k
),然后将以root用户的身份(--become
)在目标主机上执行ping模块
[root@sun25 ~]# ansible 192.168.2.191 -m ping -k --become
SSH password: # 此处输入ansible密码
192.168.2.191 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
-k
: 表示Ansible提示输入SSH密码,在没有配置免密的情况下
--become
: 尝试以其他用户的身份运行命令
批量执行命令
在自定义路径下创建资源清单文件
[root@sun25 src]# pwd
/usr/local/src
[root@sun25 src]# cat inventory.cfg
sun25
sun48
sun38
[dstore]
sun48
sun25
使用ansible的shell模块在dstore组显示'hello,ansible!'
[root@sun25 src]# ansible dstore -m shell -a '/bin/echo hello, ansible!' -i inventory.cfg
sun25 | CHANGED | rc=0 >>
hello, ansible!
sun48 | CHANGED | rc=0 >>
hello, ansible!
也可以用command模块,得到类似结果
ansible dstore -m command -a '/bin/echo hello, ansible!' -i inventory.cfg
这两个模块的主要区别在于它们处理环境变量、重定向和管道的方式
以下命令使用shell模块就可以成功运行,而使用command模块则不行
```
ansible dstore -m shell -a 'echo $HOME' -i inventory.cfg
```
五、Ansible的七个命令
安装完ansible后,发现ansible一共为我们提供了七个指令:
ansible
、ansible-doc
、ansible-galaxy
、ansible-lint
、ansible-playbook
、ansible-pull
、ansible-vault
。这里我们只查看usage部分,详细部分可以通过 "指令 -h" 的方式获取。
ansible
ansible是指令核心部分,其主要用于执行ad-hoc命令,即单条命令。默认后面需要跟主机和选项部分,默认不指定模块时,使用的是command
模块。不过默认使用的模块是可以在/etc/ansible/ansible.cfg
中进行修改的#module_name = command
。
ansible 192.168.182.130 -a 'date'
ansible-doc
该指令用于查看模块信息,常用参数有两个-l 和 -s
#列出所有已安装的模块ansible-doc -l
ansible-doc -l
#查看具体某模块的用法,这里如查看command模块
ansible-doc -s command
ansible-playbook
ansible-playbook
命令是使用最多的指令,其通过读取playbook 文件后,执行相应的动作,这个后面会做为一个重点来讲。
ansible-galaxy
ansible-galaxy
指令用于方便的从https://galaxy.ansible.com/ 站点下载第三方扩展模块,我们可以形象的理解其类似于centos下的yum、python下的pip或easy_install 。如下示例:
ansible-galaxy install aeriscloud.docker
ansible-lint
ansible-lint是对playbook的语法进行检查的一个工具。用法如下:
ansible-lint playbook.yml
ansible-pull
该指令使用需要谈到ansible的另一种模式,pull 模式,这和我们平常经常用的push模式刚好相反,其适用于以下场景:你有数量巨大的机器需要配置,即使使用非常高的线程还是要花费很多时间;你要在一个没有网络连接的机器上运行Anisble,比如在启动之后安装。
ansible-vault
ansible-vault
主要应用于配置文件中含有敏感信息,又不希望他能被人看到,vault可以帮你加密/解密这个配置文件,属高级用法。- 主要对于playbooks里比如涉及到配置密码或其他变量时,可以通过该指令加密,这样我们通过cat看到的会是一个密码串类的文件,编辑的时候需要输入事先设定的密码才能打开。
- 这种playbook文件在执行时,需要加上
--ask-vault-pass
参数,同样需要输入密码后才能正常执行。
六、Ansible组件介绍
Ansible Inventory
配置部署针对的主机必须先存放在Inventory里面,这样才能使用Ansible对它进行操作。默认Ansible的Inventory是一个静态的INI格式的文件/etc/ansible/hosts,当然,还可以通过ANSIBLE_HOSTS环境变量指定或者运行ansible和ansible-playbook的时候用-i参数临时设置
定义主机和主机组
192.168.2.191 ansible_ssh_pass=123456
[dstore]
sun48
sun38
[dstore_1]
192.168.2.191
192.168.2.179
192.168.2.187
[dstore_1:vars]
ansible_ssh_pass=123456 # 内置参数
[ansible:children] # 定义个组ansible,包含组dstore
dstore
多Inventory
Ansible还支持多个Inventory文件,这样我们就可以很方便地管理不同业务或者不同环境中的机器了
修改ansible.cfg配置文件
inventory = /etc/ansible/inventory # 放开注释,创建文件夹
创建不同业务的主机Inventory
[root@sun25 ansible]# tree inventory/
inventory/
├── cluster
└── dstore
cluster
[root@sun25 inventory]# cat cluster
[test]
192.168.2.191
192.168.2.179
192.168.2.187
[test:vars]
ansible_password=123456
test
[root@sun25 inventory]# cat dstore
192.168.2.25 ansible_password=123456
192.168.2.38 ansible_password=123456
192.168.2.48 ansible_password=123456
列出test组的主机列表
[root@sun25 inventory]# ansible test --list-hosts
hosts (3):
192.168.2.191
192.168.2.179
192.168.2.187
其实Ansible中的多个Inventory跟单个文件没什么区别,我们也可以容易定义或者引用多个Inventory,甚至可以把不同环境的主机或者不同业务的主机放在不同的Inventory文件里面,方便日后维护
测试
[root@sun25 inventory]# ansible test -m shell -a 'hostname'
192.168.2.191 | CHANGED | rc=0 >>
node191
192.168.2.187 | CHANGED | rc=0 >>
node187
192.168.2.179 | CHANGED | rc=0 >>
node179
静态Inventory
- 文本
动态Inventory
所有的主机列表和变量信息支持从外部拉取,比如我们可以从CMDB系统和Zabbix监控系统拉取所有的主机信息,然后使用Ansible进行管理。这样一来我们就可以很方便地将Ansible与其他运维系统结合起来
关于引用动态Inventory的功能配置起来也很简单。我们只需要把ansible.cfg文件中inventory的定义值改成一个执行脚本即可。这个脚本的内容不受任何编程语言限制,但是这个脚本使用参数时有一定的规范并且对脚本执行的结果也有要求。这个脚本需要支持两个参数:
·--list或者-l,这个参数运行后会显示所有的主机以及主机组的信息(JSON格式)。
·--host或者-H,这个参数后面需要指定一个host,运行结果会返回这台主机的所有信息(包括认证信息、主机变量等),也是JSON格式。
dy_script.py
#!/usr/bin/env python
import argparse
import json
def group():
host1 = [
"192.168.2.38",
"192.168.2.48",
"192.168.2.25"]
host2 = ['192.168.2.191',
'192.168.2.179',
'192.168.2.187']
group1 = 'dstore1'
group2 = 'dstore2'
hostdata = {
group1: {"hosts": host1},
group2: {"hosts": host2}
}
print(json.dumps(hostdata, indent=4))
def host(ip):
host1 = [
"192.168.2.38",
"192.168.2.48",
"192.168.2.25"]
host2 = ['192.168.2.191',
'192.168.2.179',
'192.168.2.187']
info_dict = {ip: {
"ansible_ssh_port": 22,
"ansible_ssh_user": "root",
"ansible_ssh_pass": "123456"
} for ip in host1 + host2}
print(json.dumps(info_dict[ip], indent=4))
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--list', help='list all hosts', action='store_true')
parser.add_argument('--host', help='list specific host')
args = vars(parser.parse_args())
if args['list']:
group()
elif args['host']:
host(args['host'])
else:
parser.print_help()
测试返回信息是否符合要求
[root@sun25 ansible]# python dy_script.py --list
{
"dstore2": {
"hosts": [
"192.168.2.191",
"192.168.2.179",
"192.168.2.187"
]
},
"dstore1": {
"hosts": [
"192.168.2.38",
"192.168.2.48",
"192.168.2.25"
]
}
}
[root@sun25 ansible]# python dy_script.py --host 192.168.2.25
{
"ansible_ssh_port": 22,
"ansible_ssh_pass": "123456",
"ansible_ssh_user": "root"
}
符合动态Inventory要求,开始测试
测试组
[root@sun25 ansible]# ansible -i dy_script.py dstore1 -m ping
192.168.2.48 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.2.25 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.2.38 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
测试IP列表
[root@sun25 ansible]# ansible -i dy_script.py 192.168.2.25,192.168.2.48 -m shell -a 'hostname'
192.168.2.25 | CHANGED | rc=0 >>
sun25
192.168.2.48 | CHANGED | rc=0 >>
sun48
内置参数
inventory变量参数
参数 | 说明 |
---|---|
ansible_ssh_host |
将要连接的远程主机名。如果与你想要设定的主机的别名不同,可以通过此变量设置。 |
ansible_ssh_port |
SSH 端口号。如果不是默认的端口号,通过此变量设置。 |
ansible_ssh_user |
默认的 SSH 用户名。 |
ansible_ssh_pass |
SSH 密码(这种方式并不安全,我们强烈建议使用 --ask-pass 或 SSH 密钥)。 |
ansible_ssh_private_key_file |
SSH 使用的私钥文件。适用于有多个密钥,而你不想使用 SSH 代理的情况。 |
ansible_ssh_common_args |
此设置附加到 sftp、scp 和 ssh 的默认命令行。 |
ansible_sftp_extra_args |
此设置附加到默认 sftp 命令行。 |
ansible_scp_extra_args |
此设置附加到默认 scp 命令行。 |
ansible_ssh_extra_args |
此设置附加到默认 ssh 命令行。 |
ansible_ssh_pipelining |
确定是否使用 SSH 管道。这可以覆盖 ansible.cfg 中得设置。 |
ansible_shell_type |
目标系统的 shell 类型。默认情况下,命令的执行使用 'sh' 语法,可设置为 'csh' 或 'fish'. |
ansible_python_interpreter |
目标主机的 python 路径。适用于的情况:系统中有多个 Python,或者命令路径不是 "/usr/bin/python",比如 *BSD,或者 /usr/bin/python。 |
ansible_*_interpreter |
这里的 "*" 可以是 ruby 或 perl 或其他语言的解释器,作用和 ansible_python_interpreter 类似。 |
ansible_shell_executable |
这将设置 ansible 控制器将在目标机器上使用的 shell,覆盖 ansible.cfg 中的配置,默认为 /bin/sh。 |
Ansible Ad-Hoc
Ansible命令都是并发执行的,默认并发数目由ansible.cfg中forks值来控制
对于运行时间长的情况,可以使用异步执行
测试并发数
[root@sun25 src]# ansible dstore -m shell -a 'hostname' -o -f 5
192.168.2.48 | CHANGED | rc=0 | (stdout) sun48
192.168.2.38 | CHANGED | rc=0 | (stdout) sun38
192.168.2.25 | CHANGED | rc=0 | (stdout) sun25
测试异步:
-P 0
的情况下会直接返回 job_id,后续可以根据id查询执行结果每台主机会产生不同的 job_id ,可以通过 async_status 模块查看异步任务的状态和
结果
[root@sun25 src]# ansible dstore -B 120 -P 0 -m shell -a 'hostname' -f 5 -o
192.168.2.48 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "ansible_job_id": "584675824408.3597548", "changed": true, "finished": 0, "results_file": "/root/.ansible_async/584675824408.3597548", "started": 1}
192.168.2.25 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "ansible_job_id": "634952074091.1171388", "changed": true, "finished": 0, "results_file": "/root/.ansible_async/634952074091.1171388", "started": 1}
192.168.2.38 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "ansible_job_id": "328579646977.1144684", "changed": true, "finished": 0, "results_file": "/root/.ansible_async/328579646977.1144684", "started": 1}
[root@sun25 src]# ansible 192.168.2.48 -m async_status -a 'jid=584675824408.3597548'
192.168.2.48 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"ansible_job_id": "584675824408.3597548",
"changed": true,
"cmd": "hostname",
"delta": "0:00:00.048644",
"end": "2024-02-06 14:20:52.487385",
"finished": 1,
"rc": 0,
"start": "2024-02-06 14:20:52.438741",
"stderr": "",
"stderr_lines": [],
"stdout": "sun48",
"stdout_lines": [
"sun48"
]
}
复制文件
ansible dstore -m copy -a ’ src=ansible.txt dest=/root/ansible.txt owner=root group=root mode=644 backup=yes ’-o
[root@sun25 ~]# ansible dstore -m copy -a 'src=ansible.txt dest=/root/ansible.txt owner=root group=root mode=644 backup=yes' -o
192.168.2.25 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "checksum": "5c074e046394da951a17e8baa97fb67833f20733", "dest": "/root/ansible.txt", "gid": 0, "group": "root", "mode": "0644", "owner": "root", "path": "/root/ansible.txt", "size": 14, "state": "file", "uid": 0}
192.168.2.38 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "checksum": "5c074e046394da951a17e8baa97fb67833f20733", "dest": "/root/ansible.txt", "gid": 0, "group": "root", "mode": "0644", "owner": "root", "path": "/root/ansible.txt", "size": 14, "state": "file", "uid": 0}
192.168.2.48 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "checksum": "5c074e046394da951a17e8baa97fb67833f20733", "dest": "/root/ansible.txt", "gid": 0, "group": "root", "mode": "0644", "owner": "root", "path": "/root/ansible.txt", "size": 14, "state": "file", "uid": 0}
验证下结果,通过返回MD5值
[root@sun25 ~]# ansible dstore -m shell -a 'md5sum /root/ansible.txt' -f 5 -o
192.168.2.48 | CHANGED | rc=0 | (stdout) c4c6374c8a58aadfda80777e13f17e9f /root/ansible.txt
192.168.2.25 | CHANGED | rc=0 | (stdout) c4c6374c8a58aadfda80777e13f17e9f /root/ansible.txt
192.168.2.38 | CHANGED | rc=0 | (stdout) c4c6374c8a58aadfda80777e13f17e9f /root/ansible.txt
包和服务管理
支持使用Ad-Hoc命令来管理包和服务
[root@sun25 ~]# ansible dstore -m yum -a 'name=httpd state=latest' -f 5
192.168.2.48 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"changes": {
"installed": [],
"updated": []
},
"msg": "",
"obsoletes": {
"iwl7265-firmware": {
"dist": "noarch",
"repo": "@anaconda",
"version": "22.0.7.0-69.el7"
}
},
"rc": 0,
"results": [
"All packages providing httpd are up to date",
""
]
}
192.168.2.38 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"changes": {
"installed": [],
"updated": []
},
"msg": "",
"obsoletes": {
"iwl7265-firmware": {
"dist": "noarch",
"repo": "@anaconda",
"version": "22.0.7.0-69.el7"
}
},
"rc": 0,
"results": [
"All packages providing httpd are up to date",
""
]
}
192.168.2.25 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"changes": {
"installed": [],
"updated": []
},
"msg": "",
"obsoletes": {
"iwl7265-firmware": {
"dist": "noarch",
"repo": "@anaconda",
"version": "22.0.7.0-69.el7"
}
},
"rc": 0,
"results": [
"All packages providing httpd are up to date",
""
]
}
Ansible-playbook
Playbook 是 Ansible 用于部署和配置托管式节点的自动化蓝图。YAML
-
Playbook
定义 Ansible 执行操作的顺序(从上到下)以实现总体目标的重头戏列表。
-
Play
映射到清单中受管节点的任务的有序列表。
-
Task
对定义 Ansible 执行的操作的单个模块的引用。
-
Module
Ansible 在托管节点上运行的代码单元或二进制文件。 Ansible 模块按集合进行分组,每个模块都具有完全限定的集合名称 (FQCN)。
测试1:
test.yaml
- name: My first play
hosts: dstore
tasks:
- name: Ping my hosts
ansible.builtin.ping:
- name: Print message
ansible.builtin.debug:
msg: Hello world
[root@sun25 ~]# ansible-playbook test.yaml
PLAY [My first play] ***********************************************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************************************************
ok: [192.168.2.48]
ok: [192.168.2.25]
ok: [192.168.2.38]
TASK [Ping my hosts] ***********************************************************************************************************************************
ok: [192.168.2.38]
ok: [192.168.2.25]
ok: [192.168.2.48]
TASK [Print message] ***********************************************************************************************************************************
ok: [192.168.2.25] => {
"msg": "Hello world"
}
ok: [192.168.2.38] => {
"msg": "Hello world"
}
ok: [192.168.2.48] => {
"msg": "Hello world"
}
PLAY RECAP *********************************************************************************************************************************************
192.168.2.25 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.2.38 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.2.48 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
默认会收集主机的信息,task为
Gathering Facts
**Ansible facts **
采集被管机器设备信息的 个功能,我们可以使用 setup 模块查机器的所有 facts 信息
ansible dstore -m setup
facter扩展facts信息【Puppet收集静态信息】
安装 facter ruby-json 包
ansible dstore -m shell -a 'rpm -qa ruby-json facter' # 如果没安装则返回为空 ansible dstore -m facter
ohai扩展facts信息 【chef测试节点工具】
ansible dstore -m ohai
Ansible Role
1.2版本后支持Role
对于playbook的规范,与playbook无区别
a.role的创建
可以手动创建相应目录结构或者采用ansible-galaxy init role_a
[root@sun25 opt]# tree
.
└── roles
├── role_a
│ ├── defaults # 角色的默认变量,优先级最低,可以被任何其他变量覆盖
│ │ └── main.yml
│ ├── files # 需部署的常规文件放在 此目录下,它们可以是脚本或配置文件等
│ ├── handlers #处理程序与Ansible剧本中的常规任务相似,但只在任务指示其更改了某些内容时运行
│ │ └── main.yml
│ ├── meta # 定义角色的元数据
│ │ └── main.yml
│ ├── README.md
│ ├── tasks
│ │ └── main.yml
│ ├── templates # 动态更改的文件或使用变量的文件都放置在这里
│ ├── tests # 包含这个角色的测试代码
│ │ ├── inventory
│ │ └── test.yml
│ └── vars # 此目录包含角色的其他变量。这些变量比在defaults中定义的变量具有更高的优先级
│ └── main.yml
└── site.yaml # 通常是主剧本文件,包括其他剧本文件。(这是主入口,我们通过执行这个文件来调用各个角色)
编辑task下的main.yaml
debug:
:调用了 debug 模块,这个模块用于在执行过程中打印诊断信息。
---
# tasks file for role_a
- name: Print Vars
debug:
msg: "ansible_test_roles"
编辑site.yaml
- hosts: dstore
roles:
- role: role_a
b.role调用
[root@sun25 roles]# ansible-playbook site.yaml
PLAY [dstore] ***************************************************************************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************************************************************
ok: [192.168.2.48]
ok: [192.168.2.25]
ok: [192.168.2.38]
TASK [role_a : Print Vars] **************************************************************************************************************************************************
ok: [192.168.2.25] => {
"msg": "ansible_test_roles"
}
ok: [192.168.2.38] => {
"msg": "ansible_test_roles"
}
ok: [192.168.2.48] => {
"msg": "ansible_test_roles"
}
PLAY RECAP ******************************************************************************************************************************************************************
192.168.2.25 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.2.38 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.2.48 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
c.变量使用
场景:在task中需要打印变量
---
# tasks file for role_a
- name: Print Vars
debug:
msg: "this is {{var}}"
在调用这个角色时,变量不存在则报错
- hosts: dstore
roles:
- role: role_a
vars:
var: string1
测试结果
[root@sun25 roles]# ansible-playbook site.yaml
PLAY [dstore] ******************************************************************
TASK [Gathering Facts] *********************************************************
ok: [192.168.2.25]
ok: [192.168.2.48]
ok: [192.168.2.38]
TASK [role_a : Print Vars] *****************************************************
ok: [192.168.2.25] => {
"msg": "this is string1"
}
ok: [192.168.2.38] => {
"msg": "this is string1"
}
ok: [192.168.2.48] => {
"msg": "this is string1"
}
为变量设置默认值,这样即使在调用角色没有传入任何参数也不会报错
vi defaults/main.yml # 手动创建role的话,没有该目录
var: string2
此时,既设置了默认变量,也设置了剧本变量
....
*
ok: [192.168.2.25] => {
"msg": "this is string1" # playbook中定义的变量优先级比较高
}
....
删除playbook中定义的变量后,默认变量值生效
变量优先级
- vars 最高
- defaults最低
d、模板文件
roles把所有的模板文件放置在templates
目录中
建立模板文件
cd /role_a/template
vi temp.j2
something in template
{{template_var}} # 此处引用了一个变量
添加变量
vi /role_a/vars/main.yaml
---
# vars file for role_a
var: string3
template_var: tempvar
添加task
---
# tasks file for role_a
- name: Print Vars
debug:
msg: "this is {{var}}"
- name: Copy Template
template:
src: temp.j2
dest: /tmp/temp
执行剧本
[root@sun25 roles]# ansible-playbook site.yaml
PLAY [dstore] ***************************************************************************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************************************************************
ok: [192.168.2.48]
ok: [192.168.2.25]
ok: [192.168.2.38]
TASK [role_a : Print Vars] **************************************************************************************************************************************************
ok: [192.168.2.25] => {
"msg": "this is string3"
}
ok: [192.168.2.38] => {
"msg": "this is string3"
}
ok: [192.168.2.48] => {
"msg": "this is string3"
}
TASK [role_a : Copy Template] ***********************************************************************************************************************************************
ok: [192.168.2.38]
ok: [192.168.2.48]
ok: [192.168.2.25]
PLAY RECAP ******************************************************************************************************************************************************************
192.168.2.25 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.2.38 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.2.48 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
测试文件
[root@sun25 roles]# ansible dstore -m shell -a 'md5sum /tmp/temp' -f 5 -o
192.168.2.25 | CHANGED | rc=0 | (stdout) 93d8bb859f76540ab76baac8b08533d8 /tmp/temp
192.168.2.38 | CHANGED | rc=0 | (stdout) 93d8bb859f76540ab76baac8b08533d8 /tmp/temp
192.168.2.48 | CHANGED | rc=0 | (stdout) 93d8bb859f76540ab76baac8b08533d8 /tmp/temp
Ansible Galaxy
Ansible 官方一个分享 role 的功能平台
七、Ansible 主要组成部分
ansible 命令执行来源
- USER,普通用户,即system administrator
- USER -> ansile playbook -> ansible
- CMDB,(配置管理数据库)API调用
- PUBLIC / PRIVATE CLOUD API调用
ansible 管理方式
-
Ad-Hoc
,即ansible命令,主要用于临时命令使用场景 -
Ansible-playbook
,主要用于长期规划好的,大型项目的场景,需要有前提的规划
ansible-playbook(剧本)执行过程: -
- 将已有编排好的任务集写入ansible-playbook
- 通过ansible-playbook命令分拆任务集至逐条ansible命令,按预定规则逐条执行
ansible主要操作对象
- HOSTS:主机
- NETWORKING:网络设备
注意事项:
- 执行ansible的主机一般称为主控端,中控,master或堡垒机
- 主控端python版本需要在2.6或以上
- 被控端python版本小于2.4需要安装python-simplejson
- 被控端如开启SELinux需要安装libselinux-python
- windows不能作为主控端
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类