目录
一、Ansible
1、Ansible简介
2、自动化运维工具对比:
3、Ansible特性
4、Ansible执行流程
二、ansible安装
1、实验环境
2、安装
3、主配置文件
1、主配置文件
2、配置主机清单文件(inventory)
3、查看配置文件
4、添加主机或者主机组
5、ansible命令语法:
三、Ad-Hoc组件
常用模块
1、远程复制备份模块:copy
2、yum模块
3、服务管理service模块
4、文件模块file
5、用户管理user模块
6、收集信息模块setup
四、Ansible-playbook
1、Playbook介绍
2、playbook核心元素
3、playbook基础组件
4、playbook基础使用案例
5、ansible-playbook变量使用
五、ansible-role
六、ansible常用模块
批量部署JDK+Tomcat+Jenkins
Ansible是一款类Unix系统开发的自由开源的配置和自动化工具。
它用Python写成,类似于saltstack和Puppet,但是有一个不同的优点是我们不需要在节点中安装客户端。
他是用SSH来和节点进行通信。Ansible基于Python paramiko开发,分布式,无需客户端轻量级,配置语法使用YMAL及jinja2模板语言,更强的远程命令执行操作。
ansible是新出现的自动化运维工具,基于Python开发,分布式,无需客户端,轻量级,实现了批量系统配置、批量程序部署、批量运行命令等功能,ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。
解决了容器不能免密的问题:sed -i -r 's/^(.*pam_nologin.so)/#\1/' /etc/pam.d/sshd
官方网站:https://www.ansible.com/
1、Puppet:基于 Ruby 开发,采用 C/S 架构,扩展性强,基于 SSL,远程命令执行相对较弱
2、SaltStack:基于 Python 开发,采用 C/S 架构,相对 puppet 更轻量级,配置语法使用 YAML,使得配置脚本更简单.需要配置客户端以及服务器端。每台被控制节点需要安装agent
3、Ansible:基于Python开发,分布式,无需客户端,轻量级,配置语法使用YAML语言,更强的远程命令执行操作
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:可实现多级指挥
connection plugins:连接插件,负责和被监控端实现通信,默认使用ssh连接
host inventory:主机清单,是一个配置文件里面定义监控的主机
modules:模块,核心模块,command模块、自定义模块等
plugins:modules功能的补充,包括连接插件,邮件插件等
playbook:编排,定义Ansible多任务配置文件,非必需
主机:4台 1个控制节点 3个被控制节点
所有机器全部互相解析
192.168.242.144 ansible
192.168.242.145 web-1
192.168.242.146 web-2
192.168.242.147 web-3
配置ssh公钥认证:控制节点需要发送ssh公钥给所有被控制节点
[root@ansible ~]# ssh-keygen
[root@ansible ~]# ssh-copy-id [email protected]
[root@ansible ~]# ssh-copy-id [email protected]
[root@ansible ~]# ssh-copy-id [email protected]
安装:控制节点
配置epel网络yum源(有的话忽略)
[root@ansible ~]# yum install -y epel-release
[root@ansible ~]# yum install -y ansible
[root@ansible ~]# ansible --version
[root@ansible ~]# ansible --help
/etc/ansible/ansible.cfg
主要设置一些ansible初始化的信息,比如日志存放路径、模块、插件的配置信息
配置文件中常见参数:
inventory = /etc/ansible/hosts #这个参数表示资源清单inventory文件的位置
library=/usr/share/ansible #指向存放ansible模块的目录,支持多个目录方式,只要用冒号(:)隔开就可以
forks=5 #并发连接数,默认为5
sudo_user=root #设置默认执行命令的用户
remote_port=22 #指定连接被管节点的管理端口,默认为22端口,建议修改,能够更加安全
host_key_checking=False #设置是否检查ssh主机的密匙,值为Ture/False。关闭后第一次连接不会提示配置实例
timeout=60 #设置ssh连接的超时时间,单位为秒
log_pash=/var/log/ansible.log #指定一个存储ansible日志的文件(默认不记录日志)
默认位置/etc/ansible/hosts,定义所管理的主机组及主机,可以在主配置文件中指定清单文件位置和名称
配置文件详解:
Ungrouped hosts, specify before any group headers. 未分组主机,在任何组头之前指定 blue.example.com
192.168.100.1
A collection of hosts belonging to the 'webservers' group.属于“webservers”组的主机集合[webservers]
alpha.example.org
beta.example.org
192.168.1.100
192.168.1.110
If you have multiple hosts following a pattern you can specify.如果有多个主机遵循一个模式,则可以指定
www[001:006].example.com
A collection of database servers in the 'dbservers' group.“dbservers”组中的数据库服务器集合
[dbservers]
db01.intranet.mydomain.net
db02.intranet.mydomain.net
10.25.1.56
[root@ansible ~]# rpm -qc ansible
/etc/ansible/ansible.cfg
/etc/ansible/hosts #ansible主机清单文件
vim /etc/ansible/hosts #在最后追加被管理端的机器
...
web-1 #单独添加主机,可以使用主机名称或ip地址
[web1] 组1 #添加主机组,使用[]标签指定主机组 ----标签自定义
web-1 被监控端的域名,如果未解析添加ip
web-2
up.example.com:5309 //指定 SSH 端口 5309
web5 ansible_ssh_host=web-2 //设置主机web-2的别名为 web5
web1 ansible_ssh_pass='123' //设置ssh密码,使用-k参数之后提示的密码可以不写,直接回车
www[01:50].example.com //支持通配符匹配www01,www02,...,www50
db-[a:f].example.com //通配符匹配db-a,db-b,...,db-f
[web2] 组2
web-3
#组可以包含其他组
[webzzz:children] #children-照写 #weball包括两个子组
web1
web2
#为一个组指定变量,组内每个主机都可以使用该变量:
[webzzz:vars] #设置变量,vars--照写
ansible_ssh_port=22
ansible_ssh_user=root
ansible_ssh_private_key_file=/root/.ssh/id_rsa
#ansible_ssh_pass=test #也可以定义密码,如果没有互传秘钥可以使用密码。
ansible基于ssh连接inventory中指定的远程主机时,还可以通过参数指定其交互方式:
ansible_ssh_host # 远程主机
ansible_ssh_port # 指定远程主机ssh端口
ansible_ssh_user # ssh连接远程主机的用户,默认root
ansible_ssh_pass # 连接远程主机使用的密码,在文件中明文,建议使用--ask-pass或者使用SSH keys
ansible_sudo_pass # sudo密码, 建议使用--ask-sudo-pass
ansible_connection # 指定连接类型: local, ssh, paramiko
ansible_ssh_private_key_file # ssh 连接使用的私钥
ansible_shell_type # 指定连接对端的shell类型, 默认sh,支持csh,fish
ansible_python_interpreter # 指定对端使用的python编译器的路径
Ansible Inventory 常见的内置参数:
ansible -m -a
pattern:主机清单里定义的主机组名,主机名,ip,别名等,all表示所有的主机,支持通配符,正则
: 多个主机组,组名之间用冒号隔开
*web*:组名或主机名中含web的
webserver[0]:webserver组中的第一台主机
以~开头,匹配正则
-m module_name:模块名称,默认command
-a arguments:传递给模块的参数
查看组内主机列表:
语法:ansible 组名 --list-hosts
[root@ansible ~]# [root@ansible ~]# ansible web* --list-hosts
hosts (3):
web-3
web-1
web-2
====================================
扩展:自定义主机列表使用密码登录:(了解)
[root@ansible ~]# vim /opt/hostlist
[all:vars]
ansible_ssh_port=22
ansible_ssh_user=root
#ansible_ssh_private_key_file=/root/.ssh/id_rsa
ansible_ssh_pass=test
[all]
web-1
web-2
web-3
使用:
[root@ansible ~]# ansible -i /opt/hostlist all -m ping -o
小注释:如果不通,手动连接第一次,第一次需要手动输入密码。"第一次"
-i:指定清单文件
注意:这里的ping并不是真正意义上的ping而是探测远程主机ssh是否可以连接!判断ssh端口是否存活
基本使用示例:
执行shell命令:-a 是传给模块的参数
[root@ansible ~]# ansible web-1 -m shell -a 'uptime'
web-1 | CHANGED | rc=0 >>
18:01:44 up 13:21, 3 users, load average: 0.00, 0.01, 0.05
因为默认模块就是command,所以上面命令可以不加-m:
[root@ansible ~]# ansible web-2 -a 'uptime'
web-2 | CHANGED | rc=0 >>
18:02:22 up 13:22, 3 users, load average: 0.00, 0.01, 0.05
[root@ansible ~]# ansible web1 -a 'uptime' -u root -k
SSH password:
web1 | SUCCESS | rc=0 >>
11:02:56 up 2 days, 15:07, 2 users, load average: 0.00, 0.01, 0.05
使用ssh账户和密码:-u和-k
-u 用户 //指定ssh账户
-k //指定使用ssh密码,注意:如果设置了公钥认证,这里写什么密码都可以
给节点增加用户
[root@ansible ~]# ansible web-3 -a "useradd tom"
web-3 | CHANGED | rc=0 >>
[root@ansible ~]# ansible web-3 -a "grep tom /etc/passwd"
web-3 | CHANGED | rc=0 >>
tom:x:1000:1000::/home/tom:/bin/bash
重定向输出到本地文件中:
[root@ansible ~]# ansible web-1 -m shell -a "echo hello > /opt/a.txt"
web-1 | CHANGED | rc=0 >>
[root@ansible ~]# ansible web-1 -m shell -a "cat /opt/a.txt"
web-1 | CHANGED | rc=0 >>
hello
注意:一个典型的例子就是 shell 和 command 模块. 这两个模块在很多情况下都能完成同样的工作, 以下是两个模块之间的区别:
command 模块命令将不会使用 shell 执行. 因此, 像 $HOME 这样的变量是不可用的。还有像 |,& 都将不可用。
shell 模块通过shell程序执行, 默认是/bin/sh, <, >, |, ;, & 可用。
ad hoc其实就是执行简单的命令——一条命令。对于复杂的命令则为 playbook。
帮助文档:
列出ansible支持的模块:
-l:获取列表
-s module_name:获取指定模块的使用信息
获取模块列表
[root@ansible ~]# ansible-doc -l
模块使用格式:
[root@ansible ~]# ansible-doc -s yum
参数:
-f 2 指定定要使用的并行进程数,默认为5个,临时指定,如果想要永久指定,修改主配置文件。
也可以看官方手册:https://docs.ansible.com/ansible/2.9/modules/core_maintained.html#core-supported
模块参数详解:
src=:指定源文件路径
dest=:目标地址(拷贝到哪里)
owner:指定属主
group:指定属组
mode:指定权限,可以以数字指定比如0644
backup:在覆盖之前将原文件备份,备份文件包含时间信息。有两个选项:yes|no
[root@ansible ~]# echo 123 > a.txt
[root@ansible ~]# ansible web-1 -m copy -a 'src=/root/a.txt dest=/root owner=root group=root mode=644' -o
....
[root@ansible ~]# echo 456 >> a.txt
[root@ansible ~]# ansible web-1 -m copy -a 'src=/root/a.txt dest=/root owner=root group=root mode=644 backup=true' -o
....
注释:如果文件没有变化,不会备份。只有文件内容不同,才会做备份。
在web-1上验证
[root@web-1 ~]# ls
anaconda-ks.cfg a.txt a.txt.4286.2022-05-22@18:28:53~
[root@web-1 ~]# cat a.txt
123
456
[root@web-1 ~]# cat a.txt.4286.2022-05-22@18\:28\:53~
123
copy模块:https://docs.ansible.com/ansible/2.9/modules/copy_module.html#copy-module
state= #状态是什么,干什么
state=absent 用于remove安装包
state=latest 表示最新的
state=removed 表示卸载
在用这个模块之前,可以不指定yum模块验证一下
安装:sl
[root@ansible ~]# ansible web-3 -a "yum -y install sl"
[WARNING]: Consider using the yum module rather than running 'yum'. If you need to use command because yum 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.
([警告]:考虑使用yum模块,而不是运行“yum”。如果由于yum不足而需要使用命令,可以将“warn:false”添加到此命令任务,或在ansible中设置“command\u warnings=false”。cfg以删除此消息。)
...
完毕!
[root@ansible ~]# ansible web-1 -m yum -a "name=sl" -o
web-1 | CHANGED => {"ansible_facts": {"discovered_interpreter_py.....
卸载:
[root@ansible ~]# ansible web-1 -m yum -a "name=sl state=removed" -o
web-1 | CHANGED => {"ansible_facts": {"discovered_interpreter_python......
或者
ansible web-1 -m yum -a "name=sl state=absent" -o
yum模块:https://docs.ansible.com/ansible/2.9/modules/yum_module.html#yum-module
[root@ansible-server ~]# ansible web-1 -m service -a "name=httpd state=started" #启动
[root@ansible-server ~]# ansible web-1 -m service -a "name=httpd state=stopped" #停止
[root@ansible-server ~]# ansible web-1 -m service -a "name=httpd state=restarted" #重启
[root@ansible-server ~]# ansible web-1 -m service -a "name=httpd state=started enabled=yes" #开机启动
[root@ansible-server ~]# ansible web-1 -m service -a "name=httpd state=started enabled=no" #开机关闭
模块参数详解:
owner:修改属主
group:修改属组
mode:修改权限
path=:要修改文件的路径
recurse:递归的设置文件的属性,只对目录有效
yes:表示使用递归设置
state:
touch:创建一个新的空文件
directory:当目录存在时不会进行修改
[root@ansible ~]# ansible web-1 -m file -a 'path=/root/b.txt mode=777 state=touch'
web-1 | CHANGED => {
...
}
[root@ansible ~]# ansible web-1 -m file -a 'path=/root/c.txt mode=777 state=directory'
web-1 | CHANGED => {
....
}
添加用户并设置密码:使用命令需要用双引:
[root@ansible ~]# ansible web-1 -m user -a "name=liudehua password=`echo 1234 | openssl passwd -1 -stdin`" -o
"name= " #如:指定的用户名,要安装的软件
-1 MD5加密算法
删除用户:
[root@ansible ~]# ansible web-1 -m user -a "name=liudehua state=absent" -o
adsent #删除用户,但是不会删除家目录
也可以:ansible web-1 -a "userdel -r zzz"
[root@ansible ~]# ansible web-1 -m setup #收集所有信息
[root@ansible ~]# ansible web-1 -m setup -a 'filter=ansible_all_ipv4_addresses' #只查询ipv4的地址
filter:过滤
[root@ansible ~]# ansible web-1 -m setup -a 'filter=ansible_*_mb'
[root@ansible ~]# ansible -i /home/ansible/hostlist web1 -m setup -a 'filter=ansible_processor_cores'
[root@ansible ~]# ansible all -m setup --tree /tmp/facts
扩展:
获取每台主机的IP地址:
ansible -i /opt/hostlist web-1 -m shell -a 'ip a |grep "scope global" |awk "{print $2}"'
获取每台主机的内存:
[root@xingdian ~]# ansible -i /opt/hostlist web-1 -m shell -a "free -m | awk 'NR==2'" > b.txt -o && cat b.txt | awk '{print $10}'
playbook是ansible用于配置,部署。和管理被控节点的剧本。通过playbook的详细描述,执行其中的tasks,可以让远端主机达到预期的状态。playbook是由一个或多个"play"组成的列表。当对一台机器做环境初始化的时候往往需要布置做一件事情,这是使用playbook会更加适合。通过playbook你可以一次在多台机器执行指令。通过这种预先设计的的配置保持了机器的配置统一,并很简单的执行日常任务。
ansible通过不同的模块实现相应的管理,管理的方式通过定义的清单文件(hosts)所管理的主机包括认证的方式连接的端口等。所有的功能都是通过调用不同的模块(modules)来完成不同的功能的。不管是执行单条命令还是play-book都是基于清单文件。
playbook格式:playbook有YMAL语言编写。YAML格式是类似于JSON的文件格式,便于人理解和阅读,同时便于书写。
Variables:变量元素,可传递给Tasks/Template使用;
Tasks:任务元素,有模块定义的操作的列表,即调用模块完成任务;
Templates:模块元素,使用了模块语法的文本文件,可根据变量动态生成配置文件;
Handlers:处理器元素,通常指在某事件满足时触发的操作;
Roles:角色元素
注意:一个剧本里可以有多个play,每个play只能有一个tasks,每个tasks可以有多个name
name:定义playbook或者tasks的名称(描述信息),每一个play都可以完成一个任务。
hosts:playbook中的每一个play的目的都是为了让某个或某些以某个指定用户的身份执行任务。hosts用于指定要执行指定任务的主机,其可以是一个或多个由冒号分隔主机组。与命令模式下的ansible匹配规则一样
user:remote_user则用于指定远程主机上的执行任务的用户,也可以使用user(基本都是root)
tasks:任务列表play的主题部分是task list,task list中的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后再开始第二个。
vars:定义变量(如果不使用内部变量需要提前定义)
vars_files:动用定义变量文件
notify:任务执行结果如果是发生更改了的则触发定义在handler的任务执行
handlers:用于当前关注的资源发生变化时采取的指定的操作
include:能包含的包括task,handler和playbook,可以在include的时候传递变量
案例一
[root@ansible ~]# cd /etc/ansible
[root@ansible ansible]# vim test.yml
- hosts: web-1 #-后面有空格,冒号后面有空格
user: root
tasks:
- name: test
file: state=touch path=/root/test.txt
参数解释:
hosts: 参数指定了对哪些主机进行操作;
user: 参数指定了使用什么用户登录远程主机操作;
tasks: 指定了一个任务.
name:参数同样是对任务的描述,在执行过程中会打印出
[root@ansible ansible]# ansible-playbook --syntax-check test.yml #检测是否有语法错误
playbook: Test.yml
[root@ansible ansible]# ansible-play-book test.yml #运行playbook
案例二
handlers:由特定条件触发Tasks
语法:
tasks:
- name: TASK_NAME
module: arguments #1.上面任务执行成功,然后
notify: HANDLER_NAME #2.通知他
handlers:
- name: HANDLER_NAME #3.一一对应,这里的描述与notify定义的必须一样
module: arguments #4.执行这个命令
[root@ansible ansible]# cat /root/a.txt
123
[root@ansible ansible]# vim handlers.yml
- hosts: web-2
user: root
tasks:
- name: test copy
copy: src=/root/a.txt dest=/mnt
notify: test handlers
handlers:
- name: test handlers
shell: echo "1234" >>/mnt/a.txt
注意:只有 copy 模块真正执行后,才会去调用下面的 handlers 相关的操作,追加内容。所以这种比较适合配置文件发生更改后,需要重启服务的操作。
[root@ansible ansible]# ansible-playbook handlers.yml #运行playbook
在web-2上验证
[root@localhost ~]# cat /mnt/a.txt
123
1234
案例三
安装nginx并启动服务
[root@ansible ansible]# vim yum.yml
- hosts: web-3
user: root
tasks:
- name: nginx
yum: name=nginx state=latest
- name: index
shell: echo "hello word" >/usr/share/nginx/html/index.html
notify: test nginx
handlers: test nginx
- name: start nginx
service: name=nginx state=started
[root@ansible ansible]# ansible-playbook --syntax-check yum.yml
playbook: handlers.yml
[root@ansible ansible]# ansible-playbook yum.yml
....
验证:
[root@ansible ansible]# curl web-3
hello word
案例四
自定义vars_file变量
变量调用语法:
{{ var_name }}
创建变量目录
[root@ansible ansible]# mkdir /etc/ansible/vars
[root@ansible ansible]# vim vars/file.yml #创建变量文件
src_path: /root/a.txt
dest_path: /opt/
[root@ansible ansible]# echo "自定义变量" >/root/a.txt
创建playbook引用变量文件
[root@ansible ansible]# vim vars_file.yml
- hosts: web-1
user: root
vars_files:
- /etc/ansible/vars/file.yml
tasks:
- name: vars
copy: src={{ src_path }} dest={{ dest_path }}
[root@ansible ansible]# ansible-playbook --syntax-check vars_file.yml
playbook: vars_file.yml
[root@ansible ansible]# ansible-playbook vars_file.yml
在web-1验证
[root@web-1 ~]# cat /opt/a.txt
自定义变量
案例五
循环:迭代,需要重复执行的任务;
对迭代项的引用,固定变量名为”item”,使用with_items属性给定要迭代的元素;
元素:1.列表 2.字符串 3.字典
基于字符串列表元素实战
[root@ansible ansible]# vim list.yml
- hosts:
user: root
tasks:
- name: a
yum: name={{ item }} state=latest
with_items:
- httpd
- php
- php-mysql
[root@ansible ansible]# ansible-playbook --syntax-check list.yml
[root@ansible ansible]# ansible-playbook list.yml
基于字典列表元素实战
[root@ansible ansible]# vim item.yml
- hosts: web-1
user: root
tasks:
- name: create group
group: name={{ item }} state=present
with_items:
- hr1
- hr2
- hr3
- name: create user
user: name={{ item.name }} group={{ item.group }} state=present
with_items:
- {name: "zcg",group: "hr1"}
- {name: "zcy",group: "hr2"}
- {name: "hjf",group: "hr3"}
[root@ansible ansible]# ansible-playbook --syntax-check item.yml
[root@ansible ansible]# ansible-playbook item.yml
案例六
tags使用:
给指定任务定义一个调用标识,形式如下
只运行指定标记的任务:-t 标记名称
ansible-playbook -t z1 tags.yml
跳过某一个被标记的任务:--skip-tags=标记名称
ansible-playbook --skip-tags=z1 tags.yml
从某一个任务开始往下运行:--start-at-task 任务名称
ansible-playbook --start-at-task tag2 tags.yml
[root@ansible ansible]# vim tags.yml
- hosts: web-1
user: root
tasks:
- name: tag1
file: state=touch path=/root/tag1
tags: z1
- name: tag2
file: state=touch path=/root/tag2
tags: z2
- name: tag3
file: state=touch path=/root/tag3.txt
tags: z3
[root@ansible ansible]# ansible-playbook -t z1 tags.yml
[root@ansible ansible]# ansible-playbook --skip-tags=z1 tags.yml
[root@ansible ansible]# ansible-playbook --start-at-task tag3 tags.yml
批量安装apache服务,并用浏览器访问到对应的项目
[root@ansible ansible]# mkdir apache
[root@ansible ansible]# echo "hello word" > apache/index.html
[root@ansible ansible]# vim apache/apache.conf
ServerName localhost
DocumentRoot /apache
AllowOverride all
Require all granted
[root@ansible ansible]# vim apache.yml
- hosts: web*
user: root
tasks:
- name: a
yum: name=httpd state=latest
- name: b
file: state=directory path=/apache mode=777
- name: c
copy: src=/etc/ansible/apache/index.html dest=/apache
- name: d
shell: echo "Listen 81" >>/etc/httpd/conf/httpd.conf
- name: e
copy: src=/etc/ansible/apache/apache.conf dest=etc/httpd/conf.d/
notify: f
- name: f
service: name=httpd state=started
[root@ansible ansible]# ansible-playbook --syntax-check apache/apache.yml
playbook: apache/apache.yml
[root@ansible ansible]# ansible-playbook apache/apache.yml
验证:
[root@ansible ansible]# curl web-1
hello word
Variable类型:
内建变量
自定义变量
变量调用
{{ var_name }}
内建变量:由facts组件提供,可以使用setup模块查询
案例一
[root@ansible ansible]# ansible web-1 -m setup|grep mem
"ansible_memfree_mb": 1175,
"ansible_memory_mb": {
"ansible_memtotal_mb": 1823,
[root@ansible ansible]# vim var1.yml
- hosts: web-3
user: root
tasks:
- name: vars
shell: echo {{ ansible_memtotal_mb }} >> /root/mem.txt
[root@ansible ansible]# ansible-playbook var1.yml
案例二
自定义变量:
使用命令行传递参数
为了使Playbook更灵活、通用性更强,允许用户在执行的时候传入变量的值,这个时候就需要用到“额外变量”。
[root@ansible ansible]# vim var2.yml
- hosts: '{{ hosts }}'
user: '{{ user }}'
tasks:
- name: zzz
file: state=touch path=/root/var1.txt
使用命令行变量
在命令行里面传值的方法:
[root@ansible ansible]# ansible-playbook var2.yml --extra-vars "hosts=web-2 user=root"
还可以用json格式传递参数:
[root@ansible ansible]# ansible-playbook var2.yml --extra-vars "{'hosts':'web-1','user':'root'}"
案例三
set_fact自定义facts变量
set_fact模块可以自定义facts,这些自定义的facts可以通过template或者变量的方式在playbook中使用。如果你想要获取一 个进程使用的内存的百分比,则必须通过set_fact来进行计算之后得出其值,并将其值在playbook中引用。
[root@ansible ansible]# mkdir templates
[root@ansible ansible]# vim template/my.conf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted
security risks
symbolic-links=0
# Configure the buffer pool
innodb_buffer_pool_size = {{ aaa|int }}M
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
[root@ansible ansible]# vim var3.yml
- hosts: web*
user: root
tasks:
- name: mycnf
set_fact: aaa="{{ ansible_memtotal_mb / 2 }}"
- name: ccc
template: src=templates/my.cnf dest=/etc/my.cnf owner=root group=root mode=0644
[root@ansible ansible]# ansible-playbook var3.yml
role 角色:roles是在ansible中,playbook的目录组织结构
每一个角色是有名字的,是一个目录,可以包含子目录。以特定的层级目录结构进行组织的tasks、variable、handlers、templates、files等
role_name/:这个是角色的名称
files/:存储有copy或script等模块调用的文件
tasks/:专门存储任务的目录,一个角色可以定义多个任务,此目录中至少应该有一个名为main.yml的文件,用于定义各task;其他的文件需要由main.yml进行“包含”调用
handlers/:条件,前一个任务执行成功去执行下面的,用于处理特定事物的文件。此目录中至少应该有一个名为main.yml的文件,用于定义各handler;其他的文件需要由main.yml进行“包含”调用
vars/:变量,定义变量的文件。此目录中至少应该有一个名为main.yml的文件,用于定义各variable;其他的文件需要由main.yml进行“包含”调用
templates/:模板,使用变量的文件存储由template模块调用的模板文本
meta/:此目录中至少应该有一个名为main.yml的文件,定义当前角色的特殊设定及其以来关系
default/:此目录中至少应该有一个名为main.yml的文件,用于设定默认变量
在playbook中调用角色的方法:
- hosts: HOSTS
remote_user: USERNAME
roles:
- ROLE1
- ROLE2
- { role: ROLE3, VARIABLE: VALUE, ...}
- { role: ROLE4, when: CONDITION }
案例:批量部署nginx(做这个实验之前记得将apache关闭或者卸载)
目录结构准备
[root@ansible roles]# mkdir nginx/{files,handlers,tasks,templates,vars} -p
[root@ansible roles]# touch nginx/{handlers,tasks,vars}/main.yml site.yml
[root@ansible roles]# echo "hello word" >nginx/files/index.html
[root@ansible roles]# yum -y install nginx &&cp /etc/nginx/nginx.conf nginx/templates/nginx.conf.j2 这一步是为了准备nginx主配置文件的模板文件,如果已经有的话,直接拷贝到templates目录中即可
[root@ansible roles]# tree nginx
nginx/
├── files
│ └── index.html
├── handlers
│ └── main.yml
├── tasks
│ └── main.yml
├── templates
│ └── nginx.conf.j2
└── vars
└── main.yml
编写任务
[root@ansible roles]# vim nginx/tasks/main.yml
- name: a
yum: name=nginx state=removed
- name: b
yum: name=nginx state=latest
- name: c
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
- name: d
copy: src=index.html dest=/usr/share/nginx/html/index.html
notify: start nginx
注意:这里面的src之所以不用写路径是因为roles使用的是特定的层级目录结构,会自动寻找nginx目录中对应的文件
templates模板: 用的是jinja2的语法
准备配置文件
[root@ansible roles]# vim nginx/templates/nginx.conf.j2
修改成如下内容。自定义变量
...
events {
worker_connections {{ worker_connections }};
}
...
编写变量
[root@ansible roles]# vim nginx/vars/main.yml
worker_connections: 65535
编写handlers
[root@ansible roles]# vim nginx/handlers/main.yml
- name: start nginx #这里的名称描述要与tasks任务中的notify名称描述对应
service: name=nginx state=started
编写剧本
[root@ansible roles]# vim site.yml
- hosts: web*
user: root
roles:
- nginx
语法检测
[root@ansible roles]# ansible-playbook --syntax-check site.yml
playbook: site.yml
执行剧本
[root@ansible roles]# ansible-playbook site.yml
验证:
[root@ansible roles]# curl web-1
hello word
[root@ansible roles]# curl web-2
hello word
[root@ansible roles]# curl web-3
hello word
1. setup: 查看远程主机的基本信息
2. ping: 测试远程主机的运行状态
3. file: 设置文件属性
相关选项如下:
force:需要在两种情况下强制创建软链接,一种是源文件不存在,但之后会建立的情况下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个选项:yes|no
group:定义文件/目录的属组
mode:定义文件/目录的权限
owner:定义文件/目录的属主
path:必选项,定义文件/目录的路径
recurse:递归设置文件的属性,只对目录有效,有两个选项:yes|no
src:被链接的源文件路径,只应用于state=link的情况
dest:被链接到的路径,只应用于state=link的情况
state:
directory:如果目录不存在,就创建目录
file:即使文件不存在,也不会被创建
link:创建软链接
hard:创建硬链接
touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间
absent:删除目录、文件或者取消链接文件
使用示例:
ansible test -m file -a "src=/etc/fstab dest=/tmp/fstab state=link"
ansible test -m file -a "path=/tmp/fstab state=absent"
ansible test -m file -a "path=/tmp/test state=touch"
4. copy: 把主控端的文件复制到远程主机
相关选项如下:
backup:在覆盖之前,将源文件备份,备份文件包含时间信息。有两个选项:yes|no
content:用于替代“src”,可以直接设定指定文件的值
dest:必选项。要将源文件复制到的远程主机的绝对路径,如果源文件是一个目录,那么该路径也必须是个目录
directory_mode:递归设定目录的权限,默认为系统默认权限
force:如果目标主机包含该文件,但内容不同,如果设置为yes,则强制覆盖,如果为no,则只有当目标主机的目标位置不存在该文件时,才复制。默认为yes
others:所有的file模块里的选项都可以在这里使用
src:被复制到远程主机的本地文件,可以是绝对路径,也可以是相对路径。如果路径是一个目录,它将递归复制。在这种情况下,如果路径使用“/”来结尾,则只复制目录里的内容,如果没有使用“/”来结尾,则包含目录在内的整个内容全部复制,类似于rsync
示例如下:
ansible test -m copy -a "src=/srv/myfiles/foo.conf dest=/etc/foo.conf owner=foo group=foo mode=0644"
ansible test -m copy -a "src=/mine/ntp.conf dest=/etc/ntp.conf owner=root group=root mode=644 backup=yes"
5.service模块:用于管理服务
该模块包含如下选项:
arguments:给命令行提供一些选项
enabled:是否开机启动 yes|no
name:必选项,服务名称
pattern:定义一个模式,如果通过status指令来查看服务的状态时,没有响应,就会通过ps指令在进程中根据该模式进行查找,如果匹配到,则认为该服务依然在运行
runlevel:运行级别
sleep:如果执行了restarted,在则stop和start之间沉睡几秒钟
state:对当前服务执行启动,停止、重启、重新加载等操作(started,stopped,restarted,reloaded)
使用示例:
ansible test -m service -a "name=httpd state=started enabled=yes"
asnible test -m service -a "name=foo pattern=/usr/bin/foo state=started"
ansible test -m service -a "name=network state=restarted args=eth0"
6.cron模块:用于管理计划任务
包含如下选项:
backup:对远程主机上的原任务计划内容修改之前做备份
cron_file:如果指定该选项,则用该文件替换远程主机上的cron.d目录下的用户的任务计划
day:日(1-31,*,*/2,……)
hour:小时(0-23,*,*/2,……)
minute:分钟(0-59,*,*/2,……)
month:月(1-12,*,*/2,……)
weekday:周(0-7,*,……)
job:要执行的任务,依赖于state=present
name:该任务的描述
special_time:指定什么时候执行,参数:reboot,yearly,annually,monthly,weekly,daily,hourly
state:确认该任务计划是创建还是删除
user:以哪个用户的身份执行
示例:
ansible test -m cron -a 'name="a job for reboot" special_time=reboot job="/some/job.sh"'
ansible test -m cron -a 'name="yum autoupdate" weekday="2" minute=0 hour=12 user="root
ansible test -m cron -a 'backup="True" name="test" minute="0" hour="5,2" job="ls -alh > /dev/null"'
ansilbe test -m cron -a 'cron_file=ansible_yum-autoupdate state=absent'
7.yum模块:使用yum包管理器来管理软件包
其选项有:
config_file:yum的配置文件
disable_gpg_check:关闭gpg_check
disablerepo:不启用某个源
enablerepo:启用某个源
name:要进行操作的软件包的名字,也可以传递一个url或者一个本地的rpm包的路径
state:状态(present,absent,latest)
示例如下:
ansible test -m yum -a 'name=httpd state=latest'
ansible test -m yum -a 'name="@Development tools" state=present'
ansible test -m yum -a 'name=http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm state=present'
8.user模块与group模块
user模块是请求的是useradd, userdel, usermod三个指令,goup模块请求的是groupadd, groupdel, groupmod 三个指令。
user模块
home:指定用户的家目录,需要与createhome配合使用
groups:指定用户的属组
uid:指定用的uid
password:指定用户的密码
name:指定用户名
createhome:是否创建家目录 yes|no
system:是否为系统用户
remove:当state=absent时,remove=yes则表示连同家目录一起删除,等价于userdel -r
state:是创建还是删除
shell:指定用户的shell环境
group示例
ansible all -m group -a 'name=somegroup state=present'
9. shell: shell命令
ansible默认使用的模块是command,支持多数shell命令,但不支持shell变量及管道,如果要使用,用shell模块
将Jdk、Tomcat、Jenkins的安装包上传到ansbile控制节点的/usr/src下
[root@ansible ansible]# ls /usr/src/
[root@java-server ansible]# head -2 /usr/src/startup.sh //startup.sh是tomcat的启动脚本
#!/bin/sh
source /etc/profile #加上此行,是为了启动加载到环境变量
变量文件
[root@ansible ansible]# cat /etc/ansible/vars/file.yml
下面是剧本
[root@ansible ansible]# cat jenkins.yml
- hosts: ansible-web1
user: root
vars_files:
- /etc/ansible/vars/file.yml
tasks:
##配置JDK,上传jdk、tomcat的安装包到/usr/src
- name: configure JDK1.8
copy: src={{ src_jdk_path }} dest={{ dest_jdk_path }}
- name: unzip JDK
shell: tar -xvzf /usr/src/jdk-8u211-linux-x64.tar.gz -C /usr/local
- name: rename to java
shell: mv /usr/local/jdk1.8.0_211 /usr/local/java
- name: configure JDK envirement1
shell: echo "JAVA_HOME=/usr/local/java" >> /etc/profile
- name: configure JDK envirement2
shell: echo 'PATH=$JAVA_HOME/bin:$PATH' >> /etc/profile
##Tomcat
- name: copy tomcat
copy: src={{ src_tomcat_path }} dest={{ dest_tomcat_path }}
- name: unzip tomcat
shell: tar -xvzf /usr/src/apache-tomcat-8.5.45.tar.gz -C /usr/local
- name: rename to tomcat
shell: mv /usr/local/apache-tomcat-8.5.45 /usr/local/tomcat
- name: copy startup file
copy: src=/usr/src/startup.sh dest=/usr/local/tomcat/bin
##Jenkins
- name: copy jenkins
copy: src=/usr/src/jenkins.war dest=/usr/local/tomcat/webapps/
notify: start jenkins
handlers:
- name: start jenkins
shell: nohup /usr/local/tomcat/bin/startup.sh &