ANSIBLE
云计算核心职能
- 搭建平台架构
- 日常运营保障
- 性能效率优化
相关工具
- 代码管理(SCM):GitHub、GitLab、BitBucket、SubVersion
- 构建工具:maven、Ant、Gradle
- 自动部署:Capistrano、CodeDeploy
- 持续集成(CI):Jenkins、Travis
- 配置管理:Ansible、SaltStack、Chef、Puppet
- 容器:Docker、Podman、LXC、第三方厂商如AWS
- 编排:Kubernetes、Core、Apache Mesos
- 服务注册与发现:Zookeeper、etcd、Consul
- 脚本语言:python、ruby、shell、go
- 日志管理:ELK、Logentries
- 系统监控:Prometheus、Zabbix、Datadog、Graphite、Ganglia、Nagios
- 性能监控:AppDynamics、New Relic、Splunk
- 压力测试:JMeter、Blaze Meter、loader.io ab
- 应用服务器:Tomcat、JBoss、IIS
- Web服务器:Apache、Nginx
- 数据库:MySQL、Oracle、PostgreSQL等关系型数据库;mongoDB、redis等NoSQL数据库
- 项目管理(PM):Jira、Asana、Taiga、Trello、Basecamp、Pivotal Tracker
自动化脚本 , 去写脚本,
批量处理工具,ansible 替代脚本 同一时间下发 给500 台机器 新建 /data
幂等性
1 Ansible 发展史及功能
作者:Michael DeHaan( Cobbler pxe kikstar 与 Func 作者)ansible 的名称来自科幻小说《安德的游戏》中跨越时空的即时通信工具,使用它可以在相距数光年的距离,远程实时控制前线的舰队战斗2012-03-09,发布0.0.1版,2015-10-17,Red Hat宣布1.5亿美元收购。
官网:https://www.ansible.com/
官方文档:https://docs.ansible.com/
1.1Ansible 功能
- 批量执行远程命令,可以对远程的多台主机同时进行命令的执行
- 批量安装和配置软件服务,可以对远程的多台主机进行自动化的方式配置和管理各种服务
- 编排高级的企业级复杂的IT架构任务, Ansible的Playbook和role可以轻松实现大型的IT复杂架构
- 提供自动化运维工具的开发API, 有很多运维工具,如jumpserver(堡垒机)就是基于 ansible 实现自动化管理功能
1.2 Ansible 特性
-
模块化:调用特定的模块完成特定任务,支持自定义模块,可使用任何编程语言写模块(账号,软件等)
-
Paramiko(python对ssh的实现),PyYAML,Jinja2(模板语言)三个关键模块
-
基于Python语言实现
-
部署简单,基于python和SSH(默认已安装),agentless,无需代理不依赖PKI(无需ssl)
-
安全,基于OpenSSH
-
幂等性:一个任务执行1遍和执行n遍效果一样,不因重复执行带来意外情况,此特性非绝对
cp -r /etc/ /mnt/etc.bak cp -r /etc/ /mnt/etc.bak cp -r /etc/ /mnt/etc.bak
-
支持playbook编排任务,YAML格式,编排任务,支持丰富的数据结构 剧本演员要按照 系统按照你规定的方式去执行命令
-
较强大的多层解决方案 role
1.3 Ansible架构
1.3.1 Ansible组成
- INVENTORY:Ansible管理主机的清单 /etc/anaible/hosts 需要管理的服务清单
- MODULES:Ansible执行命令的功能模块,多数为内置核心模块,也可自定义
- PLUGINS:模块功能的补充,如连接类型插件、循环插件、变量插件、过滤插件等,该功能不常用
- API:供第三方程序调用的应用程序编程接口 应用接口
1.3.2 Ansible 命令执行来源
-
USER 普通用户,即SYSTEM ADMINISTRATOR
-
PLAYBOOKS:任务剧本(任务集),编排定义Ansible任务集的配置文件,由Ansible顺序依次执行,通常是JSON格式的YML文件
-
CMDB(配置管理数据库) API 调用
-
PUBLIC/PRIVATE CLOUD API调用
2.Ansible安装和入门
2.1 安装
########yum源安装###############
yum install epel-release.noarch -y
yum install ansible -y
[root@node1 yum.repos.d]#vim CentOS-Base.repo
#加入 epel源
[epel]
name=gn
baseurl=https://mirrors.aliyun.com/epel/$releasever/x86_64
https://mirrors.cloud.tencent.com/epel/$releasever/x86_64
https://mirrors.huaweicloud.com/epel/$releasever/x86_64
https://mirrors.tuna.tsinghua.edu.cn/epel/$releasever/x86_64
gpgcheck=0
[root@node1 yum.repos.d]#yum info ansible
已加载插件:fastestmirror, langpacks
base | 3.6 kB 00:00:00
epeel | 4.7 kB 00:00:00
extras | 2.9 kB 00:00:00
updates | 2.9 kB 00:00:00
(1/3): epeel/7/group_gz | 96 kB 00:00:00
(2/3): epeel/7/updateinfo | 1.0 MB 00:00:00
(3/3): epeel/7/primary_db | 7.0 MB 00:00:04
Loading mirror speeds from cached hostfile
* base: mirrors.163.com
* epeel: mirrors.aliyun.com
* extras: mirrors.163.com
* updates: mirrors.163.com
可安装的软件包
名称 :ansible
架构 :noarch
版本 :2.9.25
发布 :1.el7
大小 :17 M
源 :epeel/7
简介 : SSH-based configuration management, deployment, and task execution system
网址 :http://ansible.com
协议 : GPLv3+
描述 : 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.
[root@node1 yum.repos.d]#yum install ansible -y
......................省略..................................
已安装:
ansible.noarch 0:2.9.25-1.el7
作为依赖被安装:
PyYAML.x86_64 0:3.10-11.el7 libyaml.x86_64 0:0.1.4-11.el7_0
python-babel.noarch 0:0.9.6-8.el7 python-jinja2.noarch 0:2.7.2-4.el7
python-markupsafe.x86_64 0:0.11-10.el7 python-paramiko.noarch 0:2.1.1-9.el7
python2-httplib2.noarch 0:0.18.1-3.el7 python2-jmespath.noarch 0:0.9.4-2.el7
完毕!
#############编译安装#########################
yum -y install python-jinja2 PyYAML python-paramiko python-babel python-crypto
wget https://releases.ansible.com/ansible/ansible-1.5.4.tar.gz
tar xf ansible-1.5.4.tar.gz
cd ansible-1.5.4
python setup.py build
python setup.py install
mkdir /etc/ansible
cp -r examples/* /etc/ansible
###############Git方式#######################
yum install git
git clone git://github.com/ansible/ansible.git --recursive
cd ./ansible
source ./hacking/env-setup
2.2相关文件
-
/etc/ansible/ansible.cfg 主配置文件,配置ansible工作特性,也可以在项目的目录中创建此文件,当前目录下如果也有ansible.cfg,则此文件优先生效,建议每个项目目录下,创建独有的ansible.cfg文件 不用修改
-
/etc/ansible/hosts 主机清单, 放 了被管理主机列表
-
/etc/ansible/roles/ 存放角色的目录
2.3 ansible 主配置文件
Ansible 的配置文件可以放在多个不同地方,优先级从高到低顺序如下
ANSIBLE_CONFIG #环境变量,注意此项用 ansible --version 看不到,但可以生效
./ansible.cfg #当前目录下的ansible.cfg
~/.ansible.cfg #当前用户家目录下的.ansible.cfg
/etc/ansible/ansible.cfg #系统默认配置文件
可以使用 来查看
[root@node1 yum.repos.d]#ansible --version
Ansible 的默认配置文件 /etc/ansible/ansible.cfg ,其中大部分的配置内容无需进行修改
[defaults]
#inventory = /etc/ansible/hosts #主机列表配置文件
#library = /usr/share/my_modules/ #库文件存放目录
#remote_tmp = $HOME/.ansible/tmp #临时py命令文件存放在远程主机目录
#local_tmp = $HOME/.ansible/tmp #本机的临时命令执行目录
#forks = 5 #默认并发数
#sudo_user = root #默认sudo 用户
#ask_sudo_pass = True #每次执行ansible命令是否询问ssh密码
#ask_pass = True
#remote_port = 22
#host_key_checking = False #检查对应服务器的host_key,建议取消此行注释,实现第一次连接自动信任目标主机
#log_path=/var/log/ansible.log #日志文件,建议启用
#module_name = command 、mod #默认模块,可以修改为shell模块
[privilege_escalation] #普通用户提权配置
#become=True
#become_method=sudo
#become_user=root
#become_ask_pass=False
2.4 inventory 主机清单文件
ansible的主要功能用在于批量主机操作,为了便捷地使用其中的部分主机,可以在inventory 主机清单文件中填写
官方文档:
https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html
默认的inventory file 位置在:
/etc/ansible/hosts
参数详细说明
ansible_ssh_host
#将要连接的远程主机名.与你想要设定的主机的别名不同的话,可通过此变量设置.
ansible_ssh_port
#ssh端口号.如果不是默认的端口号,通过此变量设置.这种可以使用 ip:端口
192.168.1.100:2222
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 的路径....
例子:
[web]
192.168.91.101:666
#可以指定ssh端口非默认的端口
192.168.91.102
[server]
192.168.91.[100:105]
#指定连续的主机
[ky15]
node[1:5]
#指定连续的主机
[server:ky15]
server
ky15
#可以嵌套组
[local]
192.168.91.100 ansible_connection=local
#指定本地连接,无需ssh配置
#ansible_connection=ssh 需要StrictHostKeyChecking no
192.168.91.103 ansible_connection=ssh ansible_ssh_port=2222 ansible_ssh_user=root ansible_ssh_password=123123
10.0.0.6 ansible_connection=ssh ansible_ssh_user=root ansible_ssh_password=123123
还可以指定用户身份 端口号 和密码
#执行ansible命令时显示别名,如web01
[websrvs]
node2
node3
[websrvs]
ansible_ssh_password=123123
例子:
[root@node1 ansible]#vim hosts
[local]
192.168.91.100 ansible_connection=local
[web]
192.168.91.101
192.168.91.102
[accp]
192.168.91.103
192.168.91.105
[webserver]
192.168.91.[101:103]
192.168.91.105
[web:children]
web
accp
[root@node1 ~]#ansible 192.168.91.105 -m ping
#可以指定 m代表使用模块 ping代表ping模块 命令探测下,需要输入 yes 或no
The authenticity of host '192.168.91.105 (192.168.91.105)' can't be established.
ECDSA key fingerprint is SHA256:ffeaxHUOVaBahhnpmEmFFpdl9iRFkdjKcuko6ISBiic.
ECDSA key fingerprint is MD5:28:cc:f0:39:36:33:b4:68:93:e2:30:d2:d5:78:38:ab.
Are you sure you want to continue connecting (yes/no)?
[root@node1 ~]#ansible accp -m ping
#指定 之前清单中的主机组 需要输入 yes 或no,但是只有一次机会,只能
The authenticity of host '192.168.91.105 (192.168.91.105)' can't be established.
ECDSA key fingerprint is SHA256:ffeaxHUOVaBahhnpmEmFFpdl9iRFkdjKcuko6ISBiic.
ECDSA key fingerprint is MD5:28:cc:f0:39:36:33:b4:68:93:e2:30:d2:d5:78:38:ab.
Are you sure you want to continue connecting (yes/no)? The authenticity of host '192.168.91.103 (192.168.91.103)' can't be established.
ECDSA key fingerprint is SHA256:+SWP6YETV3W/XC8Q6dJ0D6y9kCEWR5y1xRnl/gpIIwY.
ECDSA key fingerprint is MD5:c5:b1:f0:07:cc:df:6e:0e:b5:65:52:6f:d6:6d:76:c5.
Are you sure you want to continue connecting (yes/no)?
[root@localhost .ssh]#ansible acpp -m ping
#输入yes后
The authenticity of host '192.168.91.101 (192.168.91.101)' can't be established.
ECDSA key fingerprint is SHA256:jAdnvemeML+z00Zmk/SL5PWDVEvJqwPFID3iae+Xf4g.
ECDSA key fingerprint is MD5:f7:0e:02:3a:06:8c:71:0b:a2:b8:94:15:0f:0e:55:29.
Are you sure you want to continue connecting (yes/no)? The authenticity of host '192.168.91.102 (192.168.91.102)' can't be established.
ECDSA key fingerprint is SHA256:Sp14x5f9tQ76+x6Tsg0LSfRBqCbu6iAroJFMoWIfDwc.
ECDSA key fingerprint is MD5:91:19:be:cc:6d:ae:3c:e5:f5:9b:04:08:63:12:34:69.
Are you sure you want to continue connecting (yes/no)? yes
192.168.91.101 | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: Warning: Permanently added '192.168.91.101' (ECDSA) to the list of known hosts.\r\nAuthentication failed.",
"unreachable": true
}
[root@node1 ~]#ansible accp -m ping -k
#-k 输入密码 只有一次机会,如果密码不同无法一起管理,建议ssh免密 ,
SSH password:
192.168.91.105 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.91.103 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
ansible 默认使用 ssh 连接
所以管理前要免密登录
[root@node1 ~]#vim /etc/ssh/ssh_config
# StrictHostKeyChecking ask
# 修改35行 StrictHostKeyChecking no
[root@node1 ~]#vim /etc/ansible/ansible.cfg
71 #host_key_checking = False
开启71行的ansible的不验证即可
运维
2.5 Ansible 相关工具
- /usr/bin/ansible 主程序,临时命令执行工具
- /usr/bin/ansible-doc 查看配置文档,模块功能查看工具,相当于man ansible-doc -l |grep 关键字 具体模块名字
- /usr/bin/ansible-playbook 定制自动化任务,编排剧本工具,相当于脚本
- /usr/bin/ansible-pull 远程执行命令的工具
- /usr/bin/ansible-vault 文件加密工具
- /usr/bin/ansible-console 基于Console界面与用户交互的执行工具
- /usr/bin/ansible-galaxy 下载/上传优秀代码或Roles模块的官网平台
2.5.1 ansible
执行临时任务一次性任务
用法
ansible <host-pattern> [-m module_name] [-a args]
命令 主机或者清单中的组 -m 指定模块 -a 执行的任务
ansible 主机 -m 模块 "ansbil模块的语法"
ansible web -m yum -a "name=httpd state=lastest"
选项
--version #显示版本
-m module #指定模块,默认为command
-v #详细过程 -vv -vvv更详细
--list-hosts #显示主机列表,可简写 --list
-C, --check #检查,并不执行
-T, --timeout=TIMEOUT #执行命令的超时时间,默认10s
-k, --ask-pass #提示输入ssh连接密码,默认Key验证
-u, --user=REMOTE_USER #执行远程执行的用户,默认root
-b, --become #代替旧版的sudo 切换
--become-user=USERNAME #指定sudo的runas用户,默认为root vim /etc/sudoers 用户权限
-K, --ask-become-pass #提示输入sudo时的口令
-f FORKS, --forks FORKS #指定并发同时执行ansible任务的主机数
例子:
命令
shell > 特殊 符号
[root@node1 ~]#ansible localhost -m ping
localhost | SUCCESS => {
"changed": false,
"ping": "pong"
}
######## 提权操作 ######
[root@centos7 ~]#grep lisi /etc/sudoers
#先在被控制端(目标主机)sudo授权
zhangsan ALL=(ALL) NOPASSWD: ALL
#以zhangsan的用户连接用户,并利用sudo代表wang执行whoami命令
[root@ansible ~]#ansible 192.168.91.101 -m shell -a 'whoami' -u zhangsan -k -b --become-user=lisi
SSH password: #输入远程主机lisi用户ssh连接密码
10.0.0.8 | CHANGED | rc=0 >>
[root@node1 ~]#ansible 192.168.91.105 -m shell -a 'hostname >/opt/host.txt' -u zhangsan -k -b
SSH password:
192.168.91.105 | CHANGED | rc=0 >>
ansible 主机 -m 模块 -a "模块指令" 选项
######################## 主机列表 ###########################
##支持通配符
ansible all -m ping
ansible "*" -m ping
ansible 192.168.91.* -m ping
ansible "srvs" -m ping
ansible "192.168.91.101 192.168.91.102" -m ping
#或关系
[root@node1 ~]#ansible 'web:accp' --list-hosts
hosts (4):
192.168.91.101
192.168.91.102
192.168.91.103
192.168.91.105
#并且关系
[root@node1 ~]#ansible "web:&accp" --list-hosts
[WARNING]: No hosts matched, nothing to do
hosts (0):
#逻辑非
[root@node1 ~]#ansible 'web:!accp' --list-hosts
hosts (2):
192.168.91.101
192.168.91.102
#正则表达式
ansible "websrvs:dbsrvs" -m ping
ansible "~(k|a).*" -m ping
[root@node1 ~]#ansible "~(k|a).*" -m ping
################例子###
ansible 'kube*:etcd:!10.0.0.101' -a reboot && reboot
##并行执行
-f
[root@node1 ~]#ansible all -a "sleep 3" -f1
[root@node1 ~]#ansible all -a "sleep 3" -f4
##ansible命令执行过程
1. 加载自己的配置文件,默认/etc/ansible/ansible.cfg
#[root@node1 ~]#ansible all -a "sleep 100" -f4
#cd /root/.ansible/tmp
2. 加载自己对应的模块文件,如:command
3. 通过ansible将模块或命令生成对应的临时py文件,并将该文件传输至远程服务器的对应执行用户$HOME/.ansible/tmp/ansible-tmp-数字/XXX.PY文件
4. 给文件+x执行
5. 执行并返回结果
6. 删除临时py文件,退出
$HOME 为当前用户的家目录
执行返回结果
- 绿色:执行成功并且不需要做改变的操作
- 黄色:执行成功并且对目标主机做变更
- 红色:执行失败
配置文件中定义了
vim /etc/ansible/ansible.cfg
[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
2.5.2 ansible-doc
[root@node1 ~]#ansible-doc -l
#查看所有支持的模块
[root@node1 ~]#ansible-doc -l |wc -l
3387
[root@node1 ~]#ansible-doc -l |grep ^ping
ping Try to connect to host, verify a usable ...
pingdom Pause/unpause Pingdom alerts
q
[root@node1 ~]#ansible-doc ping
#该模块的详细信息
[root@node1 ~]#ansible-doc -s ping
#简单模块
[root@node1 ~]#ansible-doc file
#幂等性,安全性,自己写脚本
2.5.3 ansible-console
#此工具可交互执行命令,支持tab,ansible 2.0+新增
提示符格式
执行用户@当前操作的主机组 (当前组的主机数量)[f:并发数]$
常用子命令:
设置并发数: forks n 例如: forks 10
切换组: cd 主机组 例如: cd web
列出当前组主机列表: list
列出所有的内置命令: ?或help
root@all (4)[f:5]$ cd web
root@web (2)[f:5]$
root@web (2)[f:5]$ forks 1
root@web (2)[f:1]$
[root@node1 ~]#ansible-console
Welcome to the ansible console.
Type help or ? to list commands.
root@all (4)[f:5]$ ping
#直接使用模块
2.5.4 playbook
此工具用于执行编写好的 playbook 任务
范例
ansible-playbook -C hello.yml
cat hello.yml
---
#hello world yml file
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
- name: hello world
command: /usr/bin/wall hello world
2.6 模块
2015年底270多个模块,2016年达到540个,2018年01月12日有1378个模块,2018年07月15日1852个模块,2019年05月25日(ansible 2.7.10)时2080个模块,2020年03月02日有3387个模块虽然模块众多,但最常用的模块也就2,30个而已,针对特定业务只用10几个模块
常用模块帮助文档参考:
https://docs.ansible.com/ansible/2.9/modules/modules_by_category.html
https://docs.ansible.com/ansible/2.9/modules/list_of_all_modules.html
https://docs.ansible.com/ansible/latest/modules/list_of_all_modules.html
https://docs.ansible.com/ansible/latest/modules/modules_by_category.html
默认模块 可以不写
2.6.1 Command 模块
功能:在远程主机执行命令,此为默认模块,可忽略 -m 选项
注意:此命令不支持 $VARNAME < > | ; & 等,可以用shell模块实现 shell 模块是加强版的 命令模块
注意:此模块不具有幂等性
例子:
[root@node1 ~]#ansible web -a 'hostname'
192.168.91.102 | CHANGED | rc=0 >>
localhost.localdomain
192.168.91.101 | CHANGED | rc=0 >>
node2
root@node1 ~]#ansible web -a "touch /opt/ky15.txt"
#此处的 警告是 让你用 file 模块 专业的模块
[WARNING]: Consider using the file module with state=touch rather than running 'touch'. If you need to
use command because file is insufficient you can add 'warn: false' to this command task or set
'command_warnings=False' in ansible.cfg to get rid of this message.
192.168.91.102 | CHANGED | rc=0 >>
192.168.91.101 | CHANGED | rc=0 >>
[root@node1 ~]#ansible web -a "ls /opt/ky15.txt"
192.168.91.102 | CHANGED | rc=0 >>
/opt/ky15.txt
192.168.91.101 | CHANGED | rc=0 >>
/opt/ky15.txt
[root@node1 ~]#ansible web -a "echo hello > /opt/hello.log"
#不支持一些 重定向等功能
192.168.91.101 | CHANGED | rc=0 >>
hello > /opt/hello.log
192.168.91.102 | CHANGED | rc=0 >>
hello > /opt/hello.log
114 #module_name = command
2.6.1 shell模块
功能:和command相似,用shell执行命令,支持各种符号,比如:*,$, >
注意:此模块不具有幂等性
[root@node1 ~]# ansible web -m shell -a "echo hello > /opt/hello.txt"
#如果没有明确指明文件生成的目录,会默认在家目录下生成
[root@node1 ~]# ansible web -m shell -a "cat /opt/hello.txt"
#修改默认模块
113 # default module name for /usr/bin/ansible
114 module_name = shell
[root@node1 ~]#ansible web -a "echo $PATH"
192.168.91.102 | CHANGED | rc=0 >>
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
192.168.91.101 | CHANGED | rc=0 >>
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
2.6.3 Script模块
功能:在远程主机上运行ansible服务器上的脚本(无需执行权限)
注意:此模块不具有幂等性
范例:
[root@node1 ~]#vim test.sh
#!/bin/bash
hostname
[root@node1 ~]#ansible web -m script -a '/root/test.sh'
2.6.4 copy 模块
功能:从ansible服务器主控端复制文件到远程主机
注意: src=file 如果是没指明路径,则为当前目录或当前目录下的files目录下的file文件
关键字:
src 代表源文件路径
dest 代表文件落地路径
owner 属主
group 属组
mode 代表权限
backup 如果复制时有同名文件会先备份再复制(源文件要有变动才会有备份)
content
例子:
ansible web -m copy -a "src=/etc/passwd dest=/mnt/ owner=zhangsan mode=700"
ansible web -m copy -a "src=test.sh dest=/mnt/t.sh owner=zhangsan mode=700"
ansible web -m copy -a "src=/root/test.sh dest=/mnt/test2.sh owner=zhangsan mode=600 backup=yes"
#如目标存在,默认覆盖,此处指定先备份 源文件要有变动才会复制操作
ansible web -m copy -a "content='test line1\ntest line2\n' dest=/tmp/test.txt"
#指定内容,直接生成目标文件
# test line1
# test line2
ansible web -m copy -a "src=/etc dest=/backup"
ansible web -m copy -a "src=/etc/ dest=/backup"
加/ 复制加改名
不加/ 连etc一起复制
etc 不加 / 连etc 一起复制, etc会变成子目录
etc 加 / 只复制etc下的文件 把etc文件夹改名成 backup
2.6.5 Get_url 模块
功能: 用于将文件从http、https或ftp下载到被管理机节点上
常用参数如下:
- dest:指明下载文件的存放目录
- url :指明下载路径
ansible web -m get_url -a "url=https://nginx.org/download/nginx-1.18.0.tar.gz dest=/opt/"
wget https://nginx.org/download/nginx-1.18.0.tar.gz
md5sum nginx-1.18.0.tar.gz
ansible web -m get_url -a 'url=https://nginx.org/download/nginx-1.18.0.tar.gz dest=/opt checksum="md5:3ca4a37931e9fa301964b8ce889da8cb"'
url: 下载文件的URL,支持HTTP,HTTPS或FTP协议
dest:下载到目标路径(绝对路径),如果目标是一个目录,就用服务器上面文件的名称,如果目标设置了名称就用目标设置的名称
owner:指定属主
group:指定属组
mode:指定权限
force:如果yes,dest不是目录,将每次下载文件,如果内容改变,替换文件。如果否,则只有在目标不存在时才会下载该文件
checksum:对目标文件在下载后计算摘要,以确保其完整性
url_username:用于HTTP基本认证的用户名。对于允许空密码的站点,此参数可以不使用`url_password'
url_password:用于HTTP基本认证的密码。如果未指定`url_username'参数,则不会使用`url_password'参数
validate_certs:如果“no”,SSL证书将不会被验证。适用于自签名证书在私有网站上使用
timeout: URL请求的超时时间,秒为单位
wget https://nginx.org/download/nginx-1.18.0.tar.gz
ansible web -m get_url -a 'url=https://nginx.org/download/nginx-1.18.0.tar.gz dest=/opt'
##可以检测文件是否有问题
[root@node1 ~]#md5sum nginx-1.18.0.tar.gz
3ca4a37931e9fa301964b8ce889da8cb nginx-1.8.0.tar.gz
ansible web -m get_url -a 'url=https://nginx.org/download/nginx-1.18.0.tar.gz dest=/opt checksum="md5:3ca4a37931e9fa301964b8ce889da8cb"'
##### checksum 后面不要忘记 加 md5: ###
2.6.6 Fetch 模块
功能:从远程主机提取文件至ansible的主控端,copy相反,目前不支持目录
范例:
[root@localhost data]#ansible web -m fetch -a 'src=/etc/passwd dest=/mnt'
[root@node1 ~]#ansible web -m fetch -a 'src=/var/log/messages dest=/mnt'
[root@node1 mnt]#tree
.
├── 192.168.91.101
│ └── var
│ └── log
│ └── messages
└── 192.168.91.102
└── var
└── log
└── messages
6 directories, 2 files
2.6.7 File模块
功能:设置文件属性,创建软链接等
path 指定文件路径
state 文件状态 有:新建(touch) 删除(absent) 文件夹(directory) 连接文件(link)等
src 源文件 建立连接文件时 使用
mode 权限
owner 属主
group 属组
recurse 递归 修改属性时有效
范例:
ansible web -m file -a 'path=/mnt/web.txt state=touch owner=zhangsan group=zhangsan mode=755'
#创建空文件
ansible web -m file -a 'path=/mnt/web state=directory'
#新建目录
ansible web -m file -a 'src=/mnt/web path=/opt/web-link state=link'
#新建软连接 path|dest|name 这三个选项都可以使用
ansible web -m file -a 'path=/opt/web-link state=absent'
#删除文件
ansible all -m file -a "path=/data/mysql state=directory owner=mysql group=mysql"
ansible all -m file -a "path=/data/mysql state=directory owner=mysql group=mysql recurse=yes"
#递归修改目录及子目录的属性
2.6.8 stat模块
功能:检查文件或文件系统的状态
注意:对于Windows目标,请改用win_stat模块
选项
path:文件/对象的完整路径(必须)
常用的返回值判断:
exists: 判断是否存在
isuid: 调用用户的ID与所有者ID是否匹配
ansible web -m stat -a 'path=/mnt/test.txt'
#查看是否存在
192.168.91.102 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"path": "/opt/mysql",
"secontext": "unconfined_u:object_r:usr_t:s0",
"size": 18,
"state": "directory",
"uid": 0
}
2.6.9 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:设置解压缩后的文件权限
ansible web -m get_url -a 'url=https://nginx.org/download/nginx-1.18.0.tar.gz dest=/data copy=yes'
ansible web -m unarchive -a 'src=/data/nginx-1.18.0.tar.gz dest=/mnt'
web
192.168.91.101
192.168.91.102
ansible web -m unarchive -a 'src=/data/ky.tar.bz2 dest=/mnt copy=yes'
#把本机的 压缩 加压到远程主机
ansible websrvs -m unarchive -a 'src=https://nginx.org/download/nginx-1.18.0.tar.gz dest=/usr/local/src/ copy=no'
# copy=no 代表压缩文件不是去本机上查找 去远端服务器查找
2.6.10 Archive模块
功能:打包压缩保存在被管理节点
对远端机器 进行 压缩
范例:
ansible web -m archive -a "path=/var/log/ dest=/data/log.tar.bz2 format=bz2 owner=zhangsan mode=0600"
2.6.11 Hostname模块
功能:管理主机名
ansible 192.168.91.102 -m hostname -a 'name=node3 '
#一般不使用此模块,主机名会一致
2.6.12 Cron 模块
功能:计划任务
支持时间:minute,hour,day,month,weekday
关键字:
name 会生成一行注释,显示标题如下显示
job 执行的命令
范例:
ansible 192.168.91.101 -m cron -a 'hour=2 minute=30 weekday=1-5 name="backup mysql" job=/root/mysql_backup.sh'
#创建任务
ansible web -m cron -a 'hour=2 minute=30 weekday=1-5 name="backup mysql" job=/root/mysql_backup.sh'
ansible 192.168.91.101 -m cron -a 'hour=*/2 minute=30 weekday=1-5 name="backup mysql" job=/root/mysql_backup.sh disabled=yes'
ansible 192.168.91.101 -m cron -a 'hour=2 minute=30 weekday=1-5 name="backup mysql" job=/root/mysql_backup.sh disabled=no'
#删除任务
ansible websrvs -m cron -a "name='backup mysql' state=absent"
ansible websrvs -m cron -a 'state=absent name=Synctime'
2.6.13 Yum和 Apt 模块
功能:yum 管理软件包,只支持RHEL,CentOS,fedora,不支持Ubuntu其它版本apt 模块管理 Debian 相关版本的软件包
关键字:
name参数:必须参数,用于指定需要管理的软件包 安装latest present 卸载 absent
state参数:用于指定软件包的状态 ,默认值为。present,表示确保软件包已经安装,除了。present,其他可用值有 installed、 latest、absent、removed,其中 installed 与present 等效,latest 表示安装 yum 中最新的版本,absent 和 removed 等效,表示删除对应的软件包。
disable_gpg_check参数:用于禁用对 rpm 包的公钥 gpg 验证。默认值为 no,表示不禁用验证,设置为 yes 表示禁用验证,即不验证包,直接安装。在对应的 yum 源没有开启 gpg 验证的情况下,需要将此参数的值设置为 yes,否则会报错而无法进行安装。
enablerepo参数:用于指定安装软件包时临时启用的 yum 源。假如你想要从A源中安装软件,但是你不确定A源是否启用了,你可以在安装软件包时将此参数的值设置为 yes,即使A源的设置是未启用,也可以在安装软件包时临时启用A源。
disablerepo参数:用于指定安装软件包时临时禁用的 yum 源。某些场景下需要此参数,比如,当多个 yum 源中同时存在要安装的软件包时,你可以使用此参数临时禁用某个源,这样设置后,在安装软件包时则不会从对应的源中选择安装包。enablerepo 参数和 disablerepo 参数可以同时使用
name 所安装的包的名称
state present--->安装, latest--->安装最新的, absent---> 卸载软件。
update_cache 强制更新yum的缓存
conf_file 指定远程yum安装时所依赖的配置文件(安装本地已有的包)。
disable_pgp_check 是否禁止GPG checking,只用于presentor latest。
disablerepo 临时禁止使用yum库。 只用于安装或更新时。
enablerepo 临时使用的yum库。只用于安装或更新时
范例:
ansible web -m yum -a 'name=httpd state=present' #安装
ansible web -m yum -a 'name=nginx state=present enablerepo=epel' #启用epel源
进行安装
ansible websrvs -m yum -a 'name=* state=lastest exclude=kernel*,foo*' #升级除
kernel和foo开头以外的所有包
ansible websrvs -m yum -a 'name=httpd state=absent' #删除
ansible 192.168.91.101 -m yum -a "name=tree"
2.6.14 yum_repository 模块
功能:建立yum仓库模块
关键字:
name参数: 必须参数,用于指定要操作的唯一的仓库ID,也就是”.repo”配置文件中每个仓库对应的”中括号”内的仓库ID。
baseurl参数: 此参数用于设置 yum 仓库的 baseurl。
description参数: 此参数用于设置仓库的注释信息,也就是”.repo”配置文件中每个仓库对应的”name字段”对应的内容。
file参数: 此参数用于设置仓库的配置文件名称,即设置”.repo”配置文件的文件名前缀,在不使用此参数的情况下,默认以 name 参数的仓库ID作 为”.repo”配置文件的文件名前缀,同一个”.repo” 配置文件中 可以存在多个 yum 源。
enabled参数: 此参数用于设置是否激活对应的 yum 源,此参数默认值为 yes,表示启用对应的 yum 源,设置为 no 表示不启用对应的 yum 源。
gpgcheck参数: 此参数用于设置是否开启 rpm 包验证功能,默认值为 no,表示不启用包验证,设置为 yes 表示开启包验证功能。
gpgcakey参数: 当 gpgcheck 参数设置为 yes 时,需要使用此参数指定验证包所需的公钥。
state参数: 默认值为 present,当值设置为 absent 时,表示删除对应的 yum 源。
例子:
新建
ansible web -m yum_repository -a 'name=epel description=epel baseurl=https://download.fedoraproject.org/pub/epel/$releasever/$basearch/ gpgcheck=no file=epel'
删除
ansible web -m yum_repository -a 'name=epel description=epel baseurl=https://download.fedoraproject.org/pub/epel/$releasever/$basearch/ gpgcheck=no file=epel state=absent'
- name: Add multiple repositories into the same file (1/2)
yum_repository:
name: epel
description: EPEL YUM repo
file: external_repos
baseurl: https://download.fedoraproject.org/pub/epel/$releasever/$basearch/
2.6.15 Service 模块
功能:管理服务 启动 关闭 重启 reload 开机自启
关键字:
name参数: 此参数用于指定需要操作的服务名称,比如 nginx。
state参数: 此参数用于指定服务的状态,比如,我们想要启动远程主机中的 nginx,则可以将 state 的值设置为 started;如果想要停止远程主机中的服 务,则可以将 state 的值设置为 stopped。此参数的可用值有 started、stopped、restarted、reloaded。
enabled参数: 此参数用于指定是否将服务设置为开机 启动项,设置为 yes 表示将对应服务设置为开机启动,设置为 no 表示不会开机启动。
管理服务例子:
ansible web -m yum -a 'name=httpd state=present'
ansible web -m service -a 'name=httpd state=started enabled=yes'
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/^Listen 80/Listen 8080/' /etc/httpd/conf/httpd.conf"
ansible all -m service -a 'name=httpd state=restarted'
ansible 192.168.91.101 -m service -a 'name=httpd state=started enabled=yes'
2.6.16 mount 挂载和卸载
功能: 挂载和卸载文件系统
范例
#临时挂载
ansible websrvs -m mount -a 'src="UUID=b3e48f45-f933-4c8e-a700-22a159ec9077" path=/home fstype=xfs opts=noatime state=present'
#临时取消挂载
ansible websrvs -m mount -a 'path=/home fstype=xfs opts=noatime state=unmounted'
#永久挂载
ansible websrvs -m mount -a 'src=10.0.0.8:/data/wordpress path=/var/www/html/wp-content/uploads opts="_netdev" state=mounted'
#永久卸载
ansible websrvs -m mount -a 'src=10.0.0.8:/data/wordpress path=/var/www/html/wp-content/uploads state=absent'
ansible web -m mount -a "src=/dev/sr0 path=/mnt state=present fstype=iso9660"
ansible web -m mount -a "src=/dev/sr0 path=/mnt state=mounted fstype=iso9660"
#永久挂载 光盘
ansible web -m mount -a "src=/dev/sr0 path=/mnt state=absent"
##永久卸载
2.6.17 User 模块
功能:管理用户
comment 用户的描述信息
createhome 是否创建家目录
force 在使用state=absent时, 行为与userdel –force一致.
group 指定基本组
groups 指定附加组,如果指定为(groups=)表示删除所有组
home 指定用户家目录
move_home 如果设置为home=时, 试图将用户主目录移动到指定的目录
name 指定用户名
non_unique 该选项允许改变非唯一的用户ID值
password 指定用户密码,使用 SHA512 hash
remove 在使用state=absent时, 行为是与userdel –remove一致
shell 指定默认shell
state 设置帐号状态,不指定为创建,指定值为absent表示删除
system 当创建一个用户,设置这个用户是系统用户。这个设置不能更改现有用户
uid 指定用户的uid
update_ password
always 如果password参数设置的值与用户当前的加密过的密码字符串不一致,则直接更新用户的密码,默认值即为always
on_create 如果password参数设置的值与用户当前的加密过的密码字符串不一致,则不会更新用户的密码字符串,保持之前的密码设定
范例
#创建用户
ansible all -m user -a 'name=user1 comment="test user" uid=2048 home=/app/user1 group=root‘
nsible web -m user -a 'name=user3 createhome=no group=root system=yes shell=/bin/nologin'
#删除用户
ansible all -m user -a 'name=user1 state=absent‘
2.6.18Group 模块
功能:管理组
范例
#创建组
ansible websrvs -m group -a 'name=nginx gid=88 system=yes'
#删除组
ansible websrvs -m group -a 'name=nginx state=absent'
2.6.19reboot模块
[root@ansible ~]#ansible websrvs -m reboot
sed
2.6.20 Lineinfile 模块
ansible在使用sed进行替换时,经常会遇到需要转义的问题,而且ansible在遇到特殊符号进行替换时,存在问题,无法正常进行替换 。其实在ansible自身提供了两个模块:lineinfile模块和replace模块,可以方便的进行替换一般在ansible当中去修改某个文件的单行进行替换的时候需要使用lineinfile模块
regexp参数 :使用正则表达式匹配对应的行,当替换文本时,如果有多行文本都能被匹配,则只有最后面被匹配到的那行文本才会被替换,当删除文本时,如果有多行文本都能被匹配,这么这些行都会被删除。
如果想进行多行匹配进行替换需要使用replace模块
功能:相当于sed,可以修改文件内容
关键字:
path 指定要操作的文件
regexp 使用正则表达式匹配对应的行
line 修改为新的内容
insertafter 将文本插入到“指定的行”之后
insertbefore 将文本插入到“指定的行”之前
state 删除对应的文本时,需要state=absent
backrefs 1.支持后向引用、2.当未匹配到内容则不操作文件
backup 是否在修改文件之前对文件进行备份
create 当要操作的文件并不存在时,是否创建对应的文件
范例:
ansible web -m lineinfile -a "path=/etc/httpd/conf/httpd.conf regexp='^Listen' line='Listen 80'"
ansible all -m lineinfile -a "path=/etc/selinux/config regexp='^SELINUX=' line='SELINUX=disabled'"
ansible all -m lineinfile -a 'dest=/etc/fstab state=absent regexp="^#"'
2.6.21replace 模块
该模块有点类似于sed命令,主要也是基于正则进行匹配和替换,建议使用
ansible all -m replace -a "path=/etc/fstab regexp='^(UUID.*)' replace='#\1'"
ansible all -m replace -a "path=/etc/fstab regexp='^#(UUID.*)' replace='\1'"
ansible web -m replace -a "path=/etc/httpd/conf/httpd.conf regexp='^Listen.*' replace='Listen 80'"
2.6.22 setup模块
功能: setup 模块来收集主机的系统信息,这些 facts 信息可以直接以变量的形式使用,但是如果主机较多,会影响执行速度可以使用 gather_facts: no 来禁止 Ansible 收集 facts 信息
范例:
ansible all -m setup
ansible all -m setup -a "filter=ansible_nodename"
ansible all -m setup -a "filter=ansible_hostname"
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_uptime_seconds"
ansible all -m setup -a "filter=ansible_processor*"
ansible all -m setup -a 'filter=ansible_env'
3 Playbook
建议修改vim配置
vim ~/.vimrc
set ai
set ts=2
三种常见的数据格式
- XML:Extensible Markup Language,可扩展标记语言,可用于数据交换和配置
- JSON:JavaScript Object Notation, JavaScript 对象表记法,主要用来数据交换或配置,不支持注释
- YAML:YAML Ain't Markup Language YAML 不是一种标记语言, 主要用来配置,大小写敏感,不支持tab
3.1 playbook 特点
- playbook 剧本是由一个或多个"play"组成的列表
- play的主要功能在于将预定义的一组主机,装扮成事先通过ansible中的task定义好的任务角色。Task实际是调用ansible的一个module,将多个play组织在一个playbook中,即可以让它们联合起来,按事先编排的机制执行预定义的动作
- Playbook 文件是采用YAML语言编写的
3.2 YAML 语言介绍
YAML:YAML Ain't Markup Language,即YAML不是标记语言。不过,在开发的这种语言时,YAML的意思其实是:"Yet Another Markup Language"(仍是一种标记语言)
YAML是一个可读性高的用来表达资料序列的格式。YAML参考了其他多种语言,包括:XML、C语言、Python、Perl以及电子邮件格式RFC2822等。Clark Evans在2001年在首次发表了这种语言,另外Ingy döt Net与Oren Ben-Kiki也是这语言的共同设计者,目前很多最新的软件比较流行采用此格式的文件存放配置信息,如:ubuntu,anisble,docker,kubernetes等
YAML 官方网站:http://www.yaml.org
ansible 官网: https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html
3.2.1YAML 语言特性
- YAML的可读性好
- YAML和脚本语言的交互性好
- YAML使用实现语言的数据类型
- YAML有一个一致的信息模型
- YAML易于实现
- YAML可以基于流来处理
- YAML表达能力强,扩展性好
3.2.2YAML语法简介
- 在单一文件第一行,用连续三个连字号"-" 开始,还有选择性的连续三个点号( ... )用来表示文件的结尾
- 次行开始正常写Playbook的内容,一般建议写明该Playbook的功能
- 使用#号注释代码
- 缩进必须是统一的,不能空格和tab混用
- 缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行来实现的
- YAML文件内容是区别大小写的,key/value的值均需大小写敏感
- 多个key/value可同行写也可换行写,同行使用,分隔
- key后面冒号要加一个空格 比如: key: value
- value可是个字符串,也可是另一个列表
- YAML文件扩展名通常为yml或yaml
3.2.3支持的数据类型
- YAML 支持以下常用几种数据类型:
- 标量:单个的、不可再分的值
- 对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
- 数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)
3.2.4.1 scalar标量
key对应value
name: wang
使用缩进的方式
name:
wang
标量是最基本的,不可再分的值,包括:
- 字符串
- 布尔值
- 整数
- 浮点数
- Null
- 时间
- 日期
3.2.4.2 Dictionary 字典
字典由多个key与value构成,key和value之间用 :分隔, 并且 : 后面有一个空格,所有k/v可以放在一
行,或者每个 k/v 分别放在不同行
格式
account: { name: wang, age: 30 }
使用缩进方式
account:
name: wang
age: 30
例子:
#不同行
# An employee record
name: Example Developer
job: Developer
skill: Elite(社会精英)
#同一行,也可以将key:value放置于{}中进行表示,用,分隔多个key:value
# An employee record
{name: "Example Developer", job: "Developer", skill: "Elite"}
3.2.4.2 List列表
列表由多个元素组成,每个元素放在不同行,且元素前均使用"-"打头,并且 - 后有一个空格, 或者将所
有元素用 [ ] 括起来放在同一行
course:
- linux
- golang
- python
也可以使用[ ]
course: [ linux , golang , python ]
数据里面也可以包含对象
course:
- linux: manjaro
- golang: gin
- python: django
范例:
#不同行,行以-开头,后面有一个空格
# A list of tasty fruits
- Apple
- Orange
- Strawberry
- Mango
#同一行
[Apple,Orange,Strawberry,Mango]
范例:YAML 表示一个家庭
name: John Smith
age: 41
gender: Male
spouse:
name: Jane Smith
age: 37
gender: Female
children:
- name: Jimmy Smith
age: 17
gender: Male
- {name: Jenny Smith, age: 13, gender: Female}
- {name: hao Smith, age: 20, gender: Male }
3.3Playbook 核心组件
一个playbook 中由多个组件组成,其中所用到的常见组件类型如下:
- Hosts 执行的远程主机列表
- Tasks 任务集,由多个task的元素组成的列表实现,每个task是一个字典,一个完整的代码块功能需最少元素需包括 name 和 task,一个name只能包括一个task
- Variables 内置变量或自定义变量在playbook中调用
- Templates 模板,可替换模板文件中的变量并实现一些简单逻辑的文件
- Handlers 和 notify 结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
- tags 标签 指定某条任务执行,用于选择运行playbook中的部分代码。ansible具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地长。此时,如果确信其没有变化,就可以通过tags跳过此些代码片断
tips
ansible-doc yum
#查看模块 用ansible-doc 加上 模块名 可以查看模块的使用方法和例子
3.3.1 host 组件
Hosts: playbook 中的每一个play的目的都是为了让特定主机以某个指定的用户身份执行任务。hosts用 于指定要执行指定任务的主机,须事先定义在主机清单中
one.example.com one.example.com:two.example.com 192.168.1.50
192.168.1.*
Websrvs:dbsrvs #或者,两个组的并集W
ebsrvs:&dbsrvs #与,两个组的交集
webservers:!dbsrvs #在websrvs组,但不在dbsrvs组
案例
- hosts: websrvs:appsrvs
3.3.2 remote_user 组件
remote_user: 可用于Host和task中。也可以通过指定其通过sudo的方式在远程主机上执行任务,其可用于play全局或某任务;此外,甚至可以在sudo时使用sudo_user指定sudo时切换的用户
- hosts: websrvs
remote_user: zhangsan
tasks:
- name: test connection
ping:
remote_user: wang
sudo: yes
#默认sudo为root
sudo_user:wang
#sudo为wang
3.3.3 task列表和action组件
play的主体部分是task list,task list中有一个或多个task,各个task 按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个task后,再开始第二个task
task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致每个task都应该有其name,用于playbook的执行结果输出,建议其内容能清晰地描述任务执行步骤。 如果未提供name,则action的结果将用于输出。
task两种格式:
action: module arguments
#示例: action: shell wall hello
module: arguments
#示例: shell: wall hello
注意:shell和command模块后面跟命令,而非key=value
案例第一个yml 文件 发送广播
#This is a play book
- hosts: web
remote_user: root
tasks:
- name: ping
ping:
- name: wall
shell: wall hello
第二个案例
---
# first yaml file
- hosts: web
remote_user: root
gather_facts: no #不收集系统信息,提高执行效率
tasks:
- name: test network connection
ping:
- name: excute command
command: wall "hello world!"
案例 安装 httpd 再启动服务
#This is a play book
- hosts: web
remote_user: root
tasks:
- name: ping
ping:
- name: wall
shell: wall hello
- hosts: db
tasks:
- name: install httpd
yum: name=httpd
- name: start service
service: name=httpd state=started enabled=yes
案例 新建mysql用户
---
- hosts: web
tasks:
- name: create user
user: name=test uid=2000 shell=/sbin/nologin system=yes create_home=no
3.3.4 gather_facts
收集信息
gather_facts: no
表示不收集信息, 但是使用变量时需要收集
2 安装httpd并启动
---
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
-name: install httpd
yum: name=httpd
-name: start httpd
service: name=httpd state=started enabled=yes
---
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
-name: install httpd
yum: name=httpd
-name: start httpd
service:
name:httpd
state:started
enabled:yes
案例3安装nginx并启动
---
- hosts: web
tasks:
- name: Add repository
yum_repository:
name: epel
description: EPEL YUM repo
baseurl: https://download.fedoraproject.org/pub/epel/$releasever/$basearch/
gpgcheck: no
- name: install nginx
yum: name=nginx state=present
- name: config file
copy: src=/data/nginx.conf dest=/etc/nginx/nginx.conf
- name: web page
copy: src=/data/index.html dest=/usr/share/nginx/html/index.html
- name: start nginx
service: name=nginx state=started enabled=yes
案例4 停止服务,并卸载nginx
---
- hosts: web
tasks:
- name: stop nginx
service: name=nginx state=stopped
- name: remove nginx
yum: name=nginx state=absent
3.3. 5 Handlers notify
Handlers本质是task list ,类似于MySQL中的触发器触发的行为,其中的task与前述的task并没有本质上的不同,主要用于当关注的资源发生变化时,才会采取一定的操作。而Notify对应的action可用于在每个play的最后被触发,这样可避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作称为handler,也即notify中调用handler中定义的操作
注意:
- 如果多个task通知了相同的handlers, 此handlers仅会在所有tasks结束后运行一 次。
- 只有notify对应的task发生改变了才会通知handlers, 没有改变则不会触发handlers
- handlers 是在所有前面的tasks都成功执行才会执行,如果前面任何一个task失败,会导致handler跳过执行,可以使用force_handlers: yes 强制执行handler
例子: 安装nginx
---
- hosts: web
gather_facts: no
tasks:
- name: add group
group: name=nginx state=present
- name: add user
user: name=nginx state=present group=nginx
- name: web page
copy: src=/etc/yum.repos.d/epel.repo dest=/etc/yum.repos.d
- name: install nginx
yum: name=epel-release.noarch
yum: name=nginx state=present
- name: config file
copy: src=/data/nginx.conf dest=/etc/nginx/
notify:
- restart nginx
- name: web page
copy: src=/data/index.html dest=/usr/share/nginx/html
- name: start nginx
service: name=nginx state=started enabled=yes
handlers:
- name: restart nginx
service: name=nginx state=restarted
- name: stop nginx
service: name=nginx state=restarted
3.3.6 ignore_errors
如果一个task出错,默认将不会继续执行后续的其它task
利用 ignore_errors: yes 可以忽略此task的错误,继续向下执行playbook其它task
[root@ansible ansible]#cat test_ignore.yml
---
- hosts: websrvs
tasks:
- name: error
command: /bin/false
ignore_errors: yes
- name: continue
command: wall continue
3.3.7第一个 yml文件
---
#第一个playbook
- hosts: web
tasks:
- name: ping
ping:
- name: wall
shell: wall hello
######辅助设置################
[root@localhost ~]#vim .vimrc
set ai ts=2 sw=2
####################################
##########################检查语法#####################################################
[root@localhost data]#ansible-playbook --help |grep check
#检查语法
[--skip-tags SKIP_TAGS] [-C] [--syntax-check] [-D]
--syntax-check perform a syntax check on the playbook, but do not
-C, --check don't make any changes; instead, try to predict some
differences in those files; works great with --check
ansible-playbook --syntax-check f.yml
ansible-playbook -C f.yml
####################################################################################
############ 运行 #####################
[root@localhost data]#ansible-playbook f.yml
#加playbook
---
#第一个playbook
- hosts: web
gather_facts: no #收集信息,当不使用时可以不收集加快速度
tasks:
- name: ping
ping:
- name: wall
shell: wall hello
- hosts: cloud
tasks:
- name: install httpd
yum:
name: httpd
- name: start httpd
service:
name: httpd
state: started
enabled: yes
编译安装nginx
cd /opt
wget http://nginx.org/download/nginx-1.18.0.tar.gz
---
- hosts: web
gather_facts: no
tasks:
- name: install packages
yum:
name:
- gcc
- pcre-devel
- openssl-devel
- zlib-devel
- openssl
- openssl-devel
state: present
- name: unarchive
unarchive: src=/opt/nginx-1.18.0.tar.gz dest=/opt
- name: bianyi
command: ./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module
args:
chdir: /opt/nginx-1.18.0
- name: make
command: make
args:
chdir: /opt/nginx-1.18.0
- name: make install
command: make install
args:
chdir: /opt/nginx-1.18.0
- name: cpoy service
copy: src=/usr/lib/systemd/system/nginx.service dest=/usr/lib/systemd/system/nginx.service
- name: reload
command: systemctl daemon-reload
- name: link
shell: ln -s /apps/nginx/sbin/nginx /usr/bin
- name: start nginx
service: name=nginx state=started enabled=yes
- name: web page
copy: src=/data/index.html dest=/usr/share/nginx/html
一键编译安装 mysql 5.7
3.4playbook 命令
ansible-playbook <filename.yml> ... [options]
--syntax-check #语法检查,可缩写成--syntax, 相当于bash -n
-C --check #模拟执行,只检测可能会发生的改变,但不真正执行操作,dry run
--list-hosts #列出运行任务的主机
--list-tags #列出tag
--list-tasks #列出task
--limit 主机列表 #只针对主机列表中的特定主机执行 --limit 主机地址
-i INVENTORY #指定主机清单文件,通常一个项对应一个主机清单文件
--start-at-task START_AT_TASK #从指定task开始执行,而非从头开始,START_AT_TASK为任务的name
-v -vv -vvv #显示过程
[root@localhost ~]#vim .vimrc
set ai ts=2 sw=2
其中ai:自动换行;ts:tab的字符长度;sw:空格的长度 1 yum安装httpd 2 service 开启服务 3 copy 传一个 主页文件过去 4能访问
---
# this is a test file
- hosts: kg
remote_user: root
gather_facts: no
tasks:
- name: ping
ping:
- name: test
shell: wall hello
#创建用户
- hosts: accp
gather_facts: no
tasks:
- name: create user
user:
name: mysql
shell: /sbin/nologin
system: yes
create_home: no
[root@localhost ~]#ansible-playbook --help
[root@localhost ~]#ansible-playbook --syntax-check hello.yml
#语法检查
playbook: hello.yml
[root@localhost ~]#ansible-playbook -C hello.yml
- hosts: accp
tasks:
- name: install httpd
yum: name=httpd
- name: start httpd
service: name=httpd state=started enabled=yes
- hosts: web
tasks:
- name: install httpd
yum:
name: httpd
- name: config file
copy:
src: files/index.html
dest: /var/www/html
- name: start httpd
service:
name: httpd
state: started
enabled: yes
- name: stop firewalld
service:
name: firewalld
state: stopped
enabled: no
ansible all -m yum -a 'name=httpd state=absent'
#卸载httpd
- hosts: web
remote_user: root
gather_facts: no
tasks:
- name: add group nginx
group:
name: nginx
state: present
- name: add user nginx
user:
name: nginx
state: present
group: nginx
- name: Install Nginx
yum:
name: nginx
state: present
- name: web page
copy:
src: files/index.html
dest: /usr/share/nginx/html/index.html
- name: Start Nginx
service:
name: nginx
state: started
enabled: yes
3.5 tags 标签
在playbook文件中,可以利用tags组件,为特定 task 指定标签,当在执行playbook时,可以只执行特定tags的task,而非整个playbook文件
tags: [ test1,test2 ] # 写在一行
tags:
- test1
- test2
案例:
vim httpd.yml
---
# tags example
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
- name: Install httpd
yum: name=httpd state=present
- name: Install configure file
copy: src=files/httpd.conf dest=/etc/httpd/conf/
tags: conf
- name: start httpd service
tags: service
service: name=httpd state=started enabled=yes
[root@ansible ~]#ansible-playbook –t conf,service httpd.yml
3.6 指定清单文集 hosts
[root@localhost data]#ansible-playbook --list-hosts install_nginx.yml
playbook: install_nginx.yml
play #1 (web): web TAGS: []
pattern: [u'web']
hosts (2):
192.168.91.102
192.168.91.101
[root@localhost data]#ansible-playbook --list-hosts install_nginx.yml -i hosts
playbook: install_nginx.yml
play #1 (web): web TAGS: []
pattern: [u'web']
hosts (3):
192.168.91.102
192.168.91.103
192.168.91.101
3.7 Playbook中使用变量
变量名:仅能由字母、数字和下划线组成,且只能以字母开头
变量定义:
variable=value
例子:
http_port=80
变量调用方式:
通过{{ variable_name }} 调用变量,且变量名前后建议加空格,有时用"{{ variable_name }}"才生效
变量来源:
-
ansible 的 setup facts 远程主机的所有变量都可直接调用
-
通过命令行指定变量,优先级最高
ansible-playbook -e varname=value test.yml
3.7.1 使用setup模块中变量
本模块自动在playbook调用,不要用ansible命令调用,生成的系统状态信息, 并存放在facts变量中
facts 包括的信息很多,如: 主机名,IP,CPU,内存,网卡等
facts 变量的实际使用场景案例
- 通过facts变量获取被控端CPU的个数信息,从而生成不同的Nginx配置文件
- 通过facts变量获取被控端内存大小信息,从而生成不同的memcached的配置文件
- 通过facts变量获取被控端主机名称信息,从而生成不同的Zabbix配置文件
案例:使用setup变量
- 查看所有变量
[root@localhost data]#ansible localhost -m setup
localhost | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"192.168.122.1",
"192.168.91.100"
],
"ansible_all_ipv6_addresses": [
"fe80::fe7:ca03:81f:2887"
],
"ansible_apparmor": {
"status": "disabled"
},
"ansible_architecture": "x86_64",
"ansible_bios_date": "07/29/2019",
.............................................
- 查看 本机的内存大小
[root@localhost data]#ansible localhost -m setup -a "filter=ansible_memtotal_mb"
localhost | SUCCESS => {
"ansible_facts": {
"ansible_memtotal_mb": 1823
},
"changed": false
}
- 查看本机的主版本号
[root@localhost data]#ansible localhost -m setup -a "filter=ansible_distribution_major_version"
localhost | SUCCESS => {
"ansible_facts": {
"ansible_distribution_major_version": "7"
},
"changed": false
}
- 查看cpu核数
[root@localhost data]#ansible 192.168.91.101 -m setup -a "filter=ansible_processor_vcpus"
192.168.91.101 | SUCCESS => {
"ansible_facts": {
"ansible_processor_vcpus": 2,
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false
}
- 利用setup 模块中的变量生成日志文件
---
- hosts: web
remote_user: root
gather_facts: yes
tasks:
- name: create log file
file: name=/data/{{ ansible_nodename }}.log state=touch owner=zhangsan mode=600
#ansible_nodename
- 显示 es33 网卡的 IP 地址
---
- hosts: web
remote_user: root
gather_facts: yes
tasks:
- name: create log file
debug:
msg: IP address {{ ansible_ens33.ipv4.address }}
#msg: IP address {{ ansible_facts["ens33"]["ipv4"]["address"] }}
#msg: IP address {{ ansible_facts.ens33.ipv4.address }}
#msg: IP address {{ ansible_default_ipv4.address }}
#msg: IP address {{ ansible_ens33.ipv4.address }}
#msg: IP address {{ ansible_ens33.ipv4.address.split('.')[-1] }} #取IP中的最后一个数字
3.7.2 在playbook 命令行中定义变量
"{{ 变量名 }}"
使用 ansible-playbook -e 选项
例子: 在使用命令时定义变量
vim test2.yml
---
- hosts: websrvs
remote_user: root
tasks:
- name: install package
yum: name={{ pkname }} state=present
ansible-playbook -e pkname=httpd var2.yml
新建用户
---
- hosts: web
gather_facts: no
tasks:
- name: create user
user: name={{ myname }} system=yes create_home=no
- name: create user
user: name={{ myname1 }} system=yes create_home=no
ansible-playbook -e myname=cxk -e myname1=wyf playbook名字
3.7.3 定义变量文件
例子:
[root@localhost data]#vim var
# 定义变量 pkname1 pkname2
pkname1: tree
pkname2: telnet
vim test1.yml
---
- hosts: web
gather_facts: no
tasks:
- name: install {{pkname1}}
yum: name={{pkname1}} state=present
- name: install {{pkname2}}
yum: name={{pkname2}} state=present
[root@localhost data]#ansible-playbook -e "@var" test1.yml
# @代表文件 var 即是文件名
3.7.4直接在 playbook 文件 中建立变量
例子:
使用 vars组件
---
- hosts: web
vars:
username: test1
groupname: group1
tasks:
- name: create group
group: name={{ groupname }} state=present
- name: create user
user: name={{ username }} state=present
例子: 安装多个软件包
- hosts: web
vars:
web: httpd
db: mariadb-server
tasks:
- name: install {{ web }} {{ db }}
yum:
name:
- "{{ web }}"
- "{{ db }}"
state: latest
例子: 变量之间的互相调用
---
- hosts: web
vars:
collect_info: "/data/test/{{ansible_default_ipv4['address']}}/"
tasks:
- name: create ip directory
file: name="{{collect_info}}" state=directory
---
- hosts: webs
vars:
suffix: "txt"
file: "{{ ansible_nodename }}.{{suffix}}"
tasks:
- name: test var
file: path="/data/{{file}}" state=touch
3.7.5 使用独立的变量文件
可以在一个独立的playbook文件中定义变量,在另一个playbook文件中引用变量文件中的变量,比playbook中定义的变量优化级高
#先写一个变量文件
vim vars.yml
---
# variables file
package_name: mariadb-server
service_name: mariadb
#调用这个文件
vim var5.yml
---
#install package and start service
- hosts: dbsrvs
remote_user: root
vars_files:
- vars.yml
tasks:
- name: install package
yum: name={{ package_name }}
tags: install
- name: start service
service: name={{ service_name }} state=started enabled=yes
3.7.6 针对主机和主机组的变量
3.7.6.1 在主机清单中针对所有项目的主机和主机分组的变量所有项目的主机变量
在inventory 主机清单文件中为指定的主机定义变量以便于在playbook中使用
[websrvs]
www1.kgc.com http_port=80 maxRequestsPerChild=808
www2.kgc.com http_port=8080 maxRequestsPerChild=909
#只是针对单个主机
所有项目的组(公共)变量
在inventory 主机清单文件中赋予给指定组内所有主机上的在playbook中可用的变量,如果和主机变是同名,优先级低于主机变量
范例:
[websrvs:vars]
http_port=80
ntp_server=ntp.kgc.com
nfs_server=nfs.kgc.com
======================================
######################################
[all:vars]
# --------- Main Variables ---------------
# Cluster container-runtime supported: docker, containerd
CONTAINER_RUNTIME="docker"
# Network plugins supported: calico, flannel, kube-router, cilium, kube-ovn
CLUSTER_NETWORK="calico"
# Service proxy mode of kube-proxy: 'iptables' or 'ipvs'
PROXY_MODE="ipvs"
# K8S Service CIDR, not overlap with node(host) networking
SERVICE_CIDR="192.168.0.0/16"
# Cluster CIDR (Pod CIDR), not overlap with node(host) networking
CLUSTER_CIDR="172.16.0.0/16"
# NodePort Range
NODE_PORT_RANGE="20000-60000"
# Cluster DNS Domain
CLUSTER_DNS_DOMAIN="magedu.local."
例子:
[root@localhost data]#vim /etc/ansible/hosts
[web]
192.168.91.101 hname=www1 domain=accp.com
192.168.91.102 hname=www2
[web:vars]
mark="-"
[all:vars]
domain=www.kgc.com
[root@localhost data]#ansible web -m hostname -a 'name={{ hname }}{{ mark }}{{ domain }}'
192.168.91.102 | CHANGED => {
"ansible_facts": {
"ansible_domain": "sollutium.com",
"ansible_fqdn": "dedicated.sollutium.com",
"ansible_hostname": "www2-kgc",
"ansible_nodename": "www2-kgc.com",
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"name": "www2-kgc.com"
}
192.168.91.101 | CHANGED => {
"ansible_facts": {
"ansible_domain": "sollutium.com",
"ansible_fqdn": "dedicated.sollutium.com",
"ansible_hostname": "www1-kgc",
"ansible_nodename": "www1-kgc.com",
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"name": "www1-kgc.com"
}
3.8 template 模板技术
模板是一个文本文件,可以做为生成文件的模版,并且模板文件中还可嵌套jinja2语法
Jinja2 是一个现代的,设计者友好的,仿照 Django 模板的 Python 模板语言。 它速度快,被广泛使用,并且提供了可选的沙箱模板执行环境保证安全:
特性:
- 沙箱中执行
- 强大的 HTML 自动转义系统保护系统免受 XSS
- 模板继承
- 及时编译最优的 python 代码
- 可选提前编译模板的时间
- 易于调试。异常的行数直接指向模板中的对应行。
- 可配置的语法
官方文档
http://jinja.pocoo.org/
https://jinja.palletsprojects.com/en/2.11.x/
官方中文文档
http://docs.jinkan.org/docs/jinja2/
https://www.w3cschool.cn/yshfid/
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
*:用右边的数乘左边的操作数。 {{ 2 * 2 }} 会返回 4 。也可以用于重 复一个字符串多次。 {{ '=' * 80 }}
会打印 80 个等号的横条\
**:取左操作数的右操作数次幂。 {{ 2**3 }} 会返回 8
比较操作符
== 比较两个对象是否相等
!= 比较两个对象是否不等
> 如果左边大于右边,返回 true
>= 如果左边大于等于右边,返回 true
< 如果左边小于右边,返回 true
<= 如果左边小于等于右边,返回 true
逻辑运算符
对于 if 语句,在 for 过滤或 if 表达式中,它可以用于联合多个表达式
and 如果左操作数和右操作数同为真,返回 true
or 如果左操作数和右操作数有一个为真,返回 true
not 对一个表达式取反
(expr)表达式组
true / false true 永远是 true ,而 false 始终是 false
3.8.1template
template功能:可以根据和参考模块文件,动态生成相类似的配置文件 template文件必须存放于templates目录下,且命名为 .j2 结尾 yaml/yml 文件需和templates目录平级,目录结构如下示例:
范例:利用template 同步nginx配置文件
#准备templates/nginx.conf.j2文件
mkdir templates
vim nginx.conf.j2
worker_processes {{ ansible_processor_vcpus }};
worker_processes {{ ansible_processor_vcpus+1s }};
[root@ansible ~]#vim temnginx.yml
---
- hosts: web
gather_facts: yes
tasks:
- name: config file
tags: page
#copy: src=/data/index.html dest=/apps/nginx/html
template: src=nginx.conf.j2 dest=/apps/nginx/conf/nginx.conf
notify:
- restart nginx
handlers:
- name: restart nginx
service: name=nginx state=restarted
[root@ansible ~]#ansible-playbook temnginx.yml
#去节点上查看
[root@localhost ~]# pstree -p|grep nginx
|-nginx(54233)-+-nginx(54234)
| |-nginx(54235)
| `-nginx(54236)
3.8.2 template中使用流程控制for和 if
template中也可以使用流程控制 for 循环和 if 条件判断,实现动态生成文件功能
3.8.2.1 for循环
格式
{% for i in EXPR %}
...
{% endfor %}
示例:
{% for i in range(1,10) %}
server_name web{{i}};
{% endfor %}
例子1:
vim templates/for.j2
{% for i in range(1,10) %}
servername {{i}};
{% endfor %}
vim test.yml
---
- hosts: web
tasks:
- name: template
template: src=for.j2 dest=/data/test.txt
[root@node2 data]#cat test.txt
servername 1;
servername 2;
servername 3;
servername 4;
servername 5;
servername 6;
servername 7;
servername 8;
servername 9;
例子2 : 生成nginx多虚拟主机
[root@localhost data]#vim templates/for1.j2
# 准备 j2 文件
{% for vhost in nginx_vhosts %}
server {
listen {{ vhost }}
}
{% endfor %}
[root@localhost data]#vim test.yml
# 准备 yml 文件
---
- hosts: web
vars:
nginx_vhosts:
- 81
- 82
- 83
tasks:
- name: template config
template: src=for1.j2 dest=/data/test.conf
[root@node2 data]#cat test.conf
server {
listen 81
}
server {
listen 82
}
server {
listen 83
}
3.9 循环迭代
迭代:当有需要重复性执行的任务时,可以使用迭代机制
3.9.1 迭代with_items(loop)
对迭代项的引用,固定内置变量名为"item"
要在task中使用with_items给定要迭代的元素列表
注意: ansible2.5版本后,可以用loop代替with_items
列表元素格式:
- 字符串
- 字典
例子: 批量建立用户
---
- hosts: web
gather_facts: no
tasks:
- name: create user
user: name={{ item }} state=present groups=wheel
with_items:
- testuser1
- testuser2
- testuser3
#注意= 号后不要空格
#上面语句的功能等同于下面的语句
- name: add several users
user: name=testuser1 state=present groups=wheel
- name: add several users
user: name=testuser2 state=present groups=wheel
- name: add several users
user: name=testuser3 state=present groups=wheel
例子: 批量删除文件
---
- hosts: web
gather_facts: no
tasks:
- name: delete file
file: path={{ item }} state=absent
with_items:
- /data/file1
- /data/file2
- /data/file3
例子:批量安装软件
---
- hosts: web
gather_facts: no
tasks:
- name: install packeages
yum: name={{ item }} state=present
#yum: name=nginx,ftp,memcached
with_items:
- vsftpd
- ftp
- tree
例子:批量复制文件
---
- hosts: websrvs
remote_user: root
tasks:
- name: copy file
copy: src={{ item }} dest=/tmp/{{ item }}
with_items:
- file1
- file2
- file3
3.9.2 迭代嵌套子变量
在迭代中,还可以嵌套子变量,关联多个变量在一起使用
例子: 建立用户
---
- hosts: web
gather_facts: no
tasks:
- name: create group
group: name={{ item }} state=present
with_items:
- nginx
- mysql
- tomcat
- name: create user
user: name={{ item.user }} group={{ item.group }} uid={{ item.uid }} state=present
with_items:
- { user: 'nginx', group: 'nginx' , uid: '80' }
- { user: 'mysql', group: 'mysql' , uid: '3306' }
- { user: 'tomcat', group: 'tomcat' , uid: '8080' }
例子: 复制文件
#ansible-doc file
- name: Create two hard links
file:
src: '/tmp/{{ item.src }}'
dest: '{{ item.dest }}'
state: hard
loop:
- { src: x, dest: y }
- { src: m, dest: n }
例子: 批量修改密码
---
- hosts: ssh-host
gather_facts: false
tasks:
- name: change user passwd
user: name={{ item.name }} password={{ item.chpass | password_hash('sha512') }} update_password=always
with_items:
- { name: 'root', chpass: '123456' }
- { name: 'app', chpass: '654321' }
3.10 逐行处理
范例: with_lines 逐行处理
- hosts: localhost
tasks:
- debug: msg={{ item }}
with_lines: ps aux
3.11 playbook使用 when
when语句可以实现条件测试。如果需要根据变量、facts或此前任务的执行结果来做为某task执行与否的前提时要用到条件测试,通过在task后添加when子句即可使用条件测试,jinja2的语法格式
范例:条件判断
---
- hosts: websrvs
remote_user: root
tasks:
- name: "shutdown RedHat flavored systems"
command: /sbin/shutdown -h now
when: ansible_os_family == "RedHat"
例子:
[root@localhost data]#ansible web -m setup -a "filter=ansible_os_family"
192.168.91.102 | SUCCESS => {
"ansible_facts": {
"ansible_os_family": "RedHat",
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false
}
192.168.91.101 | SUCCESS => {
"ansible_facts": {
"ansible_os_family": "RedHat",
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false
}
192.168.91.11 | SUCCESS => {
"ansible_facts": {
"ansible_os_family": "Debian",
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false
}
---
- hosts: web
tasks:
- name: install sl "{{ ansible_os_family }}"
yum: name=sl
when: ansible_os_family == "RedHat"
- name: install sl "{{ ansible_os_family }}"
apt: name=sl
when: ansible_os_family == "Debian"
#ansible_os_family
4 role 角色
角色是ansible自1.2版本引入的新特性,用于层次性、结构化地组织playbook。roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。简单来讲,roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷地include它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中
运维复杂的场景:建议使用 roles,代码复用度高
roles:多个角色的集合目录, 可以将多个的role,分别放至roles目录下的独立子目录中,如下示例
roles/
mysql/
nginx/
tomcat/
redis/
默认roles存放路径
/root/.ansible/roles
/usr/share/ansible/roles
/etc/ansible/roles
官方文档:
https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html
4.1 Ansible Roles目录编排
roles目录结构如下所示
每个角色,以特定的层级目录结构进行组织
roles目录结构
playbook1.yml
playbook2.yml
roles/
project1/
tasks/
files/
vars/
templates/
handlers/
default/
meta/
project2/
tasks/
files/
vars/
templates/
handlers/
default/
meta/
Role各目录作用
- roles/project/ :项目名称,有以下子目录
- files/ :存放由copy或script模块等调用的文件
- templates/:template模块查找所需要模板文件的目录
- tasks/:定义task,role的基本元素,至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含
- handlers/:至少应该包含一个名为main.yml的文件;此目录下的其它的文件需要在此文件中通过include进行包含
- vars/:定义变量,至少应该包含一个名为main.yml的文件;此目录下的其它的变量文件需要在此文件中通过include进行包含
- meta/:定义当前角色的特殊设定及其依赖关系,至少应该包含一个名为main.yml的文件,其它文件需在此文件中通过include进行包含
- default/:设定默认变量时使用此目录中的main.yml文件,比vars的优先级低
4.2 建立role
创建role的步骤
1 创建role的目录结构.在以roles命名的目录下分别创建以各角色名称命名的目录,如mysql等,在每个角色命名的目录中分别创建相关的目录和文件,比如tasks、files、handlers、templates和vars等目录;用不到的目录可以创建为空目录,也可以不创建
2 编写和准备role的功能文件
3 编写playbook文件调用需要的角色应用于指定的主机
针对大型项目使用Roles进行编排
范例: 利用 ansible-galaxy 创建角色目录的结构
[root@localhost roles]#mkdir -pv /etc/ansible/roles/nginx/{tasks,templates,handlers,files}
mkdir: 已创建目录 "/etc/ansible/roles/nginx/tasks"
mkdir: 已创建目录 "/etc/ansible/roles/nginx/templates"
mkdir: 已创建目录 "/etc/ansible/roles/nginx/handlers"
mkdir: 已创建目录 "/etc/ansible/roles/nginx/files"
[root@localhost roles]#tree
.
└── nginx
├── files
├── handlers
├── tasks
└── templates
5 directories, 0 files
[root@localhost nginx]#vim tasks/main.yml
[root@localhost nginx]#cat tasks/main.yml
- include: group.yml
- include: user.yml
- include: install.yml
- include: config.yml
- include: webpage.yml
- include: service.yml
[root@localhost nginx]#vim tasks/group.yml
- name: groups
group: name=nginx state=present
[root@localhost nginx]#vim tasks/user.yml
- name: user
user: name=nginx state=present
[root@localhost nginx]#vim tasks/install.yml
- name: install epel
yum: name=epel-release.noarch state=present
- name: install nginx
yum: name=nginx state=present
[root@localhost nginx]#vim tasks/config.yml
- name: web file
copy: src=/data/index.html dest=/usr/share/nginx/html/
[root@localhost nginx]#vim tasks/service.yml
- name: start nginx
service: name=nginx state=started
[root@localhost nginx]#tree
.
├── files
├── handlers
├── tasks
│ ├── config.yml
│ ├── group.yml
│ ├── install.yml
│ ├── main.yml
│ ├── service.yml
│ └── user.yml
└── templates
标签:web,name,ansible,nginx,state,ANSIBLE,root
From: https://www.cnblogs.com/zhj0708/p/18276913