简介


        ansible是自动化运维工具,不是一个服务,可同时为多台主机安装软件。ansible不需要安装agent,部署简单,基于现有的ssh服务。是模块化的,调用特定模块,完成特定任务,支持主从模式,支持自定义模块,支持playbook,ansible是用python研发的,依赖两个组件PyYAML,python-paramiko。


安装ansible:

置好epel yum源,然后安装即可:

yum install ansible

/etc/ansible/ansible.cfg        主配置文件

/etc/ansible/hosts                 主机清单

/etc/ansible/roles                  角色配置文件

/usr/bin/ansible                    主程序

/usr/bin/ansible-doc             文档

/usr/bin/ansible-playbook    剧本


去除ssh应答:

vim /etc/ansible/ansible.cfg
host_key_checking=false


配置通信


配置SSH基于密钥方式通讯:

        ansible是基于ssh配置管理、应用部署、任务执行等功能,因此需要配置ansible端基于密钥认证的方式联系各个被管理节点。

生成秘钥对:在管理端上执行如下命令

ssh-keygen -t rsa -P ''

        -p    指定密码,然后会提示秘钥要保存的位置,如果是在家目录下选择默认直接回车即可。这个-P的密码会在第一次使用ansible时提示输入密码。

        生成秘钥对后要将公钥部分放在每一个要被管理的主机相应目录下,包括本主机,使用命令:

ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.96.130

-i    指定公钥文件位置

回车后输入这个主机的密码。

测试是否成功:

ssh 192.168.96.132 'ifconfig'


基于账户密码通讯:

        如果不使用基于秘钥的方式进行通讯还可以在主机列表中定义连接主机的用户和密码。配置方式为打开 /etc/hosts 文件,在里面定义如下格式内容。

[websrvs]
192.168.96.130  ansible_ssh_user=username ansible_ssh_password=password
[sbsrvs]
192.168.96.132  ansible_ssh_user=username ansible_ssh_password=password

每个主机后面都要写账号和密码。

统一配置变量:

[elk]
10.1.55.73
10.1.55.98
10.1.55.106
[elk:vars]
ansible_ssh_user=root
ansible_ssh_port=6033


配置主机清单


配置hosts文件:

使用ansible前要配置主机清单:/etc/ansible/hosts

192.168.96.132
[websrvs]
192.168.96.130
[sbsrvs]
192.168.96.130

主机清单的使用:

指定全部主机 all:

ansible all -m command -a 'ifconfig'

指定组名:

ansible websrvs -m command -a 'ifconfig'

-a    指明要使用的命令以及参数 a = argument

默认模块 -m command 可以省略

ansible all -a 'ifconfig'


ansible使用格式:

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

例:如果执行结果是正确的则会返回绿色字体,否者返回红色字体,默认模块为command可省略。

ansible 192.168.96.132 -m command -a 'ifconfig'
ansible 192.168.96.130 -m command -a 'ifconfig'
ansible all -m command -a 'ifconfig'
ansible all -a 'ifconfig'

        -i      指定主机清单位置。如果不填写主机信息则使用-i 来指定主机的清单。

        -f      为一次性连接几台,如果主机非常多无法同时连接,ansible会自动分批次进行连接,-f就是指定每次连接的个数。

        -m     指定模块,默认为command模块。

        args: key=value,注意:command模块要执行命令无须为key=value格式,而是直接给出要执行的命令即可。

        更多信息使用 man ansible来查看。


ansible-doc文档查看命令:

        使用 ansible-doc 命令可以查看响应模块文档,ansible-doc命令可以使用-h选项来查看这个命令的使用帮助。要查询某个模块的使用方法使用 -s 选项,如想查看command命令的使用方法 ansible-doc -s command 即可看到响应的帮助信息。


使用模块

        ansible有各种各样的模块,使用ansible-doc -s module_name 来查看模块具体的使用方法,可以帮助我们更好的进行操作,如ping模块,ansible all -m ping,-m为指定模块名称。

执行一些命令:

ansible websrvs -a 'wget -O /tmp/xxx.rpm http://xxx.rpm'


常用模块


command模块:

command -a 'COMMAND'

        默认为command模块,command模块要执行命令无须为key=value格式,直接给出要执行的命令即可。


user模块:

user -a 'name= state={present|absent} system= uid='

        user模块用来创建用户,name为必须项,present必须要存在,absent表示必须要删除,-m指定模块名称,system=yes可以创建一个系统用户,即使这个命令再次执行一遍也不会多创建一个账户出来,更多选项可查看帮助。

例:

ansible websrvs -m user -a 'name=username state=present'


group模块:

group -a 'name= gid= state= system='


cron模块:

cron -a 'name= minute= hour= day= month= weekday= job= user= state='

        定时任务模块,name为必须,用来描述这个任务是用来做什么的,其他可以不写,默认为星号 * ,user表示这个任务是给那个用户的,job为要执行的命令本身。

例:

ansible all -m cron -a 'name="sync time from ntpserver" minute="*/10" job="/sbin/ntpdate 192.168.96.132 &> /dev/null"'

这个例子是一个通过ansible同步时间的计划任务,可以使用crontab -l 来查看各个主机的计划任务是否存在。

例二:

ansible uat -m cron -a 'name="clear log" minute="*/30" job="bash /root/bin/clear.sh" state=present'


copy模块:

copy -a 'dest= src= mode= owner= group='

        可以用来分发配置文件,dest为存放配置文件的绝对路径;src为要复制文件的位置,如果是一个目录就会进行递归复制,mode为复制文件的权限。

例:

ansible all -m copy -a 'src=/etc/fstab dest=/tmp/fstab.tmp mode=600'


file模块:

file -a 'path= mode= owner= group= state={directory|link|present|absent} src='

        用来设置文件属性,可以用来创建目录、文件、链接,如果创建链接使用src来指定连接位置,path文件位置。

例:

ansible all -m file -a 'path=/tmp/testdir state=directory'
ansible all -m file -a 'path=/tmp/fstab.link state=link src=/tmp/fstab.tmp'
ansible all -m file -a 'path=/tmp/fstab.link state=absent force=yes'


ping模块:ping 没有参数

ansible all -m ping


yum模块:

yum -a 'name= state={present|latest|absent}'

        latest表示最新版本,name后面为要安装的软件名称,absent卸载。

例:

ansible all -m yum -a 'name=nginx state=latest'


service模块:

service -a 'name= state={started|stopped|restarted} enabled={yes|no}'

        可以用于启动或关闭服务,name为服务名称,enabled是否开机启动

例:

ansible all -m service -a 'name=nginx state=started enabled=yes'


shell模块:

shell -a 'COMMAND'

        可以用来设置账户密码,如果用command命令使用echo输出其实是在当前主机上输出的,而不是在目标主机上输出的。

ansible all -m shell -a 'echo qiyang | passwd --stdin qiyang'


script模块:

script -a '/path/to/script'

        用来执行脚本。

ansible all -m script -a 'test.sh'


setup模块:

setup

        用来收集主机数据,以便根据各个主机的情况来配置,收集来的数据可以在playbooks中直接作为变量使用。

ansible all -m setup


playbooks


        预演脚本,可以将要执行的命令脚本等信息通过一个脚本编排好,然后去执行。脚本的格式如下,后缀名一般为yml,如vim test.yml,运行脚本 ansible-playbook test.yml 格式。

playbook的核心元素:

        tasks:任务

        variables:变量

        templates:模板

        handlers:处理器

        roles:角色

简单示例:

- hosts: websrvs
  remote_user: root
  tasks:
    - name: create nginx group
      group: name=nginx system=yes gid=208

- hosts: dbsrvs
  remote_user: root
  tasks:
  - name: copy file to dbsrvs
    copy: src=/etc/inittab dest=/tmp/inittab.ans

角色:事先预定义好的角色/代码段,需要的时候可以直接应用在某台主机上,可以重复使用类似于函数的概念。


ansible-blaybooks:每个hosts为一个主机任务,所有主机执行完成第一个任务后再去执行第二个任务。

ansible-playbook install-nginx.yml

例1:

- hosts: websrvs # 主机名
  remote_user: root # 用户名
  tasks: # 任务
  - name: create nginx group # 描述
	group: name=nginx system=yes gid=208
  - name: create nginx user
	user: name=nginx uid=208 group=nginx system=yes

- hosts: dbsrvs
  remote_user: root
  tasks:
  - name: copy file to dbsrvs
	copy: src=/etc/inittab dest=/tmp/inittab.ans

例2:安装httpd并复制配置文件和启动服务。

- hosts: websrvs
  remote_user: root
  tasks:
  - name: install httpd
    yum: name=httpd state=latest
  - name: copy configure file for httpd
    copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
  - name: start httpd service
    service: name=httpd state=started enabled=true


handlers:由某事件触发所执行的操作,当配置文件发生改变触发 restart httpd 事件,然后执行下面的handlers任务,注意:事件名称要一样。

例:当配置文件发生改变时会触发事件

- hosts: websrvs
  remote_user: root
  tasks:
  - name: install httpd
    yum: name=httpd state=latest
  - name: copy configure file for httpd
    copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
    notify:
    - restart httpd # 当配置文件发生变化时,则执行名称为“restart httpd”的handles
  - name: start httpd service
    service: name=httpd state=started enabled=true
  handlers: # 执行这一段
  - name: restart httpd
    service: name=httpd state=restarted


使用变量:定义变量使用vars,使用变量要用花括号将变量名括起来。这个变量还可以是ansible中的内置变量,内置变量可以使用setup模块查看到,ansible all -m setup。

- hosts: websrvs
  remote_user: root
  vars:
  - package: httpd # 定义变量
  - service: httpd
  tasks:
  - name: install httpd
    yum: name={{ package }} state=latest # 使用变量
  - name: copy configure file for httpd
    copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
    notify:
    - restart httpd
  - name: start httpd service
    service: name={{ service }} state=started enabled=true # 使用变量
  handlers:
  - name: restart httpd
    service: name=httpd state=restarted


例2:使用内置变量

- hosts: websrvs
  remote_user: root
  tasks:
  - name: copy file
    copy: content={{ ansible_all_ipv4_addresses }} dest=/tmp/ipv4.txt

主机变量:可以在 /etc/ansible/hosts 中定义主机时为其添加主机变量,以便于在playbook中使用。

[websrvs]
192.168.96.130 http_port=80 maxRequestsPerChild=800 # 定义变量
192.168.96.132 http_port=8080 maxRequestsPerChild=900

在playbook中可以直接使用变量。

- hosts: websrvs
  remote_user: root
  tasks:
  - name: copy file
    copy: content={{ http_port }} dest=/tmp/ipv4.txt # 使用变量

组变量:

[websrvs]
192.168.96.130 http_port=80 maxRequestsPerChild=800
192.168.96.132 http_port=8080 maxRequestsPerChild=900
[websrvs:vars]
ntp_server=ntp.scriptjc.com
nfs_server=nfs.scriptjc.com

        定义好后就可以在playbook中使用了{{ ntp_server }}。

inventory参数:

[websrvs]
192.168.96.130 ansible_ssh_user=username ansible_ssh_pass=password


条件测试:条件测试使用when关键字,这里面用到的变量 ansible_default_ipv4.address 在setup模块中可以看到。这个例子中如果when中的条件满足则在这个主机中创建用户。

- hosts: websrvs
  remote_user: root
  vars:
  - username: user1
  tasks:
  - name: create user {{ username }} 
    user: name={{ username }} state=present
    when: ansible_default_ipv4.address == "192.168.96.132"


迭代:

        重复执行某个任务,相当于循环。这个item是固定的,每次执行就会取一个with_items下面的值。如果有多个变量可以使用json格式。

- hosts: websrvs
  tasks:
  - name: add users
    user: name={{ item }} state=present groups=wheel
    with_items:
     - user2
     - user3

多参数循环:

- hosts: websrvs
  tasks:
  - name: create users
    user: name={{ item.name }} state=present groups={{ item.groups }}
    with_items:
    - { name: 'user4', groups: 'wheel' }
    - { name: 'user5', groups: 'root' }

        在with_items下面定义了json格式的数据,这个数据会被每次循环调用一个。引用变量时写上{{ item.xxx }} 即可调用,item格式是固定的。


templates模板:

        可以在某个配置文件中使用变量,灵活定义配置文件。

        1、要使用template功能首先要在 /etc/ansible/hosts 文件中定义如下主机变量:

[websrvs]
192.168.96.132 http_port=80
192.168.96.130 http_port=8080

        2、定义配置文件模板,将配置文件中要动态修改的地方使用 {{ http_port }} 这样的形式修改好后保存即可,会自动替换为各自主机中定义的变量值。

        3、然后编写playbook文件,将写好的配置模板写在src后面。

- hosts: websrvs
  remote_user: root
  vars:
  - package: httpd
  - service: httpd
  tasks:
  - name: install httpd
	yum: name={{ package }} state=latest
  - name: copy configure file for httpd
	template: src=/root/conf/httpd.conf.2 dest=/etc/httpd/conf/httpd.conf
	notify:
	- restart httpd
  - name: start httpd service
	service: name={{ service }} state=started enabled=true
  handlers:
  - name: restart httpd
	service: name=httpd state=restarted


算术运算:

        Jinja 允许你用计算值,jinja是基于python的模板引擎。这在模板中很少用到,但是为了完整性允许其存在。支持下面的 运算符:

        +        把两个对象加到一起。通常对象是素质,但是如果两者是字符串或列表,你可以用这 种方式来衔接它们。无论如何这不是首选的连接字符串的方式!连接字符串见 ~ 运算符。 {{ 1 + 1 }} 等于 2 。

        -         用第一个数减去第二个数。 {{ 3 - 2 }} 等于 1 。

        /         对两个数做除法。返回值会是一个浮点数。 {{ 1 / 2 }} 等于 {{ 0.5 }} 。

        //        对两个数做除法,返回整数商。 {{ 20 // 7 }} 等于 2 。

        %        计算整数除法的余数。 {{ 11 % 7 }} 等于 4 。

        *        用右边的数乘左边的操作数。 {{ 2 * 2 }} 会返回 4 。也可以用于重 复一个字符串多次。 {{ ‘=’ * 80 }} 会打印 80 个等号的横条。

        **       取左操作数的右操作数次幂。 {{ 2**3 }} 会返回 8 。

比较操作符:

        ==    比较两个对象是否相等。

        !=     比较两个对象是否不等。

        >      如果左边大于右边,返回 true 。

        >=    如果左边大于等于右边,返回 true 。

        <      如果左边小于右边,返回 true 。

        <=    如果左边小于等于右边,返回 true 。


逻辑运算符:

        对于 if 语句,在 for 过滤或 if 表达式中,它可以用于联合多个表达式:

        and        如果左操作数和右操作数同为真,返回 true 。

        or           如果左操作数和右操作数有一个为真,返回 true 。

        not         对一个表达式取反(见下)。

        (expr)     表达式组。


tags只运行部分任务:

        tags标签可以让playbook自运行部分的tasks任务,而不会全部运行。

先在playbook中定义tags,如下:

- hosts: websrvs
  remote_user: root
  vars:
  - package: httpd
  - service: httpd
  tasks:
  - name: install httpd
	yum: name={{ package }} state=latest
  - name: copy configure file for httpd
	template: src=/root/conf/httpd.conf.2 dest=/etc/httpd/conf/httpd.conf
	tags: # 定义tags
	- conf
	notify:
	- restart httpd
  - name: start httpd service
	service: name={{ service }} state=started enabled=true
  handlers:
  - name: restart httpd
	service: name=httpd state=restarted

定义好后可以在就可以在命令后面添加 --tags="名称" 运行部分playbook:

ansible-playbook httpd.yml --tags="conf"


roles:

        roles可以重复调用剧本,可以将各个功能分别实现再组合起来,有利于管理和修改。

创建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模块会自动在此目录中寻找Jinja2模板文件;

        handlers目录:此目录中应当包含一个main.yml文件,用于定义此角色用到的各handler;在handler中使用include包含的其它的handler文件也应该位于此目录中;

        vars目录:应当包含一个main.yml文件,用于定义此角色用到的变量;

        meta目录:应当包含一个main.yml文件,用于定义此角色的特殊设定及其依赖关系;ansible 1.3及其以后的版本才支持;

        default目录:为当前角色设定默认变量时使用此目录;应当包含一个main.yml文件。

目录结构:

/root/ansible/
├── roles
│   ├── dbsrvs
│   │   ├── file
│   │   ├── handlers
│   │   ├── meta
│   │   ├── tasks
│   │   ├── template
│   │   └── vars
│   └── websrvs
│       ├── file
│       ├── handlers
│       │   └── main.yml
│       ├── meta
│       │   └── main.yml
│       ├── tasks
│       │   └── main.yml
│       ├── template
│       └── vars
│           └── main.yml
└── site.yml

在site.yml中定义内容如下:

- hosts: 192.168.96.132
  remote_user: root
  roles:
  - websrvs

- hosts: 192.168.96.130
  remote_user: root
  roles:
  - dbsrvs

- hosts: 192.168.96.131
  remote_user: root
  roles:
  - websrvs
  - dbsrvs

在 ansible/websrvs/tasks/main.yml 文件中定义如下内容:这个文件中只定义所有的任务。

- name: install httpd package
  yum: name=httpd
- name: install configuration file
  copy: src=httpd.conf dest=/etc/httpd/conf/httpd.conf
  tags:
  - conf
  notify:
  - restart httpd
- name: start httpd
  service: name=httpd state=started

在 ansible/websrvs/tasks/main.yml 中定义如下内容:这个文件中只定义handlers。

- name: restart httpd
  service: name=httpd state=restarted

执行playbook:在dbsrvs中也同样格式定义内容,定义好后运行site.yml就可以了。


批量复制文件:

- hosts: test
  remote_user: root
  tasks:
  - name: copy file
    copy:
      src: '{{ item.src }}'
      dest: '{{ item.dest }}'
    with_items:
      - { src: './demo.txt', dest: '/root/demo.txt' }
      - { src: '', dest: '' }