ansible自动化批量部署工具

Ansible简介

ansible是一个自动化批量部署工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。
ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。

Ansible基于Python开发,底层拥有python三大模块 :

paramiko
jinja2
yaml

1.总体构架

ansible自动化批量部署工具_第1张图片

Ansible:Ansible的核心程序
Host Lnventory:记录了每一个由Ansible管理的主机信息,信息包括ssh端口,root账号密码,ip地址等等。可以通过file来加载,可以通过CMDB加载
Playbooks:yaml格式文件,多个任务定义在一个文件中,使用时可以统一调用,“剧本”用来定义那些主机需要调用那些模块来完成的功能。
Core Modules:Ansible执行任何管理任务都不是由Ansible自己完成,而是由核心模块完成;Ansible管理主机之前,先调用core Modules中的模块,然后指明管理Host Lnventory中的主机,就可以完成管理主机。
Custom Modules:自定义模块,完成Ansible核心模块无法完成的功能,此模块支持任何语言编写。
Cinnection Plugins:连接插件,Ansible和Host通信使用

2.工作原理:

ansible加载hosts文件,通过免秘钥或配置文件参数来批量管理主机
agent:ansibel不需要客户端或agent(代理)

3.Ansible优点:

  1. Stupied Simple,上手简单,学习曲线平滑
  2. SSH by default,安全,无需安装客户端
  3. 配置简单、功能强大、扩展性强
  4. 支持API及自定义模块。可通过Python轻松扩展
  5. 通过Playbooks来定制强大的配置、状态管理
  6. 提供一个功能强大、操作性强的Web管理界面和REST API接口——AWX平台
  7. 幂等性:一种操作重复多次结果相同

4.ansible安装

yum install epel-release -y
yum install ansible -y

5.ansible server管理客户端的两种配置方法

ansible server :192.168.30.30
受管理的客户端1:192.68.30.149
受管理的客户端2:192.68.30.150

第一种方法:
ansible server :ssh-keygen

[root@c1 ~]# ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): id_rsa.pub
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in id_rsa.pub.
Your public key has been saved in id_rsa.pub.pub.
The key fingerprint is:
SHA256:8E0RUOqcAZCmrA0eyOaa9O8rLbyAe2IpfPv8R8xvIL0 root@c1
The key's randomart image is:
+---[RSA 2048]----+
|    .o. .o+.     |
|    o  . . .     |
|o. o  . o .      |
|o+o    = =       |
|++.     S .      |
|o+.    . *       |
|=o+ .   o +      |
|==o*..   E o     |
|+o.oO*o.. .      |
+----[SHA256]-----+

scp id_rsa.pub root@client ip:/root/.ssh/authorized_keys

[root@c1 ~]# scp /root/.ssh/id_rsa.pub [email protected]:/root/.ssh/authorized_keys 
[email protected]'s password: 
id_rsa.pub                                              100%  389   411.2KB/s   00:00
[root@c1 ~]# scp /root/.ssh/id_rsa.pub [email protected]:/root/.ssh/authorized_keys 
[email protected]'s password: 
id_rsa.pub                                              100%  389    11.2KB/s   00:00 

ansible配置

[root@c1 ~]# vim /etc/ansible/ansible.cfg
......
remote_port    = 22          #ssh端口号默认22,如果改的话ssh配置的端口号也得改
......
private_key_file = /root/.ssh/id_rsa    #私钥文件路径
......

配置受管理的客户端组

[root@c1 ~]# vim /etc/ansible/hosts
......
#在最后添加
[testhosts]
192.168.30.149    
192.168.30.151

ansible连通性测试:

[root@c1 ~]# ansible testhosts -m ping
192.168.30.149 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
192.168.30.151 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}

执行命令测试:

[root@c1 ~]# ansible testhosts -m command -a 'uptime'

注意:第一次执行,需要输入yes来验证公钥,后续无需再输入
再次执行

[root@c1 ~]# ansible testhosts -m command -a 'uptime'
192.168.30.151 | CHANGED | rc=0 >>
 15:44:34 up 32 min,  3 users,  load average: 0.00, 0.01, 0.05

192.168.30.149 | CHANGED | rc=0 >>
 15:44:34 up  4:00,  4 users,  load average: 0.00, 0.01, 0.05

第二种方法:
vim /etc/ansible/hosts
ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass=root

在hosts文件的末尾添加
[testhosts]
192.168.30.149 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass=root
192.168.30.151 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass=root

保存退出进行ansible连通性测试

[root@c1 ~]# ansible testhosts -m ping
192.168.30.149 | FAILED! => {
    "msg": "Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this.  Please add this host's fingerprint to your known_hosts file to manage this host."
}
192.168.30.151 | FAILED! => {
    "msg": "Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this.  Please add this host's fingerprint to your known_hosts file to manage this host."

出现上面问题是因为启用了主机密钥检查,所以我们可以修改/etc/ansible/ansible.cfg配置文件来跳过这个检查

[root@c1 ~]# vim /etc/ansible/ansible.cfg
host_key_checking = False   #默认是注释的,打开注释即可

保存退出再测试结果正常:

[root@c1 ~]# ansible testhosts -m ping
192.168.30.151 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
192.168.30.149 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}

6.ansible常用命令

ansible-doc -l  #查看支持的模块
ansible-doc -s MODEL_NAME #查看模块用法
ansible命令应用基础
ansible  [options]
-f fork:启动并发 线程数
-m model_name:要使用的模块
-a args:特有的参数

ansible all -m ping  #查看client端是否正常ping通
ansible webserver -m setup  #查看客户端信息
ansible webserver -m copy -a 'src=/root/git_test/code.txt  dest=/root/test'  #copy文件到client端
ansible webserver -m user -a "name=test state=present" #创建test用户
ansible webserver -m user -a "name=test state=absent"  #删除test用户
ansible webserver -m yum -a 'name=epel-relese state=latest'   #yum安装
ansible webserver -m systemd -a 'name=httpd state=stopped enabled=no'    #停止httpd服务
ansible webserver -m script -a '/tmp/test,sh'    #运行脚本
ansible webserver -m command 'date'    #查看时间

7.playbooks:

一个任务代表一个play,多个play组合成叫做playbooks
一个yaml或yml文件就是一个playbooks

yaml介绍
yaml是一个可读性高的用来表达资料序列的格式,yaml参考了其他多种语言,包括:xml,c语言,python,perl以及电子邮件格式RFC2822等,ClarkEvans在2001年在首次发表了这种语言。

yaml的可读性好
yaml和脚本语言的交互性好
yaml使用实现语言的数据类型
yaml有一个一致的信息模型
yaml易于实现
yaml可以基于流程来处理
yaml表达能力强,扩展性好

ansible执行yaml/yml文件格式:

ansible-playbook *.yml/*.yaml

例1:playbook基础语法比较严格

    - hosts: testhosts      #声明主机组
      remote_user: root     #声明以谁的身份执行
      tasks:                #任务组
      - name: yum remove nginx     #任务名
        yum: name=nginx state=absent    #模块:用法
      - name: yum install httpd
        yum: name=httpd state=latest
      - name: systemctl start httpd
        systemd: name=httpd state=started
[root@c1 ~]# ansible-playbook test.yml

PLAY [testhosts] ***********************************************************************

TASK [Gathering Facts] *****************************************************************
ok: [192.168.30.151]
ok: [192.168.30.149]

TASK [yum remove nginx] ****************************************************************
changed: [192.168.30.151]
changed: [192.168.30.149]

TASK [yum install httpd] ***************************************************************
changed: [192.168.30.151]
changed: [192.168.30.149]

TASK [systemctl start httpd] ***********************************************************
changed: [192.168.30.151]
changed: [192.168.30.149]

PLAY RECAP *****************************************************************************
192.168.30.149             : ok=4    changed=3    unreachable=0    failed=0   
192.168.30.151             : ok=4    changed=3    unreachable=0    failed=0 

例2:有变量的playbook

- hosts: testhosts
  remote_user: root
  vars:
  - packages: tree
  tasks:
  - name: yum install tree
    yum: name={{ packages }} state=latest
  - name: yum install httpd
    yum: name=httpd state=latest
  - name: systemctl start httpd
    systemd: name=httpd state=started


[root@c1 ~]# ansible-playbook test.yml

PLAY [testhosts] ***********************************************************************

TASK [Gathering Facts] *****************************************************************
ok: [192.168.30.151]
ok: [192.168.30.149]

TASK [yum install tree] ****************************************************************
changed: [192.168.30.151]
changed: [192.168.30.149]

TASK [yum install httpd] ***************************************************************
ok: [192.168.30.151]
ok: [192.168.30.149]

TASK [systemctl start httpd] ***********************************************************
ok: [192.168.30.151]
ok: [192.168.30.149]

PLAY RECAP *****************************************************************************
192.168.30.149             : ok=4    changed=1    unreachable=0    failed=0   
192.168.30.151             : ok=4    changed=1    unreachable=0    failed=0

已经执行过的任务再次执行显示ok,这就是幂等性:一种操作重复多次结果相同

例3:迭代

- hosts: testhosts
  remote_user: root
  vars:
  - packages: tree
  tasks:
  - name: yum install tree
    yum: name={{ packages }} state=latest
  - name: yum install httpd
    yum: name=httpd state=latest
  - name: create many user
    user: name={{ item }}
    with_items:
    - test1
    - test2
    - test3

[root@c1 ~]# ansible-playbook test.yml

PLAY [testhosts] ***********************************************************************

TASK [Gathering Facts] *****************************************************************
ok: [192.168.30.149]
ok: [192.168.30.151]

TASK [yum install tree] ****************************************************************
ok: [192.168.30.151]
ok: [192.168.30.149]

TASK [yum install httpd] ***************************************************************
ok: [192.168.30.151]
ok: [192.168.30.149]

TASK [create many user] ****************************************************************
changed: [192.168.30.151] => (item=test1)
changed: [192.168.30.149] => (item=test1)
changed: [192.168.30.151] => (item=test2)
changed: [192.168.30.149] => (item=test2)
changed: [192.168.30.151] => (item=test3)
changed: [192.168.30.149] => (item=test3)

PLAY RECAP *****************************************************************************
192.168.30.149             : ok=4    changed=1    unreachable=0    failed=0   
192.168.30.151             : ok=4    changed=1    unreachable=0    failed=0

例4:触发器notify

- hosts: testhosts
  remote_user: root
  vars:
  - packages: tree
  tasks:
  - name: yum install tree
    yum: name={{ packages }} state=latest
  - name: create many user
    user: name={{ item }}
    with_items:
    - test1
    - test2
    - test3
  - name: cp testcp.txt
    copy: src=/root/testcp.txt dest=/root/
    notify:
    - restart httpd
  handlers:
  - name: restart httpd
    systemd: name=httpd state=restarted

[root@c1 ~]# ansible-playbook test.yml

PLAY [testhosts] ***********************************************************************

TASK [Gathering Facts] *****************************************************************
ok: [192.168.30.151]
ok: [192.168.30.149]

TASK [yum install tree] ****************************************************************
ok: [192.168.30.151]
ok: [192.168.30.149]

TASK [create many user] ****************************************************************
ok: [192.168.30.149] => (item=test1)
ok: [192.168.30.151] => (item=test1)
ok: [192.168.30.151] => (item=test2)
ok: [192.168.30.149] => (item=test2)
ok: [192.168.30.149] => (item=test3)
ok: [192.168.30.151] => (item=test3)

TASK [cp testcp.txt] *******************************************************************
changed: [192.168.30.149]
changed: [192.168.30.151]

RUNNING HANDLER [restart httpd] ********************************************************
changed: [192.168.30.151]
changed: [192.168.30.149]

PLAY RECAP *****************************************************************************
192.168.30.149             : ok=5    changed=2    unreachable=0    failed=0   
192.168.30.151             : ok=5    changed=2    unreachable=0    failed=0

template:模板

  1. 在yml文件里调用template模块
  2. 把要拷贝的文件里面的参数改成变量
  3. 在/etc/ansible/hosts里添加变量

例5:模板templates

- hosts: testhosts
  remote_user: root
  vars:
  - packages: tree
  tasks:
  - name: yum install tree
    yum: name={{ packages }} state=latest
  - name: create many user
    user: name={{ item }}
    with_items:
    - test1
    - test2
    - test3
  - name: cp httpd.conf
    template: src=/etc/httpd/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
    notify:
    - restart httpd
  handlers:
  - name: restart httpd
    systemd: name=httpd state=restarted

将ansible server端的httpd.conf配置文件LISTEN监听端口改为{{ port }}保存

......
Listen {{ port }}
......

修改ansible的hosts文件为主机组的主机添加变量

[testhosts]
192.168.30.149 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass=root port=6500
192.168.30.151 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass=root port=6600


[root@c1 ~]# ansible-playbook test.yml 

PLAY [testhosts] ***********************************************************************

TASK [Gathering Facts] *****************************************************************
ok: [192.168.30.151]
ok: [192.168.30.149]

TASK [yum install tree] ****************************************************************
ok: [192.168.30.151]
ok: [192.168.30.149]

TASK [create many user] ****************************************************************
ok: [192.168.30.151] => (item=test1)
ok: [192.168.30.149] => (item=test1)
ok: [192.168.30.151] => (item=test2)
ok: [192.168.30.149] => (item=test2)
ok: [192.168.30.151] => (item=test3)
ok: [192.168.30.149] => (item=test3)

TASK [cp httpd.conf] *******************************************************************
changed: [192.168.30.151]
changed: [192.168.30.149]

RUNNING HANDLER [restart httpd] ********************************************************
changed: [192.168.30.151]
changed: [192.168.30.149]

PLAY RECAP *****************************************************************************
192.168.30.149             : ok=5    changed=2    unreachable=0    failed=0   
192.168.30.151             : ok=5    changed=2    unreachable=0    failed=0  

执行完毕之后查看客户端所有启用的端口号发现149客户端端口6500已启用,151客户端6600已启用

8.roles介绍

有这样的情景:有三台需要管理的主机安装了不同的软件httpd、php、mysql,现又有一台主机要安装httpd和php,如果再新定义playbook就会重复之前的代码比较麻烦,这时就要用到roles,创建后利于模块化调用,多次调用。
把每个play封装到角色里,调用时只需添加角色就行

hosts: 后可添加主机组,ip或多个ip

hosts: host1
role:
- webserver

hosts: host2
role:
- phpserver

hosts: host3
role:
-dbserver

hosts: host4
role:
-webserver
-phpserver

创建roles及角色目录

[root@c1 ~]# mkdir -pv ansible_playbooks/roles/{webserver,phpserver}/{files,handlers,tasks,templates,vars}
mkdir: 已创建目录 "ansible_playbooks"
mkdir: 已创建目录 "ansible_playbooks/roles"
mkdir: 已创建目录 "ansible_playbooks/roles/webserver"
mkdir: 已创建目录 "ansible_playbooks/roles/webserver/files"
mkdir: 已创建目录 "ansible_playbooks/roles/webserver/handlers"
mkdir: 已创建目录 "ansible_playbooks/roles/webserver/tasks"
mkdir: 已创建目录 "ansible_playbooks/roles/webserver/templates"
mkdir: 已创建目录 "ansible_playbooks/roles/webserver/vars"
mkdir: 已创建目录 "ansible_playbooks/roles/phpserver"
mkdir: 已创建目录 "ansible_playbooks/roles/phpserver/files"
mkdir: 已创建目录 "ansible_playbooks/roles/phpserver/handlers"
mkdir: 已创建目录 "ansible_playbooks/roles/phpserver/tasks"
mkdir: 已创建目录 "ansible_playbooks/roles/phpserver/templates"
mkdir: 已创建目录 "ansible_playbooks/roles/phpserver/vars"

ansible自动化批量部署工具_第2张图片
ansible自动化批量部署工具_第3张图片

用roles将testhosts主机组中主机配置相同的httpd服务
(1)配置roles同级yml文件,命名的名字一定为site.yml

- hosts: testhosts
  remote_user: root
  roles:
  - webserver

(2)配置角色webserver
将httpd配置文件拷贝到files目录下,用files目录下的文件配置出的主机是一样的,如果用templates模板,修改监听端口号5000

[root@c1 ~]# cp /etc/httpd/conf/httpd.conf playbooks/roles/webserver/files/

(3)创建tasks的main.yml(文件名必须为main,后缀可以是yaml,yml)文件并编辑如下内容

[root@c1 ~]# vim playbooks/roles/webserver/tasks/main.yml
- name: yum install httpd
  yum: name=httpd state=latest
- name: copy httpd conf
  copy: src=httpd.conf dest=/etc/httpd/conf/httpd.conf
  notify:
  - start httpd

上述程序添加了notify触发器需要在handlers下编写触发操作写在main.yml中

[root@c1 ~]# vim playbooks/roles/webserver/handlers/main.yml
- name: start httpd
  systemd: name=httpd state=started

(4)在roles同级目录里运行:

[root@c1 playbooks]# ansible-playbook site.yml 

PLAY [testhosts] ***************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.30.151]
ok: [192.168.30.149]

TASK [webserver : yum install httpd] *******************************************
changed: [192.168.30.149]
changed: [192.168.30.151]

TASK [webserver : copy httpd conf] *********************************************
changed: [192.168.30.149]
changed: [192.168.30.151]

RUNNING HANDLER [webserver : start httpd] **************************************
changed: [192.168.30.151]
changed: [192.168.30.149]

PLAY RECAP *********************************************************************
192.168.30.149             : ok=4    changed=3    unreachable=0    failed=0   
192.168.30.151             : ok=4    changed=3    unreachable=0    failed=0 

在客户端看服务端口号已启动都为5000

配置不同端口的httpd服务就用到templates

(1)将httpd配置文件拷贝到templates目录下并将httpd的端口号改为如下格式的变量

......
Listen {{ port }}
......

(2)修改ansible的hosts文件为主机组的主机添加变量

[testhosts]
192.168.30.149 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass=root port=6500
192.168.30.151 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass=root port=6600

(3)在roles同级目录执行site.yml

[root@c1 playbooks]# ansible-playbook site.yml 

PLAY [testhosts] ***************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.30.151]
ok: [192.168.30.149]

TASK [webserver : yum install httpd] *******************************************
changed: [192.168.30.149]
changed: [192.168.30.151]

TASK [webserver : copy httpd conf] *********************************************
changed: [192.168.30.149]
changed: [192.168.30.151]

RUNNING HANDLER [webserver : start httpd] **************************************
changed: [192.168.30.151]
changed: [192.168.30.149]

PLAY RECAP *********************************************************************
192.168.30.149             : ok=4    changed=3    unreachable=0    failed=0   
192.168.30.151             : ok=4    changed=3    unreachable=0    failed=0

执行完毕之后查看客户端所有启用的端口号发现149客户端端口6500已启用,151客户端6600已启用

你可能感兴趣的:(Ansible)