Linux Ansible
ansible环境准备
ansible安装
管理端
安装ansible(yum安装需要EPEL源)
1 | yum install -y ansible |
查看ansible软件包的部分文件
1 | rpm -ql ansible | egrep -v "^/usr/(share|lib)" |
受控端
安装依赖和关闭SELinux
1 | 安装依赖 |
受控端通过"getenforce"查看SELinux是否关闭。
配置ansible主机清单
/etc/ansible/host为主机清单,这里记录了哪些IP可被管理。
在该文件末尾追加以下受控端IP地址:
1 | 172.16.1.7 |
管理端分发SSH公钥给受控端
批量管理的通信以SSH密钥登录方式进行的,因此必须确保管理端分发给其他服务器SSH密钥。
1 | [root@m01 /server/scripts]# ansible all -a "hostname" |
主机清单配置方式
分组配置主机列表
/etc/ansible/host
1 | [web] |
测试
1 | ansible web -a "hostname" |
模式匹配配置主机列表
/etc/ansible/host
1 | [web] |
等价于
1 | [web] |
主机列表加入SSH端口号
可以指定SSH端口号
1 | [web] |
那么使用"ansible web -a "hostname"测试时,默认连接到远程主机web01的52222端口。
主机列表组划分子组
1 | [rsync:children] --- 嵌入子组信息 |
测试
1 | ansible rsync -a "hostname" |
加入特殊变量
主机列表后面加上特殊变量
1 | [web] |
ansible_ssh_port:要连接的SSH端口号
ansible_ssh_user:以什么用户身份建立连接
ansible_ssh_pass:用户密码
除了这些写,还可以将变量存放在vars中。
设置主机清单变量
1 | [web] |
常用模块
Module Index — Ansible Documentation
command模块(默认模块)
command – Execute commands on targets — Ansible Documentation
1 | ansible 主机名称/主机组名称/主机地址信息/all -m(指定应用的模块信息) 模块名称 -a(指定动作信息) "执行什么动作" |
chdir - 在执行命令之前对目录进行切换
creates - 如果文件存在了,不执行命令操作
removes - 如果文件存在了, 这个步骤将执行
free_form(required) - 使用command模块的时候,-a参数后面必须写上一个合法linux命令信息
注意事项:
有些符号信息无法识别: <", “>”, “|”, “;” and “&”
管理服务器终端:
1 | ansible 172.16.1.31 -m command -a "chdir=/root/violet touch violet.txt" |
'-m’若不指定,默认指定command,即"-m command"。上述命令相当于在172.16.1.31主机上创建/root/violet/violet.txt
1 | ansible 172.16.1.31 -m command -a "creates=/root/violet touch violet.txt" |
如果目标主机/root/violet存在,则不创建violet.txt。
1 | ansible 172.16.1.31 -m command -a "removes=/root/violet touch violet.txt" |
如果目标主机/root/violet存在,则创建violet.txt,默认创建在目标主机家目录。目标主机root家目录可以看到violet.txt文件创建。
shell模块
shell – Execute commands in nodes(在节点上执行操作)
chdir - 在执行命令之前对目录进行切换
creates - 如果文件存在了,不执行命令操作
removes - 如果文件存在了, 这个步骤将执行
free_form(required)
The command module takes a free form command to run.
There is no parameter actually named ‘free form’. See the examples!
1 | ansible 172.16.1.31 -m shell -a "hostname" |
在目标主机上执行"hostname"命令。
1 | ansible 172.16.1.31 -m command -a "chdir=/tmp touch oldboy.txt" |
1 | ansible 172.16.1.31 -m command -a "creates=/tmp/hosts touch oldboy.txt" |
1 | ansible 172.16.1.31 -m command -a "removes=/tmp/hosts chdir=/tmp touch oldboy.txt" |
实践应用: 利用shell执行脚本
第一个步骤: 编写一个脚本
第二个步骤: 将脚本发送到远程主机
第三个步骤: 将脚本权限进行修改(添加执行权限)
第四个步骤: 运行ansible命令执行脚本
script模块
copy模块
copy – Copy files to remote locations — Ansible Documentation
1 | ansible 172.16.1.31 -m copy -a "src=/root/ana.txt dest=./" |
补充说明: ansible软件输出颜色说明:
01. 绿色信息: 查看主机信息/对主机未做改动
02. 黄色信息: 对主机数据信息做了修改
03. 红色信息: 命令执行出错了
04. 粉色信息: 忠告信息
05. 蓝色信息: 显示ansible命令执行的过程???
copy模块扩展用法
比较hash值如果相同则不会再次传输
在传输文件时修改文件的属主和属组信息:
1 | ansible 172.16.1.31 -m copy -a "src=/etc/ansible/file/rsync/rsync.password dest=/etc/ owner=oldboy group=oldboy" |
在传输文件时修改文件的权限信息:
1 | ansible 172.16.1.31 -m copy -a "src=test.txt dest=./ owner=violet group=violet mode=644" |
在传输数据文件信息时对远程主机源文件进行备份:
远程主机中对test.txt修改后,管理端执行以下命令
1 | ansible 172.16.1.31 -m copy -a "src=test.txt dest=./ owner=violet group=violet mode=664 backup=yes" |
可以发现远程主机的文件备份了:
1 | [root@nfs01 ~]# ll |
创建一个文件并直接编辑文件的信息
1 | ansible 172.16.1.31 -m copy -a "content='123456' dest=./test.txt" |
远程主机终端查询文件
1 | [root@nfs01 ~]# cat test.txt |
可以发现写入的内容没有换行符。
自行研究:
directory_mode
local_follow
复制目录信息
1 | [root@m01 ~]# tree violet |
src后面目录没有/: 将目录本身以及目录下面的内容都进行远程传输复制
查看远程主机
1 | [root@nfs01 ~]# tree ~ |
1 | [root@m01 ~]# ansible 172.16.1.31 -m copy -a "src=/root/violet/ dest=./" |
src后面目录有/: 只将目录下面的内容都进行远程传输复制
1 | [root@nfs01 ~]# tree ~ |
remote_src
no : src参数指定文件信息,会在本地管理端服务进行查找
yes : src参数指定文件信息,会从远程主机上进行查找
1 | ansible 172.16.1.31 -m copy -a "src=test.txt dest=./ remote_src=no" #省略remote_src,默认为no |
test.txt复制到远程主机
1 | ansible 172.16.1.31 -m copy -a "src=/root/test.txt dest=~ remote_src=yes" |
查询远程主机是否存在src指定的文件"/root/test.txt",若有将管理端文件移动到远程主机。
fetch模块
fetch – Fetch files from remote nodes — Ansible Documentation
1 |
yum模块
yum – Manages packages with the yum package manager — Ansible Documentation
1 | ansible 172.16.1.41 -m yum -a 'name=iotop' |
mount模块
mount – Control active and configured mount points — Ansible Documentation
user模块
user – Manage user accounts — Ansible Documentation
实例
1 | ansible 172.16.1.41 -m user -a 'name=violet01' |
service模块
ping模块
synchronize模块
什么要选取好模块
比如你在shell模块中使用"yum install -y"命令,那么远程主机执行时会再次下载软件包,而使用yum模块则不会,从速度看,yum模块反而更快。
在shell模块中scp,文件重复复制,如果使用copy模块,会检验hash值,若一致,代表源文件和目标文件一致,不会再次传输文件。
setup模块
setup – Gathers facts about remote hosts — Ansible Documentation
setup模块用于收集并打印被管理主机系统的详细信息(包括硬件信息)。
剧本(Playbook)
使用剧本
在管理端编写剧本
1 | mkdir /etc/ansible/ansible-playbook |
运行剧本
1 | 剧本语法检查 |
[剧本名]以.yaml
结尾。请按照"剧本语法检查 - 模拟运行剧本 - 运行剧本"或"模拟运行剧本 - 运行剧本"的流程编写和测试剧本。
rsync服务自动化部署剧本
/etc/ansible/ansible-playbook/rsync_server.yaml
1 | - hosts: 172.16.1.41 |
使用变量
Using Variables — Ansible Documentation
变量的定义有三种:运行时变量、剧本变量 、主机清单(/etc/ansible/hosts)变量。
剧本变量
定义格式
1 | vars: |
key为变量名,value为变量值。通过{{ 变量名 }}
引用定义的变量值。
实例请参考rsync服务自动化部署剧本。
运行时变量
--extra-vars
或-e
用于运行时变量,例子如下:
测试实例仍使用rsync服务自动化部署剧本,不过需要修改点细节,方便演示效果:
/etc/ansible/ansible-playbook/rsync_server.yaml
1 | - hosts: 172.16.1.41 |
运行剧本,并指定运行时变量
1 | ansible-playbook rsync_server.yaml --extra-vars="passfile=rsync.password" |
主机清单(Inventory)变量
主机清单变量使用前必须有主机清单。
主机清单就是主机列表。主机清单格式:
1 | [清单名] |
有了主机清单,那么就可以定义主机清单变量了
格式如下
1 | [清单名:vars] |
以下例子展示如何使用主机清单和主机清单变量,不过我们还是以rsync服务自动化部署剧本为例:
1 | [rsync_client] |
/etc/ansible/ansible-playbook/rsync_server.yaml中修改部分细节
1 | - hosts: 172.16.1.41 |
改为
1 | - hosts: rsync_server |
变量优先级
运行时变量 > 剧本变量 > 主机清单(/etc/ansible/hosts)变量。
选用变量的原则
由于运行时变量需要再命令行上指定,批量化管理时显得过于繁琐,因此尽量使用剧本变量和主机清单变量
注册变量
Using Variables — Ansible Documentation
注册变量是什么意思
Another major use of variables is running a command and registering the result of that command as a variable. When you execute a task and save the return value in a variable for use in later tasks, you create a registered variable.
注册变量就是将运行的命令的结果集存放到一个变量的过程。
当我们声明了一个"将结果集存放指定变量"的操作,那么我们就完成了注册变量。那么该如何注册变量?
1 | - name: check rsync server port |
我们调用shell模块完成netstat命令,那么netstat命令的输出结果集会保存到"get_server_port"变量中,也就是说我们注册了"get_server_port"变量,该变量值为输出结果集。在debug模块中我们以标准输出
的形式输出了变量值。
特殊变量
Special Variables — Ansible Documentation
使用介绍
什么是特殊变量
特殊变量是由Ansible设置和维护的,用户不能直接设置这些变量。
特殊变量有Magic,Facts和Connection变量,这些变量可以认为是内置变量。
特殊变量从何而来
Ansible Facts and How to use them - Ansible Facts Index
Ansible在运行剧本时,默认会调用setup模块来收集远程主机的信息(Facts),而这些信息会被写入保留变量( reserved variable)中。保留变量指的是许多特定的变量名交由Ansible维护,而用户不能直接设置这些变量名。
只要知道特殊变量名,那么就可以直接引用而不需要设置变量。
变量的组成与使用(引用)
首先要明白的一点是,这些变量值打印出来,都是一大堆输出信息,这是因为一个变量是由许多数据类型(List, Dictionary等等)实体组成的。
在剧本中若想引用变量的值:通过{{ 变量名 }}
来引用。
在剧本中若想引用变量的其中一个元素的值:通过{{ 变量名.元素名}}
来引用。
查看变量和元素的数据类型
方法一
1 | 打印某个主机的全部信息 |
方法二
/etc/ansible/ansible-playbook/debug.yaml
1 | - name: Ansible Variable Example Playbook |
运行剧本
1 | [root@m01 /etc/ansible/ansible-playbook]# ansible-playbook debug.yaml |
变量中某个元素的数据类型通过{{
的方式查看。注意一定要使用剧本才能进行查看。
Magic变量
什么是Magic变量
These variables cannot be set directly by the user; Ansible will always override them to reflect internal state.
特殊变量有哪些
变量名 | 描述 |
---|---|
ansible_check_mode | Boolean that indicates if we are in check mode or not |
ansible_dependent_role_names | The names of the roles currently imported into the current play as dependencies of other plays |
ansible_diff_mode | Boolean that indicates if we are in diff mode or not |
ansible_forks | Integer reflecting the number of maximum forks available to this run |
ansible_inventory_sources | List of sources used as inventory |
ansible_limit | Contents of the --limit CLI option for the current execution of Ansible |
ansible_loop | A dictionary/map containing extended loop information when enabled via loop_control.extended |
ansible_loop_var | The name of the value provided to loop_control.loop_var . Added in 2.8 |
ansible_play_batch | List of active hosts in the current play run limited by the serial, aka ‘batch’. Failed/Unreachable hosts are not considered ‘active’. |
ansible_play_hosts | The same as ansible_play_batch |
ansible_play_hosts_all | List of all the hosts that were targeted by the play |
ansible_play_role_names | The names of the roles currently imported into the current play. This list does not contain the role names that are implicitly included via dependencies. |
ansible_playbook_python | The path to the python interpreter being used by Ansible on the controller |
ansible_role_names | The names of the roles currently imported into the current play, or roles referenced as dependencies of the roles imported into the current play. |
ansible_run_tags | Contents of the --tags CLI option, which specifies which tags will be included for the current run. |
ansible_search_path | Current search path for action plugins and lookups, i.e where we search for relative paths when you do template: src=myfile |
ansible_skip_tags | Contents of the --skip_tags CLI option, which specifies which tags will be skipped for the current run. |
ansible_verbosity | Current verbosity setting for Ansible |
ansible_version | Dictionary/map that contains information about the current running version of ansible, it has the following keys: full, major, minor, revision and string. |
group_names | List of groups the current host is part of |
groups | A dictionary/map with all the groups in inventory and each group has the list of hosts that belong to it |
hostvars | A dictionary/map with all the hosts in inventory and variables assigned to them |
inventory_hostname | The inventory name for the ‘current’ host being iterated over in the play |
inventory_hostname_short | The short version of inventory_hostname |
inventory_dir | The directory of the inventory source in which the inventory_hostname was first defined |
inventory_file | The file name of the inventory source in which the inventory_hostname was first defined |
omit | Special variable that allows you to ‘omit’ an option in a task, i.e - user: name=bob home={{ bobs_home|default(omit) }} |
play_hosts | Deprecated, the same as ansible_play_batch |
ansible_play_name | The name of the currently executed play. Added in 2.8 . |
playbook_dir | The path to the directory of the playbook that was passed to the ansible-playbook command line. |
role_name | The name of the currently executed role |
role_names | Deprecated, the same as ansible_play_role_names |
role_path | The path to the dir of the currently running role |
Facts变量
什么是Facts变量
These are variables that contain information pertinent to the current host (inventory_hostname). They are only available if gathered first.
变量名 | 描述 |
---|---|
ansible_facts | Contains any facts gathered or cached for the inventory_hostname Facts are normally gathered by the setup module automatically in a play, but any module can return facts. |
ansible_local | Contains any ‘local facts’ gathered or cached for the inventory_hostname. The keys available depend on the custom facts created. See the setup module for more details. |
ansible_hostname
也是一个内置变量。
ansible_hostname built-in variable holds the hostname of the remote host just like the inventory_hostname, the difference is that
ansible_hostname
takes the hostname of the remote machine from the facts collected during thegather_facts
section of your playbook.Ansible Inventory_hostname & ansible_hostname Examples | Devops Junc
连接变量
什么是连接变量
Connection variables are normally used to set the specifics on how to execute actions on a target. Most of them correspond to connection plugins, but not all are specific to them; other plugins like shell, terminal and become are normally involved. Only the common ones are described as each connection/become/shell/etc plugin can define its own overrides and specific variables.
变量名 | 描述 |
---|---|
ansible_become_user | The user Ansible ‘becomes’ after using privilege escalation. This must be available to the ‘login user’. |
ansible_connection | The connection plugin actually used for the task on the target host. |
ansible_host | The ip/name of the target host to use instead of inventory_hostname. |
ansible_python_interpreter | The path to the Python executable Ansible should use on the target host. |
ansible_user | The user Ansible ‘logs in’ as. |
判断
when: (条件判断)
。
我们对这个实例rsync服务自动化部署剧本进行修改:
1 | - hosts: rsync_server |
循环(Loop)
不同模块不能在一个task,以下为错误实例:
1 | tasks: |
" - name"标签里面代表一个task,一个task只能出现同种模块。
对于同一模块可以在一个task出现多次,并且模块使用的参数一致,那么就可以使用循环功能。
循环实例:
1 | - hosts: rsync_server |
错误忽略
使用"ignore_errors"可忽略当前task的错误
1 | - hosts: rsync_server |
但发现该task错误时,会忽略该错误,并往下执行。
标签
应用需求:比如某剧本有1000个task,中间第500task的模块执行错误,那么我想要修改这个错误,如果不使用标签功能,那么我要等前面499task的模块执行完后才能开始测试第500task,因此这样编写效率太低了。通过标签功能我们可以执行剧本中指定的task。
一个标签实例:
1 | - hosts: rsync_server |
对task使用tags: <tag_value>
进行标记。
运行剧本时使用标签:
1 | ansible-playbook -t t2 rsync_server.yaml |
-t, --tags
- only run plays and tasks tagged with these values指定-t选项后,只运行指定标签的task。
也可以选择对指定标签做跳过操作:
1 | ansible-playbook --skip-tags=t2 rsync_server.yaml |
--skip-tags
- only run plays and tasks whose tags do not match these values指定–skip-tags选项后,被指定的标签的task是不会被执行的。
触发
触发源:当task模块执行状态为changed,那么就会触发通知。
响应源:当触发通知被特定的handler接收了,那么响应源就会执行响应的动作。
在触发源的task中加入notify:
语句,并在响应源的task编写在handlers:
语句中。
在rsync服务自动化部署剧本中,一旦在copy模块中传输rsyncd.conf给远程主机后,检查到文件changed状态,那么就会触发剧本中一个响应task:
1 | - hosts: rsync_server |
我们改变rsyncd.conf中的port为874,那么剧本运行后,远程主机的文件发生改变,那么就会触发响应源。
Ansible查阅
1 | ansible-doc -l #列出模块使用简介 |