0%

自动化运维工具之ansible

ansible简介:

ansible is Simple IT Automation。

ansible是一个简单的自动化运维工具,能够轻松实现配置、命令管理等常见运维工作。另外,它是一种Python语言开发的agentless工具,通过ssh服务连接被管理端,不需要在被管理端额外安装监管程序。这也意味着ansible主机的安全至关重要。

ansible特征:

模块化设计:调用特定模块来完成特定任务,有Paramiko, PyYAML和Jinja2三个关键模块

部署简单:agentless

playbook:可根据YAML文件进行多个特定任务的执行

ansible对管理主机与托管主机的要求:请参阅http://www.ansible.com.cn/docs/intro_installation.html#control-machine-requirements

安装与使用:

安装:

1
yum -y install ansible  #注意要使用epel源

配置文件:

/etc/ansible/ansible.cfg
/etc/ansible/hosts #主机列表文件,可使用ansible.cfg的inventory条目来指定
/etc/ansible/roles/ #角色目录

主程序:

ansible

ansible-doc

ansible-playbook

ansible-doc命令:

ansible-doc -l #获取ansible模块列表

ansible-doc -s MODULE #获取指定模块的使用帮助

需要注意在ansible-doc -s MODULE 获取特定模块使用帮助时,模块选项带”=”表示-a “args”运行时必须给定此参数

ansible命令:

ansible [-f forks] [-m module_name] [-a args]

#指定运行命令的被管控端列表,在inventory文件(默认为/etc/ansible/hosts)中定义的组或”all”

-i PATH, –inventory=PATH #指定inventory文件位置。不指定则使用默认文件/etc/ansible/hosts

-f NUM, –forks=NUM #指定NUM个主机为一个批次,一同运行命令(数量较多的主机分批运行,以防止同时运行占用过多网络资源)

–private-key=PRIVATE_KEY_FILE #登录时使用的私钥文件位置

-m NAME, –module-name=NAME ##模块名称

-M DIRECTORY, –module-path=DIRECTORY #模块搜索目录,默认在/usr/share/ansible/

-a ‘ARGUMENTS’, –args=’ARGUMENTS’ ##模块参数,不同模块参数可能不同

-s, –sudo #以-u指定的用户身份sudo到root身份运行

-u USERNAME, –user=USERNAME #使用指定远程用户身份来运行命令,而不是当前用户

–list-hosts #显示匹配的用户列表

ansible常用模块用法:

需要注意在ansible-doc -s MODULE 获取特定模块使用帮助时,模块选项带”=”表示-a “args”运行时必须给定此参数

ping

无其他参数。能够ping通被管控端则返回“pong”

command

直接在被管控端运行命令并打印命令结果。

shell

运行具有shell特性的命令时使用,如管道、输入输出重定向

copy

将本地文件复制给被管控主机,若被管控主机内存在此文件会直接覆盖。

dest= #复制到远程主机的绝对路径。”=”表示必须给定参数

src #本地文件路径

owner/group #将复制的文件修改属组属主

content #制定文件内容

cron

设置计划任务

name= #指明计划任务名称

day、hour、minute、month、weekday #计划任务运行周期

reboot #计划任务在重启时运行

job #执行的命令

state #有两个参数:present,创建计划任务;absent,删除计划任务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@Ansible-Server ~]# ansible centos7 -m cron -a 'minute=*/5 name=synctime job="ntpdate 172.16.0.1 > /dev/null" state=present'
172.18.31.101 | success >> {
"changed": true,
"jobs": [
"synctime"
]
}

172.18.31.102 | success >> {
"changed": true,
"jobs": [
"synctime"
]
}
file

设置文件属性信息,包括创建链接文件、修改属主属组信息、权限、SELinux信息

path= #被管控主机文件或路径名

src #原文件名称,仅在state=link时使用,用以创建链接文件

state #有多个参数:directory,创建目录;hard,硬链接;link,软链接;absent,删除;touch,与平时使用的touch命令一致

hostname

name= #主机名

yum

管理yum软件包平台的被管控端软件包信息

name= #软件包名

state #安装:present,latest;卸载:absent

service

name= #服务名

state started/stoped/restarted|reloaded #启动|停止|…服务

uri

向指定站点请求web服务

url= #可使用http|https指定url

user

管理用户账号信息

name= #用户名

state #present,创建新用户;absent,删除用户

system #yes/no指明系统账户

uid

shell #指明shell

comment #指明注释信息

home #家目录

password #密码

remove #当state=absent时,同时删除家目录

group
setup

收集被管控主机信息,这些键值对信息的key都是内置变量,可直接引用。

script

复制文件到远程主机名运行(默认复制到远程主机的/tmp目录下)

template

仅使用在ansible-playbook模板文件内!基于模板文件生成一个文件复制到远程主机

src= #本机template文件位置

dest= #目标节点文件位置

ansible-playbook用法介绍:

ansible-playbook根据由yaml标记语言编写的yml文件来运行,以完成配置多节点多任务 。

YAML语言将所有元素安装父子关系以缩进表示,元素属性以键值对表示。

1
2
3
4
5
6
7
- hosts: all
remote_user: root
tasks:
- name: create a user user1
user: name=user1 system=true uid=301
- name: create a user user2
user: name=user2 system=true uid=302</pre>

YAML标记语言语法格式很简单,只有三点:

缩进:使用两个空格表示父子关系,不要使用Tab

冒号:键值对以”:”分开,后面跟一个空格,然后跟value

短横杠:使用”-“加一个空格,使用同样的缩进来表示同一个key有多个值

playbook核心元素:

Hosts #被管控主机列表

Tastk #任务

Variables #变量,内置变量/自定义变量

Templates #模板,包含了模板语法的文本文件

Handlers #特定条件触发的任务

Roles #角色,运行的一类目标主机

playbook基础组件:

模块:modules

通知:notify

标签:tags

变量:variables

模板:template

条件测试:when

循环:根据item进行迭代

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- host: host-pattern   #指定运行命令的主机节点,多个以":"分隔
remote_user: user #远程主机上执行命令的用户
sudo_user: user #可选项,当需要使用用户sudo到另一个用户时使用
tasks: #任务列表。会在所有主机上依次运行任务列表,而不是在一个节点一次性运行完所有任务
- name: NAME #指定任务名称,会在运行时显示
MODULE: ARGS #指定使用的模块和模块选项
notify: HANDLERS #当该任务运行后为chage时,通知相应的handlers。
tags: TAGS #在运行时可指定只运行此tasks,以TAGS标识,多个tasks可使用同一个TAGS
tasks:
- name: install conf file to centos7
template: src=/FILE dest=/FILE #使用template模块
when: 条件判断语句 #使用条件判断
handlers: #handlers列表,可理解为特殊的tasks。在特定条件下触发,当收到其他任务通知时触发
- name: NAME
MODULE: ARGS #指定使用的模块和模块选项

YAML文件variables(变量)定义:

(1) facts:内置变量(如ansible all -m setup输出的结果内的变量),可直接调用;

(2) ansible-playbook命令的命令行中的自定义变量:

-e VARS, –extra-vars=VARS

(3) playbook文件中定义:

1
2
3
vars:
- username: tomcat
- groupname: tomcat

(4) 通过roles传递变量;

a. 对应role目录下的var/main.yml文件中定义;注意该文件格式

1
2
username=user1
groupname=grp1

b. 调用role的yml文件中:

1
2
roles:
- { role: nginx,username: daemon }

(5) Host Inventory(hosts文件中定义)

(a) 向不同的主机传递不同的变量;

1
IP/HOSTNAME varaiable=value var2=value2</pre>

(b) 向组中的主机传递相同的变量;

1
2
[groupname:vars]
variable=value

ansible-playbook命令:

ansible-playbook <filename.yml> … [options]

<filename.yml> #YAML文件位置

-t, TAGS, –tags=TAGS #当在yaml文件中定义由tag时,可以使用此指令指定只运行yaml文件中带有特定标签的部分

-e VARS, –extra-vars=VARS #自定义变量,可在yaml文件中调用

–check #测试运行,不“真实”运行

template模板:

template中使用Jinja2模板编程语言格式语法。实际上,模板只是普通文件中嵌入了Jinja2编程语言格式的变量、逻辑、算数运算而已。

字面量

  • 字符串:使用单引号或双引号;

  • 数字:整数,浮点数;

  • 列表:[item1, item2, …]

  • 元组:(item1, item2, …)

  • 字典:{key1:value1, key2:value2, …}

  • 布尔型:true/false

算术运算

  • +, -, , /, //, %, *

如:NaN

比较操作

  • ==, !=, >, >=, <, <=

逻辑运算

  • and, or, not
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@Ansible-Server ~]# cp /etc/nginx/nginx.conf /root/nginx.conf.j2
#修改以下行:
worker_processes {{ ansible_processor_vcpus - 1 }};
#编写playbook的yml文件:
[root@Ansible-Server ~]# cat nginx.yml
- hosts: all
remote_user: root
tasks:
- name: install nginx
yum: name=nginx state=present
- name: copy nginx config file
template: src=/root/nginx.conf.j2 dest=/etc/nginx/nginx.conf
notify: restart nginx
tags: copyconf
handlers:
- name: restart nginx
service: name=nginx state=restarted

[root@Ansible-Server ~]# ansible-playbook --check nginx.yml #测试运行
修改/root/nginx.conf.j2任意一处位置,再次运行测试
[root@Ansible-Server ~]# ansible-playbook -t copyconf nginx.yml #仅运行tags为copyconf的任务,由于notify设置,handlers中的name为restart nginx的任务也会运行

条件测试:

when语句:在task中使用,jinja2的语法格式的判断语句

(1) 根据变量的值

1
2
3
4
5
6
7
tasks: 
- name: install conf file to centos7
template: src=files/nginx.conf.c7.j2 dest=/etc/nginx/nginx.conf
when: ansible_distribution_major_version == "7"
- name: install conf file to centos6
template: src=files/nginx.conf.c6.j2 dest=/etc/nginx/nginx.conf
when: ansible_distribution_major_version == "6"

(2) 对运行结果进行过滤

1
2
3
4
5
6
7
8
9
10
tasks:
- command: /bin/false
register: result
ignore_errors: True
- command: /bin/something
when: result|failed
- command: /bin/something_else
when: result|succeeded
- command: /bin/still/something_else
when: result|skipped

(3) 将字符串转换成数值后比较

1
2
3
tasks:
- shell: echo "only on Red Hat 6, derivatives, and later"
when: ansible_os_family == "RedHat" and ansible_lsb.major_release|int >= 6

(4) 根据序列元素个数

1
2
3
4
tasks:
- command: echo {{ item }}
with_items: [ 0,2,4,6,8,10 ]
when: item > 5

详细可参考:http://blog.csdn.net/kellyseeme/article/details/50609591

循环:

迭代,需要重复执行的任务;

对迭代项的引用,固定变量名为”item”;而后,要在task中使用with_items给定要迭代的元素列表

列表方法:字符串、字典

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[root@Ansible-Server ~]# cat install_some_packages.yml 
- hosts: centos7
remote_user: root
tasks:
- name: install nginx memcached php-fpm
yum: name={{ item }} state=present
with_items:
- nginx
- memcached
- php-fpm

#字典列表实例
[root@Ansible-Server ~]# cat addusers.yml
- hosts: all
remote_user: root
tasks:
- name: add groups
group: name={{ item }} state=present
with_items:
- group1
- group2
- group3
- name: add users
user: name={{ item.name }} group={{ item.group }} state=present
with_items:
- { name: 'user1',group: 'group1' }
- { name: 'user2',group: 'group2' }
- { name: 'user3',group: 'group3' }

角色(roles)

每个角色,以特定的层级目录结构进行组织。如:

1
2
3
4
5
6
7
8
mysql/
files/ #存放由copy或script模块等调用的文件;
templates/ #template模块查找所需要模板文件的目录;
tasks/ #至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含
handlers/ #至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含
vars/ #至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含
meta/ #至少应该包含一个名为main.yml的文件,定义当前角色的特殊设定及其依赖关系;其它的文件需要在此文件中通过include进行包含
default/ #设定默认变量时使用此目录中的main.yml文件

playbook调用roles方法:

注意:在roles子目录下调用其他资源时直接写文件名即可,roles会自动到指定目录查找。

定义好的roles目录可以打包拷贝到其他主机反复使用,灰常方便。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#在playbook调用角色方法1:
- hosts: websrvs
remote_user: root
roles:
- mysql
- memcached
- nginx

#在playbook调用角色方法2:传递变量给角色
- hosts:
remote_user:
roles:
- { role: nginx, username: nginx } #role用于指定角色名称;后续的k/v用于传递变量给角色

#基于条件测试实现角色调用;
roles:
- { role: nginx, when: "ansible_distribution_major_version == '7' " }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#创建角色目录
[root@Ansible-Server ~]# cd /etc/ansible/roles/
[root@Ansible-Server roles]# mkdir nginx/{,files,templates,tasks,handlers,vars,meta,default}
[root@Ansible-Server roles]# cd nginx/templates/
[root@Ansible-Server templates]# cp /etc/nginx/nginx.conf nginx.conf.j2
[root@Ansible-Server templates]# vim nginx.conf.j2
#修改内容
worker_processes {{ ansible_processor_vcpus }};

#创建tasks主yml文件
[root@Ansible-Server handlers]# cd ../tasks/
[root@Ansible-Server tasks]# cat main.yml
- name: install nginx
yum: name=nginx state=present
- name: copy config file
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
tags: copy-config-file
notify: restart nginx

#创建handlers主yml文件
[root@Ansible-Server tasks]# cd ../handlers/
[root@Ansible-Server handlers]# cat main.yml
- name: restart nginx
service: name=nginx state=restarted

#编写playbook的yml文件进行测试:
[root@Ansible-Server handlers]# cd
[root@Ansible-Server ~]# cat install-nginx.yml
- hosts: centos7
remote_user: root
roles:
- nginx

#运行测试与运行
[root@Ansible-Server ~]# ansible-playbook --check install-nginx.yml
[root@Ansible-Server ~]# ansible-playbook install-nginx.yml
#修改任意一处template文件进行测试
[root@Ansible-Server ~]# vim /etc/ansible/roles/nginx/templates/nginx.conf.j2
[root@Ansible-Server ~]# ansible-playbook -t copy-config-file install-nginx.yml</pre>