自动化工具――ansible

一、什么是ansible

   我们在管理服务器时首先应该是安装操作系统,而关于自动化安装操作系统工具常见的有:cobbler。而在装完操作系统后就是配置系统的相关服务的配置文件,而关于此类的自动化工具常见的有:puppet、saltstack。而日常维护中我们还需要在各主机执行相关命令等操作,而此类的自动化工具就有:func、fabric已经ansible。最后也是重要的监控系统运行状态的相关自动化工具:cacti、nagios和zabbix等。下面就是将ansible工具的使用。

   ansible是个什么东西呢?官方的title是“Ansible is Simple IT Automation”――简单的自动化IT工具。这个工具的目标有这么几项:让我们自动化部署APP;自动化管理配置项;自动化的持续交付;自动化的(AWS)云服务管理。 所有的这几个目标本质上来说都是在一个台或者几台服务器上,执行一系列的命令而已。

ansible的基础架构:

wKiom1Xyll7z25RIAAG1mUO7oyE284.jpg

运维工具常见的工作模式

  • agent模式: 基于ssl实现。代理工作在被监控端。像puppet。 

  • agentless模式: 基于ssh服务实现工作在被监控端。监控端是ssh的客户端。 

ansible是工作在agentless模式下具有幂等性。ansible在控制端只需要告诉监控端的期望状态就可以实现批量部署。

ansible是基于模块工作的ansible本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块ansible只是提供一种框架。架构包括:

  • 连接插件connection plugins负责和被监控端实现通信。 

  • Host Inventory:指定操作的主机,是一个配置文件里面定义监控的主机。 

  • 各种模块核心模块command模块自定义模块 。

  • 借助于插件完成记录日志邮件等功能。

  • PlayBooks:剧本执行多个任务时。并非必需可以让节点一次性运行多个任务。


二、安装使用ansible

1、安装ansible

# yum install -y ansible


2、安装ansible后几个重要文件说明

/etc/ansible/ansible.cfg :配置文件
/etc/ansible/hosts :Host Inventory文件
/usr/bin/ansible :ansible命令
/usr/bin/ansible-doc :模块相关命令
/usr/bin/ansible-playbook :执行PlayBooks的命令


3、定义Host Inventory

[webservers]
node1
node2
[dbservers]
node2
node3

说明:各从节点的主机名必须要和上面所定义的一致。


4、定义基于ssh的密钥连接

[root@Director ~]# ssh-keygen -t rsa -P ''
[root@Director ~]# ssh-copy-id -i .ssh/id_rsa.pub root@node1
[root@Director ~]# ssh-copy-id -i .ssh/id_rsa.pub root@node2 
[root@Director ~]# ssh-copy-id -i .ssh/id_rsa.pub root@node3

语法格式:

ansible <host-pattern> [-f forks] [-m module_name] [-a args]

 -m module:默认为command

获取ansible命令所有模块的信息:

[root@Director ~]# ansible-doc -l

查看指定模块的文档:

[root@Director ~]# ansible-doc -s 模块


5、基本应用

测试是否能连接个host:

[root@Director ~]# ansible all -m ping
node1 | success >> {
    "changed": false, 
    "ping": "pong"
}
node2 | success >> {
    "changed": false, 
    "ping": "pong"
}
node3 | success >> {
    "changed": false, 
    "ping": "pong"
}

同步查看个host的时间:

[root@Director ~]# ansible all -a 'ntpdate 202.120.2.101'
[root@Director ~]# ansible all -m command -a 'date' 
node3 | success | rc=0 >>
Mon Sep  7 11:51:54 CST 2015

node1 | success | rc=0 >>
Mon Sep  7 11:51:54 CST 2015

node2 | success | rc=0 >>
Mon Sep  7 11:51:54 CST 2015

将Director机器上的cpcom.sh文件拷贝到定义为webservers的机器上的/tmp目录下:

[root@Director  ~]# ansible webservers -m copy -a "src=/root/shell/cpcom.sh dest=/tmp"

验证是否成功:

[root@Director ~]# ansible webservers -a "ls /tmp/cpcom.sh"
node1 | success | rc=0 >>
/tmp/cpcom.sh
node2 | success | rc=0 >>
/tmp/cpcom.sh

将个节点定义个同步时间的周期任务:

[root@Director ~]# ansible all -m cron -a 'name="ntpdate" minute=*/5 hour=* day=* month=* job="/usr/sbin/ntpdate 202.120.2.101 &> /dev/null"'
[root@Director ~]# ansible all -a "crontab -l"
node3 | success | rc=0 >>
#Ansible: ntpdate
*/5 * * * * /usr/sbin/ntpdate 202.120.2.101 &> /dev/null

node1 | success | rc=0 >>
#Ansible: ntpdate
*/5 * * * * /usr/sbin/ntpdate 202.120.2.101 &> /dev/null

node2 | success | rc=0 >>
#Ansible: ntpdate
*/5 * * * * /usr/sbin/ntpdate 202.120.2.101 &> /dev/null

安装openssl包:

说明,state:选项present|absent,安装或者卸载。name= :安装的包名。

[root@Director ~]# ansible all -m yum -a "state=present name=openssl"


下面的概念摘自:http://guoting.blog.51cto.com/8886857/1553446          

三、YAML语言介绍

1、YAML简介

   YAML是一个可读性高的用来表达资料序列的格式。YAML参考了其他多种语言包括XML、C语言、Python、Perl以及电子邮件格式RFC2822等。Clark Evans在2001年在首次发表了这种语言另外Ingy dtNet与Oren Ben-Kiki也是这语言的共同设计者。 YAML Ain't Markup Language即YAML不是XML。不过在开发的这种语言时YAML的意思其实是"Yet Another Markup Language"仍是一种标记语言。其特性 

  • YAML的可读性好 

  • YAML和脚本语言的交互性好 

  • YAML使用实现语言的数据类型 

  • YAML有一个一致的信息模型 

  • YAML易于实现 

  • YAML可以基于流来处理 

  • YAML表达能力强扩展性好


2、YAML语法及playbooks简单应用举例

   YAML的语法和其他高阶语言类似,并且可以简单表达清单、散列表、标量等数据结构。其结构(Structure)通过空格来展示,序列(Sequence)里的项用"-"来代表,Map里的键值对用":"分隔。 playbook是由一个或多个“play”组成的列表。play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的task定义好的角色。从根本上来讲,所谓task无非是调用ansible的一个module。将多个play组织在一个playbook中,即可以让它们联同起来按事先编排的机制同唱一台大戏。下面是一个简单示例。

- hosts: webservers
   vars:
     http_port: 80
     max_clients: 256
   remote_user: root
   tasks:
   - name: ensure apache is at the latest version
     yum: name=httpd state=present
   - name: ensure apache is running
     service: name=httpd state=started
   handlers:
     - name: restart apache
       service: name=httpd state=restarted

YAML文件扩展名通常为.yaml,如example.yaml。


3、playbook基础组件

  • Hosts和Users 

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

  -hosts: webservers
   remote_user: root

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

  - hosts: webservers
    remote_user: test
    tasks:
      - name: test connection
        ping:
        remote_user: test
        sudo: yes
  • 任务列表和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
  • 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


4、ymal中的变量

  • 变量命名 :变量名仅能由字母、数字和下划线组成且只能以字母开头。 

  • facts :facts是由正在通信的远程目标主机发回的信息这些信息被保存在ansible变量中。要获取指定的远程主机所支持的所有facts可使用如下命令进行 

# ansible hostname -m setup 这个命令可以获得被监控端主机的各种信息将这些信息得到后保存到变量中。
  • 自定义变量 :在 yaml 中可以使用vars关键字来定义变量 

vars:
  var_name: value
  • 变量的引用 :{{ var_name }} 

  • 特殊的变量迭代: 当有需要重复性执行的任务时可以使用迭代机制。其使用格式为将需要迭代的内容定义为item变量引用并通过with_items语句来指明迭代的元素列表即可。 

 

示例 :例如在被控端添加 2 个用户 

方式1一般做法

- name: add user testuser1
  user: name=testuser1 state=present groups=wheel
- name: add user testuser2
  user: name=testuser2 state=present groups=wheel

方式2使用变量方式

- name: add several users
  vars:
   user1: testuser1
   user2: testuser2
  user: name={{ user1 }} state=present groups=wheel
  user: name={{ user2 }} state=present groups=wheel

方式3使用迭代方式

- name: add several users
  user: name={{ item }} state=present groups=wheel
  with_items:    
    - testuser1    
    - testuser2
事实上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' }


5、Inentory文件的格式
   inventory文件遵循INI文件风格中括号中的字符为组名。可以将同一个主机同时归并到多个不同的组中此外当如若目标主机使用了非默认的SSH端口还可以在主机名称之后使用冒号加端口号来标明。

[webservers]
www1.magedu.com:2222
www2.magedu.com
[dbservers]
db1.magedu.com
db2.magedu.com
db3.magedu.com

如果主机名称遵循相似的命名模式还可以使用列表的方式标识各主机例如

[webservers]
www[01:50].example.com
[databases]
db-[a:f].example.com

主机变量 :可以在inventory中定义主机时为其添加主机变量以便于在playbook中使用。例如 

[webservers]
www1.magedu.com http_port=80 maxRequestsPerChild=808
www2.magedu.com http_port=303 maxRequestsPerChild=909

组变量 :组变量是指赋予给指定组内所有主机上的在playbook中可用的变量。例如 

[webservers]
www1.magedu.com
www2.magedu.com
 
[webservers:vars]
ntp_server=ntp.magedu.com
nfs_server=nfs.magedu.com

组嵌套 :inventory中组还可以包含其它的组并且也可以向组中的主机指定变量。不过这些变量只能在ansible-playbook中使用而ansible不支持。例如 

[apache]
httpd1.magedu.com
httpd2.magedu.com
 
[nginx]
ngx1.magedu.com
ngx2.magedu.com
 
[webservers:children]
apache
nginx
 
[webservers:vars]
ntp_server=ntp.magedu.com

inventory参数 :ansible基于ssh连接inventory中指定的远程主机时还可以通过参数指定其交互方式常用的参数如下所示 

  • ansible_ssh_host  # 要连接的主机名 

  • ansible_ssh_port  # 端口号默认是22 

  • ansible_ssh_user  # ssh连接时默认使用的用户名 

  • ansible_ssh_pass  # ssh连接时的密码 

  • ansible_sudo_pass # 使用sudo连接用户是的密码 

  • ansible_ssh_private_key_file # 秘钥文件如果不想使用ssh-agent管理时可以使用此选项 

  • ansible_shell_type # shell的类型默认sh 

ansible的循环机制还有更多的高级功能具体请参见官方文档http://docs.ansible.com/playbooks_loops.html。


6、playbooks
   playbook是由一个或多个“play”组成的列表。play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的task定义好的角色。 从根本上来讲所谓task无非是调用ansible的一个module。将多个play组织在一个playbook中即可以让它们联同起来按事先编排的机制同唱一台大戏。下面列举下playbook基础组件 : 

  • Hosts和Users   

playbook中的每一个play的目的都是为了让某个或某些主机以某个指定的用户身份执行任务。

hosts用于指定要执行指定任务的主机其可以是一个或多个由冒号分隔主机组。

remote_user则用于指定远程主机上的执行任务的用户。

不过remote_user也可用于各task中。也可以通过指定其通过sudo的方式在远程主机上执行任务其可用于play全局或某任务。 

此外甚至可以在sudo时使用sudo_user指定sudo时切换的用户。

- hosts: webnodes
  remote_user: mageedu
  tasks:
  - name: test connection   ping:
    remote_user: mageedu    sudo: yes
  • 任务列表和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
  • 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


7、tags

   tags用于让用户选择运行或路过playbook中的部分代码。ansible具有幂等性因此会自动跳过没有变化的部分即便如此有些代码为测试其确实没有发生变化的时间依然会非常地长。此时如果确信其没有变化就可以通过tags跳过此些代码片断。 示例基于playbooks实现web服务的部署 

  • 提供好Inventory文件 

# /etc/ansible/hosts基于秘钥认证
[webhosts]
172.16.10.22
172.16.10.33
  • 编辑 palybooks 剧本 

# vim  /root/web.yaml
- name: web service
  remote_user: root
  hosts: webhosts
  vars:
    packages: httpd
  tasks:
    - name: install httpd      yum: name={{ packages }} state=present
      tags: install
    - name: configuration httpd
      copy: src=/root/httpd.conf dest=/etc/httpd/conf/httpd.conf
      tags: conf
      notify:
        - restart httpd
    - name: service httpd start
      service: name=httpd enabled=no state=started
      tags: start
    - name: add centos and hadoop user
      user: name={{ item }} state=absent
      tags: adduser
      with_items:
        - centos
        - hadoop
  handlers:
        - name: restart httpd
          service: name=httpd state=restarted
  • 准备好配置文件 

 将web的配置放到指定目录 src=/root/httpd.conf

  • 开始部署 

# ansible-playbooks /root/web.yml

yaml脚本应用举例:

[root@Director ~]# cat httpd.yaml 
- hosts: all
  remote_user: root
  tasks:
    - name: install httpd
      yum: state=latest name=httpd
    - name: httpd configure file
      copy: src=/root/httpd.conf dest=/etc/httpd/conf/httpd.conf force=yes
      notify:
        - restart httpd
  handlers:
    - name: restart httpd
      service: name=httpd state=restarted
[root@Director ~]# ansible-playbook httpd.yaml 

PLAY [all] ******************************************************************** 

GATHERING FACTS *************************************************************** 
ok: [node3]
ok: [node2]
ok: [node1]

TASK: [install httpd] ********************************************************* 
changed: [node3]
changed: [node2]
changed: [node1]

TASK: [httpd configure file] ************************************************** 
changed: [node3]
changed: [node1]
changed: [node2]

NOTIFIED: [restart httpd] ***************************************************** 
changed: [node3]
changed: [node1]
changed: [node2]

PLAY RECAP ******************************************************************** 
node1                      : ok=4    changed=3    unreachable=0    failed=0   
node2                      : ok=4    changed=3    unreachable=0    failed=0   
node3                      : ok=4    changed=3    unreachable=0    failed=0   
[root@Director ~]# ansible all -m shell -a "ss -tunl | grep 8080"
node3 | success | rc=0 >>
tcp    LISTEN     0      128                   :::8080                 :::* 

node2 | success | rc=0 >>
tcp    LISTEN     0      128                   :::8080                 :::*     

node1 | success | rc=0 >>
tcp    LISTEN     0      128                   :::8080                 :::*


你可能感兴趣的:(ansible)