自动化运维工具——ansible(中)

1.Ansible playbook 简介

playbook 是 ansible 用于配置,部署,和管理被控节点的剧本。 通过 playbook 的详细描述,执行其中的一系列 tasks ,可以让远端主机达到预期的状态。playbook 就像 Ansible 控制器给被控节点列出的的一系列 to-do-list ,而被控节点必须要完成。 也可以这么理解,playbook 字面意思,即剧本,现实中由演员按照剧本表演,在Ansible中,这次由计算机进行表演,由计算机安装,部署应用,提供对外服务,以及组织计算机处理各种各样的事情。

2.Ansible playbook使用场景

执行一些简单的任务,使用ad-hoc命令可以方便的解决问题,但是有时一个设施过于复杂,需要大量的操作时候,执行的ad-hoc命令是不适合的,这时最好使用playbook。 就像执行shell命令与写shell脚本一样, 也可以理解为批处理任务,不过playbook有自己的语法格式。 使用playbook你可以方便的重用这些代码,可以移植到不同的机器上面,像函数一样,最大化的利用代码。在你使用Ansible的过程中,你也会发现,你所处理的大部分操作都是编写playbook。可以把常见的应用都编写成playbook,之后管理服务器会变得十分简单。

3.Ansible playbook格式

3.1格式简介

playbook由YMAL语言编写。YAML( /ˈjæməl/ )参考了其他多种语言,包括:XML、C语言、Python、Perl以及电子邮件格式RFC2822,Clark Evans在2001年5月在首次发表了这种语言,另外Ingy döt Net与OrenBen-Kiki也是这语言的共同设计者。 YMAL格式是类似于JSON的文件格式,便于人理解和阅读,同时便于书写。首先学习了解一下YMAL的格式,对我们后面书写playbook很有帮助。

以下为playbook常用到的YMAL格式:

1、文件的第一行应该以 "---" (三个连字符)开始,表明YMAL文件的开始。

2、在同一行中,#之后的内容表示注释,类似于shell,python和ruby。

3、YMAL中的列表元素以”-”开头然后紧跟着一个空格,后面为元素内容。

4、同一个列表中的元素应该保持相同的缩进。否则会被当做错误处理。

5、play中hosts,variables,roles,tasks等对象的表示方法都是键值中间以":"分隔表示,":"后面还要增加一个空格。

下面是一个举例:

---
- hosts: web
  remote_user: root
  tasks:  
    - name: install nginx.repo
      copy: src=/etc/yum.repos.d/nginx.repo dest=/etc/yum.repos.d/nginx.repo
      
    - name: install nginx
      yum: name=nginx state=present
      
    - name: start nginx
      service: name=nginx state=started

我们的文件名称应该以.yml结尾,像我们上面的例子就是nginx.yml。其中,有三个部分组成:

host部分:使用 hosts 指示使用哪个主机或主机组来运行下面的 tasks ,每个 playbook 都必须指定 hosts ,hosts也可以使用通配符格式。主机或主机组在 inventory 清单中指定,可以使用系统默认的/etc/ansible/hosts,也可以自己编辑,在运行的时候加上-i选项,指定清单的位置即可。在运行清单文件的时候,–list-hosts选项会显示那些主机将会参与执行 task 的过程中。

remote_user:指定远端主机中的哪个用户来登录远端系统,在远端系统执行 task 的用户,可以任意指定,也可以使用 sudo,但是用户必须要有执行相应 task 的权限。

tasks:指定远端主机将要执行的一系列动作。tasks 的核心为 ansible 的模块,前面已经提到模块的用法。tasks 包含 name 和要执行的模块,name 是可选的,只是为了便于用户阅读,不过还是建议加上去,模块是必须的,同时也要给予模块相应的参数。

使用ansible-playbook运行playbook文件,得到如下输出信息,输出内容为JSON格式。并且由不同颜色组成,便于识别。一般而言 | 绿色代表执行成功,系统保持原样 | 黄色代表系统代表系统状态发生改变 | 红色代表执行失败,显示错误输出 执行有三个步骤:1、收集facts 2、执行tasks 3、报告结果

3.2核心元素

playbook的核心元素:

Hosts:主机组; Tasks:任务列表; Variables:变量,设置方式有四种; Templates:包含了模板语法的文本文件; Handlers:由特定条件触发的任务;

一般会先执行task,收到notify后执行handlers

3.3基本组件

playbook配置文件的基础组件:

Hosts:运行指定任务的目标主机

remote_user:在远程主机上执行任务的用户;

sudo_user:

tasks:任务列表

模块,模块参数:

格式:

(1) action: module arguments

(2) module: arguments

注意:shell和command模块后面直接跟命令,而非key=value类的参数列表;

handlers:任务,在特定条件下触发;接收到其它任务的通知时被触发;

(1) 某任务的状态在运行后为changed时,可通过“notify”通知给相应的handlers;

(2) 任务可以通过“tags“打标签,而后可在ansible-playbook命令上使用-t指定进行调用;

举例:

① 定义playbook

[root@ansible ~]# cat test2.yml 
---
- hosts: web
  remote_user: root
  tasks:
    - name: copy configure
      copy: src=/root/default.conf dest=/etc/nginx/conf.d/default.conf backup=yes
      notify: reload   #当nginx.conf发生改变时,通知给相应的handlers
      tags: reloadnginx  #打标签
   
    - name: start nginx service
      service: name=nginx state=started
      tags: startnginx
 
  handlers:   #注意,前面没有-,是两个空格
    - name: reload
      service: name=nginx state=restarted   #为了在进程中能看出来

运行前三部曲

检查错误

ansible-playbook nginx.yml --syntax-check

列出所有任务

ansible-playbook nginx.yml --list-task

列出在那些机器执行

ansible-playbook nginx.yml --list-hosts

运行

ansible-playbook nginx.yml

② 测试运行结果 写完了以后,我们就可以运行了

[root@ansible ~]# ansible-playbook test2.yml

PLAY [web] ***************************************************************************

TASK [Gathering Facts] ***************************************************************
ok: [webserver1]
ok: [webserver2]

TASK [copy configure] ****************************************************************
ok: [webserver2]
ok: [webserver1]

PLAY RECAP ***************************************************************************
webserver1                 : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
webserver2                 : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

看看两台机器的端口是否开启:
[root@ansible ~]# ansible web -m shell -a 'ss -nutlp |grep nginx'

③ 测试标签 我们在里面已经打上了一个标签,所以可以直接引用标签。但是我们需要先把服务关闭,再来运行剧本并引用标签:(执行标签的内容)

先将nginx关闭,然后来测试一下标签
[root@ansible ~]# ansible web -m service -a 'name=nginx state=stopped'

[root@ansible ~]# ansible-playbook test2.yml -t startnginx

PLAY [web] ***************************************************************************

TASK [Gathering Facts] ***************************************************************
ok: [webserver1]
ok: [webserver2]

TASK [start nginx service] ***********************************************************
changed: [webserver1]
changed: [webserver2]

PLAY RECAP ***************************************************************************
webserver1                 : ok=2    changed=1    unreachable=0    failed=0    skipped
webserver2                 : ok=2    changed=1    unreachable=0    failed=0    skipped

[root@ansible ~]# ansible web -m shell -a 'ss -nplt | grep nginx'

④ 测试notify 我们还做了一个notify(类似触发器),来测试一下: 首先,它的触发条件是配置文件被改变,所以我们去把配置文件中的端口改一下:

[root@server ~]# vim default.conf
    listen       88;

然后我们重新加载一下这个剧本:

[root@ansible ~]# ansible-playbook test2.yml -t reloadnginx

发现我们执行的就是reload段以及我们定义的notify部分。 我们来看一看我们的端口号:

[root@ansible ~]# ansible web -m shell -a 'ss -nplt | grep nginx'
webserver1 | CHANGED | rc=0 >>
LISTEN     0      128          *:88                       *:*                   users:(("nginx",pid=4078,fd=6),("nginx",pid=4077,fd=6))
webserver2 | CHANGED | rc=0 >>
LISTEN     0      128          *:88                       *:*                   users:(("nginx",pid=4284,fd=6),("nginx",pid=4283,fd=6))

可以看出,我们的nginx端口已经变成了88.

3.4variables部分

上文中,我们说到了variables是变量,有四种定义方 法,现在我们就来说说这四种定义方法:

① facts :可直接调用

上一篇中,我们有说到setup这个模块,这个模块就是通过调用facts组件来实现的。我们这里的variables也可以直接调用facts组件。 具体的facters我们可以使用setup模块来获取,然后直接放入我们的剧本中调用即可。

ansible_all_ipv4_addresses:仅显示ipv4的信息 ---> [u'192.168.95.143']

ansible_eth0['ipv4']['address']:仅显示ipv4的信息 ---> eth0 的ip地址

ansible_devices:仅显示磁盘设备信息

ansible_distribution:显示是什么系统,例:centos,suse等

ansible_distribution_version:仅显示系统版本

ansible_machine:显示系统类型,例:32位,还是64位

ansible_eth0:仅显示eth0的信息

ansible_hostname:仅显示主机名

ansible_kernel:仅显示内核版本

ansible_lvm:显示lvm相关信息

ansible_memtotal_mb:显示系统总内存

ansible_memfree_mb:显示可用系统内存

ansible_memory_mb:详细显示内存情况

ansible_swaptotal_mb:显示总的swap内存

ansible_swapfree_mb:显示swap内存的可用内存

ansible_mounts:显示系统磁盘挂载情况

ansible_processor:显示cpu个数(具体显示每个cpu的型号)

ansible_processor_vcpus:显示cpu个数(只显示总的个数)

ansible_python_version:显示python版本

例如:批量修改主机 host 文件

[root@ansible ~]# cat cphosts.yml 
---
- hosts: web
  vars:
    IP: "{{ ansible_ens33['ipv4']['address'] }}"
  tasks: 
    - name: cp old hosts
      shell: mv /etc/hosts /etc/hosts.bak

    - name: cp ansible to other server
      copy: src=/root/hosts dest=/etc owner=root group=root mode=0644

    - name: 在新的hosts文件后面追加各自机器内网ip和hostname
      lineinfile: dest=/etc/hosts line="{{ IP }} {{ ansible_hostname }}"

[root@ansible ~]# ansible-playbook cphosts.yml --syntax-check

playbook: cphosts.yml


[root@ansible ~]# ansible-playbook cphosts.yml

PLAY [web] ***************************************************************************

TASK [Gathering Facts] ***************************************************************
ok: [webserver1]
ok: [webserver2]

TASK [cp old hosts] ******************************************************************
changed: [webserver1]
changed: [webserver2]

TASK [cp ansible to other server] ****************************************************
changed: [webserver1]
changed: [webserver2]

TASK [在新的hosts文件后面追加各自机器内网ip和hostname] ***********************************************
ok: [webserver1]
ok: [webserver2]

PLAY RECAP ***************************************************************************
webserver1                 : ok=4    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
webserver2                 : ok=4    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
② 用户自定义变量

我们也可以直接使用用户自定义变量,想要自定义变量有以下两种方式:

通过命令行传入:ansible-playbook命令的命令行中的-e VARS, --extra-vars=VARS,这样就可以直接把自定义的变量传入。

在playbook中定义变量:我们也可以直接在playbook中定义我们的变量:

vars:

  - var1: value1

  - var2: value2

举例

① 定义剧本 我们就使用全局替换把我们刚刚编辑的文件修改一下:

替换后并进行部分修改:

这样一来,我们的剧本就定义完成了。

② 拷贝配置文件 我们想要在被监管的机器上安装什么服务的话,就直接在我们的server端上把该服务的配置文件拷贝到我们的/root/目录下。这样我们的剧本才能正常运行。 我们就以keepalived服务为例:

[root@ansible ~]# cp /etc/keepalived/keepalived.conf  .
[root@ansible ~]# ll
总用量 32
-rw-------. 1 root root 1244 10月 19 09:03 anaconda-ks.cfg
-rw-r--r--. 1 root root    0 10月 19 16:52 a.txt
-rw-r--r--. 1 root root  411 11月 10 20:11 cphosts.yml
-rw-r--r--. 1 root root 1072 11月 10 19:17 default.conf
-rw-r--r--. 1 root root  233 11月 10 20:11 hosts
-rw-r--r--. 1 root root 3598 11月 10 20:26 keepalived.conf
-rw-rw-rw-. 1 root root 1116 10月 13 17:34 my_system_initialize_1.sh
-rw-r--r--. 1 root root  282 11月 10 16:32 test1.yml
-rw-r--r--. 1 root root  423 11月 10 20:22 test2.yml

③ 运行剧本,变量由命令行传入

[root@ansible ~]# ansible-playbook test2.yml --syntax-check

playbook: test2.yml

[root@ansible ~]# ansible-playbook test2.yml -e rpmname=keepalived

PLAY [web] ****************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************
ok: [webserver2]
ok: [webserver1]

TASK [install keepalived] *************************************************************************************************************
ok: [webserver1]
ok: [webserver2]

TASK [copy configure] *****************************************************************************************************************
changed: [webserver1]
changed: [webserver2]

TASK [start keepalived service] *******************************************************************************************************
changed: [webserver1]
changed: [webserver2]

RUNNING HANDLER [reload] **************************************************************************************************************
changed: [webserver2]
changed: [webserver1]

PLAY RECAP ****************************************************************************************************************************
webserver1                 : ok=5    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
webserver2                 : ok=5    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

④ 修改剧本,直接定义变量

同样的,我们可以直接在剧本中把变量定义好,这样就不需要在通过命令行传入了。以后想要安装不同的服务,直接在剧本里把变量修改一下即可。(yum模块修改一下,name={{ rpmname }})

⑤ 运行定义过变量的剧本 我们刚刚已经把变量定义在剧本里面了。现在我们来运行一下试试看:

③ 通过roles传递变量

具体的,我们下文中说到 roles 的时候再详细说明。

④ Host Inventory

我们也可以直接在主机清单中定义。 定义的方法如下:

向不同的主机传递不同的变量:
IP/HOSTNAME varaiable=value var2=value2
向组中的主机传递相同的变量:
[groupname:vars]
variable=value

Ansible Inventory 内置参数

使用内置变量把用户名密码写在Inventory中,也就是/etc/ansible/hosts文件里,缺点就是暴露了账号密码,不安全。如果有多个主机需要使用同样的变量,可以用组变量的形式,书写格式如下:

[web]
192.168.100.10
192.168.100.11
192.168.100.12 
[web:vars]  #给名为webservers的组定义一个变量,:vars是固定格式
ansible_ssh_port=22
ansible_ssh_user='root'
ansible_ssh_pass='1234.com'

3.5模板 templates

模板是一个文本文件,嵌套有脚本(使用模板编程语言编写)。 Jinja2:Jinja2是python的一种模板语言,以Django的模板语言为原本。 模板支持:

字符串:使用单引号或双引号;

  数字:整数,浮点数;

  列表:[item1, item2, ...]

  元组:(item1, item2, ...)

  字典:{key1:value1, key2:value2, ...}

  布尔型:true/false

  算术运算:

    +, -, *, /, //, %, **

  比较操作:

    ==, !=, >, >=, <, <=

  逻辑运算:

    and, or, not

通常来说,模板都是通过引用变量来运用的。

举例

① 定义模板

我们将/root/default.conf改个名,然后编辑一下,就可以定义成我们的模板文件了:

[root@ansible ~]# mv default.conf default.conf.j2

[root@ansible ~]# vim default.conf.j2
    listen       {{ nginxport }};    

② 修改剧本

我们现在需要去修改剧本来定义变量:

需要修改的部分如图所示。

③ 运行剧本 上面的准备工作完成后,我们就可以去运行剧本了:

3.6条件测试

when语句:在task中使用,jinja2的语法格式。 举例如下:

tasks:
  - name: install conf file to centos7
    template: src=files/nginx.conf.c7.j2
    when: ansible_distribution_major_version == "7"
  - name: install conf file to centos6
    template: src=files/nginx.conf.c6.j2
    when: ansible_distribution_major_version == "6"

循环:迭代,需要重复执行的任务; 对迭代项的引用,固定变量名为"item",而后,要在task中使用with_items给定要迭代的元素列表; 举例如下:

tasks:
  - name: unstall web packages
    yum: name={{ item }} state=absent
    with_items:
      - httpd
      - php
      - php-mysql

3.7字典

ansible playbook 还支持字典功能。举例如下:

[root@ansible ~]# cat dir.yml 
---
- hosts: web
  remote_user: root
  tasks: 
    - name: add some groups
      group: name={{ item }} state=present
      with_items:
        - group11
        - group12
        - group13
    - name: add some users
      user: name={{ item.name }} group={{ item.group }} state=present
      with_items: 
        - { name: 'user11', group: 'group11' }
        - { name: 'user12', group: 'group12' }
        - { name: 'user13', group: 'group13' }  

自动化运维工具——ansible是一款开源的IT自动化工具,广泛应用于软件部署、配置管理和任务协同等领域。它的最大特点是简单易用、功能强大且跨平台。 首先,ansible具有简单易用的特点。它使用简单的YAML语言作为配置文件,无需编写复杂的脚本。用户只需要简单地定义主机和操作即可完成任务的执行。这使得即便是非开发人员,也能轻松上手使用ansible进行自动化管理。 其次,ansible功能强大。它支持广泛的操作系统、云平台和网络设备,并提供了丰富的模块化功能。通过在任务使用ansible的模块,我们可以实现系统配置、软件安装、文件传输等各种常见操作。此外,ansible不仅支持并发执行任务,还能够将任务分组执行,并提供了强大的变量和条件控制功能。 再次,ansible跨平台。无论是在Linux、Unix还是Windows系统上,ansible都能够良好地运行。此外,它还支持云平台,如AWS、Azure等,以及网络设备,如Cisco、Juniper等。这使得ansible成为一个非常灵活的自动化运维工具,能够满足各种不同环境和需求的自动化管理。 最后,ansible还具有良好的社区支持。ansible拥有庞大的用户社区和活跃的开发者社区,有大量的文档、示例和插件可供参考和使用。这使得我们在使用ansible时能够获得快速解答和支持,同时也能够从社区学习到更多的技巧和经验。 总而言之,ansible是一款简单易用、功能强大且跨平台的自动化运维工具。它在软件部署、配置管理和任务协同等方面具有广泛的应用,并且得到了良好的社区支持。无论是企业还是个人,都可以通过ansible来提高工作效率和自动化管理水平。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值