核心组件:
Host Inventory: 主机列表,每个主机都要在本地有个注册 IP地址、掩码、监听端口等,使Ansible远程管理主机成为可能
Core Moudles: 核心模块可以完成大部分日常管理任务,并非能完成所有任务
Custom Modules: 自定义模块
Connection Plugins: 各种连接插件,连接每一个被管理的主机
Plugins
PlayBooks: 把一个主机要完成的多个任务统统定义在一个yaml文本文件中,可以多次调用
特性:
基于Python语言实现,由Paramiko PyYAML和jinjia2三个关键模块;
部署简单,不用安装agent端
默认使用SSH协议
(1)基于秘钥认证
(2)在inventory文件中指定账号和密码
使用主从模式,master: ansible, ssh client slave: ssh server
支持自定义模块,支持各种编程语言
支持Playbook
基于模块完成各种任务
安装:
依赖EPEL yum install ansible -y
配置文件:/etc/ansible/ansible.cfg
Invertory文件:/etc/ansible/hosts
如何查看模块文件:
ansible-doc -l 列出所有的模块
ansible-doc -s MODULE_NAME 查看模块帮助
ansible命令应用基础:
语法:ansible
-f forks: 一次性控制多少个主机执行任务,启动的并发线程数
-m module_name: 要使用的模块
-a args : 模块特有的参数
常用模块:copy、cron、command
command:
命令模块,默认模块,用于在远程执行命令 ansible all -m command -a 'date' == ansible all -a 'date'
ansible 113.142.35.60 -m command -a 'date'
ansible wekeserver -m command -a 'date'
ansible all -m command -a 'date'
使用 creates 参数,判断一个文件是否存在,存在的话,就跳过后面的执行命令
ansible wekeserver -m command -a 'creates=/tmp/weke1.ans ls -l /etc/passwd'
113.142.35.62 | success | rc=0 >>
skipped, since /tmp/weke1.ans exists
113.142.35.60 | success | rc=0 >>
-rw-r--r-- 1 root root 1670 Jan 14 18:56 /etc/passwd
cron:
present: 安装
absent: 移除
ansible wekeserver -m cron -a 'minute="*/2" job="/bin/echo hello" name="test cron" state=present'
user:
添加用户:
ansible wekeserver -m user -a ' name="ZYH" password="ZYH123456" '
删除用户:
ansible wekeserver -m user -a 'group="ZYH" name="ZYH" password="ZYH123456" state=absent '
group:
添加组:
ansible wekeserver -m group -a 'gid="888" name="mysql" state=present system=yes'
删除组:
ansible wekeserver -m group -a 'gid="888" name="mysql" state=absent system=yes'
将用户添加到组里:
ansible wekeserver -m user -a 'group=mysql password=ZYH name=ZYH '
copy:
src指明本地文件路径(绝对路径或相对路径) dest只能使用绝对路径
ansible all -m copy -a 'src=/root/scfg dest=/tmp/scfg.ansible owner=root mode=640'
在远程主机自动创建一个文件并写入内容,支持转义
content 取代src,表示直接用此处指定的信息生成为目标文件内容,二者不可同时使用
ansible all -m copy -a 'content="Hello Ansible\nHello world" dest=/tmp/test.ansible'
file:
path指定要修改的文件
ansible all -m file -a 'owner=mysql group=mysql mode=644 path=/tmp/fstab.ansible'
state=link用于指定符号链接 src指明源文件 path指明符号链接文件路径
ansible all -m file -a 'owner=mysql group=mysql mode=644 path=/tmp/fstab.link src=/tmp/fstab.ansible state=link'
ping:
测试主机的连通性
ansible all -m ping
service:
管理服务
enabled 表示开机自启动,取值为true或false
name指定要启动的服务
state指定启动还是停止,取值有started、stopped、restarted
ansible wekeserver -m service -a 'enabled=true name=vsftpd state=started'
shell:
在远程主机上运行命令
尤其是在用到管道等功能的复杂命令时,建议使用shell
与command不同的是,此模块可以支持命令管道,同时还有另一个模块也具备此功能:raw
实例1:
113.142.35.60 | success | rc=0 >>
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
113.142.35.62 | success | rc=0 >>
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
script:
将本地脚本在远程主机上执行,注意要使用相对路径指定脚本
ansible all -m script -a 'ansible.sh'
yum:
安装程序包
name指明要安装的程序包,可以带上版本号;state:present、latest表示安装,absent表示卸载
ansible all -m yum -a 'name=zsh'
ansible all -m yum -a 'name=zsh state=absent'
setup:
收集远程主机的facts
每个被管理的节点在接收并运行管理命令之前,会将自己的主机相关信息,如操作系统版本、IP地址等报告给远程的ansible主机
ansible all -m setup
收集网卡信息
ansible all -m setup -a 'filter=ansible_em[0-2]'
synchronize:
使用rsync同步文件。使用rsync 模块,系统必须安装rsync 包,否则无法使用这个模块
- hosts: wekeserver
remote_user: root
tasks:
- name: install rsync package
yum: name=rsync state=latest
tasks:
- name: rsync the file
synchronize: src=/root/zabbix-2.4.5.tar.gz dest=/tmp/
Ansible PlayBooks
YAML: 它是一个可读性高的用来表达资料序列的格式,YAML参考了其他多种语言,包括:XML、C语言、Python、Perl以及电子邮件格式RFC2822。
YAML是"YAML Ain't a Markup Language"(YAML不是一种置标语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:"Yet Another Markup Language"(仍是一种置标语言)
YAML的特性:
可读性好
YAML和脚本语言的交互性好
YAML使用实现语言的数据类型
有一个一致的信息模块
YAML易于实现
YAML可以基于流来处理
YAML表达能力强,扩展性好
YAML的语法:
YAML的语法和其他高级语言类似,并且可以简单表达清单、散列表、标量等数据结构。其结构通过空格来展示,序列里的项用"-"来表示,Map里的键值对用":"来分隔
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:12
gender:Female
YAML文件扩展名通常为.yaml
list
列表中的所有元素均使用"-"打头,例如:
#A list of tasty fruits
- Apple
- Orange
- Mango
dictionary
字典通过key与value进行标识,例如:
name: Example Developer
job: Developer
skill: Elite
也可以将key:value放置在{}中进行表示,例如:
{name: Example Developer,job: Developer,skill: Elite}
Ansible中使用的YAML基础元素:
1.变量
1.1 变量命名
变量名仅能由字母、数字和下划线组成,且只能以字母开头。
1.2 facts
facts是由正在通信的远程目标主机发回的消息,这些消息被保存在ansible的变量中,要获取指定的远程主机所支持
的所有facts,可使用如下命令:
ansible hostname -m setup
1.3 register
把任务的输出定义为变量,然后用于其他任务,例如:
tasks:
- shell:/usr/bin/foo
register:foo_result
ignore_errors:True
1.4通过命令行传递变量
在运行playbook的时候也可以传递一些变量供playbook使用,例如:
amsible-playbook test.yaml --extra-vars "hosts=www user=weke"
1.5通过roles传递变量
当给一个主机应用角色的时候可以传递变量,然后在角色内使用这些变量,如下:
- hosts:webservers
roles:
- common
- {role:foo_app_instance, dir:'/web/htdocs/a.com', port:8080}
2.Inventory
ansible的主要功能在于批量操作主机,为了便捷的使用其中的一部分主机,可以在Inventory file中将其分组命名,默认的Inventory file为/etc/ansible/hosts
Inventory file可以有多个,且也可以通过Dynamic Inventory来动态生成
2.1文件格式
Inventory文件遵循INI文件风格,中括号中的字符为组名,可以将同一个主机同时归并到多个不同的组中,此外,当如若目标主机使用了非默认的SSH端口,还可以
在主机名称之后使用冒号加端口号来标明。
ntp.weke.com
[webservers]
www1.weke.com:2222
www2.weke.com
[dbservers]
db1.weke.com
db2.weke.com
db3.weke.com
如果主机名称遵循相似的命名模式,还可以使用列表的方式识别各主机,例如:
[webservers]
www[1:50].example.com
[databases]
db-[a:f].example.com
2.2主机变量
可以在inventory中定义主机时为其添加主机变量以便于在playbook中使用,例如:
[webservers]
www1.example.com http_port=80 maxRequestsPerChild=888
www2.example.com http_port=8080 maxRequestsPerChild=999
2.3组变量
组变量是指在赋予给指定组内所有主机上的在playbook中可用的变量,例如:
[webservers]
www1.example.com
www2.example.com
[webservers:vars]
ntp_server=ntp.example.com
nfs_server=nfs.example.com
2.4组嵌套
Inventory中,组还可以包含其他组,并且也可以向组中的主机指定变量,不过,这些变量只能在Ansible-playbook中使用,而ansible不支持,例如:
[apache]
httpd1.example.com
httpd2.example.com
[nginx]
nginx1.example.com
nginx2.example.com
[webservers:children]
apache
nginx
[webservers:vars]
ntp_server=ntp.example.com
2.5Inventory参数
ansible基于ssh连接inventory中指定的远程主机时,还可以通过参数指定其交互方式,这些参数如下所示:
ansible_ssh_host
ansible_ssh_port
ansible_ssh_user
ansible_ssh_pass
ansible_sudo_pass
ansible_connection
ansible_ssh_private_key_file
ansible_shell_type
ansible_python_interpreter
Ansible中使用的YAML基础元素:
变量
Inventory
条件测试
迭代
playbook的组成结构:
Inventory
Modules
Ad Hoc Commands
Playbooks
Tasks: 任务,即调用模块完成的某操作
Variables: 变量
Templates: 模块
Handlers: 处理器,由某事件触发执行的操作
Roles: 角色
基本结构:
- host : webservers
remote_user : root
tasks :
- task1
module_name : module_args
- task2
简单示例:
nginx.yml
- hosts: wekeserver
remote_user: root
tasks:
- name: create nginx group
group: name=nginx system=yes gid=808
- name: create nginx user
user: name=nginx uid=808 group=nginx system=yes
- hosts: dbservers
remote_user: root
tasks:
- name: copy file to dbservers
copy: src=/etc/inittab dest=/tmp/inittab.ans
ansible-playbook nginx.yml
Apache的安装启动:
httpd.yml
- hosts: wekeserver
remote_user: root
tasks:
- name: install httpd package
yum: name=httpd state=latest
- name: install configuration file for httpd
copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
- name: start httpd service
service: enabled=true name=httpd state=started
ansible-playbook httpd.yml
Handlers:
用于当关注的资源发生变化时采取一定的操作。
“notify”这个action可用于在每个play的最后被触发,这样可以避免多次有改变发生时每次都执行指定的操作,取而代之,
仅在所有的变化发生完成后一次性地执行指定操作,在notify中列出的操作称为handler,也即notify中调用handler中定义的操作.
- name: template configuration file
template: src=template.j2 dest=/etc/foo.conf
notify:
- restart memcached
- restart apache
handler是task列表,这些task与前述的task并没有本质上的不同,handler与task是同级别的。
handlers:
- name: restart memcached
service: name=memcached state=started
- name: restart apache
service: name=apache state=started
示例:
修改了httpd的配置文件之后,重启httpd
- hosts: wekeserver
remote_user: root
tasks:
- name: install httpd package
yum: name=httpd state=latest
- name: install configuration file for httpd
copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify:
- restart httpd
- name: start httpd service
service: enabled=true name=httpd state=started
handlers:
- name: restart httpd
service: name=httpd state=restarted
playbook中的变量:
使用vars声明变量,使用{{***}}引用变量
- hosts: wekeserver
remote_user: root
vars:
- package: httpd
- service: httpd
tasks:
- name: install httpd package
yum: name=`package` state=latest
- name: install configuration file for httpd
copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify:
- restart httpd
- name: start httpd service
service: enabled=true name=`service` state=started
handlers:
- name: restart httpd
service: name=httpd state=restarted
有些变量不用定义,可以直接使用,例如ansible_all_ipv4_addresses
- hosts: wekeserver
remote_user: root
tasks:
- name: copy file
copy: content="`ansible_all_ipv4_addresses`" dest=/tmp/vars.ans
vim /etc/ansible/hosts
[wekeserver]
113.142.35.60 testvar="35.60"
113.142.35.62 testvar="35.62"
- hosts: wekeserver
remote_user: root
tasks:
- name: copy file
copy: content="`ansible_all_ipv4_addresses`,`testvar`" dest=/tmp/vars.ans
playbook中的条件测试
如果需要根据变量、facts或此前任务的执行结果来做为某task执行与否的前提时要用到条件测试。
1.when语句
只有条件满足才会执行,不然会skipping
在task后添加when子语句即可使用条件测试:when语句支持jinjia2表达式语法,例如:
tasks:
- name: "shutdown Debian flavored systems"
command: /sbin/shutdown -h now
when: ansible_os_family -- "Debian"
示例:
- hosts: all
remote_user: root
vars:
- username: user10
tasks:
- name: create `username` user
user: name=`username`
when: ansible_fqdn == "localhost.localdomain"
when语句中还可以使用Jinjia2的大多数“filter”,例如要忽略此前某语句的错误并基于其结果(failed或success)运行后面指定
的语句,可使用类似如下形式:
task:
- command: /bin/false
register: result
ignore_errors: True
- command: /bin/something
when: result|failed
- command: /bin/something_else
when: result|success
- command: /bin/still/something_else
when: result|skipped
2.迭代
当有需要重复性执行的任务时,可以使用迭代机制,其使用格式为将需要迭代的内容定义为item变量引用,并通过with_items语句来指明迭代的元素列表即可。
重复同类task时使用
调用:item
定义循环列表:with_items
注意:with_items中的列表值也可以是字典,但引用时要使用item.KEY的方式
with_items:
- apache
- php
-mysql-server
- {name:apache, conf: conffiles/httpd.conf}
- {name:php, conf: conffiles/php.ini}
- {name:mysql-server, conf: conffiles/my.cnf}
例如:
- name: add several users
user: name=`item` state=present groups=wheel
with_items:
- testuser1
- testuser2
上面语句的功能等同于下面的语句:
- name: add user testuser1
user: name=testuser1 state=present groups=wheel
- name: add user testuser2
user: name=testuser2 state=present groups=wheel
事实上,with_items中可以使用元素还可以为hashes,例如:
- name: add several users
user: name=`item`.`name` state=present groups=`item`.`groups`
with_items:
- {name: 'testuser1',groups: 'wheel'}
- {name: 'testuser2',groups: 'root'}
3.Templates:
vim /etc/ansible/hosts
[wekeserver]
113.142.35.60 http_port=8010 maxClients=500
113.142.35.62 http_port=8030 maxClients=700
mkdir /root/templates
cp /etc/httpd/conf/httpd.conf /root/templates/httpd.conf.j2
vim /root/templates/httpd.conf.j2
MaxClients `maxClients`
Listen `http_port`
ServerName `ansible_fqdn`
vim httpd.yml
- hosts: wekeserver
remote_user: root
vars:
- package: httpd
- service: httpd
tasks:
- name: install httpd package
yum: name=`package` state=latest
- name: install configuration file for httpd
template: src=/root/templates/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
notify:
- restart httpd
- name: start httpd service
service: enabled=true name=`service` state=started
handlers:
- name: restart httpd
service: name=httpd state=restarted
4.Jinjia2 常用运算符
Jinjia允许你用计算值,这在模板中很少用到,但是为了完整性允许其存在,支持下面的运算符:
+
把两个对象加到一起,通常对象是数字,但是如果两者是字符串或者列表,你可以用这种方式来衔接它们,
无论如何这不是首选的连接字符串的方式!连接字符串可看~运算符。{{1+1}}等于2
-
减法,`3 - 2`等于1
/
除法,返回值会是一个浮点数。{{1 / 2}}等于`0`.`5`
//
除法,返回值为整数。{{20 // 7 }}等于2
%
计算余数。{{11 % 7}}等于4
*
用右边的数乘左边的数。{{2 * 2}}返回4,也可以用于重复一个字符串多次,{{‘-’* 80}}会打印80个-
**
取左操作数的右操作数次幂。 {{2**3}}返回8
5.Tags
tags用于让用户选择运行或者路过playbook中的部分代码,ansible具有幂等性,因此会自动跳过没有变化的部分,
即便如此,有些代码为测试其确实没有发生变化的时间依然会非常的长。此时,如果确信其没有变化,就可以通过
tags跳过此些代码片段。
在playbook可以为某个或某些任务定义一个"标签",在执行此playbook时,通过为ansible-playbook命令使用--tags
选项就能实现仅运行指定的tasks而非所有的。
- hosts: wekeserver
remote_user: root
vars:
- package: httpd
- service: httpd
tasks:
- name: install httpd package
yum: name=`package` state=latest
- name: install configuration file for httpd
template: src=/root/templates/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
tags:
- conf
notify:
- restart httpd
- name: start httpd service
service: enabled=true name=`service` state=started
handlers:
- name: restart httpd
service: name=httpd state=restarted
特殊tags: always
6.roles
ansible自1.2版本引入的新特性,用于层次性、结构化地组织playbook。roles能根据层次型结构自动装载变量文件。
tasks已经handlers等。要使用roles只需要在playbook中使用include指令即可。简单来讲,roles就是通过分别将变量、
文件、任务、模块及处理器放在单独的目录中,并可以便捷的include它们的一种机制,角色一般用于基于主机构建服务的
场景中,但也可以用于创建守护进程等场景中。
一个roles的案例如下:
site.yml
webservers.yml
fooservers.yml
roles/
common/
files/
templates/
tasks/
handlers/
vars/
meta/
webservers/
files/
templates/
tasks/
handlers/
vars/
meta/
创建role的步骤:
(1)创建以roles命名的目录
(2)在roles目录中分别创建以各角色名称命名的目录,如webservers等
(3)在每个角色命名的目录中分别创建files、handlers、meta、tasks、templates和vars目录,用不到的目录可以创建为空目录,或者不创建
(4)在playbook文件中,调用各角色
role内各目录中可用的文件:
tasks目录:至少应该包含一个名为main.yml的文件,其定义了此角色的任务列表,此文件可以使用include包含其他的位于此目录中的task文件。
files目录:存放由copy或script等模块调用的文件
templates:template模块会自动在此目录中寻找Jinjia2模板文件
handlers目录:此目录中应包含一个main
yml文件:用于定义此角色用到的各种handler,在handler中使用include包含其他的handler文件也应该位于此目录中
vars目录:应该包含一个main.yml文件,用于定义此角色用到的变量
meta目录:应该包含一个main.yml文件,用于定义此角色的特殊设定及依赖关系,ansible 1.3及其以后的版本才支持
default目录:为当前角色设定默认变量时使用此目录,应该包含一个main.yml文件
(1)目录名同角色名
(2)目录结构有固定格式: files、templates、tasks
(3)site.yml定义playbook,额外也可以有其他的yml文件
在编写yml脚本时,一定要确保格式正确,name和下面