自动运维工具 Ansible 实践与总结
ansible是一款自动化运维工具,基于Python开发,可以实现批量系统设置、批量程序部署、批量执行命令等功能。特点如下:
Ansible完全基于Python开发,要求python的版本为2.6以上。
Ansible丰富的内置模块,近600个模块完全满足日常功能所需
Ansible默认通过SSH协议管理机器,因此,客户端无需任何配置,管理端配置好后即可使用。
Ansible目前属于Redhat公司,最新版本为Ansible2.9。
应用环境:
应用代码自动化部署
系统管理配置自动化
支持持续交付自动化
支持云计算,大数据平台环境
批量任务执行可以写成脚本,不用分发到远程就可以执行
支持非root用户管理操作,支持sudo
使用python编写,维护更简单。
1.ansible的命令套件
安装完ansible后,ansible一共提供了七个指令,分别是:ansible、ansible-doc、ansible-galaxy、ansible-lint、ansible-playbook、ansible-pull、ansible-vault 。
(1)ansible
ansible是指令核心部分,其主要用于执行ad-hoc命令,即单条命令。默认后面需要跟主机和选项部分,默认不指定模块时,使用的是command模块。
(2)ansible-doc
该指令用于查看模块信息,常用参数有两个-l 和 -s ,具体如下:
例如,列出所有已安装的模块
# ansible-doc -l
查看具体某模块的用法,这里如查看command模块
# ansible-doc -s command
(3)ansible-galaxy
ansible-galaxy 指令用于方便的从https://galaxy.ansible.com/ 站点下载第三方扩展模块,可以形象的理解其类似于centos下的yum、python下的pip或easy_install 。
(4)ansible-lint
ansible-lint是对playbook的语法进行检查的一个工具。用法是ansible-lint playbook.yml 。
(5)ansible-playbook
该指令是使用最多的指令,其通过读取playbook 文件后,执行相应的动作,这个后面会做为一个重点来讲。
(6)ansible-pull
该指令使用需要谈到ansible的另一种模式:pull 模式,这和平常经常用的push模式刚好相反,其适用于以下场景:
有数量巨大的机器需要配置,即使使用非常高的线程还是要花费很多时间
要在一个没有网络连接的机器上运行Anisble,比如在启动之后安装。
(7)ansible-vault
ansible-vault主要应用于配置文件中含有敏感信息,又不希望被人看到,vault可以帮你加密/解密这个配置文件,属高级用法。主要对于playbooks里比如涉及到配置密码或其他变量时,可以通过该指令加密,这样我们通过cat看到的是一个密码串类的文件,编辑的时候需要输入事先设定的密码才能打开。这种playbook文件在执行时,需要加上 –ask-vault-pass参数,同样需要输入密码后才能正常执行。
注:上面七个指令,用的最多的只有两个ansible 和ansible-playbook ,这两个一定要掌握,其它五个属于拓展或高级部分。
2.ansible的执行模式
ansible执行自动化任务,分为两种执行模式:
(1)、命令行模式:单个模块,单条命令的批量执行。常用语测试环境。
(2)、playbook:这个可以理解成为面向对象的编程,就像上面举例那样可以把多个想要执行的任务放到一个playbook中,当然多个任务在事物逻辑上最好是有上下联系的。通过多个任务可以完成一个总体的目标,这就是playbook。常用于线上生产环境。
1、简单的主机和组
ansible的配置文件位于/etc/ansible目录下,主要有ansible.cfg、hosts文件。本节重点介绍主机与组定义文件/etc/ansible/hosts.
/etc/ansible/hosts最简单的格式如下:
[webservers]
[dbservers]
中括号中的名字代表组名,可以根据需求将庞大的主机分成具有标识的组,如上面分了两个组webservers和dbservers组;
主机(hosts)部分可以使用域名、主机名、IP地址表示;当然使用前两者时,也需要主机能反解析到相应的IP地址,一般此类配置中多使用IP地址;
2、指定主机范围
可在/etc/ansible/hosts文件中,指定主机的范围,示例如下:
[web]
www[01:50].ixdba.net
[db]
db[a:f].ixdba.en
3、主机变量
[web]
192.168.78.11 http_port=80
192.168.78.12 http_port=80
还可以改成这样:
[web]
192.168.78.11
192.168.78.12
[web:vars]
http_port=80
4、主机组变量
[webhost]
host1
host2
[dbhost]
host2
host3
[allhosts:children]
webhost
Dbhost
主机组可以包含主机组,主机的变量可以通过继承关系,继承到最高等级的组的变量。定义主机组之间的继承关系我们使用”:children”来表示
3.ansible的命令模式
命令行模式ansible常用选项
命令行模式是指ansible临时执行的一条或多条命令,并且不需要保存命令,对于复杂的命令后面会讲用playbook。在使用ansible时,就要提到模块,所有的命令执行都要依赖于事先写好的模块,默认安装好的ansible里面已经自带了很多模块,如:command、raw、shell、file、cron等,具体可以通过ansible-doc -l 进行查看 。
ansible命令的常用选项:
-m MODULE_NAME:指定要执行的模块的名称,如果不指定-m选项,默认是COMMAND模块。
-a MODULE_ARGS,:指定执行模块对应的参数选项。
-k:提示输入SSH登录的密码而不是基于密钥的验证
-K:用于输入执行su或sudo操作时需要的认证密码。
-b:表示提升权限操作。
--become-method:指定提升权限的方法,常用的有 sudo和su,默认是sudo。
--become-user:指定执行 sudo或su命令时要切换到哪个用户下,默认是root用户。
-B SECONDS:后台运行超时时间
-C:测试一下会改变什么内容,不会真正去执行,主要用来测试一些可能发生的变化
-f FORKS,:设置ansible并行的任务数。默认值是5
-i INVENTORY: 指定主机清单文件的路径,默认为/etc/ansible/hosts
命令行模式的ansible执行,需要按以下格式进行操作:
ansible 主机或组 -m 模块名 -a '模块参数' ansible参数
主机和组:是在/etc/ansible/hosts 里进行指定的部分,当然动态Inventory使用的是脚本从外部应用里获取的主机。
模块名:可以通过ansible-doc -l 查看目前安装的模块,默认不指定时,使用的是command模块,具体可以查看/etc/ansible/ansible.cfg 的“#module_name = command ” 部分,默认模块可以在该配置文件中进行修改;
模块参数:可以通过 “ansible-doc 模块名” 查看具体的用法及后面的参数;
ansible参数:可以通过ansible命令的帮忙信息里查看到,这里有很多参数可以供选择,如是否需要输入密码、是否sudo等。
4.Playbook
playbook字面意思,即剧本,现实中由演员按照剧本表演,在Ansible中,这次由计算机进行表演,由计算机安装,部署应用,提供对外服务,以及组织计算机处理各种各样的事情。
那么为什么要使用playbook呢?
执行一些简单的任务,使用命令行模式可以方便的解决问题,但是有时一个设施过于复杂,需要大量的操作时候,执行命令行模式是不适合的,这时最好使用playbook,就像执行shell命令与写shell脚本一样,也可以理解为批处理任务,不过playbook有自己的语法格式。
playbook的构成
playbook是由一个或多个“play”组成的列表。play的主要功能在于,将事先合并为一组的主机装扮成事先通过ansible定义好的角色。将多个play组织在一个playbook中就可以让它们联同起来按事先编排的机制完成一系列复杂的任务。
其主要有以下四部分构成
target部分: 定义将要执行 playbook 的远程主机组
variable部分: 定义playbook运行时需要使用的变量
task部分: 定义将要在远程主机上执行的任务列表
handler部分: 定义task 执行完成以后需要调用的任务
(1) Hosts和Users
playbook中的每一个play的目的都是为了让某个或某些主机以某个指定的用户身份执行任务。
hosts:用于指定要执行指定任务的主机,每个playbook都必须指定hosts,hosts也可以使用通配符格式。主机或主机组在inventory清单中指定,可以使用系统默认的/etc/ansible/hosts,也可以自己编辑,在运行的时候加上-i选项,可指定自定义主机清单的位置。在运行清单文件的时候,--list-hosts选项会显示那些主机将会参与执行任务的过程中。
remote_user:用于指定在远程主机上执行任务的用户。可以指定任意用户,也可以使用sudo,但是用户必须要有执行相应任务的权限。
(2)任务列表(tasks list)
play的主体部分是task list。
task list中的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后再开始第二个。在运行自上而下某playbook时,如果中途发生错误,则所有已执行任务都将回滚,因此在更正playbook后需要重新执行一次。
task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的(幂等性; 即一个命令,即使执行一次或多次, 其结果也一样),这意味着多次执行是安全的,因为其结果均一致。tasks包含name和要执行的模块,name是可选的,只是为了便于用户阅读,建议加上去,模块是必须的,同时也要给予模块相应的参数。
定义tasks推荐使用module: options”的格式,例如:
service: name=httpd state=running
(3) handlers
用于当关注的资源发生变化时采取一定的操作。handlers是和“notify”配合使用的。
“notify”这个动作可用于在每个play的最后被触发,这样可以避免多次有改变发生时,每次都执行指定的操作,通过“notify”,仅在所有的变化发生完成后一次性地执行指定操作。
在notify中列出的操作称为handler,也就是说notify用来调用handler中定义的操作。
注意:在 notify中定义的内容一定要和handlers中定义的“ - name”内容一样,这样才能达到触发的效果,否则会不生效。
(4) tags
tags用于让用户选择运行或略过playbook中的部分代码。ansible具有幂等性,因此会自动跳过没有变化的部分;但是当一个playbook任务比较多时,一个一个的判断每个部分是否发生了变化,也需要很长时间。因此,如果确定某些部分没有发生变化,就可以通过tags跳过这些代码片断
5.Ansible-playbook 应用举例
1、shell 模块
在远程节点上执行命令,用法和command模块一样,不过shell模块执行命令的时候使用的是/bin/sh,所以shell模块可以执行任何命令。
- hosts: 172.16.213.231
remote_user: root
tasks:
- name: ansible shell
shell: ps -ef|grep sshd&&mkdir /opt/hdp
- name: ansible command
command: touch /opt/hdp/hadoop.txt
上面这个命令是执行远程机器上的脚本,脚本路径为/tmp/install.sh(远程主机上的脚本,非本机的),然后将执行命令的结果存放在远程主机路径/tmp/install.log中,注意在进行保存文件的时候,写上全路径,否则就会保存在登录之后的默认路径中
2、raw模块
raw模块功能类似与前面说的command、shell能够完成的操作,raw也都能完成。不同的是,raw模块不需要远程主机上的python环境。
ansible要执行自动化操作,需要管理机上装ansible,客户机上也需要安装python,如果客户机上没有安装python模块,那么command、shell模块将无法工作,而raw却可以正常工作,因此,如果有的机器是没有装python,或者说安装的python版本在python2.4以下,就可以使用raw模块来装python、python-simplejson等。
- hosts: 172.16.213.231
remote_user: root
tasks:
- name: ansible raw1
raw: ps -ef|grep sshd|awk '{print $2}'>/tmp/ssh.log
- name: ansible raw2
raw: dnf -y install python36-devel
3. file模块
- hosts: 10.0.8.10
remote_user: root
tasks:
- name: mkdir cdh directory
file: path=/opt/cdh state=directory mode=0755
- name: chmod bin
file: dest=/opt/bigdata/jdk/bin mode=0755 recurse=yes
- name: link files
file: src=/etc/ssh/sshd_config dest=/mnt/sshd_config owner=timli state=link
- name: delete files
file: path=/tmp/openssl-1.0.1t.tar.gz state=absent
- name: chown files
file: path=/mnt/syncfile.txt owner=nobody mode=0644
4.copy 模块
- hosts: 10.0.8.10
remote_user: root
gather_facts: false
tasks:
- name: copy and chown
copy: src=/etc/sudoers dest=/mnt/sudoers owner=root group=root mode=440 backup=yes
- name: checking files
copy: src=/etc/sudoers dest=/mnt/sudoers validate='visudo -cf %s'
- name: copy directory
copy: src=/etc/crontab/ dest=/mnt/bak owner=hadoop group=hadoop directory_mode=644
5.Synchronize
比拷贝模块快很多
- hosts: 10.0.8.10
remote_user: root
gather_facts: false
tasks:
- name: synchronize rsync directory
synchronize: src=/usr/share/nginx/modules dest=/mnt/bak1 delete=yes
6.Service 模块
root@VM-8-6-ubuntu:/etc/ansible# cat service.yml
- hosts: 10.0.8.10
remote_user: root
gather_facts: false
tasks:
- name:
service: name=nginx state=restarted enabled=yes
7 Cron 模块
- hosts: 10.0.8.10
remote_user: root
gather_facts: false
tasks:
- name: cron examples
cron: backup=true name=autobackup weekday=6 minute=30 hour=1 user=root
- name: create user
hosts: 10.0.8.10
user: root
gather_facts: false
tasks:
- name: start createuser
user: name="{{item.us}}" groups=hadoop,wheel
with_items:
- {us: hadoopuser003}
- {us: hadoopuser004}
- {us: hadoopuser005}
- {us: hadoopuser006}