01-自动化运维工具-ansible¶
Ansible基础知识介绍¶
简单介绍¶
ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块。
Ansible是一个自动化统一配置管理工具,自动化主要体现在Ansible集成了丰富模块以及功能组件,可以通过一个命令完成一系列的操作,进而能减少重复性的工作和维护成本,可以提高工作效率。
总体架构¶
ansible只是提供一种框架。主要包括:
(1)、连接插件connection plugins:负责和被监控端实现通信;
(2)、host inventory:指定操作的主机,是一个配置文件里面定义监控的主机;
(3)、各种模块核心模块、command模块、自定义模块;
(4)、借助于插件完成记录日志邮件等功能;
(5)、playbook:剧本执行多个任务时,非必需可以让节点一次性运行多个任务。
Ansible的特性¶
1.模块化:调用特定的模块,完成特定的任务
2.基于Python语言实现,由Paramiko,PyYAML和Jinja2三个关键模块
3.部署简单,agentless
4.支持主从模式
5.支持自定义模块
6.支持Playbook
(1)、no agents:不需要在被管控主机上安装任何客户端;
(2)、no server:无服务器端,使用时直接运行命令即可;
(3)、modules in any languages:基于模块工作,可使用任意语言开发模块;
(4)、yaml,not code:使用yaml语言定制剧本playbook;
(5)、ssh by default:基于SSH工作;
(6)、strong multi-tier solution:可实现多级指挥
ansible优缺点¶
(1)、轻量级,无需在客户端安装agent,更新时,只需在操作机上进行一次更新即可;
(2)、批量任务执行可以写成脚本,而且不用分发到远程就可以执行;
(3)、使用python编写,维护更简单,ruby语法过于复杂;
(4)、支持sudo。
无需客户端
与Chef、Puppet以及Saltstack(现在也支持Agentless方式salt-ssh)不同,Ansible是无客户端Agent的,所以无需在客户机上安装或配置任何程序,就可以运行Ansible任务。由于Ansible不会在客户机上安装任何软件或运行监听程序,因此消除了许多管理开销,我们可以在即可上手使用Ansible管理服务器,同时Ansible的更新也不会影响任何客户机。
使用SSH进行通讯
默认情况下,Ansible使用SSH协议在管理机和客户机之间进行通信。可以使用SFTP与客户机进行安全的文件传输。
并行执行
Ansible与客户机并行通信,可以更快地运行自动化任务。默认情况下,forks值为5,可以按需,在配置文件中增大该值。
任务执行流程¶
说明:
(1)、以上内容大多是基于他人分享的基础上总结而来,学习借鉴之用;
(2)、本次安装基于 CentOS 6.4 系统环境。
概念术语描述¶
Ansible使用过程中会用到一些概念术语,我们先介绍一下。
Ansible的与节点有关的重要术语包括控制节点,受管节点,清单和主机文件:
控制节点(Control node):指安装了Ansible的主机,也叫Ansible服务器端,管理机。 Ansible控制节点主要用于发布运行任务,执行控制命令。Ansible的程序都安装在控制节点上,控制节点需要安装Python和Ansible所需的各种依赖库。注意:目前Ansible还不能安装在Windows下。
受控节点(Managed nodes):也叫客户机,就是想用Ansible执行任务的客户服务器。
清单(Inventory):受控节点的列表,就是所有要管理的主机列表。
host文件:清单列表通常保存在一个名为host文件中。在host文件中,可以使用IP地址或者主机名来表示具体的管理主机和认证信息,并可以根据主机的用户进行分组。缺省文件:/etc/ansible/hosts,可以通过-i指定自定义的host文件。
模块(Modules):模块是Ansible执行特定任务的代码块。比如:添加用户,上传文件和对客户机执行ping操作等。Ansible现在默认自带450多个模块,,Ansible Galaxy公共存储库则包含大约1600个模块。
任务(Task):是Ansible客户机上执行的操作。可以使用ad-hoc单行命令执行一个任务。
剧本(Playbook):是利用YAML标记语言编写的可重复执行的任务的列表,playbook实现任务的更便捷的读写和贡献。比如,在Github上有大量的Ansible playbooks共享,你要你有一双善于发现的眼睛你就能找到大量的宝藏。
角色(roles):角色是Ansible 1.2版本引入的新特性,用于层次性、结构化地组织playbook。roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。
参考资料推荐¶
官方文档:https://docs.ansible.com/ansible/latest/index.html
gitlab: https://github.com/ansible/ansible
中文手册 http://www.ansible.com.cn/index.html
Ansible安装部署使用¶
环境准备¶
系统版本:CentOS Linux release 7.6.1810 (Core) 系统内核:3.10.0-957.el7.x86_64
主机名称 | 主机IP(管理网eth0) | 角色名称 | 规格 | 数据盘 |
---|---|---|---|---|
192e168e2e11 | 192.168.2.11 | master/agent | 2C2G/50GB | 500GB |
192e168e2e12 | 192.168.2.12 | agent | 2C2G/50GB | 500GB |
配置阿里云的base源和epel源(CentOS7)
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum repolist
安装配置¶
1.安装ansible批量管理工具,只需在管理端安装即可 master端:管理端
[root@192e168e2e11 ]# yum -y install ansible
配置文件¶
我们关注ansible主要关注一下的配置文件
/etc/ansible/ansible.cfg 主配置文件
/etc/ansible/hosts 主机清单,需要管理的主机列表,支持分组取名
ansible通过ssh实现配置管理,应用部署,任务执行等功能,因此,需要事先配置ansible端能基于秘钥认证的方式联系各管理节点
Ansible默认安装好后有一个配置文件/etc/ansible/ansible.cfg,该配置文件中定义了ansible的主机的默认配置部分,如默认是否需要输入密码、是否开启sudo认证、action_plugins插件的位置、hosts主机组的位置、是否开启log功能、默认端口、key文件位置等等。
具体如下:
[root@192e168e2e11 ]# vi /etc/ansible/ansible.cfg
[defaults]
# some basic default values...
hostfile = /etc/ansible/hosts \\指定默认hosts配置的位置
# library_path = /usr/share/my_modules/
remote_tmp = $HOME/.ansible/tmp
pattern = *
forks = 5
poll_interval = 15
sudo_user = root \\远程sudo用户
#ask_sudo_pass = True \\每次执行ansible命令是否询问ssh密码
#ask_pass = True \\每次执行ansible命令时是否询问sudo密码
transport = smart
remote_port = 22
module_lang = C
gathering = implicit
host_key_checking = False \\关闭第一次使用ansible连接客户端是输入命令提示
log_path = /var/log/ansible.log \\需要时可以自行添加。chown -R root:root ansible.log
system_warnings = False \\关闭运行ansible时系统的提示信息,一般为提示升级
# set plugin path directories here, separate with colons
action_plugins = /usr/share/ansible_plugins/action_plugins
callback_plugins = /usr/share/ansible_plugins/callback_plugins
connection_plugins = /usr/share/ansible_plugins/connection_plugins
lookup_plugins = /usr/share/ansible_plugins/lookup_plugins
vars_plugins = /usr/share/ansible_plugins/vars_plugins
filter_plugins = /usr/share/ansible_plugins/filter_plugins
fact_caching = memory
[accelerate]
accelerate_port = 5099
accelerate_timeout = 30
accelerate_connect_timeout = 5.0
# The daemon timeout is measured in minutes. This time is measured
# from the last activity to the accelerate daemon.
accelerate_daemon_timeout = 30
配置文件ansible.cfg约有350行语句,大多数为注释行默认配置项。该文件遵循INI格式,分为如下几类配置
(1)[defaults]
其中日志执行存放路径值得关注,方便查看执行中报错内容
log_path = /var/log/ansible.log # 执行日志存放目录
[defaults]
# inventory = /etc/ansible/hosts # 定义Inventory
# library = /usr/share/my_modules/ # 自定义lib库存放目录
# remote_tmp = $HOME/.ansible/tmp # 临时文件远程主机存放目录
# local_tmp = $HOME/.ansible/tmp # 临时文件本地存放目录
# forks = 5 # 默认开启的并发数
# poll_interval = 15 # 默认轮询时间间隔
# sudo_user = root # 默认sudo用户
# ask_sudo_pass = True # 是否需要sudo密码
# ask_pass = True # 是否需要密码
# roles_path = /etc/ansible/roles # 默认下载的Roles存放的目录
# host_key_checking = False # 首次连接是否需要检查key认证,建议设为False
# timeout = 10 # 默认超时时间
# timeout = 10 # 如没有指定用户,默认使用的远程连接用户
# log_path = /var/log/ansible.log # 执行日志存放目录
# module_name = command # 默认执行的模块
# action_plugins = /usr/share/ansible/plugins/action # action插件的存放目录
# callback_plugins = /usr/share/ansible/plugins/callback # callback插件的存放目录
# connection_plugins = /usr/share/ansible/plugins/connection # connection插件的存放目录
# lookup_plugins = /usr/share/ansible/plugins/lookup # lookup插件的存放目录
# vars_plugins = /usr/share/ansible/plugins/vars # vars插件的存放目录
# filter_plugins = /usr/share/ansible/plugins/filter # filter插件的存放目录
# test_plugins = /usr/share/ansible/plugins/test # test插件的存放目录
# strategy_plugins = /usr/share/ansible/plugins/strategy # strategy插件的存放目录
# fact_caching = memory # getfact缓存的主机信息存放方式
# retry_files_enabled = False
# retry_files_save_path = ~/.ansible-retry # 错误重启文件存放目录
…
上述是日常可能用到的配置,这些多数保持默认即可。
**注意:**在首次链接时,把# host_key_checking = False # 首次连接是否需要检查key认证,建议设为False
(2)[privilege_escalation]
出于安全角度考虑,部分公司不希望直接以root的高级管理员权限直接部署应用,往往会开放普通用户权限并给予sudo的权限,该部分配置主要针对sudo用户提权的配置。
[privilege_escalation]
# become=True # 是否sudo
# become_method=sudo # sudo方式
# become_user=root # sudo后变为root用户
# become_ask_pass=False # sudo后是否验证密码
(3)[paramiko_connection]
定义paramiko_connection配置,该部分功能不常用,了解即可。
[paramiko_connection] # 该配置不常用到
# record_host_keys=False # 不记录新主机的key以提升效率
# pty=False # 禁用sudo功能
(4)[ssh_connection]
Ansible默认使用SSH协议连接对端主机,该部署是主要是SSH连接的一些配置,但配置项较少,多数默认即可。
[ssh_connection]
# pipelining = False # 管道加速功能,需配合requiretty使用方可生效
(5)[accelerate]
Ansible连接加速相关配置。因为有部分使用者不满意Ansible的执行速度,所以Ansible在连接和执行速度方面也在不断地进行优化,该配置项在提升Ansibile连接速度时会涉及,多数保持默认即可。
[accelerate]
# accelerate_port = 5099 # 加速连接端口
# accelerate_timeout = 30 # 命令执行超时时间,单位秒
# accelerate_connect_timeout = 5.0 # 连接超时时间,单位秒
# accelerate_daemon_timeout = 30 # 上一个活动连接的时间,单位分钟
# accelerate_multi_key = yes
(6)[selinux]
关于selinux的相关配置几乎不会涉及,保持默认配置即可。
[selinux]
# libvirt_lxc_noseclabel = yes
# libvirt_lxc_noseclabel = yes
(7)[colors]
Ansible对于输出结果的颜色也进行了详尽的定义且可配置,该选项对日常功能应用影响不大,几乎不用修改,保持默认即可。
[colors]
# highlight = white
# verbose = blue
# warn = bright purple
# error = red
# debug = dark gray
# deprecate = purple
# skip = cyan
# unreachable = red
# ok = green
# changed = yellow
# diff_add = green
# diff_remove = red
# diff_lines = cyan
秘钥分发¶
(1)生成秘钥
[root@192e168e2e11 ~]# ssh-keygen
(2)分发秘钥
ansible all -m copy -a "src=~/.ssh/id_rsa.pub dest=~/.ssh/authorized_keys mode=600"
在分发秘钥以前要保证安装以下软件
[root@192e168e2e11 ]# yum -y install expect
以下为分发秘钥的脚本
[root@linux-node1 ~]# cat keys_send.sh
#!/bin/bash
# this scripts comes from chris trainning's student.
# e_mail:838997384@qq.com
# qqinfo:838997384
# function: remote dis ssh key.
# version:1.2.1v
################################################
# chris trainning info.
# QQ 838997384
# site:http://www.etiantian.org
# blog:http://www.74cto.com
################################################
. /etc/init.d/functions
HOSTS=(
192.168.56.11
192.168.56.12
192.168.56.13
192.168.56.14
)
function CREATE_keys(){
[ ! -f /root/.ssh/id_dsa.pub ] && ssh-keygen -t dsa -N '' -f ~/.ssh/id_dsa &>/dev/null
}
function PASS_PASSWD(){
ip=$1
expect -c "
set timeout 90
spawn ssh-copy-id -i /root/.ssh/id_dsa.pub $ip
expect \"continue connecting (yes/no)\?\"
send \"yes\r\"
expect \"*password:\"
send \"123456\r\"
expect eof" >/dev/null 2>&1
}
function FENFA_id_dsa(){
for ((i=0; i<${#HOSTS[*]}; i++))
do
PASS_PASSWD ${HOSTS[i]}
CHECK_KEYS=`ssh ${HOSTS[i]} 'ls -l /root/.ssh/|grep authorized_keys'|wc -l`
if [[ $CHECK_KEYS -eq 1 ]];then
action "${HOSTS[i]} send id_dsa is successful" /bin/true
else
action "${HOSTS[i]} send id_dsa is failed copied" /bin/false
fi
done
}
main(){
CREATE_keys
FENFA_id_dsa
}
main
Ansible常见模块详解¶
[root@192e168e2e11 ]# ansible-doc -l #查看常见的模块
[root@192e168e2e11 ]# ansible-doc user #查看user模块的常见参数
command模块¶
## 在远程主机上执行命令
相关选项如下:
creates:一个文件名,当该文件存在,则该命令不执行
free_form:要执行的linux指令
chdir:在执行指令之前,先切换到该目录
removes:一个文件名,当该文件不存在,则该选项不执行
executable:切换shell来执行指令,该执行路径必须是一个绝对路径
例子01:远程执行命令
[root@192e168e2e11 ~]# ansible web -m command -a "date"
192.168.2.12 | CHANGED | rc=0 >>
Mon Aug 1 16:55:55 CST 2022
192.168.2.11 | CHANGED | rc=0 >>
Mon Aug 1 16:55:55 CST 2022
例子02:creates:一个文件名,当该文件存在,则该命令不执行
文件不存在的场景:
[root@192e168e2e11 ~]# ansible web -m shell -a "creates=/tmp/test date"
192.168.2.12 | CHANGED | rc=0 >>
Mon Aug 1 16:56:36 CST 2022
192.168.2.11 | CHANGED | rc=0 >>
Mon Aug 1 16:56:36 CST 2022
文件存在的场景:
[root@192e168e2e11 ~]# ansible web -m shell -a "creates=/tmp/test date"
192.168.2.12 | SUCCESS | rc=0 >>
skipped, since /tmp/test exists
192.168.2.11 | SUCCESS | rc=0 >>
skipped, since /tmp/test exists
shell模块¶
## 切换到某个shell执行指定的指令,参数与command相同。
与command不同的是,此模块可以支持命令管道,同时还有另一个模块也具备此功能:raw
用途:用于执行远程服务器上的脚本
示例:
(1)远程执行命令:
[root@192e168e2e11 ~]# ansible web -m shell -a "date"
192.168.2.12 | CHANGED | rc=0 >>
Mon Aug 1 16:59:16 CST 2022
192.168.2.11 | CHANGED | rc=0 >>
Mon Aug 1 16:59:16 CST 2022
(2)先在本地创建一个SHELL脚本
cat >/tmp/rocketzhang_test.sh<<EOF
#!/bin/sh
date +%F_%H:%M:%S
EOF
chmod +x /tmp/rocketzhang_test.sh
(3) 将创建的脚本文件分发到远程
ansible web -m copy -a "src=/tmp/rocketzhang_test.sh dest=/tmp/rocketzhang_test.sh owner=root group=root mode=0755"
(4) 远程执行结果
[root@192e168e2e11 ~]# ansible web -m shell -a "sh /tmp/rocketzhang_test.sh"
192.168.2.12 | CHANGED | rc=0 >>
2022-08-01_17:01:05
192.168.2.11 | CHANGED | rc=0 >>
2022-08-01_17:01:05
group模块¶
作用:创建删除用户组
例子1:创建user01用户组
[root@192e168e2e11 ~]# ansible web -m group -a "name=user01 gid=1000 state=present system=yes"
192.168.2.12 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"gid": 1000,
"name": "user01",
"state": "present",
"system": true
}
192.168.2.11 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"gid": 1000,
"name": "user01",
"state": "present",
"system": true
}
例子2:删除user01用户组
[root@192e168e2e11 ~]# ansible web -m group -a "name=user01 gid=1000 state=absent system=yes"
192.168.2.12 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"name": "user01",
"state": "absent"
}
192.168.2.11 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"name": "user01",
"state": "absent"
}
user模块¶
作用:在所有的服务器上创建一个用户
state表示是否存在
name表示用户的名称
例子01:创建用户
[root@192e168e2e11 ~]# ansible web -m user -a "name=user01 state=present password=123456 uid=1000 shell=/bin/bash"
192.168.2.12 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"comment": "",
"create_home": true,
"group": 1000,
"home": "/home/user01",
"name": "user01",
"password": "NOT_LOGGING_PASSWORD",
"shell": "/bin/bash",
"state": "present",
"system": false,
"uid": 1000
}
例子02:删除用户
[root@192e168e2e11 ~]# ansible web -m user -a "name=user01 state=absent password=123456 uid=1000 shell=/bin/bash"
192.168.2.12 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"force": false,
"name": "user01",
"remove": false,
"state": "absent"
}
cron模块¶
Cron - 运行管理任务计划和 crontab 条目,可以新建、删除 crontab 条目。
点击(此处)折叠或打开
[root@localhost ~]# ansible-doc cron
## 打印 Cron 模块帮助信息。
name 任务计划的描述信息。
cron_file 如果指定此文件,将替换远程主机上的该用户的任务计划。
minute 分( 0-59 ,* ,*/2 )
hour 时( 0-23 ,* ,*/2 )
day 日( 1-31 ,* ,*/2 )
month 月( 1-12 ,* ,*/2 )
weekday 周( 0-6 或 1-7 ,* )
job 要执行的命令,state 要等于 present 。
backup 是否先备份再创建新的任务计划。
user 以哪个用户新建任务计划,默认 root 。
state (present/absent) 指定任务计划是创建,还是删除。
special_time (reboot/yearly/annually/monthly/weekly/daily/hourly)
Special time specification nickname. (added in Ansible 1.3)
[root@192e168e2e11 ~]# ansible web -m cron -a "name='sync time from ntpserver' minute=*/5 hour=1,3,5,7,9 month=10 user=root job='ntpdate us.pool.ntp.org'"
当然我们也可以取消定时任务的名称说明
[root@192e168e2e11 ~]# ansible web -m cron -a "name='sync time from ntpserver' minute=*/5 hour=1,3,5,7,9 month=10 user=root state=absent job='ntpdate us.pool.ntp.org'"
copy模块¶
## 复制文件到远程主机
相关选项如下:
backup:在覆盖之前,将源文件备份,备份文件包含时间信息。有两个选项:yes|no
content:用于替代“src”,可以直接设定指定文件的值
dest:必选项。要将源文件复制到的远程主机的绝对路径,如果源文件是一个目录,那么该路径也必须是个目录
directory_mode:递归设定目录的权限,默认为系统默认权限
force:如果目标主机包含该文件,但内容不同,如果设置为yes,则强制覆盖,如果为no,则只有当目标主机的目标位置不存在该文件时,才复制。默认为yes
others:所有的file模块里的选项都可以在这里使用
src:被复制到远程主机的本地文件,可以是绝对路径,也可以是相对路径。如果路径是一个目录,它将递归复制。在这种情况下,如果路径使用“/”来结尾,则只复制目录里的内容,如果没有使用“/”来结尾,则包含目录在内的整个内容全部复制,类似于rsync。
例子01:复制文件
[root@192e168e2e11 ]# touch /tmp/test01
[root@192e168e2e11 ]# ansible 192.168.56.11 -m copy -a "src=/tmp/test01 dest=/opt/test01"
192.168.56.11 | SUCCESS => {
"changed": true,
"checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
"dest": "/tmp/test01",
"gid": 0,
"group": "root",
"mode": "0600",
"owner": "root",
"path": "/tmp/test01",
"size": 0,
"state": "file",
"uid": 0
}
例子02:复制文件并给文件授权
[root@192e168e2e11 ]# ansible 192.168.56.11 -m copy -a "src=/tmp/test01 dest=/opt/test01 mode=600 owner=root group=root"
192.168.56.11 | SUCCESS => {
"changed": true,
"checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
"dest": "/tmp/test01",
"gid": 0,
"group": "root",
"mode": "0600",
"owner": "root",
"path": "/tmp/test01",
"size": 0,
"state": "file",
"uid": 0
}
例子03:复制目录
[root@192e168e2e11 ]# mkdir /tmp/mulu -p
[root@192e168e2e11 ]# touch /tmp/mulu/file{1..10}
[root@192e168e2e11 ]# ls /tmp/mulu/
file1 file10 file2 file3 file4 file5 file6 file7 file8 file9
[root@192-168-56-200 ~]# ansible 192.168.56.11 -m copy -a "src=/tmp/mulu dest=/tmp/"
例子04:复制目录并授权
[root@192e168e2e11 ~]# ansible web -m copy -a "src=/tmp/mulu dest=/opt/"
192.168.2.12 | CHANGED => {
"changed": true,
"dest": "/opt/",
"src": "/tmp/mulu"
}
192.168.2.11 | CHANGED => {
"changed": true,
"dest": "/opt/",
"src": "/tmp/mulu"
}
file模块¶
相关选项如下:
force:需要在两种情况下强制创建软链接,一种是源文件不存在,但之后会建立的情况下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个选项:yes|no
group:定义文件/目录的属组
mode:定义文件/目录的权限
owner:定义文件/目录的属主
path:必选项,定义文件/目录的路径
recurse:递归设置文件的属性,只对目录有效
src:被链接的源文件路径,只应用于state=link的情况
dest:被链接到的路径,只应用于state=link的情况
state:
directory:如果目录不存在,就创建目录
file:即使文件不存在,也不会被创建
link:创建软链接
hard:创建硬链接
touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间
absent:删除目录、文件或者取消链接文件
示例:
(1)远程文件符号链接创建
ansible 192.168.2.12 -m file -a "src=/etc/resolv.conf dest=/tmp/resolv.conf state=link"
(2)远程创建目录并设置文件的权限属性
ansible 192.168.2.12 -m file -a "path=/opt/test02 state=directory mode=600 owner=root group=root"
(3)远程创建文件
ansible 192.168.2.12 -m file -a "path=/tmp/file01 state=touch"
(4)远程删除一个文件
ansible 192.168.2.12 -m file -a "path=/tmp/file01 state=absent"
ping模块¶
[root@192e168e2e11 ~]# ansible 192.168.56.11 -m ping
192.168.56.11 | SUCCESS => {
"changed": false,
"ping": "pong"
}
[root@192e168e2e11 ~]# ansible 192.168.2.11 -m ping
[root@192e168e2e11 ~]# ansible 192.168.2.11,192.168.2.12 -m ping
yum模块¶
(1)安装软件的例子
ansible 192.168.2.12 -m yum -a "name=nginx state=latest"
(2).卸载软件的例子,卸载只需将latest改成absent即可(不推荐使用)
ansible 192.168.2.12 -m yum -a "name=nginx state=absent"
service模块¶
管理被管理段主机的服务
启动服务
ansible 192.168.2.12 -m service -a "name=nginx state=started enabled=yes"
停止服务
ansible 192.168.2.12 -m service -a "name=nginx state=stopped enabled=no"
重启服务
ansible 192.168.2.12 -m service -a "name=nginx state=restarted enabled=no"
script模块¶
Runs a local script on a remote node after transferring it
在远程节点上运行一个本地脚本
例子01:
[root@192e168e2e11 ~]# vim /tmp/date.sh
#!/bin/bash
echo "This is scripts test" >/tmp/test01.txt
本地脚本在远程服务器执行
ansible 192.168.2.12 -m script -a "/tmp/date.sh"
lineinfile模块¶
用于文件内的内容处理
追加内容
ansible 192.168.2.12 -m lineinfile -a "dest=/etc/hosts line='192.168.2.12 192e168e2e12'"
删除内容
ansible 192.168.2.12 -m lineinfile -a "dest=/etc/hosts state=absent line='192.168.2.12 192e168e2e12'"
(1) 在sudo文件中root开头之后加入line=的内容,insertafter可以写正则或EOF(结尾),同理还有insertbefore也可以写正则或BOF(开头)
ansible 192.168.56.11 -m lineinfile -a "dest=/etc/sudoers line='appuser ALL=(ALL) NOPASSWD:ALL' insertafter=^root"
(2) 去掉正则匹配的所有行
ansible 192.168.56.11 -m lineinfile -a "dest=/etc/sudoers state=absent regexp=^appuser"
(3)修改或注释所匹配的行数,比如说禁用selinux
ansible 192.168.56.11 -m lineinfile -a "dest=/etc/selinux/config regexp='^SELINUX=' line='SELINUX=disabled'"
(4)在匹配的内容前增加一行
ansible 192.168.56.11 -m lineinfile -a "dest=/etc/sysconfig/iptables insertbefore='^COMMIT' line='-A INPUT -p tcp --dport 80 -j ACCEPT'"
(5)在匹配的内容后增加一行
ansible 192.168.56.11 -m lineinfile -a "dest=/etc/sysconfig/iptables insertafter='^COMMIT' line='-A INPUT -p tcp --dport 81 -j ACCEPT'"
(6)删除某一行内容
ansible 192.168.56.11 -m lineinfile -a "dest=/etc/sysconfig/iptables state=absent regexp='^-A INPUT -p tcp --dport 81 -j ACCEPT'"
(7)文件存在就添加一行
ansible 192.168.56.11 -m lineinfile -a "dest=/etc/hosts line='192.168.1.1 192_168_1_1'"
(8) 如果匹配到,引用line这一行作为替换。如果没有匹配到,则完全引用line这一行作为添加
ansible 192.168.56.11 -m lineinfile -a "dest=/etc/sudoers state=present regexp='^%wheel' line='%wheel ALL=(ALL) NOPASSWD: ALL'"
2.2.0版本出现的问题:
- hosts: 192.168.56.11
remote_user: root
tasks:
- name: Disabled selinux
lineinfile: dest={{ item.dest }} regexp={{ item.regexp }} line={{ item.line }}
with_items:
- { dest: '/etc/ssh/sshd_config',regexp: '#Port 22',line: 'Port 22' }
- { dest: '/etc/ssh/sshd_config',regexp: '^#Protocol 2',line: 'Protocol 2' }
- { dest: '/etc/ssh/sshd_config',regexp: '#UseDNS yes',line: 'UseDNS no' }
iptables模块¶
添加一条tcp的80端口
ansible 192.168.2.12 -m iptables -a "action=insert chain=INPUT jump=ACCEPT protocol=tcp destination_port=80"
添加一条udp的69端口
ansible 192.168.2.12 -m iptables -a "action=insert chain=INPUT jump=ACCEPT protocol=udp destination_port=69"
删除防火墙规则
ansible 192.168.2.12 -m iptables -a "action=insert state=absent chain=INPUT jump=ACCEPT protocol=tcp destination_port=80"
生产环境配置防火墙例子:
- name: Config accept tcp rule insert to elasticsearch iptables
iptables: action=insert chain=INPUT jump=ACCEPT protocol=tcp destination_port={{ item }}
with_items:
- "{{ elasticsearch_iptables_accept_tcp_port }}"
tags: install_config_elasticsearch
- name: Insert tcp rule to /etc/sysconfig/iptables
lineinfile:
path: /etc/sysconfig/iptables
insertafter: '^:OUTPUT ACCEPT '
line: '-A INPUT -p tcp -m tcp --dport {{ item }} -j ACCEPT'
with_items:
- "{{ elasticsearch_iptables_accept_tcp_port }}"
tags: install_config_elasticsearch
mysql相关模块¶
1.启动数据库
ansible 192.168.56.11 -m service -a "name=mariadb state=started enabled=yes"
2.创建数据库
ansible 192.168.56.11 -m mysql_db -a "name=zabbix state=present encoding=utf8"
3.创建数据库用户并授权
ansible 192.168.56.11 -m mysql_user -a "name=zabbix password=zabbix priv='zabbix.*:ALL,GRANT' state=present"
cd /usr/share/doc/zabbix-server-mysql-3.0.8
zcat create.sql.gz >/root/create.sql
4.导入数据库。从sql文件中导入
ansible 192.168.56.11 -m mysql_db -a "name=zabbix state=import target=/root/create.sql"
synchronize模块¶
sync数据同步文件等
http://www.mamicode.com/info-detail-1313203.html
选项说明
archive # 是否采用归档模式同步,即以源文件相同属性同步到目标地址
checksum # 是否效验
compress # 开启压缩,默认为开启
copy_links # 同步的时候是否复制连接
delete # 删除源中没有而目标存在的文件(即以推送方为主)
dest= # 目标地址
dest_port # 目标接受的端口,ansible配置文件中的 ansible_ssh_port 变量优先级高于该 dest_port 变量
dirs # 以非递归的方式传输目录
existing_only # Skip creating new files on receiver.
group # Preserve group
links # Copy symlinks as symlinks.
mode # 模式,rsync 同步的方式 PUSH\PULL,默认都是推送push。如果你在使用拉取pull功能的时候,可以参考如下来实现mode=pull 更改推送模式为拉取模式
recursive # 是否递归 yes/no
rsync_opts # 使用rsync 的参数
rsync_path # 服务的路径,指定 rsync 命令来在远程服务器上运行。这个参考rsync命令的--rsync-path参数,--rsync-path=PATH # 指定远程服务器上的rsync命令所在路径信息
rsync_timeout # 指定 rsync 操作的 IP 超时时间,和rsync命令的 --timeout 参数效果一样.
set_remote_user # put user@ for the remote paths. If you have a custom ssh config to define the remote user for
src=\‘#\‘" # 源,同步的数据源
times #
--exclude=.Git 忽略同步.git结尾的文件
由于模块默认启用了archive参数,该参数默认开启了recursive, links, perms, times, owner,group和-D参数。如果你将该参数设置为no,那么你将停止很多参数,比如会导致如下目的递归失败,导致无法拉取
使用rsync 模块,系统必须安装rsync 包,否则无法使用这个模块
如果有将远程服务器上的文件同步到管理服务器的需求,那么就需要此模块
[root@192e168e2e12 ~]# touch /tmp/file1
[root@192e168e2e12 ~]# echo "nihao" >/tmp/file1
[root@192e168e2e11 ~]# ansible 192.168.2.12 -m synchronize -a "mode=pull src=/tmp/file1 dest=/tmp/ archive=yes checksum=yes"
[root@192e168e56e200 tasks]# ll /tmp/file1
-rw-r--r-- 1 root root 0 Jul 3 22:52 /tmp/file1
unarchive模块¶
用于解压文件,模块包含如下选项:
copy:在解压文件之前,是否先将文件复制到远程主机,默认为yes。若为no,则要求目标主机上压缩包必须存在。
creates:指定一个文件名,当该文件存在时,则解压指令不执行
dest:远程主机上的一个路径,即文件解压的路径
grop:解压后的目录或文件的属组
list_files:如果为yes,则会列出压缩包里的文件,默认为no,2.0版本新增的选项
mode:解决后文件的权限
src:如果copy为yes,则需要指定压缩文件的源路径
owner:解压后文件或目录的属主
示例如下:
- unarchive: src=foo.tgz dest=/var/lib/foo
- unarchive: src=/tmp/foo.zip dest=/usr/local/bin copy=no
- unarchive: src=https://example.com/example.zip dest=/usr/local/bin copy=no
数据库文件复制实例:
- name: Tar mariadb file to /usr/local
unarchive: src=/usr/local/{{ mariadb }} dest=/usr/local/ remote_src=yes
生成数据:
[root@192e168e2e11 ~]# mkdir -p test01
[root@192e168e2e11 ~]# touch /root/test01/file{1..10}.txt
[root@192e168e2e11 ~]# tar zcf test01.tar.gz test01
使用例子:
ansible 192.168.2.11 -m unarchive -a 'src=/root/test01.tar.gz dest=/usr/local/src/ copy=no mode=0755'
fetch 模块¶
用途:用于从 远程主机
中拷贝文件到 管理主机
注意:不能拷贝目录
ansible 192.168.2.11 -m fetch -a "src=/var/log/messages dest=/opt/"
ansible web -m fetch -a "src=/var/log/messages dest=/opt/"
setup模块¶
## 用来查看远程主机的一些基本信息,或者一些远程服务器变量的引用
ansible 192.168.2.12 -m setup
1.setup获取ipv4信息
ansible 192.168.2.12 -m setup -a "filter=ansible_all_ipv4_addresses"
2.获取内存信息
ansible 192.168.2.12 -m setup -a "filter=ansible_memory_mb"
3.通过通配符实现模糊匹配,比如以”mb”关键字结尾的信息。
ansible 192.168.2.12 -m setup -a "filter=*mb"
常用关键字
ansible_all_ipv4_addresses #所有机器的ipv4地址
ansible_all_ipv6_addresses #所有机器的ipv6地址
ansible_date_time #系统时间
ansible_kernel #内核版本
ansible_default_ipv4 #默认机器的ipv4地址
ansible_default_ipv6 #默认机器的ipv6地址
ansible_distribution #linux系统发行版本,如centos,ubuntu,debian等
ansible_nodename #主机名
ansible_pkg_mgr #包管理器
ansible_python_version #python版本
ansible变量应用¶
变量的命名规范¶
只能包含数字,下划线,字母 只能用下划线或字母开头
引用系统内置变量¶
大家肯定疑问,这个facts是个啥?
facts组件是Ansible用于采集被管理机器设备信息的一个功能,采集的机器设备信息主要包含IP地址,操作系统,以太网设备,mac 地址,时间/日期相关数据,硬件信息等。
那话又说回来了,采集这些信息有什么用呢?有的时候我们需要根据远程主机的信息作为执行条件操作,例如,根据远程服务器使用的操作系统版本,可以安装不同版本的软件包;或者也可以显示与每台远程计算机相关的一些信息,例如每台设备上有多少RAM可用。
所以,在一些业务场景中,facts对我们是很有帮助的,省去了我们好多工作,大大提高了工作效率。
ansible 192.168.2.12 -m setup
由于输出的内容实在是太多了,我们可以使用filter
参数来查看指定的信息,比如这样:
ansible 192.168.2.12 -m setup -a 'filter=ansible_all_ipv4_addresses'
ansible 192.168.2.12 -m setup -a 'filter=ansible_os_family'
例子01:查看远程服务器的IP地址
[root@192e168e2e11 ansible]# vim test.yml
- hosts: 192.168.2.12
remote_user: root
tasks:
- name: IPADDR {{ ansible_all_ipv4_addresses }} {{ ansible_os_family }}
shell: echo IPADDR {{ ansible_all_ipv4_addresses }}
register注册变量¶
ansible register 这个功能非常有用。当我们需要判断对执行了某个操作或者某个命令后,如何做相应的响应处理(执行其他 ansible 语句),则一般会用到register 。
我们需要判断sdc是否存在,如果存在了就执行一些相应的脚本,则可以为该判断注册一个register变量,并用它来判断是否存在,存在返回 succeeded, 失败就是 failed.
[root@192e168e2e11 ~]# cd /etc/ansible
[root@192e168e2e11 ansible]# vim test.yml
- hosts: 192.168.2.12
remote_user: root
tasks:
- name: /dev/sdc disk is exsit
shell: lsblk |grep sda|wc -l
register: result
ignore_errors: True
- name: echo {{ result.stdout }}
shell: echo "disk is ok" >>/tmp/disk.txt
when: result.stdout == '0'
通过命令行传递变量¶
创建一个test.yml的剧本
[root@192e168e2e11 ansible]# vim test.yml
- hosts: 192.168.2.12
remote_user: root
tasks:
- name echo {{ vars01 }} {{ vars02 }}
shell: echo
在运行playbook的时候也可以传递一些变量供playbook使用
[root@192e168e2e11 ansible]# ansible-playbook test.yml --extra-vars "vars01=zhangsan vars02=lisi"
PLAY [192.168.2.12] *********************************************************************************
TASK [Gathering Facts] ******************************************************************************
ok: [192.168.2.12]
TASK [echo zhangsan lisi] ***************************************************************************
changed: [192.168.2.12]
PLAY RECAP ******************************************************************************************
192.168.2.12 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
引用主机清单变量¶
例子02:也可以在host文件中去定义变量
[root@192e168e2e11 ansible]# vim hosts
[web]
192.168.2.11 USER=zhangsan
192.168.2.12 USER=zhangsan
[web:vars]
ansible_ssh_port=22
ansible_ssh_user=root
ansible_ssh_pass=P@sswd
YUM_IPADDR=192.168.2.241
yml配置文件修改如下
[root@192e168e2e11 ansible]# vim test.yml
- hosts: 192.168.2.12
remote_user: root
tasks:
- name: YUM {{ YUM_IPADDR }} {{ USER }}
shell: echo YUM {{ YUM_IPADDR }} {{ USER }}
playbook定义变量¶
我们一般可以在playbook剧本中去定义变量
[root@192e168e2e11 ansible]# cat test.yml
- hosts: 192.168.2.12
remote_user: root
vars:
USER: zhangsan
PASS: 123456
tasks:
- name: echo {{ USER }} {{ PASS }}
shell: echo
在文件中定义变量¶
我们可以创建一个文件,在文件中定义变量,并使用yml文件引用文件中的变量
[root@192e168e2e11 ansible]# vim vars_list.yml
USER: zhangsan
PASS: 123456
PORT:
- 22
- 23
- 80
[root@192e168e2e11 ansible]# cat test.yml
- hosts: 192.168.2.12
remote_user: root
vars_files:
- ./vars_list.yml
tasks:
- name: echo {{ USER }} {{ PASS }}
shell: echo
执行结果如下:
[root@192e168e2e11 ansible]# ansible-playbook test.yml
PLAY [192.168.2.12] *********************************************************************************
TASK [Gathering Facts] ******************************************************************************
ok: [192.168.2.12]
TASK [echo zhangsan 123456 [22, 23, 80]] ***********************************************************
changed: [192.168.2.12]
PLAY RECAP ******************************************************************************************
192.168.2.12 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
通过roles传递变量¶
当给一个主机应用角色的时候可以传递变量,然后再角色内使用这些变量
- hosts: 192.168.2.12
roles:
- common
- { role: foo_app_instance, dir:’/web/htdocs/a.com’, port: 8080 }
facts变量的缓存¶
https://www.cnblogs.com/zhangmingcheng/p/13964564.html
Ansible facts 是远程系统的信息,主要包含IP地址,操作系统,以太网设备,mac 地址,时间/日期相关数据,硬件信息等信息。
Ansible facts 对于需要根据远程主机的信息作为执行条件操作的场景非常有用。例如,根据远程服务器使用的操作系统版本,可以安装不同版本的软件包。或者也可以显示与每台远程计算机相关的一些信息,例如每台设备上有多少 RAM 可用。
不同网络环境下的耗时肯定是不同的,但是设置缓存是肯定可以加快 Ansible 运行速度的,特别是 playbook 的运行。
另外,可以在空闲时间手动进行 facts 缓存的更新,从而避免执行真正的任务时再去更新缓存。
[root@localhost ansible]# cat ansible.cfg
gathering = smart
log_path = ./logs/ansible.log
fact_caching = jsonfile
fact_caching_connection = ./facts
fact_caching_timeout = 86400
Inventory列表¶
ansible的主要功能用于批量主机操作,为了便捷的使用其中的部分主机,可以在inventory file中将其分组命名,
默认的inventory为/etc/ansible/hosts
Inventory列表格式¶
inventory文件遵循INI文件风格,中括号中的字符为组名,可以将同一个主机同事归并到多个不同的组中,此外,当如若目标主机使用啦非默认的SSH端口,还可以在主机名称之后使用冒号加端口号来标明
[test01]
192.168.56.11
192.168.56.[12:15]
www.[01.03].com
[test02]
192.168.56.16
www1.chris.com
www-[a:f].example.com
Inventory主机变量¶
可以在inventory中定义主机时为其添加主机变量以便于在playbook中使用
[test01]
192.168.56.11 http_port=80
Inventory组变量¶
组变量是指赋予给指定组内所有主机上的在playbook中可用的变量
[test01]
192.168.56.11 http_port=80
[test01:vars]
ansible_ssh_user="root"
ansible_ssh_pass="123456"
YUM_IPADDR=110.76.187.100
NTP_SERVER=110.76.187.100
Inventory组嵌套¶
inventory中,组还可以包含其他的组,并且也可以向组中的主机指定变量,不过,这些变量只能在ansible-playbook中使用,而ansible不支持:
[test01]
192.168.56.11
[test02]
192.168.56.12
[test_zong:children]
test01
test02
[test_zong:vars]
ansible_ssh_user="root"
ansible_ssh_pass="123456"
YUM_IPADDR=110.76.187.100
NTP_SERVER=110.76.187.100
inventory常用参数¶
ansible_ssh_host
将要连接的远程主机名.与你想要设定的主机的别名不同的话,可通过此变量设置.
ansible_ssh_port
ssh端口号.如果不是默认的端口号,通过此变量设置.
ansible_ssh_user
默认的 ssh 用户名
ansible_ssh_pass
ssh 密码(这种方式并不安全,我们强烈建议使用 --ask-pass 或 SSH 密钥)
ansible_sudo_pass
sudo 密码(这种方式并不安全,我们强烈建议使用 --ask-sudo-pass)
ansible_sudo_exe (new in version 1.8)
sudo 命令路径(适用于1.8及以上版本)
ansible_connection
与主机的连接类型.比如:local, ssh 或者 paramiko. Ansible 1.2 以前默认使用 paramiko.1.2 以后默认使用 'smart','smart' 方式会根据是否支持 ControlPersist, 来判断'ssh' 方式是否可行.
ansible_ssh_private_key_file
ssh 使用的私钥文件.适用于有多个密钥,而你不想使用 SSH 代理的情况.
ansible_shell_type
目标系统的shell类型.默认情况下,命令的执行使用 'sh' 语法,可设置为 'csh' 或 'fish'.
ansible_python_interpreter
目标主机的 python 路径.适用于的情况: 系统中有多个 Python, 或者命令路径不是"/usr/bin/python",比如 \*BSD, 或者 /usr/bin/python
不是 2.X 版本的 Python.我们不使用 "/usr/bin/env" 机制,因为这要求远程用户的路径设置正确,且要求 "python" 可执行程序名不可为 python以外的名字(实际有可能名为python26).
与 ansible_python_interpreter 的工作方式相同,可设定如 ruby 或 perl 的路径....
主机配置文件示例:
[targets]
localhost ansible_connection=local
other1.example.com ansible_connection=ssh ansible_ssh_user=mpdehaan
other2.example.com ansible_connection=ssh ansible_ssh_user=mdehaan
更多详见:
http://docs.ansible.com/ansible/index.html
主机组变量引用¶
{{ groups['web'].0 }} {{ groups['web'].1 }}
{{ ceph_all[0] }}
ansible ceph_all[0] -m copy -a "src=../jijia.conf dest=/tmp/"
- hosts: localhost
remote_user: root
tasks:
- name: IPADDR {{ groups['ceph_all'] }}
shell: echo {{ item }}
with_items:
- "{{ groups['ceph_all'] }}"
- hosts: ceph_all
remote_user: root
tasks:
- name: IPADDR {{ groups['ceph_all'] }} {{ ansible_hostname }}
shell: echo {{ item }} {{ ansible_hostname }} >> /tmp/ip.txt
run_once: true
delegate_to: localhost
with_items:
- "{{ groups['ceph_all'] }}"
playbooks剧本深入¶
核心元素:
1.tasks:任务
2.variables:变量
3.templates:模板
4.handers:处理器
5.roles角色
playbook的组成:playbook是由一个或多个“play”组成的列表,可以让它们联同起来按事先编排的机制执行;所谓task无非是调用ansible的一个module,而在模块参数中可以使用变量;模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致;
执行模型:task list中的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后再开始第二个。在顺序运行某playbook时,如果中途发生错误,所有已执行任务都将回滚,因此,在修改playbook后重新执行一次即可;
task组成:每个task都应该有其name,用于playbook的执行结果输出,建议其内容尽可能清晰地描述任务执行步骤。如果未提供name,则action的结果将用于输出;
notify指定handler的执行机制:“notify”这个action可用于在每个play的最后被触发,在notify中列出的操作称为handler,仅在所有的变化发生完成后一次性地执行指定操作。
YAML入门¶
YAML介绍¶
YAML是一个可读性高的用来表达资料序列的格式,YAML参考了其他多种语言,包括XML,C语言,Python,Perl以及电子邮件格式,Clark Evans在2001年首次发表了这种语言。
特性:
YAML的可读性好
YAML和脚本语言的交互性好
YAML使用实验的语言的数据类型
YAML有一个一致的信息模型
YAML易于实现
YAML表达能力强,扩展性好
YAML语法¶
多行缩进
数据结构可以用类似大纲的缩排方式呈现,结构通过缩进来表示,连续的项目通过减号“-”来表示,map结构里面的key/value对用冒号“:”来分隔。样例如下:
house:
family:
name: Doe
parents:
- John
- Jane
children:
- Paul
- Mark
- Simone
address:
number: 34
street: Main Street
city: Nowheretown
zipcode: 12345
注意:
字串不一定要用双引号标识;
在缩排中空白字符的数目并不是非常重要,只要相同阶层的元素左侧对齐就可以了(不过不能使用TAB字符);
允许在文件中加入选择性的空行,以增加可读性;
在一个档案中,可同时包含多个文件,并用“——”分隔;
选择性的符号“...”可以用来表示档案结尾(在利用串流的通讯中,这非常有用,可以在不关闭串流的情况下,发送结束讯号)。
list列表¶
列表的所有元素均使用 “-” 开头 例子如下
- test01
- test02
- test03
YAML生产例子¶
安装nginx的总体步骤,安装,配置,启动
[root@linux-node1 ansible]# cat nginx.yml
- hosts: test
remote_user: root
tasks:
- name: install a pkg
yum: name=nginx state=latest
# - name: copy conf file nginx.conf
# copy: src=/tmp/nginx.conf dest=/etc/nginx/nginx.conf
- name: start nginx service
service: name=nginx state=started enabled=yes
playbooks入门¶
playbook是由一个或多个play组成的列表,play的主要功能在于先归并为一组的主机装扮成事先通过ansible中的task定义好的角色,从根本上来讲,所谓task无非是调用一个module,将多个play组织在一个playbook中,即可以让他们连同起来事先编排的机制同唱一个大戏
组成结构¶
├── group_vars #放置各种变量的目录,我这里没用
├── hosts #主机和组配置,默认为/etc/ansible/hosts
├── roles #角色目录,里边可以有多个角色,这里只配置了一个common
│ └── common
│ ├── files #用于文件或目录分发的目录
│ ├── handlers #放置处理程序,如重启某个服务
│ │ └── main.yml
│ ├── tasks #任务列表
│ │ └── main.yml
│ └── templates #放置模板目录,这里未用
└── site.yml #主入口配置,ansible-playbook 执行的第一个参数,也可以叫别的名称
文件内容¶
(1)hosts
[ctx-lf-web]
10.199.72.34
[ctx-bj-web]
10.0.32.34
[ctx-lf-db]
10.199.134.21
[ctx-bj-db]
10.0.32.39
[ctx-web:children] #通过这种方式,将lf和bj这2个组的主机都归类为ctx-web中,这样后续site.yml的host绑定ctx-web就可以操作以下两个分组
ctx-lf-web
ctx-bj-web
[ctx-db:children]
ctx-lf-db
ctx-bj-db
[ctx-bj:children]
ctx-bj-web
ctx-bj-db
[ctx-lf:children]
ctx-lf-web
ctx-lf-db
(2) site.yml文件
---
- hosts: [ctx-bj, ctx-db] #可以选择多个分组,这个要和hosts中能找到
remote_user: sre #因为需要通过远端普通用户使用sudo的方式,所以还需要配置sudo
sudo: yes
roles:
- common #将hosts和common这个角色绑定,这个common需要在roles目录中存在
(3) init/tasks/main.yml文件
[root@192-168-56-200 roles]# cat init/tasks/main.yml
---
- include: base.yml
#- include: ssh_pubkey_send.yml
#- include: optimize_users_and_groups.yml
基础组件¶
host和user
playbook中的每一个play的目的都是为了让某个或某些主机以某个指定的用户身份执行任务,
hosts用于指定任务的主机,其可以是一个或多个由冒号分割主机组:
remote_user用于指定远程主机上的执行任务的用户
- hosts: 192.168.56.11
remote_user: root
任务列表和action¶
Playbooks的主体部分是task list,task list中的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成每一个任务后再开始第二个,在运行自下而下某个playbook时,如果中途发生错误,所有已执行任务都将回滚,因此,在更正playbooks后重新执行一次即可,task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量,模块执行时幂等的,这意味着多次执行时安全的,因为其结果均一致,每个task都应该有其name,用于playbook的执行结果输出,建议其内容尽可能清晰地描述任务步骤,如何未提供name,则action的结果将用于输出
简单任务列表例子¶
例子01:创建一个nginx用户的
- hosts: 192.168.56.11
remote_user: root
tasks:
- name: create nginx group
group: name=nginx system=yes gid=208
- name: create nginx user
user: name=nginx uid=208 group=nginx system=yes
例子02:安装httpd服务
- hosts: 192.168.56.11
remote_user: root
tasks:
- name: install httpd package
yum: name=httpd state=latest
- name: install config file for httpd
copy: src=/etc/httpd/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
- name: start httpd service
service: enabled=true name=httpd state=started
忽略错误信息¶
如果想忽略当前执行的tasks的错误,继续执行下一个,可以使用ignore_errors
- name: 02-temporary Disabled selinux
shell: setenforce 0
ignore_errors: True
playbooks深入¶
handlers¶
用于当关注的资源发生变化时采取一定的操作,
notify这个action可用于在每个play的最后被触发,这样可以避免多次有改变发生时每次都执行指定的操作,仅在所有的变化完成后一次性执行指定操作,在notify中列出的操作称为handler,也即notify中调用handler中定义的操作
- hosts: 192.168.56.11
remote_user: root
tasks:
- name: install httpd package
yum: name=httpd state=latest
- name: install config file for httpd
copy: src=/etc/httpd/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify: restart httpd service
- name: start httpd service
service: enabled=true name=httpd state=started
handlers:
- name: restart httpd service
service: enabled=true name=httpd state=restarted
条件测试¶
在有的时候play的结果依赖于变量、fact或者是前一个任务的执行结果,从而需要使用到条件语句。
例子01:当系统的发行版本为RedHat的时候,则输出如下内容
- hosts: 192.168.56.11
remote_user: root
tasks:
- name: This is test
command: echo "This is test and"
#when: ansible_os_family == "RedHat"
when: ansible_os_family == "Debian"
例子02:当主机名称为192-168-56-11的时候,创建一个user10的用户
- hosts: 192.168.56.11
remote_user: root
vars:
- username: user10
tasks:
- name: create {{ username }} user
user: name={{ username }}
when: ansible_fqdn == "192-168-56-11"
例子03:生产环境的例子
- name: Copy zabbix.repo to centos6
template: src=templates/zabbix_centos6.repo dest=/etc/yum.repos.d/zabbix.repo
when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "6"
变量得出的方法
[root@192-168-56-200 test]# ansible 192.168.56.11 -m setup|grep ansible_distribution_major_version
"ansible_distribution_major_version": "7",
迭代测试¶
当有需要重复性执行的任务时,可以使用迭代机制,其使用格式为将需要的迭代的内容定义为item。并通过with_items语句来指明迭代元素列表即可
重复性的语句
- name: add user testuser1
user: name=testuser1 state=present groups=wheel
- name: add user testuser2
user: name=testuser2 state=present groups=wheel
简单的写法
- name: add serveral user
user: name={{ item }} state=present groups=wheel
with_items:
- testuser1
- testuser2
事实上,with_items中可以使用元素,
- hosts: 192.168.56.11
remote_user: root
tasks:
- name: add several users
user: name={{ item.name }} state=present groups={{ item.groups }}
with_items:
- { name: 'testuser1', groups: 'wheel' }
- { name: 'testuser2', groups: 'root' }
tags标签¶
tags用于让用户选择运行或跳过playbook中的部分代码,ansible具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时候依然会比较长,此时确信其没有变化,就可以通过tags跳过这些代码。
tags:在playbook可以为某个或某些任务定义一个标签,在执行此playbook时,通过为ansible-playbook命令使用 --tags选项能实现仅运行指定的task而非所有的
- hosts: 192.168.56.11
remote_user: root
tasks:
- name: add user testuser1
user: name=testuser1 state=present groups=wheel
- name: add user testuser2
user: name=testuser2 state=present groups=wheel
tags: add_testuser2
运行如下
ansible-playbook test01.yml --tags="add_testuser2"
meta依赖关系¶
meta/main.yml 用来配置模块一些元信息,比如支持的平台,Ansible最小依赖版本,
这个模块的标签,依赖,作者的信息等等。
ansible-galaxy init 创建项目生成的模板如下
---
galaxy_info:
author: Sébastien Han
description: Installs Ceph Monitor
license: Apache
min_ansible_version: 1.7
platforms:
- name: Ubuntu
versions:
- trusty
categories:
- system
dependencies:
- { role: ceph.ceph-common, when: not containerized_deployment }
- { role: ceph.ceph-docker-common, when: containerized_deployment }
roles角色入门¶
简单介绍¶
ansible自1.2版本引入的新特性,用于层次性,结构化组织playbook,roles能够根据层次结构自动装载变量文件,task以及handlers等,要使用roles只需在playbook中使用include指令即可,简单来讲,roles就是通过分别将变量,任务,模块及处理器放置于单独的目录中,并可以便捷地include他们的一种机制,角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中。
创建role的步骤¶
(1)创建以roles命名的目录
(2)在roles目录中分别创建以各角色命令的目录,如webservers等
(3)在每个角色命名的目录中分别创建files,handlers,meta,task,templates和vars目录,用不到的目录可以创建为空目录,也可以不创建
(4)在playbook文件中。使用各角色
role目录结构¶
目录结构:
├── roles #角色目录,里边可以有多个角色,这里只配置了一个common
│ └── common
│ ├── files #用于文件或目录分发的目录
│ ├── handlers #放置处理程序,如重启某个服务
│ │ └── main.yml
│ ├── tasks #任务列表
│ │ └── main.yml
│ └── templates #放置模板目录,这里未用
目录详解:
task目录:至少包含一个名为main.yml的文件,其定义了此角色的任务列表,此文件可以使用include包含其他位于此目录的task文件。
files目录:存放于copy或scripts等模块调用的文件
templates目录: template模块会自动在此目录中寻找Jinja2模板文件
handlers目录:此目录中应该包含一个main.yml文件,用于定义此角色用到的各handler,在handler中使用include包含的其他的handler文件也应该位于此目录中
vars目录:应当包含一个main.yml文件,用于定义此角色用到的变量
meta目录:应当包含一个main.yml文件,用于定义此角色的特殊设定及其依赖关系
default目录:为当前角色设定默认变量时使用此目录,应当包含一个main.yml文件
实战role¶
Playbooks代码规范¶
1.代码脚本的层级规范为4格一个层级
role_init () {
HOSTVAR=([yum_repo_host]='base.yml' \
[ntp_server_host]='chrony_install_and_config.yml' \
[ntp_server_host]='ntp_install_and_config.yml' \
[dns_server_host]='dns_config.yml')
TACK_PATH="./roles/init/tasks/main.yml"
VARS_PATH="./group_vars/all"
check_fun "${!HOSTVAR[*]}" "${HOSTVAR[*]}" "${#HOSTVAR[@]}" $TACK_PATH $VARS_PATH
}
2.playbook文件的名称统一首字母小写
[root@192-168-56-200 tasks]# ll
total 68
-rw-r--r-- 1 root root 534 Jun 9 17:38 add_user.yml
-rw-r--r-- 1 root root 1385 Jun 9 17:38 base.yml
-rw-r--r-- 1 root root 212 Jun 9 17:38 chrony_install_and_config.yml
3.单词与名称的连接最好统一使用下划线进行连接
\4. playbook文件的内容中,name的名称都统一首字母大写
5.tags名称统一首字母小写
6.playbook文件统一使用include的方式进行编写
7.提交commit的时候一定要有标题,然后接着是内容
commit c5b821c695db62468e0e354e3e95c6471de55cc2
Author: huangwenguang <2393470186@qq.com>
Date: Mon May 8 20:03:10 2017 +0800
Initialize the system
Add a role to the initialization system, and the default includes the following:
1.Password length and account limits
2.Stop the system service NetworkManager and firewalled
3.The Hostname config
4.The sshd and ssh config
5.Cover the CentOS-Base repository
other options:
1.Configure SSH authentication
2.Optimize users and groups
3.Add user
4.Limits configuration
5.The history size configuration
6.Disabled selinux
7.Copy epel repository
8.Installation packages include vim net-tools ntpdate
9.Chrony install and config
10.Network adapter configuration
11.The system kernel configuration
12.Dns configuration
13.Reboot the system
8.如果你加入的是新功能的话,那么一定要创建一个新的分支,新的分支的名称一定简单易懂
9.每个task任务之间需要空一行,保持代码的可读性
Ansible使用循环¶
标准循环¶
模式1:标准循环
[root@192-168-56-200 test]# cat test01.yml
- hosts: 192.168.56.11
remote_user: root
tasks:
- name: add several users
user: name={{ item }} state=present groups=wheel
with_items:
- testuser1
- testuser2
#------------------end
or
with_items: "{{ somelist }}"
模式2:字典循环
- hosts: 192.168.56.11
remote_user: root
tasks:
- name: add several users
user: name={{ item.name }} state=present groups={{ item.groups }}
with_items:
- { name: 'testuser1', groups: 'wheel' }
- { name: 'testuser2', groups: 'root' }
嵌套循环¶
- hosts: 192.168.56.11
remote_user: root
tasks:
- name: give users access to multiple databases
command: "echo name={{ item[0] }} priv={{ item[1] }} test={{ item[2] }}"
with_nested:
- [ 'alice', 'bob' ]
- [ 'clientdb', 'employeedb', 'providerdb' ]
- [ '1', '2', ]
字典循环¶
- hosts: 192.168.56.11
remote_user: root
vars:
users:
alice:
name: Alice Appleworth
telephone: 123-456-7890
bob:
name: Bob Bananarama
telephone: 987-654-3210
tasks:
- name: Print phone records
debug: msg="User {{ item.key }} is {{ item.value.name }} ({{ item.value.telephone }})"
with_dict: "{{ users }}"
文件循环¶
with_file 是将每个文件的文件内容作为item的值
with_fileglob 是将每个文件的全路径作为item的值, 在文件目录下是非递归的, 如果是在role里面应用改循环, 默认路径是roles/role_name/files_directory
准备环境
[root@192-168-56-200 test]# mkdir /tmp/file -p
[root@192-168-56-200 test]# touch /tmp/file/file{1..20}
(1) with_file例子
- hosts: 192.168.56.11
remote_user: root
tasks:
- copy: src={{ item }} dest=/opt/file/ owner=root mode=600
with_fileglob:
- /tmp/file/*
(2)with_together例子
- hosts: 192.168.56.11
remote_user: root
tasks:
- command: echo "msg={{ item.0 }} and {{ item.1 }}"
with_together:
- [ 1, 2, 3 ]
- [ 4, 5 ]
子元素循环¶
with_subelements 有点类似与嵌套循环, 只不过第一个参数是个dict, 第二个参数是dict下的一个子项.
整数序列(with_sequence)with_sequence 产生一个递增的整数序列,
- hosts: 192.168.56.11
remote_user: root
tasks:
# create groups
- group: name=evens state=present
- group: name=odds state=present
# create some test users
- user: name={{ item }} state=present groups=evens
with_sequence: start=0 end=32 format=testuser%02x
# create a series of directories with even numbers for some reason
- file: dest=/var/stuff/{{ item }} state=directory
with_sequence: start=4 end=16 stride=2
# a simpler way to use the sequence plugin
# create 4 groups
- group: name=group{{ item }} state=present
with_sequence: count=4
flatten循环¶
- hosts: 192.168.56.11
remote_user: root
tasks:
- name: Example of looping over a command result
shell: echo {{ item }}
with_flattened:
- [1, 2, 3]
- [[3,4 ]]
- [ ['red-package'], ['blue-package']]
register循环¶
- hosts: 192.168.56.11
remote_user: root
tasks:
- shell: echo "{{ item }}"
with_items:
- one
- two
register: echo
变量echo是一个字典, 字典中result是一个list, list中包含了每一个item的执行结果
inventory循环¶
- hosts: 192.168.56.11
remote_user: root
tasks:
# show all the hosts in the inventory
- debug: msg={{ item }}
with_inventory_hostnames: all
# show all the hosts matching the pattern, ie all but the group www
- debug: msg={{ item }}
with_inventory_hostnames: all:!www
ansible-tower web界面¶
准备环境¶
1.The Tower installer creates a self-signed SSL certificate and keyfile at /etc/tower/tower.cert and /etc/tower/tower.key for HTTPS communication. These can be replaced after install with your own custom SSL certificates if you desire, but the filenames are required to be the same.(如果需要替换之前的/etc/tower/tower.cert、/etc/tower/tower.key证书,需要保证替换之后的证书和之前的证书名称相同)
2.If using Ansible version 1.8 or later, ensure that fact caching using Redis is not enabled in ansible.cfg on the Tower machine.(如果使用可执行版本1.8或更高版本,请确保在Ansible Tower上的ansible.cfg中未启用使用Redis的fact caching。)
3.Note that the Tower installation must be run from an internet connected machine that can install software from trusted 3rd-party places such as Ansible’s software repository, and your OS vendor’s software repositories.(请注意,Tower安装必须通过互联网连接的机器运行,该机器可以从可靠的第三方场所安装软件,如Ansible的软件仓库和您的OS供应商的软件库。)
4.(1)支持的操作系统:
Red Hat Enterprise Linux 7 64-bit
CentOS 7 64-bit
Ubuntu 14.04 LTS 64-bit
Ubuntu 16.04 LTS 64-bit
注意:Ansible Tower requires Red Hat Enterprise Linux 7.2 or later.
(2)最少2G内存,推荐4G+内存
(3)20 GB of dedicated hard disk space(20 GB专用硬盘空间)
10 GB of the 20 GB requirement must be dedicated to /var/, where Tower stores its files and working directories (dedicating less space will cause the installation to fail)
(4)64-bit support required (kernel and runtime)
安装过程¶
1.下载ansible tower
下载地址:http://releases.ansible.com/ansible-tower/setup/
含有安装包文件的版本:http://releases.ansible.com/ansible-tower/setup-bundle/
2.安装ansible tower
a.设置主机信息
sed -i "s#admin_password=''#admin_password='123456'#g" inventory
sed -i "s#pg_host=''#pg_host='127.0.0.1'#g" inventory
sed -i "s#pg_port=''#pg_port='5432'#g" inventory
3.安装postgresql数据库(YUM安装)
yum install http://download.postgresql.org/pub/repos/yum/9.4/redhat/rhel-7.2-x86_64/pgdg-redhat94-9.4-3.noarch.rpm
yum install postgresql94-server postgresql94-contrib
- 设置开机启动
systemctl enable postgresql-9.4.service
5.初始化数据库
/usr/pgsql-9.4/bin/postgresql94-setup initdb
\6. 启动postgresql
service postgresql-9.4 start
\7. 创建用户
su - postgres
-bash-4.2$ psql
postgres=# CREATE ROLE awx CREATEDB PASSWORD 'admin' LOGIN;
postgres=# \q
-bash-4.2$ exit
sed -i 's#peer#md5#g' /var/lib/pgsql/9.4/data/pg_hba.conf
sed -i 's#ident#md5#g' /var/lib/pgsql/9.4/data/pg_hba.conf
service postgresql-9.4 restart
\8. 测试awx用户连接,输入密码连接,并创建数据库
-bash-4.2$ psql -U awx -d postgres -h 127.0.0.1
postgres=# create database awx;
postgres=# \q
9.配置相关的参数
[root@192-168-56-17 ansible-tower-setup-bundle-3.0.3-1.el7]# vim inventory
[primary]
localhost ansible_connection=local
[secondary]
[database]
[all:vars]
admin_password='123456'
redis_password='123456'
pg_host='127.0.0.1'
pg_port='5432'
pg_database='awx'
pg_username='awx'
pg_password='admin'
10.开始安装ansibler-tower
[root@192-168-56-17 ansible-tower-setup-bundle-3.0.3-1.el7]# ./setup.sh
出现如下界面,则表示安装完成
PLAY RECAP *********************************************************************
localhost : ok=109 changed=45 unreachable=0 failed=0
The setup process completed successfully.
Setup log saved to /var/log/tower/setup-2017-06-15-11:13:01.log
Ansibel相关优化¶
1.开启ansible任务的执行时间
[defaults]
callback_whitelist = timer,profile_tasks
2.fork 提高并行执行主机数量
[defaults]
fork = 100
3.poll_interval:降低轮询间隔时间,有助于加快获取任务结果
[defaults]
poll_interval = 1
internal_poll_interval = 0.001
4.fact_cache:将facts信息第一次收集后缓存到Memcache/Redis或者文件中
[defaults]
fact_caching = jsonfile
5.选择性收集facts信息
在配置文件中可排除收集:
[defaults]
gather_subset = !hardware
在play中定义:
- hosts: all
gather_facts: false
只收集minimal:
- hosts: all
gather_facts: false
pre_tasks:
- setup:
gather_subset:
- '!all'
6.ssh参数:增加control_path的使用时间
[ssh_connection]
ssh_args = -C -o ControlMaster=auto -o ControlPersist=180s
默认会有
-o PreferredAuthentications = gssapi-with-mic,gssapi-keyex,hostbased,publickey
如果只有publickey一种认证方式可以只指定publickey
-o PreferredAuthentications = publickey
7.control_path:开后ssh socket持久化,复用ssh连接
[ssh_connection]
control_path = %(directory)s/ansible-ssh-%%h-%%r
8.pipelinling:开后ssh pipelining,容户端从管道中读取执行渲染后的脚本,而不是在客户端创建临时文件
[ssh_connection]
pipelining = True
9.serial:将play_hosts中的主机再分批执行,降低控制机的cpu便用
- hosts: all
serial: 50%
10.strategy:默认linear,每个主机的单个task执行完成会等待其他都完成后再执行下个任务,设置free可不等待其他主机
- hosts: all
strategy: linear
11.mitogen strategy(https://mitogen.networkgenomics.com/ansible_detailed.html) 插件:提高ansible的执行效率,在理想的环境下预计速度将提高1.25倍至7倍,并且CPU使用率至少降低2 倍
mitogen 插件确实牛逼闪闪:
§ 主机使用一个连接复用(默认每执行一个task或者loop循环都会重新打开一次连接)
§ 渲染的执行代码暂存于内存中
§ 减少多路复用ssh隧道的时间消耗
§ 减少临时文件传输的带宽
§ 代码重用,避免了调用Python和重新编译导入的成本
[defaults]
strategy_plugins = /path/to/mitogen-0.2.9/ansible_mitogen/plugins/strategy
strategy = mitogen_linear
- hosts: web-servers
strategy: linear
tasks:
- name: Install Python if necessary.
raw: test -e /usr/bin/python || apt install -y python-minimal
- hosts: web-servers
strategy: mitogen_linear
roles:
- nginx
- initech_app
- y2k_fix
测试:
配置插件前:
配置插件后:
循环执行shell提高了22.6倍,循环传输文件提高了8.7倍。
测试playbook:
---
- hosts: kgc_server
tasks:
- name: Create directory
file: path=/tmp/soft state=directory
- name: Loop copy files
copy: src={{ item }} dest=/tmp/soft/
loop:
- "{{ inventory_dir }}/tf_1"
- "{{ inventory_dir }}/tf_2"
- "{{ inventory_dir }}/tf_3"
- "{{ inventory_dir }}/tf_4"
- "{{ inventory_dir }}/tf_5"
- name: Loop execution shell
shell: echo {{ item }}
loop: "{{ range(0,100) | list }}"
- name: Delete tmp
file: path=/tmp/soft state=absent
遇到的问题总结¶
问题1:在使用copy模块的时候,部分主机出现以下报错:
"msg": "Aborting, target uses selinux but python bindings (libselinux-python) aren't installed!"
解决方法:在被管理的主机上安装libselinux
yum -y install libselinux-python
问题2:在执行ansible host -m ping的时候遇到如下报错
192.168.56.6 | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh.",
"unreachable": true
}
解决方法:修改配置文件/etc/ansible/ansible.cfg
[root@linux-node-ansible ansible]# vim /etc/ansible/ansible.cfg
host_key_checking = False #将True改为False
然后清空/root/.ssh/known_hosts配置文件,重新执行命令即可
问题3:ansible “failed to resolve remote temporary directory from ansible-tmp”
问题最终解决办法安装高版本的openssh
yum update openssh -y
nsible “failed to resolve remote temporary directory from ansible-tmp” 问题最终解决办法