运维工具的分类:
	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 root@172.16.75.4
[root@3 ~]# ssh-copy-id -i .ssh/id_rsa.pub root@172.16.75.5
[root@3 ~]# ssh-copy-id -i .ssh/id_rsa.pub root@172.16.75.6
[root@3 ~]# ssh-copy-id -i .ssh/id_rsa.pub root@172.16.75.13
[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 <host-pattern> [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 type> ] [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

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

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: servicestart

    3.在handlers目录中创建处理其主任务playbook:main.yml

  • name: restart memcached service: name=memcached state=restarted

    4.在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
  • hosts: 172.16.75.13 remote_user: root roles:

    • memcached [root@3 ansible]# ansible-playbook memcached.yml

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

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}