核心组件:

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 <host-pattern> [-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和下面