3.1 Ad-Hoc使用场景
所谓Ad-Hoc,简而言之是"临时命令",英文中作为形容词有"特别的,临时"的含义。Ad-Hoc只是官方对Ansible命令的一种称谓。
从功能上讲,Ad-Hoc是相对于Ansible-playbook而言的,Ansible提供两种完成任务方式:一种是Ad-Hoc命令集,即ansible,另一种就是Ansible-playbook了,即命令Ansible-playbook。前者更注重于解决一些简单的或者平时工作中临时遇到的任务,相当于Linux系统命令行下的Shell命令,后者更适合与解决复杂或需固化下来的任务,相当于Linux系统的Shell Scripts。
- 需要使用Ad-Hoc的场景
情景1:
节假日将至,我们需要关闭所有不必要的服务器,并对所有服务器进行节前健康检查。
情景2:
临时更新Apache&Nginx的配置文件,且需同时将其分发至所有需更新该配置的Web服务器
2. 需要使用ansible-playbook的场景
情景1:
新购置的服务器安装完系统后需做一系列固化的初始化工作,诸如:定制防火墙策略、添加NTP时间同步配置、添加EPEL源等。
情景2:
业务侧每周定期对生产环境发布更新程序代码。
3.2 Ad-Hoc命令集介绍
3.2.1 Ad-Hoc命令集用法简介
Ad-Hoc命令集由/usr/bin/ansible实现,其命令用法如下:
ansible <host-pattern> [options]
可用选项如下。
- -v,--verbose:输出更详细的执行过程信息,-vvv可得到执行过程所有信息。
- -i PATH,--inventory=PATH:指定inventory信息,默认/etc/absible/hosts。
- -f NUM,--forks=NUM:并发线程数,默认5个线程。
- --private-key=PRIVATE_KEY_FILE:指定密钥文件。
- -m NAME,--module-name=NAME:指定执行使用的模块。
- -M DIRECTORY,--module-path=DIRECTORY:指定模块存放路径,默认/usr/share/ansible,也可以通过ANSIBLE_LIBRARY设定默认路径。
- -a 'ARGUMENTS',--args='ARGUMENTS':模块参数。
- -k,--ask-pass SSH:认证密码。
- -K,--ask-sudo-pass sudo:用户的密码(--sudo时使用)。
- -o,--one-line:标准输出至一行。
- -s,--sudo:相当于Linux系统下的sudo命令。
- -t DIRECTORY,--tree=DIRECTORY:输出信息至DIRECTORY目录下,结果文件以远程主机名命名。
- -T SECONDS,--timeout=SECONDS:指定连接远程主机的最大超时,单位是秒。
- -B NUM,--background=NUM:后台执行命令,超NUM秒后中止正在执行的任务。
- -P NUM,--poll=NUM:定期返回后台任务进度。
- -u USERNAME,--user=USERNAME:指定远程主机以USERNAME运行命令。
- -U SUDO_USERNAME,--sudo-user=SUDO_USERNAME:使用sudo,相当于Linux下的sudo命令。
- -c CONNECTION,--connection=CONNECTION:指定连接方式,可用选项paramiko(SSH)、ssh、local,local方式常用于crontab和kickstarts。
- -l SUBSET,--limit=SUBSET:指定运行主机。
- -l ~REGEX,--limit=~REGEX:指定运行主机(正则)。
- --list-hosts:列出符合条件的主机列表,不执行任何命令。
ansiblemaster:192.168.230.100
ansibleslave1 :192.168.230.240
ansibleslave2 : 192.168.230.247
首先配置三台主机的hosts的文件:
配置ansible的host分组
情景1:检查proxy组所有主机是否存活。
执行命令:
ansible proxy -f 5 -m ping
其中ansibleslave1,ansibleslave2是指命令执行的主机,SUCCESS表示命令执行成功,">>{}"表示详细返回结果如下。""change":false""表示没有对主机做变更,""ping":"pong""表示执行了ping命令返回结果为pong。
情景2:返回proxy组所有主机的hostname,并打印最详细的执行过程到标准输出。
执行命令:
ansible proxy -s -m command -a 'hostname' -vvv
执行结果诠释:
情景3:列出proxy组所有主机列表。
情景4:对10.21.40.61服务器以root执行sleep 20,设置最大连接超时时长为2s,且设置为后台运行模式,执行过程每2s输出依次进度,如5s还未执行完则终止该任务。
//time命令可省,为方便观察结果,这里使用time命令查看执行时长
time ansible 10.21.40.61 -B 5 -P 2 -T 2 -m command -a 'sleep 20' -u root
执行结果诠释:
3.2.2 通过Ad-Hoc查看系统设置
情景1:批量查看proxy组所有主机的磁盘容量(使用command模块)。
执行命令:
执行结果诠释:
以ansibleslave2的返回为例,SUCCESS表示命令执行成功,rc=0表示ResultCode=0,即命令返回结果,返回码为0,表示命令执行成功,>>后面跟的内容相当于在本地执行df -lh后的结果返回。
情景2:批量查看远程主机内存使用情况(shell模块)
3.2.3 通过Ad-Hoc研究Ansible的并发特性
返回结果分析如下:
1)同样的命令多次执行,但每次的输出结果都不一定一样。
2)输出结果不是按照/etc/ansible/hosts中[proxy]定义的主机顺序输出。
3)结果输出基本上遵循每次输出3条记录(线程池始终保持3个线程,所以每次输出小于等于3都是正常的)。
Ansible使用multiprocessing管理多线程。
3.2.4 通过Ad-Hoc研究Ansible的模块使用
模块链接:http://docs.ansible.com/ansible/modules_by_category.html
ansible-doc [options] [module...]
可用选项如下。
- --version:显示工具版本号
- -h,--help:显示该help说明
- -M MODULE_PATH,--module-path=MODULE_PATH:指定Ansible模块的默认加载目录。
- -l,--list:列出所有可用的模块。
- -s,--snippet:只显示playbook说明的代码段。
- -v:显示工具版本号。
情景1:显示所有可用模块。
情景2:以yum模块为例,我们希望获取yum模块的HELP说明。
【示例1】安装redhat-lsb并查看服务器系统版本号。
步骤1:安装redhat-lsb。
其中:
- "changed":主机是否有变更,true为有;false为没有(第1次运行或事先没有安装,返回值一般是true,否则为false)。
- "msg":安装过程信息。
- "rc":0,resultcode:结果状态码,非0返回码往往是红色并且错误的返回,非常明显。
步骤2:查看系统版本号。
部分执行结果诠释:
- ansibleslave1:表示命令执行的对象。
- success:表示命令执行的返回状态为成功状态
- rc=0:表示命令执行的状态码为0。
- >>:该符号后返回的所有内容为执行lsb_release -a命令返回的信息。
- LSB Version:表示该系统的内核版本信息。
- Distributor ID:表示发行厂商。
- Description:表示版本简要信息。
- Release:表示该系统的发行版本号。
- Codename:表示发行版代号。
【示例2】为所有服务器安装ntp服务,并设置为开机启动。
步骤1:安装ntp服务。
步骤2:启动ntp服务,并设置为开机启动。
3.3 Ad-Hoc组管理和特定主机变更
3.3.1 Ad-Hoc组定义
Ad-Hoc的组功能定义在Inventory文件中,默认路径是/etc/ansible/hosts,书写格式遵循INI风格,中括号中的字符为组名。可以将同一个主机同时归并到多个不同的组中;此外,若目标主机使用了非默认的SSH端口,还可以在主机名称之后使用冒号加端口来表明。
如下为inventory文件实例,包括了组定义即冒号加端口号功能的使用。
ntp.magedu.com
[webservers]
www1.magedu.com:2222
www2.magedu.com
[dbservers]
db1.magedu.com
db2.magedu.com
db3.magedu.com
如果远程主机名称遵循相似的命名模式,还可以使用列表的方式标识各主机,如下案例为大家展示改写法。
[webservers]
www[01:50].magedu.com
[databases]
db-[a:f].magedu.com
本次架构规划了前端Proxy,Web Servers和后面DB一套完整应用,图中共定义了Proxy、App、NoSQL和DB这4个组。
应用分布如下。
- [proxy]组:Nginx;
- [app]组:Nginx+PHP+Django;
- [nosql]组:Redis;
- [db]组:Mariadb。
3.3.2 Ad-Hoc配置管理:配置Proxy与Web Servers实践
(1)Ad-Hoc配置管理Proxy(即Nginx)
wget http://mirror.switch.ch/ftp/pool/4/mirror/scientificlinux/6.5/x86_64/updates/fastbugs/python-devel-2.6.6-52.el6.x86_64.rpm
wget http://mirror.switch.ch/ftp/pool/4/mirror/scientificlinux/6.5/x86_64/updates/fastbugs/python-libs-2.6.6-52.el6.x86_64.rpm
wget http://mirror.switch.ch/ftp/pool/4/mirror/scientificlinux/6.5/x86_64/updates/fastbugs/python-2.6.6-52.el6.x86_64.rpm
卸载原来的,python包
rpm -ivh python-devel-2.6.6-52.el6.x86_64.rpm python-libs-2.6.6-52.el6.x86_64.rpm python-2.6.6-52.el6.x86_64.rpm
解决:
部分结果诠释:
"changed":true, //表示本次命令对执行的目标有变更,如再执行一次则为false,表示执行的目标没有变更,这里的false和true不代表该命令执行成功或失败,只是表示执行目标是否被变更
"rc":0, //resultcode的简写,表示命令的执行结果状态返回,非0均为异常,命令执行失败
"results": //执行结果信息返回
Ansible的YUM模块同样支持指定某版本安装,其name参数指定具体版本地址(网络或本地均可)。YUM模块也支持从网络或本地安装。
如果从网络安装,执行命令:
ansilbe proxy -m yum -a "name=http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm state=present"
如果从本地安装,执行命令:
ansible proxy -m yum -a "name=/usr/local/src/nginx-release-centos-6-0.el6.ngx.noarch.rpm state=present"
(2)Ad-Hoc配置管理Web Servers
Web Servers需同时部署Nginx、PHP和Django,其中Nginx、PHP依然通过YUM模块实现,Django推荐使用PIP或easy_install方式。
1)Nginx、PHP安装命令如下:
ansible app -m yum -a "name=php state=present"
2)Django安装命令如下:
步骤1:安装MySQL-python和python-setuptools依赖包。
ansible app -m yum -a "name=MySQL-python state=present"
ansible app -m yum -a "name=python-setuptools state=present"
步骤2:安装Django
升级python2.6.6到python2.7.13(点击打开链接)
ansible app -m pip -a "name=django==1.9 state=present"
步骤3:检查Django安装是否正常,执行命令如下:
3.3.3 Ad-Hoc配置后端:配置NoSQL与Database Servers实践
安装Redis:
安装MariaDB:
步骤1:添加yum源,vim编辑/etc/yum.repos.d/mariadb.repo添加内容如下。
[mariadb]
name=MariaDB
baseurl=http://yum.mariadb.org/10.1/centos6-x86
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1
步骤2:安装MariaDB-server
执行如下命令:
yum remove mysql-libs
步骤2:安装MariaDB-server,
步骤3:安装MariaDB-client,
步骤4:开启防火墙3306访问权限。
3.3.4 Ad-Hoc特定主机变更
Ansible有多种方式实现针对特定主机做变更。
1)--limit:通过--limit参数限定主机做变更。
情景:在App组中启动192.168.37.15的NTP服务。
ansible app -m command -a "service ntpd status" --limit "192.168.230.237"
2)指定IP:通过指定具体IP限定主机做变更。
情景:查看192.168.230.237的NTP服务
ansible 192.168.230.237 -m command -a "service ntpd status"
3)用":"做分隔符,指定多台机器做变更。
启动192.168.230.237和192.168.230.238的ntp服务
ansible "192.168.230.237:192.168.230.238" -m command -a "service ntpd status"
4)通过"*"泛匹配,更灵活的针对多台主机做变更。
ansible 192.168.230.* -m command -a "service ntpd status"
3.4 Ad-Hoc用户与组管理
Ansible系统用户模块有如下两个:
- Linux系统用户管理:user。
- Windows系统用户管理:win_user。
3.4.1 Linux用户管理
场景1:新增用户。
需求描述:新增用户dba,使用BASH Shell,附加组为admins,dbagroup,家目录为/home/dba/。
该场景中我们可以掌握如下技能点。
1)groups设定:groups=用户组1,用户组2.....
2)增量添加属组:append=yes
3)表明属组状态为新建:state=present
场景2:修改用户属组。
需求描述:修改DBA附加组为dbagroups(即删除admins组权限)。
该场景中我们可以掌握如下技能点。
全量变更属组信息:append=no
场景3:修改用户属性。
需求描述:设置dba用户的过期时间为2016/6/1 18:00:00(UNIXTIME:1464775200)。
该场景中我们可以掌握如下技能点。
1)设置用户登录过期时间:expire=1464775200
2)UNIX时间转换:2016/6/1 18:00:00需转换为UNIXTIME格式
ansible db -m user -a "name=dba expires=1464775200"
场景4:删除用户。
需求描述:删除用户DBA,并删除其家目录和邮件列表。
该场景中我们可以掌握如下技能点:
1)表明属组状态为删除:state=absent
2)设定remove=yes:remove=yes
删除成功
场景5:变更用户密码
需求描述:设置系统用户tom的密码为redhat123.
方式一:使用命令mkpasswd生成密码。
查找安装包名称:yum whatprovides */mkpasswd,
yum install expect
Debian Ubuntu执行命令:sudo apt-get install whois
方式2:使用Python的passlib、getpass库生成密码。
pip install passlib
python 3.x系列版本使用如下命令(sha512加密算法)
python -c "from passlib.hash import sha512_crypt; import getpass; print(sha512_crypt.encrypt(getpass.getpass()))"
普通加密算法。
python -c 'import crypt; print(crypt.crypt("redhat123","dba"))'
Python2.x(sha512加密算法)
python -c "from passlib.hash import sha512_crypt; import getpass; print sha512_crypt.encrypt(getpass.getpass())"
普通加密算法
python -c 'import crypt; print(crypt.crypt("redhat123","dba"))'
3.4.2 Windows用户管理
场景:新增用户stanley,密码为magedu@123,属组为Administrators。
ansible windows -m win_user -a "name=stanley passwd=magedu@123 group=Administrators"
- account_disabled-----禁用用户登录;
- account_locked-------解锁用户
- groups---------用户所属组
- name---------用户名
- password_expired----------下次登录修改密码。
- user_cannot_change_password---------用户是否可修改密码
3.4.3 应用层用户管理
情景:新增MySQL用户stanley,设置登录密码为magedu@bj,对zabbix.*表有ALL权限。
ansible db -m mysql_user -a 'login_host=localhost login_password=magedu login_user=root name=stanley password=magedu@bj priv=zabbix.*:ALL state=present'
在db服务器上测试登录
mysql -ustanley -pmagedu@bj
执行命令:
show grants for 'stanley'@'localhost';验证权限是否正确。
其实如上命令存在很大的安全隐患,因为MySQL的登录信息完全暴露在命令台。Ansible建议的使用方式如下。
1)在远程主机的~/.my.cnf文件中配置root的登录信息,配置信息如下:
[client]
user=root
password=magedu
2)命令行执行命令如下:
ansible db -m mysql_user -a 'name=stanley password=magedu@bj priv=zabbix.*:ALL state=present'
此方式密码将不再暴露在控制台,在一定程度上提高了服务安全性。