Chinaunix首页 | 论坛 | 博客
  • 博客访问: 637283
  • 博文数量: 244
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 130
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-27 09:53
个人简介

记录学习,记录成长

文章分类

全部博文(244)

我的朋友

分类: LINUX

2015-11-29 18:19:40

自动化运维工具ansible安装部署
一.ansible介绍
1.简介
ansible是新出现的基于Python开发的自动化运维工具,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的特点,实现了批量系统配置、批量程序部署、批量运行命令等功能。ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。主要包括:
(1)、连接插件connection plugins:负责和被监控端实现通信;

(2)、host inventory:指定操作的主机,是一个配置文件里面定义监控的主机;

(3)、各种模块核心模块、command模块、自定义模块;

(4)、借助于插件完成记录日志邮件等功能;

(5)、playbook:剧本执行多个任务时,非必需可以让节点一次性运行多个任务。

2.ansible架构

3.特点
1.不需要代理,不需要客户端

2.没有服务器端,使用时直接运行命令

3.不基于pki工作

4.基于模块工作

5.支持YAML定义剧本

6.默认基于ssh工作

7.可以实现多级指挥

4.任务执行流程

二.ansible安装(这里使用yum方式安装)
1.源码安装
下载地址:
1.1先解决依赖关系
[root@localhost ~]# yum install python-jinja2 PyYAML python-paramiko 
python-babel python-crypto python-setuptools

1.2编译安装
[root@localhost ~]# tar xf ansible-1.9.4.tar.gz

[root@localhost ~]# cd ansible-1.9.4

[root@localhost ansible-1.9.4]# python setup.py build

[root@localhost ansible-1.9.4]# python setup.py install
遇到错误:error: Setup script exited with error: command 'gcc' failed with exit status 1
解决办法:
yum install -y python-devel 
再次python setup.py install后安装成功;

1.3然后创建ansible目录并将配置文件复制到该目录中:
[root@localhost ansible-1.9.4]# mkdir /etc/ansible
[root@localhost ansible-1.9.4]# cp -r examples/* /etc/ansible/
[root@localhost ansible-1.9.4]# ls /etc/ansible/
ansible.cfg  hosts

2.yum安装
EPEL源中有ansible的安装包,配置好EPEL源后直接yum install ansible即可;
也可以先下载在安装:
ansible包下载地址:

三.配置ansible
1.修改/etc/ansible/hosts文件为
[root@localhost ansible]# cat hosts
[webservers]
node1.a.com
node2.a.com

hosts文件定义了所能识别的所有主机,其内容:
1.1可以将所有主机写入此文件,那么此后所做的操作就会影响所有写入的主机;

1.2可以以[主机组名]的方式定义属于同一组的所有主机,如定义[webservers]段,将所有的web主机的IP或者主机名写入段中,此后就可以用ansible实施诸如servicehttpdstatus等仅对web主机所做的操作了,而其他主机则不会受影响,当然一个组中的主机也可以在其他组中出现,不一定每个组中的主机都不相同;

1.3可以用通配符的方式定义,如node[1:3].a.com,表示定义了node1.a.com node2..a.com和node3.a.com三台主机;

1.4可以直接写入主机IP,也可以写入主机名,但是必须保证能解析这些主机名;

2.配置主机互信
控制台主机是通过SSH区联系被控制主机的,那么就需要实现主机互信使控制台主机的命令送到被控端去执行,避免每一次都要输入密码;
[root@localhost ~]# ssh-keygen -t rsa -f /root/.ssh/id_rsa -P ''

[root@localhost ~]# ssh-copy-id -i .ssh/id_rsa.pub node1

[root@localhost ~]# ssh-copy-id -i .ssh/id_rsa.pub node2
这里因为/etc/hosts文件所以能解析:
[root@localhost ~]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.85.144  node1.a.com     node1
192.168.85.145  node2.a.com     node2

3.测试ansible能否执行
如查看所有主机时间是否一致:
[root@localhost ~]# ansible all -a 'date'
node2.a.com | success | rc=0 >>
Sat Nov 28 20:28:21 CST 2015

node1.a.com | success | rc=0 >>
Sat Nov 28 20:28:21 CST 2015

四.ansible用法
1.基本语法
语法格式:ansible [-f forks] [-m module_name] [-a args]
其中:
host-pattern:对哪些主机操作,可以是所有主机all或者定义的组;

-f forks:并行级别,即每次对几个主机操作,默认为5个,主机量多时可以调整该值;

-m module_name:指定模块名称;
默认模块为command,为-m command时可以省略不写,指的是让被控主机执行指定的命令,如
[root@localhost ~]# ansible webservers -a 'service httpd status'
node1.a.com | FAILED | rc=3 >>
httpd is stopped

node2.a.com | FAILED | rc=3 >>
httpd is stopped

-a args:指定模块的参数;

2.ansible的模块和模块参数

2.1列出ansible的所有模块
[root@localhost ~]# ansible-doc -l

2.2列出某模块的参数
[root@localhost ~]# ansible-doc -s 模块名

如:
模块copy可以将本地(控制端)文件复制到其他主机(被控端)上,其参数有:
[root@localhost ~]# ansible-doc -s copy
- name: C o p i e s   f i l e s   t o   r e m o t e   l o c a t i o n s .
  action: copy
    backup             # Create a backup file including the timestamp information so you can get the ori
    content            # When used instead of 'src', sets the contents of a file directly to the specifi
    dest=              # Remote absolute path where the file should be copied to. If src is a directory,
    directory_mode     # When doing a recursive copy set the mode for the directories. If this is not se
    follow             # This flag indicates that filesystem links, if they exist, should be followed.
    force              # the default is `yes', which will replace the remote file when contents are diff
    group              # name of the group that should own the file/directory, as would be fed to `chown
    mode               # mode the file or directory should be, such as 0644 as would be fed to `chmod'. 
    owner              # name of the user that should own the file/directory, as would be fed to `chown'
    selevel            # level part of the SELinux file context. This is the MLS/MCS attribute, sometime
    serole             # role part of SELinux file context, `_default' feature works as for `seuser'.
    setype             # type part of SELinux file context, `_default' feature works as for `seuser'.
    seuser             # user part of SELinux file context. Will default to system policy, if applicable
    src                # Local path to a file to copy to the remote server; can be absolute or relative.
    validate           # The validation command to run before copying into place.  The path to the file 
示例:将本地的a.txt文件复制到node1和node2的/tmp目录下
[root@localhost ~]# ansible webservers -m copy -a "src=/root/a.txt dest=/tmp/"
验证:
[root@localhost ~]# ansible webservers -a "ls /tmp"
node2.a.com | success | rc=0 >>
a.txt

node1.a.com | success | rc=0 >>
a.txt

五.ansible-playbook
当我们按照期望去部署多台服务器工作的时候,可能任务会不止一个,如去安装服务,启动服务,设置服务开机启动等,我们希望这些任务能同时执行,虽然ansible可以批量执行任务,但是每次都执行一次ansible会大大浪费时间,所以,此时就需要playbooks,而ansible playbooks依赖YAML语言工作;

1.YAML介绍:
YAML是一种直观的能够被电脑识别的数据序列化格式,是一个可读性高并且容易被人阅读,容易和脚本语言交互,用来表达资料序列的编程语言。
YAML Ain't Markup Language即YAML不是XML。不过,在开发的这种语言时YAML的意思其实是:"Yet Another Markup Language"(仍是一种标记语言)。其特性:

    可读性好

    脚本语言的交互性好

    使用实现语言的数据类型

    有一个一致的信息模型

    易于实现

    可以基于流来处理

    表达能力强,扩展性好
更多的内容及规范参见

2.YAML语法
YAML的语法和其他高阶语言类似,并且可以简单表达清单、散列表、标量等数据结构。其结构(Structure)通过空格来展示,序列(Sequence)里的项用"-"来代表,Map里的键值对用":"分隔。

示例:表示一个人的信息
name: John Smith
age: 41
spouse:
    name: Jane Smith
    age: 37
children:
    -   name: Jimmy Smith
        age: 17
    -   name: Jenny Smith
        age 13

YAML文件扩展名通常为.yaml
3.ansible playbook
playbook是由一个或多个play组成的列表。play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的task定义好的角色。从根本上来讲,所谓task无非是调用ansible的一个module。将多个play组织在一个playbook中,即可以让它们联同起来按事先编排的机制同时工作。

如:
[root@localhost ~]# cat test.yaml 
- hosts: webservers
  remote_user: root
  tasks:
    - name: add a user
      user: uid=1234 name=testuser system=no
    - name: excute a command
      command: /bin/date
hosts表示要操作的主机,因为可以有多个hosts,所以在前面加了个-号;
remote_user表示以哪个用户的身份区执行;
task表示要对该hosts执行的任务;
name表示某一任务的描述;
user: uid=1234 name=testuser system=no表示添加用户的uid为1234,用户名为testuser,且不是系统用户

执行测试:
[root@localhost ~]# ansible-playbook test.yaml
PLAY [webservers] ************************************************************* 
GATHERING FACTS *************************************************************** 
ok: [node2.a.com]
ok: [node1.a.com]

TASK: [add a user] ************************************************************ 
changed: [node2.a.com]
changed: [node1.a.com]

TASK: [excute a command] ****************************************************** 
changed: [node1.a.com]
changed: [node2.a.com]

PLAY RECAP ******************************************************************** 
node1.a.com                : ok=3    changed=2    unreachable=0    failed=0   
node2.a.com                : ok=3    changed=2    unreachable=0    failed=0   

4.playbook基础组件
4.1  Hosts和Users
playbook中的每一个play的目的都是为了让某个或某些主机以某个指定的用户身份执行任务。hosts用于指定要执行指定任务的主机,其可以是一个或多个由冒号分隔主机组;remote_user则用于指定远程主机上的执行任务的用户。如上面示例中的
- hosts: webservers
remote_user: root

不过,remote_user也可用于各task中。也可以通过指定其通过sudo的方式在远程主机上执行任务,其可用于play全局或某任务;此外,甚至可以在sudo时使用sudo_user指定sudo时切换的用户。
- hosts: webnodes
 remote_user: lw
 tasks:
   - name: test connection
     ping:
     remote_user: lw
     sudo: yes

4.2 任务列表和action
play的主体部分是task list。task list中的各任务在所有主机上完成第一个任务后再开始第二个。在运行自下而下的某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/command || /bin/true

或者使用ignore_errors来忽略错误信息:
tasks:
 - name: run this command and ignore the result
   shell: /usr/bin/command
   ignore_errors: true

4.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

如:
先将控制端主机httpd配置文件中监听端口改为8080
[root@localhost ~]# cat http.yaml 
- hosts: webservers
  remote_user: root
  tasks:
    - name: ensure httpd is the latest
      yum: state=latest name=httpd
    - name: ensure httpd configuration file changed
      copy: src=/etc/httpd/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf force=yes
      notify:
        - restart httpd
  handlers:
    - name: restart httpd service
      service: name=httpd state=restarted
这里先yum保证httpd版本是最新的,然后将本地已修改的httpd.conf文件复制(覆盖原文件)到被控端的指定位置,再确保配置文件已经修改后,notify才调用handlers执行httpd服务重启操作,如果配置文件没变,那么就不会重启服务;
注意:notify后的restart httpd要和handlers中的- name保持一致;

执行测试:
[root@localhost ~]# ansible-playbook http.yaml
PLAY [webservers] ************************************************************* 

GATHERING FACTS *************************************************************** 
ok: [node1.a.com]
ok: [node2.a.com]

TASK: [ensure httpd is the latest] ******************************************** 
ok: [node2.a.com]
ok: [node1.a.com]

TASK: [ensure httpd configuration file changed] ******************************* 
ok: [node2.a.com]
ok: [node1.a.com]

PLAY RECAP ******************************************************************** 
node1.a.com                : ok=3    changed=0    unreachable=0    failed=0   
node2.a.com                : ok=3    changed=0    unreachable=0    failed=0 

验证:
[root@localhost ~]# ansible webservers -m raw -a 'netstat -ntlp | grep :8080'
node2.a.com | success | rc=0 >>
tcp        0      0 :::8080                     :::*                        LISTEN      26461/httpd         

node1.a.com | success | rc=0 >>
tcp        0      0 :::8080                     :::*                        LISTEN      26943/httpd           
阅读(4157) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~