ansible简单使用
一、ansible简介
ansible是新出现的 自动化 运维工具 , 基于Python研发 。 糅合了众多老牌运维工具的优点实现了批量操作系统配置、批量程序的部署、批量运行命令等功能。 仅需在管理工作站上安装 ansible 程序配置被管控主机的 IP 信息,被管控的主机无客户端。 ansible 应用程序存在于 epel( 第三方社区 ) 源,依赖于很多 python 组件。
二、ansible特性
①模块化设计,调用特定的模块来完成特定的任务,本身是核心组件,短小精悍
②基于python语言实现,由Paramiko、PyYAML和Jinja2三个关键模块实现
③部署简单,不需要在被控制端安装任何组件
④支持自定义模块功能
⑤支持playbook剧本,连续任务按先后设置顺序完成
⑥期望每个命令具有幂等性(不会重复执行相同的命令。例如不会重复安装软件)
三、ansible架构

ansible : ansible自身核心模块
Modules: core modules(自带模块)、 custom modules(自定义模块)
connection plugins:连接插件,一般默认基于ssh 协议连接
host inventory:主机库,定义可管控的主机列表
Playbooks:剧本执行多个任务。并非必需让节点一次性运行多个任务
Plugins (loh、mail):借助于插件完成记录日志邮件等功能

四、安装ansible(操作均在主控端)
1、安装epel源 2、yum install -y ansible
这里我们使用ssh key实现 主控端于被控端的连接
# ssh-keygen -t rsa -P '' //生成密钥 # ssh-copy-id -i .ssh/id_rsa.pub root@192.168.10.12 //把公钥分配到被控端主机 # ssh-copy-id -i .ssh/id_rsa.pub root@192.168.10.13 # ssh-copy-id -i .ssh/id_rsa.pub root@192.168.10.14
定义 Host Inventory,定义可管控的主机
# tree /etc/ansible/ /etc/ansible/ ├── ansible.cfg #ansible主配置文件 ├── hosts #Host Inventory配置文件 └── roles
#vim /etc/ansible/hosts [webserver] //主机组名 192.168.10.12 192.168.10.13 [dbserver] 192.168.10.13 192.168.10.14
*定义可管控主机的说明
1、[ ]方括号中是组名,用于对系统进行分类,便于对不同系统进行个别的管理,一个系统也可以属于不同的组,比如一台服务可以同时属于webserver组和dbserver组
2、被控主机,可以用域名(必需可以DNS解析或更改hosts文件),也可以用IP
3、如果有主机的SSH端口不是标准的22端口,例如:可以明确表示为 192.168.12.12:8021
4、如果不是SSH key,而是使用密码,则需要设置用户名和密码,例如 : 192.168.12.12:8021 ansible_ssh_user=root ansible_ssh_pass=123456
5、一组相似的hostname,可简写如下:
[webserver]
www[01:50].example.com
6、ansible_sudo 定义hosts sudo用户,例如:ansible_sudo=yadmin
ansible_sudo_pass 定义hosts sudo密码,例如:ansible_sudo_pass=123456
ansible_sudo_exe 定义hosts sudo路径,例如:ansible_sudo_exe=/usr/bin/sudo
通过上面我们知道Ansible默认的Inventory文件是/etc/ansible/hosts, 实际上Ansible还支持多个Inventory文件,这样我们就可以方便的管理不同业务或者不同环境中的机器。
1、首先准备一个文件夹,里面将存放多个Inventory文件
mkdir /etc/ansible/Inventory
cd /etc/ansible/Inventory
vim docker #定义inventory,格式和上面介绍的一样
vim hosts
2、修改ansible.cfg文件中的inventory的值,这里不再是指向一个文件,而是指向一个目录
inventory = /etc/ansible/inventory
五、基本使用
ansible <host-pattern> [-m module_name] [-a args] [options]
<host-pattern> : 指定组名,表示控制这个组的主机,all:表示所有的主机
-m module_name :使用哪个模块,默认是command
-a args : 传递给模块的参数
在所有主机上执行date命令 # ansible all -m command -a 'date' #因为command是默认是,所以可以省略,写成ansible -a 'date' 192.168.10.14 | SUCCESS | rc=0 >> Mon May 2 16:00:52 EDT 2016 192.168.10.13 | SUCCESS | rc=0 >> Mon May 2 16:00:53 EDT 2016 192.168.10.12 | SUCCESS | rc=0 >> Mon May 2 16:00:53 EDT 2016
使用 ping模块检查所有主机
[root@c1 ~]# ansible all -m ping
192.168.10.14 | SUCCESS => {
"changed": false,
"ping": "pong"
}
192.168.10.12 | SUCCESS => {
"changed": false,
"ping": "pong"
}
192.168.10.13 | SUCCESS => {
"changed": false,
"ping": "pong"
}
使用raw模块,支持管道命令
# ansible dbserver -m raw -a "ip addr|grep 'eno16777736'"
192.168.10.14 | SUCCESS | rc=0 >>
2: eno16777736: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
inet 192.168.10.14/24 brd 192.168.10.255 scope global eno16777736
192.168.10.13 | SUCCESS | rc=0 >>
2: eno16777736: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
inet 192.168.10.13/24 brd 192.168.10.255 scope global eno16777736
使用copy模块,复制文件到被控所有主机
# ansible all -m copy -a 'src=/root/sellsa.txt dest=/root/'
还是可以指定属主,属组,权限(传输完成之后,文件在被控端的属主和属组是heboan,权限是0644)
# ansible all -m copy -a 'src=/root/sellsa.txt dest=/root/ owner=heboan group=heboan mode=0644'
使用 cron模块,为dbserver组的主机设置定时任务计划
#ansible dbserver -m cron -a 'name="ntpdate by heboan at 2016-4-28" minute=*/3 hour=* day=* month=* weekday=* job="/usr/sbin/ntpdate s1a.time.edu.cn"'
# ansible dbserver -a 'crontab -l' 192.168.10.13 | SUCCESS | rc=0 >> #Ansible: ntpdate by heboan at 2016-4-28 */3 * * * * /usr/sbin/ntpdate s1a.time.edu.cn 192.168.10.14 | SUCCESS | rc=0 >> #Ansible: ntpdate by heboan at 2016-4-28 */3 * * * * /usr/sbin/ntpdate s1a.time.edu.cn
使用yum模块安装软件
# ansible webserver -m yum -a 'name=httpd state=present'
使用service模块启动服务,并开机启动
# ansible webserver -m service -a 'name=httpd state=started enabled=yes'
192.168.10.12 | SUCCESS => {
"changed": true,
"enabled": true,
"name": "httpd",
"state": "started"
}
192.168.10.13 | SUCCESS => {
"changed": true,
"enabled": true,
"name": "httpd",
"state": "started"
}
使用group模块添加用户组
# ansible dbserver -m group -a 'name=sellsa gid=1010'
使用user模块添加用户
# ansible dbserver -m user -a 'name=sellsa uid=1010 group=sellsa password=123456'
六、更多模块使用帮助文档
#ansible-doc -l 列出模块名及功能描述
#ansible-doc -s <module_name> 输出模块使用方法
七、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表达能力强,扩展性好
YAML的语法和其他高阶语言类似,并且可以简单表达清单、散列表、标量等数据结构。其结构(Structure)通过空格来展示,序列(Sequence)里的项用"-"来代表,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 13
gender: Female
YAML文件扩展名通常为.yaml,如example.yaml
八、playbooks
playbook是由一个或多个“play”组成的列表。play的主要功能在于将事先并归为一组的 主机装扮成事先通过ansible中的task定义好的角色,从根本上来讲,所谓的task就是调用ansible的一个module。将
多个play组织在一个playbook中就可以让它们连同起来按事先安排的机制同唱一台大戏。
下面是一个简单的示例
- hosts: webnodes
vars
http_port: 80
max_clients: 256
remote_user: root
tasks:
- name: ensure apache is at lasted version
yum: name=httpd state=latest
- name: ensure apache is running
service: name=httpd state=started
handlers:
- name: restart apache
service: name=httpd state=restarted
playbook基础组件
1、Hosts和Users
playbook中的每一个play的目的都是为了让某个或某些主机以某个指定的用户身份执行任务。hosts用于指定要执行指定任务的主机,其可以是一个或多个由冒号分隔主机组;remote_user则用于指定远程主机上的执行任务的用户。如上面示例中的
- hosts: webnodes
remotes_user: root
不过,remote_user也可用于各task中。也可以通过指定其通过sudo的方式在远程主机上执行任务,其可用于play全局或某任务;此外,甚至可以在sudo时使用sudo_user指定sudo时切换的用户
- hosts: webnodes
remote_user: heboan
tasks:
- name: test connection
ping:
remote_user: heboan
sudo: yes
2、任务列表和action
play的主体部分是task list。task list中的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后再开始第二个。在运行自下而下某playbook时,如果中途发生错误,所有已执行任务都将回滚,因此,在更正playbook后重新执行一次即可。
task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致。
每个task都应该有其name,用于playbook的执行结果输出,建议其内容尽可能清晰地描述任务执行步骤。如果未提供name,则action的结果将用于输出。
定义task的可以使用“action: module options”或“module: options”的格式,推荐使用后者以实现向后兼容。如果action一行的内容过多,也中使用在行首使用几个空白字符进行换行。
tasks:
- name: make sure apache is running
service: name=httpd state=running
在众多模块中,只有command和shell模块仅需要给定一个列表而无需使用“key=value”格式,例如:
tasks:
- name: disable selinux
command: /sbin/setenforce 0
如果命令或脚本的退出码不为零,可以使用如下方式替代:
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand || /bin/true
或者使用ignore_errors来忽略错误信息
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand
ignore_errors: True
3、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并没有本质上的不同。
handlers:
- name: restart memcached
service: name=memcached state=restarted
- name: restart apache
service: name=apache state=restarted
九、案例-基于playbooks事先web部署
1、提供好Inventory文件
# cat /etc/ansible/hosts 基于秘钥认证 [webserver] 192.168.88.3 192.168.88.2
2、编辑playbooks剧本
#vim /root/web.yaml
- hosts: webserver
remote_user: root
tasks:
- name: install httpd
yum: name=httpd state=present
- name: start httpd
service: name=httpd enabled=yes state=started
- name: httpd.conf configure file
copy: src=/root/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify: #修改了配置文件需要重启服务才会生效,所以这里要关联一个重启操作
- restart httpd
handlers:
- name: restart httpd #这里是上面的 restart httpd要执行的动作
service: name=httpd state=restarted
3、准备好配置文件
将web的配置放到指定目录 src=/root/httpd.conf #这里我把监听端口改成了8080
4、开始部署
# ansible-playbook /root/web.yaml


浙公网安备 33010602011771号