核心组件:

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]


-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和下面