运维工具的分类:
agentless:无代理端程序,通过依赖于SSH协议,安全性有限;
ansible,fabric,saltstack;
agent:基于代理程序实现安全通信;
puppet,Zabbix,func;
主要功能:
1.批量的系统部署;
2.批量的程序部署;
3.批量的运行命令;
ansible的特性:
1.模块化:ansible核心仅仅提供了一组命令行工具(框架),真正的运维管理功能需要各个模块来实现;
2.基于python语言开发实现的,需要有Paromiko,jinja2,PyYMAL三个关键模块的支持;
3.Agentless,部署简单,默认依靠SSH协议;
4.支持自定义模块;
5.支持playbook;
6.快速失败,执行效率O(1),幂等性;
ansible应用程序的结构:
ansible核心:提供核心命令行工具;
Host Inventory:主机清单,指定ansible能够操纵和管理的主机列表及分组情况;
Playbook:剧本,可以重复执行或同时执行一个或多个任务的具有YAML语言的格式的文件文件;
一般,文件的后缀名称为:.yml或.yaml;
modules:
核心模块;
自定义模块;
插件(Connection Plugins):
连接器插件:在与后端被管设备进行通信之前用于建立通信会话连接的插件;
邮件发送的插件
日志记录的插件
ansible的安装:
到目前为止,ansible的rpm包只能由EPEL源提供;
使用yum命令来安装即可;(CentOS 7.5(1803))
# yum install ansible
ansible的程序环境:
主配置文件:/etc/ansible/ansible.cfg
主机清单文件:/etc/ansible/hosts
主程序:
/usr/bin/ansible
/usr/bin/ansible-doc
/usr/bin/ansible-playbook
主机清单的文件格式:
1.单纯的主机列表:
将主机名或IP地址按照每行一个的格式写入/etc/ansible/hosts文件;
2.主机分组:
[websrvs]
IP_ADDR1
...
HOSTNAME1
...
[dbsrvs]
IP_ADDR2
...
HOSTNAME2
...
[wang]
172.16.75.2
3.主机范围表示:
web01-web10
web[01:10]
172.16.72.[2:10]
首先主控设备和被控设备之间要实现基于密钥的ssh通信:
[root@3 ~]# ssh-keygen -t rsa -P '123456'
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Created directory '/root/.ssh'.
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:YVqUBbBJLgN1aFuVZdlzMuR+ahlj+UVHh0Bex4XATko root@3
The key's randomart image is:
+---[RSA 2048]----+
| ....+o+*+*=o.+*|
| .o+.+o.EoB.+oo|
| .oo+ +. +o= o|
| .o + ..... ..|
| . S * . .|
| . B . |
| + . |
| . |
| |
+----[SHA256]-----+
[root@3 ~]# ls .ssh
id_rsa id_rsa.pub
[root@3 ~]# ssh-copy-id -i .ssh/id_rsa.pub [email protected]
[root@3 ~]# ssh-copy-id -i .ssh/id_rsa.pub [email protected]
[root@3 ~]# ssh-copy-id -i .ssh/id_rsa.pub [email protected]
[root@3 ~]# ssh-copy-id -i .ssh/id_rsa.pub [email protected]
[root@3 ~]# ssh 172.16.75.5 //登录尝试
Enter passphrase for key '/root/.ssh/id_rsa':
各主机都可登陆后,编辑/etc/ansible/hosts文件
规定出我们所提供的服务器,保存即可:
172.16.75.4
172.16.75.5
172.16.75.6
172.16.75.13
我们用ansible中的ping模块,ping一下我们的被控设备,因为我们之前设置了ssh密码所以在ping的时候,
每一台被控设备被ping通之前都需要输入一次密码,之后再ping的时候,就不需要了:
[root@3 ~]# ansible all -m ping
172.16.75.5 | SUCCESS => {
"changed": false,
"ping": "pong"
}
172.16.75.13 | SUCCESS => {
"changed": false,
"ping": "pong"
}
172.16.75.4 | SUCCESS => {
"changed": false,
"ping": "pong"
}
172.16.75.6 | SUCCESS => {
"changed": false,
"ping": "pong"
}
还可以将被控设备进行分组:
[root@3 ~]# vim /etc/ansible/hosts
[test1]
172.16.75.4
172.16.75.5
[test2]
172.16.75.6
172.16.75.13
这时,我们在以组为单位进行测试:
[root@3 ~]# ansible test1 -m ping
Enter passphrase for key '/root/.ssh/id_rsa': //要输入ssh中设置的密码
172.16.75.4 | SUCCESS => {
"changed": false,
"ping": "pong"
}
Enter passphrase for key '/root/.ssh/id_rsa':
172.16.75.5 | SUCCESS => {
"changed": false,
"ping": "pong"
}
当然在主控设备和被控设备之间实现基于密钥的ssh通信时我们可以不设置密码,
这样在实验的时候就简单方便多了。
ansible命令:
ansible - Define and run a single task 'playbook' against a set of hosts
格式:
ansible [options]
常用选项:
-a MODULE_ARGS, --args MODULE_ARGS
在使用某些模块时,用于指定该模块所需要的参数;
-e, --extra-vars
在ansible的命令行中用于设置执行ansible任务时的自定义变量;
-m MODULE_NAME, --module-name MODULE_NAME
在执行ansible任务时,所选择使用的模块;如果未给出该选项,默认选择使用"command"模块;
-C, --check
并不真正的在被管主机上运行任务,而是测试看结果是否会发生改变;
ansible-doc命令:
ansible-doc - plugin documentation tool
格式:
ansible-doc [-l|-F|-s] [options] [-t ] [plugin]
常用选项:
-l, --list:
列表显示当前所有可用的ansible模块;
-s, --snippet:
获取模块的使用规则,其结果通常是剧本中的用法;
常用的ansible模块:
1.command模块:
Executes a command on a remote node
示例:
[root@3 ~]# ansible all -m command -a "useradd testuser01"
[root@3 ~]# ansible all -m command -a "id testuser01"
2.shell模块(使用管道或者通配符时使用此模块 ):
Execute commands in nodes.
示例:
[root@3 ~]# ansible all -m shell -a "echo qhdlink | passwd --stdin testuser01"
3.user模块:
Manage user accounts
常用的参数:
name: 指定欲管理的用户账户名称;必选参数;
create_home: 是否为用户创建家目录,除非显式给出"no"值,默认创建;
system: 是否将用户创建为系统用户;
uid: 为指定的用户指定一个固定的UID;
group: 为指定的用户指定一个主要组;
groups: 为指定的用户添加一个附加组;
state: 此次ansible任务的执行状态;必选参数;
present:创建;
absent:删除;
force: 当state=absent时,该任务相当于"userdel --force";
remove: 当state=absent时,该任务相当于"userdel --remove | userdel -r";
shell: 为指定的用户指定一个默认登录shell;
示例:
[root@3 ~]# ansible all -m user -a "name=testuser02 system=yes uid=333
create_home=no shell=/sbin/nologin state=present"
[root@3 ~]# ansible all -m user -a "name=testuser01 state=absent remove=yes"
4.group模块:
Add or remove groups
常用的参数:
gid: 为指定组名的组指定一个GID;
name: 指定组名;必选参数
state: 此次ansible任务的执行状态;必选参数;
present:创建;
absent:删除;
system: 是否将组设置为系统组;
示例:
[root@3 ~]# ansible all -m group -a "name=wzc system=yes gid=345 state=present"
[root@3 ~]# ansible all -m group -a "name=wzc state=absent"
5.copy模块:
Copies files to remote locations
常用的参数:
dest: 此次ansible的复制任务的目标位置,必须用绝对路径表示;
注意:
1.如果src指定的路径是目录,则dest必须指定目录;
2.如果dest的路径是以"/"做结尾或src是一个目录时,若dest不存在,则创建;
3.如果src和dest都是文件,若dest表示的路径中有目录不存在,则不会创建并报告错误;
src: 此次ansible的复制任务的源文件的位置,可以使用相对路径也可以使用绝对路径;
注意:
1.如果src所指定的路径是以"/"结尾,仅复制该目录下的文件到目标位置;
2.如果src所指定的路径不以"/"结尾,就会复制所有路径中包含的目录的内容到目标位置;
类似于rsync;
mode: 设置目标位置文件的权限属性;
owner: 设置目标位置文件的属主;
group: 设置目标位置文件的属组;
force: 如果目标位置文件已经存在,是否覆盖;默认为yes;
示例:
[root@3 ~]# ansible test1 -m copy -a "content='hello\neverybody\n' force=yes
dest=/tmp/hello.txt mode=0600 owner=testuser02"
[root@3 ~]# ansible test1 -m copy -a "src=/etc/yum.repos.d/CentOS-Base.repo
dest=/tmp owner=ftp group=daemon mode=0640"
6.cron模块:
Manage cron.d and crontab entries
常用的参数:
name: cron任务的名称;在删除时必须指定,创建时如果不指定,则自动创建一个新的cron任务;
month: 月份;
day: 天;
hour: 小时;
minute: 分钟;
weekday: 星期;
job: 此次定义的工作的具体内容,即:命令;
state:
present:创建;
absent:删除;
user: 指定此次修改的计划任务的所有者;
示例:
在各被控设备中定制计划任务:
[root@3 ~]# ansible all -m cron -a "name='Update Time' minute=*/10 job='/usr/sbin/ntpdate
172.16.72.3 &> /dev/null' state=present"
172.16.75.4 | CHANGED => {
"changed": true,
"envs": [],
"jobs": [
"Update Time"
]
}
172.16.75.13 | CHANGED => {
"changed": true,
"envs": [],
"jobs": [
"Update Time"
]
}
172.16.75.6 | CHANGED => {
"changed": true,
"envs": [],
"jobs": [
"Update Time"
]
}
172.16.75.5 | CHANGED => {
"changed": true,
"envs": [],
"jobs": [
"Update Time"
]
}
到被控设备中查看结果:
[root@4 ~]# crontab -l
#Ansible: Update Time
*/10 * * * * /usr/sbin/ntpdate 172.16.72.3 &> /dev/null
在各被控设备中删除已经定制计划任务:
[root@3 ~]# ansible all -m cron -a "name='Update Time' state=absent"
172.16.75.5 | CHANGED => {
"changed": true,
"envs": [],
"jobs": []
}
172.16.75.6 | CHANGED => {
"changed": true,
"envs": [],
"jobs": []
}
172.16.75.13 | CHANGED => {
"changed": true,
"envs": [],
"jobs": []
}
172.16.75.4 | CHANGED => {
"changed": true,
"envs": [],
"jobs": []
}
到被控设备中查看结果:
[root@4 ~]# crontab -l
[root@4 ~]# //没有内容,以为我们在上述操作中包计划任务删除了
7.hostname模块:
Manage hostname
参数:
name: 指定主机名;
注意:如果直接拿来设置主机名,会导致所有主机同名;绝大多数情况下,会结合变量进行主机名的设置,
以保证不同的主机被设置不同的主机名;
示例:
[root@3 ~]# ansible 172.16.75.4 -m hostname -a "name=www.wzc4.com"
172.16.75.4 | SUCCESS => {
"ansible_facts": {
"ansible_domain": "wzc4.com",
"ansible_fqdn": "www.wzc4.com",
"ansible_hostname": "www",
"ansible_nodename": "www.wzc4.com"
},
"changed": true,
"name": "www.wzc4.com"
}
[root@3 ~]# ansible 172.16.75.5 -m hostname -a "name=www.wzc5.com"
172.16.75.5 | SUCCESS => {
"ansible_facts": {
"ansible_domain": "wzc5.com",
"ansible_fqdn": "www.wzc5.com",
"ansible_hostname": "www",
"ansible_nodename": "www.wzc5.com"
},
"changed": true,
"name": "www.wzc5.com"
}
[root@3 ~]# ansible 172.16.75.6 -m hostname -a "name=www.wzc6.com"
172.16.75.6 | SUCCESS => {
"ansible_facts": {
"ansible_domain": "wzc6.com",
"ansible_fqdn": "www.wzc6.com",
"ansible_hostname": "www",
"ansible_nodename": "www.wzc6.com"
},
"changed": true,
"name": "www.wzc6.com"
}
设置后我可以到相应的被控设备中进行查看:
[root@6 ~]# hostname
www.wzc6.com
8.※script模块:
Runs a local script on a remote node after transferring it
示例:
[root@3 ~]# vim wang.sh
#!/bin/bash
#
RESULT=$[8*8]
echo $RESULT > /tmp/result.txt
[root@3 ~]# bash wang.sh
[root@3 ~]# ls /tmp
result.txt
ssh-KVa0apXzLIGs
systemd-private-ffdc1f169b5043de8d909b21e2879be4-chronyd.service-SVcLuO
systemd-private-ffdc1f169b5043de8d909b21e2879be4-colord.service-NcK0Ud
systemd-private-ffdc1f169b5043de8d909b21e2879be4-cups.service-nJ3xkU
systemd-private-ffdc1f169b5043de8d909b21e2879be4-httpd.service-XyJKo5
systemd-private-ffdc1f169b5043de8d909b21e2879be4-mariadb.service-NN5DhV
systemd-private-ffdc1f169b5043de8d909b21e2879be4-rtkit-daemon.service-6DybaR
tracker-extract-files.0
yum_save_tx.2018-07-26.15-38.MSxPB9.yumtx
yum_save_tx.2018-08-13.15-25.8tKTAR.yumtx
yum_save_tx.2018-08-13.16-43.xOgRwj.yumtx
[root@localhost ~]# cat /tmp/result.txt
64
在被控设备中,执行主控设备中的脚本:
[root@3 ~]# ansible test1 -m script -a "/root/wang.sh"
172.16.75.4 | CHANGED => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to 172.16.75.4 closed.\r\n",
"stderr_lines": [
"Shared connection to 172.16.75.4 closed."
],
"stdout": "",
"stdout_lines": []
}
172.16.75.5 | CHANGED => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to 172.16.75.5 closed.\r\n",
"stderr_lines": [
"Shared connection to 172.16.75.5 closed."
],
"stdout": "",
"stdout_lines": []
}
在被控设备中查看结果:
[root@4 ~]# cat /tmp/result.txt
64
9.service模块:
Manage services
常用的参数:
name: 指定要管理的服务的名称;
enabled: 设置要管理的服务是否随操作系统启动而启动;
state:
started
stopped
restarted
reloaded
示例:
在没被指定任务的主机中查看3306端口是否打开:
[root@5 ~]# ss -tnl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:111 *:*
LISTEN 0 5 192.168.122.1:53 *:*
LISTEN 0 128 *:22 *:*
LISTEN 0 128 127.0.0.1:631 *:*
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 128 :::111 :::*
LISTEN 0 128 :::22 :::*
LISTEN 0 128 ::1:631 :::*
LISTEN 0 100 ::1:25 :::*
我们可以在主控设备中打开服务:
[root@3 ~]# ansible 172.16.75.5 -m service -a "name=mariadb enabled=yes state=started"
172.16.75.5 | CHANGED => {
"changed": true,
"enabled": true,
"name": "mariadb",
"state": "started",
"status": {
……
}
在被控设备中查看服务是否开启:
[root@5 ~]# ss -tnl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 50 *:3306 //服务正常开启 *:*
LISTEN 0 128 *:111 *:*
LISTEN 0 5 192.168.122.1:53 *:*
LISTEN 0 128 *:22 *:*
LISTEN 0 128 127.0.0.1:631 *:*
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 128 :::111 :::*
LISTEN 0 128 :::22 :::*
LISTEN 0 128 ::1:631 :::*
LISTEN 0 100 ::1:25 :::*
10.yum模块:
Manages packages with the `yum' package manager
常用的参数:
name: 指定此次要管理的程序包的名称,还可以加上版本号;如果想要一次管理多个程序包,
可以使用","分隔程序包名称的列表;
state:
`present' or `installed', `latest' :都表示安装;
`absent' or `removed' :都表示卸载;
示例:
[root@3 ~]# ansible websrvs -m yum -a "name=httpd,php-fpm state=present"
11.※setup模块:
Gathers facts about remote hosts:关于远程主机的变量的相关内容
示例:
[root@3 ~]# ansible 172.16.75.5 -m setup
172.16.75.5 | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"192.168.122.1",
"192.168.68.54",
"172.16.75.5"
],
"ansible_all_ipv6_addresses": [
"fe80::f72a:4d4b:bc9f:f31f",
"fe80::2a67:77ba:109f:558f",
"fe80::8268:e185:d13d:2712",
"fe80::d493:483c:f1c9:2bd5"
],
"ansible_apparmor": {
"status": "disabled"
},
"ansible_architecture": "x86_64",
"ansible_bios_date": "07/02/2015",
"ansible_bios_version": "6.00",... //很多,这里就不写了
YAML
YAML介绍
YAML是一个可读性高的用来表达资料序列的格式。YAML参考了其他多种语言,
包括:XML、C语言、Python、Perl以及电子邮件格式RFC2822等。
Clark Evans在2001年在首次发表了这种语言,另外Ingy döt Net与Oren Ben-Kiki也是这语言的共同设计者。
YAML Ain't Markup Language,即YAML不是XML。不过,在开发的这种语言时,YAML的意思其实是:
"Yet Another Markup Language"(仍是一种标记语言)。其特性:
YAML的可读性好
YAML和脚本语言的交互性好
YAML使用实现语言的数据类型
YAML有一个一致的信息模型
YAML易于实现
YAML可以基于流来处理
YAML表达能力强,扩展性好
更多的内容及规范参见http://www.yaml.org
YAML语法
YAML的语法和其他高阶语言类似,并且可以简单表达列表、数据字典、键值对等数据结构。
其结构(Structure)通过空格来展示,列表里的项用"-"来代表,数据字典里的键值对用":"分隔。
list
列表的所有元素均使用“-”打头,例如:
# A list of tasty fruits
- Apple
- Orange
- Strawberry
- Mango
dictionary
字典通过key与value进行标识,例如:
---
# An employee record
name: Example Developer
job: Developer
skill: Elite
也可以将key:value放置于{}中进行表示,例如:
---
# An employee record
{name: Example Developer, job: Developer, skill: Elite}
下面是一个示例。
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
YAML文件扩展名通常为.yaml,如example.yaml。
playbook的核心元素:基本结构;
- hosts:
remote_user:
vars:
var1: value1
var2: value2
tasks:
- name1:
module_name:
tags:
notify:
- name2
...
...
roles:
- role_name1
- role_name2
...
handlers:
ansible-playbook命令:
ansible-playbook - Runs Ansible playbooks, executing the defined tasks on the targeted hosts.
格式:
ansible-playbook [options] playbook.yml [playbook2 ...]
常用选项:
-C, --check
测试运行剧本中任务,不做任何改变;
-e, --extra-vars
在命令行中设置额外的变量或者修改某个指定的变量的值;
-t, --tags
指明只运行那些与指定的标记匹配的任务;
测试playbook的示例(:
[root@localhost ansible]# vim test.yml
- hosts: all //指定被控主机
remote_user: root //远程连接被控主机所使用的用户
tasks:- name: create group gwzc11 //我们创建这个任务的目的(就是为这个任务取个名字)
group: name=gwzc1 gid=455 system=yes //所调用的模块,以及调用模块后所给出参数 - name: create user uwzc1
user: name=uwzc1 uid=456 system=yes create_home=no group=gwzc1
[root@3 ansible]# ansible-playbook --check test.yml
- name: create group gwzc11 //我们创建这个任务的目的(就是为这个任务取个名字)
PLAY [all] *****
TASK [Gathering Facts] *****
ok: [172.16.75.4]
ok: [172.16.75.13]
ok: [172.16.75.6]
ok: [172.16.75.5]
TASK [create group gwzc1] **
changed: [172.16.75.6]
changed: [172.16.75.5]
changed: [172.16.75.13]
changed: [172.16.75.4]
TASK [create user uwzc1] ***
changed: [172.16.75.4]
changed: [172.16.75.13]
changed: [172.16.75.5]
changed: [172.16.75.6]
PLAY RECAP *****
172.16.75.13 : ok=3 changed=2 unreachable=0 failed=0
172.16.75.4 : ok=3 changed=2 unreachable=0 failed=0
172.16.75.5 : ok=3 changed=2 unreachable=0 failed=0
172.16.75.6 : ok=3 changed=2 unreachable=0 failed=0
利用playbook安装nginx应用:
- hosts: 172.16.75.6
remote_user: root
tasks:- name: install nginx
yum: name=nginx state=present
[root@3 ansible]# ansible-playbook --check test.yml
- name: install nginx
PLAY [172.16.75.6] *****
TASK [Gathering Facts] *****
ok: [172.16.75.6]
TASK [install nginx] ***
changed: [172.16.75.6]
PLAY RECAP *****
172.16.75.6 : ok=2 changed=1 unreachable=0 failed=0
handlers:
处理器;
事实上,handlers也是定义了任务,但该任务并非每次都必然被执行,只是在特殊的条件下触发执行;
在ansible中,特殊条件一般是指handlers接收到了其他任务发送的通知信息;
变量:variables
变量的定义方式:
1.facts:利用setup模块从被管设备上取回的变量,可以直接使用;
注意:如果使用ansible命令行工具向被管设备执行任务时,默认并没有可用的facts变量;只有在运行ansible-playbook命令执行playbook时,首先会获取被管设备上的facts变量,从而可以直接调用;
如果想要调用facts变量,都需要在playbook中调用;
2.在hosts inventory中定义变量:
1) 为不同的主机定义同一变量的不同变量值;
示例:在/etc/ansible/hosts文件中定义;
[root@localhost ansible]# vim hosts
# This is the default ansible 'hosts' file.
#
# It should live in /etc/ansible/hosts
#
# - Comments begin with the '#' character
# - Blank lines are ignored
# - Groups of hosts are delimited by [header] elements
# - You can enter hostnames or ip addresses
# - A hostname/ip can be a member of multiple groups
[test1]
172.16.75.4 nname=www1.wang.com
172.16.75.5 nname=www2.wang.com
[wang]
172.16.75.4
[root@3 ansible]# ansible test1 -m hostname -a "name={{ nname }}"
172.16.75.4 | SUCCESS => {
"ansible_facts": {
"ansible_domain": "wang.com",
"ansible_fqdn": "www1.wang.com",
"ansible_hostname": "www1",
"ansible_nodename": "www1.wang.com"
},
"changed": true,
"name": "www1.wang.com"
}
172.16.75.5 | SUCCESS => {
"ansible_facts": {
"ansible_domain": "wang.com",
"ansible_fqdn": "www2.wang.com",
"ansible_hostname": "www2",
"ansible_nodename": "www2.wang.com"
},
"changed": true,
"name": "www2.wang.com"
}
2) 向某个主机组中传递变量值:
示例:
[test1:vars]
ngx_port=80
在templates中调用生效;
3.在ansible命令行或ansible-playbook命令行中通过-e选项传递变量值;
-e var1=value1 -e var2=value2 ...
4.在YAML格式的playbook文件中定义并引用(只能使用以下格式);
vars:
var1: value1
var2: value2
...
5.在roles中定义变量;
6.在playbook中调用roles时,向roles传递变量值;
7.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 的路径....
变量调用的方式:
{{ var_name }}
12.template模块:
Templates a file out to a remote server
模板文件:纯文本文件,嵌套了某种编程语言脚本代码的文本文件;
python语言将自身代码嵌套进纯文件文件的脚本语言,Jinja2;以"j2"后缀命名的文件;
在jinja2脚本文件中,表达式的最简单的表现形式,称为"字面量";
字面量:
字符串:通常是使用单引号或双引号引用的内容;
列表:可变化的数据结构;
[item1, item2, ...]
元组:不可变数据结构;
(item1, item2, ...)
字典:
{key1: value1, key2: value2, ...}
布尔型:true | false
操作符号:
算术运算符:+, -, *, /, %, //, **
比较操作符:==, !=, <, >, <=, >=
逻辑运算符:and, or, not
template模块的常用参数:
src:在ansible主控设备上的Jinja2格式的模板文件的路径;.j2
dest:将模板文件复制到远程主机后的文件路径;
owner、group、mode、setype等;
ansible的角色(roles):
角色:一个完整的应用服务的配置集合;
默认情况下,存放各个角色的目录是:/etc/ansible/roles
在上述目录中,创建一个与要管理的应用服务相关或相同的目录名称即可;
/etc/ansible/roles/httpd
/etc/ansible/roles/nginx
...
在每个应用服务项目中,都需要有一套严格标准的目录结构:
/etc/ansible/roles/nginx/{files/,templates/,tasks/,handlers/,vars/,meta/,default/}/main.yml
files/:
用于存放由copy模块或script模块所用到的静态文件;
templates/:
template模块查找和复制所需的Jinja2格式的模板文件的目录;
因此,存储于该目录中的文件都必须以".j2"为文件的后缀名称;
tasks/:
定义ansible所执行的任务所使用的yml文件的集合;至少要包含一个main.yml文件作为访问入口;
如果该目录中有其他的yml格式的文件,需要在main.yml文件中以include命令将其包含;
handlers/:
定义处理器时所使用的yml文件的集合;至少要包含一个main.yml文件作为访问入口;
如果该目录中有其他的yml格式的文件,需要在main.yml文件中以include命令将其包含;
vars/:
定义自定义变量时所使用的yml文件的集合;至少要包含一个main.yml文件作为访问入口;
如果该目录中有其他的yml格式的文件,需要在main.yml文件中以include命令将其包含;
meta/:
定义当前角色的某些特定属性和依赖关系;至少要包含一个main.yml文件作为访问入口;
如果该目录中有其他的yml格式的文件,需要在main.yml文件中以include命令将其包含;
default/:
定义默认变量时使用的目录,至少要包含一个main.yml文件作为访问入口;
如果该目录中有其他的yml格式的文件,需要在main.yml文件中以include命令将其包含;
memcached角色配置示例:
1.完善目录结构:
[root@3 ansible]# mkdir -pv /etc/ansible/roles/memcached/{files,templates,tasks,handlers,vars,meta,default}
2.在tasks目录中创建主任务playbook:main.yml
- name: install memcached
yum: name=memcached state=present
tags: instmemc - name: provide config file
template: src=memcached.j2 dest=/etc/sysconfig/memcached
tags: provcfg
notify: restart memcached -
name: start memcached service
service: name=memcached state=started
tags: servicestart3.在handlers目录中创建处理其主任务playbook:main.yml
-
name: restart memcached
service: name=memcached state=restarted4.在templates目录中提供配置文件,memcached.j2
[root@3 memcached]# cp /etc/sysconfig/memcached memcached/templates/memcached.j2
[root@3 memcached]# vim templates/memcached.j2
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="{{ ansible_memtotal_mb//4 }}" //修改成这样,定义以此主机4分之一的内存来开启memcached
OPTIONS=""
[root@3 ansible] vim memcached.yml - hosts: 172.16.75.13
remote_user: root
roles:- memcached
完成后调用roles:
[root@3 ansible] vim memcached.yml
- memcached
- hosts: 172.16.75.13
remote_user: root
roles:- memcached
[root@3 ansible]# ansible-playbook memcached.yml
- memcached
PLAY [172.16.75.13] ****
TASK [Gathering Facts] *****
ok: [172.16.75.13]
TASK [memcached : install memcached] ***
changed: [172.16.75.13]
TASK [memcached : provide config file] *****
ok: [172.16.75.13]
TASK [memcached : start memcached service] *****
changed: [172.16.75.13]
PLAY RECAP *****
172.16.75.13 : ok=4 changed=2 unreachable=0 failed=0
同理我们还可以用这个方法安装nginx:
[root@3 roles]# mkdir -pv /etc/ansible/roles/nginx/{files,templates,tasks,handlers,vars,meta,default}
[root@3 nginx]# vim tasks/main.yml
- name: install nginx package
yum: name=nginx state=present - name: provide nginx config file
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
notify: reload nginx config
tags: provconf - name: start nginx service
service: name=nginx state=started enabled=true
[root@3 nginx]# vim handlers/main.yml - name: reload nginx config
service: name=nginx state=reloaded
[root@3 nginx]# cp /etc/nginx/nginx.conf templates/nginx.conf.j2
[root@3 ansible]# vim nginx.yml - hosts: 172.16.75.6
remote_user: root
roles:- nginx
[root@3 ansible]# ansible-playbook --check nginx.yml
- nginx
PLAY [172.16.75.6] *****
TASK [Gathering Facts] *****
ok: [172.16.75.6]
TASK [nginx : install nginx package] ***
changed: [172.16.75.6]
TASK [nginx : provide nginx config file] ***
changed: [172.16.75.6]
TASK [nginx : start nginx service] *****
changed: [172.16.75.6]
RUNNING HANDLER [nginx : reload nginx config] **
changed: [172.16.75.6]
PLAY RECAP *****
172.16.75.6 : ok=5 changed=4 unreachable=0 failed=0
测试成功;
在playbook中调用roles的方法1:
- hosts: hosts_group_name
remote_user: root
roles:- role_name1
- role_name2
...
在playbook中调用roles的方法2:在调用roles的时候向roles传递变量:
-
hosts: hosts_group_name
remote_user: root
roles:- { role: role_name1, var1: value1, var2: value2, ...}
- { role: role_name2, var1: value1, var2: value2, ...}
...
role键用于指定角色名称,必须给出的内容;后续的键值对用于向前面的角色传递变量;
在playbook中调用roles的方法3:在调用角色的时候可以根据某个条件来执行:
- hosts: hosts_group_name
remote_user: root
roles:- { role: role_name1, when: condition}