ansible入门,使用ansible-playbook,通过剧本批量管理(二)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/ck784101777/article/details/102619042

[ansible入门一]https://blog.csdn.net/ck784101777/article/details/102593155

一、ansible的七种武器

1.第一种武器 ansible

ansible命令,用于执行临时性工作,必须掌握

2.第二种武器 ansible-doc

ansible-doc是ansible模块的文档说明,针对每个模块都有详细的说明及应用案例介绍,功能和Linux系统man命令类似

3.第三种武器 ansible-console

ansible-console是ansible为用户提供的交互式工具,用户可以再ansible-console虚拟出来的终端上像用Sheel一样使用ansible内置命令.这为习惯使用shell交互式的用户提供了体验

4.第四种武器 ansbile-galaxy

ansbile-galaxy从github上下载管理Roles的一款工具,与python的pip类似

5.第五种武器 ansible-playbook

ansible-playbook是日常应用中使用频率最高的命令,工作机制是通过读取先编写好的playbook文件实现批量管理,可以理解为按一定条件组成的ansible任务集

6.第六种武器 ansible-valut

ansible-valut主要用于配置文件加密,如编写的playbook文件中包含敏感信息,不能随意让人查看,可以通过ansible-vault加密次文件

7.第7种武器 ansbile-pull/push

ansbile-pull,ansible有两种工作模式pull/push,默认使用push模式工作,pull和push工作模式机制刚好相反.push将命令推送至远程,pull从远程加载命令

适用与大批量机器需要配置,即使使用高并发线程仍旧需要花费很多时间,其效率几乎可以无限提升,对运维人员技术水平和前瞻性规划有较高要求

本章重点将ansible-playbook这一用法

 

二、ansible-playbook

学习anisble-playbook分为以下步骤:

了解playbook是什么->了解playbook的语法格式(了解yaml,playbook由yaml语言编写)->了解playbook的语法中play的构成->能看懂playbook的执行结果(了解JSON,显示结果以JSON输出)

1.playbook是什么

 playbook是ansbile用于配置,部署和管理托管主机的剧本,通过playbook的详细描述,执行其中的一些列tasks,可以让远端主机达到预期状态,也就是说,playbook字母字母意思即剧本,现实中由演员按剧本表演,在ansible中由计算机进行安装,部署应用提过对外服务,以及组织计算机处理各种各样的事

2.为什么使用playbook

 批量处理机器的常规操作是写一个循环脚本,通过ssh远程执行操作,常规的方式首先是脚本与客户机耦合性高,如果托管机ip变动还要修改脚本.而playbook可以反复使用编写好的代码,且仅放在管理机上.playbook像函数一样,最大化的利用代码,在使用ansible的过程中,处理的大部分操作都是在别写playbook

 而且anible提供了大量的模块,都可以在playbook中使用

3.playbook的语法格式

-playbook由YAML语言编写,遵循YAML标准

-在同一行中,#之后的内容表示注释

-同一个列表中的元素应该保持相同的缩进

-playbook由一个或多个play组成

-play包含hosts,variables,roles,tasks等对象,其表示方法都是键值中间以":"分隔表示

-YAML还有一个小的怪癖,它的文件开始必须写---,这是YAML格式的一部分,表明一个文件的开始,如同shell的#!/bin/bash

3.5YAML语言(补充)

YAML基础语法:

-YAML的结构通过空格来展示

-数组使用'-'表示

-键值对通过':'表示

-使用缩进表示数据层级结构关系

-一般每个缩进由两个以上空格组成(非必须,但是不要使用tab,且保证至少有一个空格的缩进)

-#表示注释

例子:

键值对:  "名字":"流的华"

或 "名字":

    "流的华"

数组: "名字":

       -"流的华"

       -"锅富成"

       -"章学游"

以上三个值都隶属于'名字'这个键

4.play的构成

-hosts:定义将要执行playbook的远程主机组

-remote_user:定义使用什么用户执行命令(一般是root)

-vars:定义playbook运行时需要使用的变量

-tasks:定义将要在远程主机上执行的任务列表

-handlers:定义task执行完成后需要调用的任务

5.playbook执行结果

-使用ansible-playbook运行playbook文件,输出内容为JSON格式,由不同颜色组成便于识别

-绿色代表执行成功

-黄色也是执行成功,一般是文件被改动后显示黄色,并显示change:ture

-红色代表执行失败

-***代表系统状态发生改变

5.5.JSON(补充)

-Json是JavaScript对象表示法,它是一种基于文本独立与语言的轻量级数据交换格式

-JSON中的分隔符限于单引号"'",小括号"()",中括号"[]",大括号"{}",冒号":"和逗号""

-JSON是纯文本语言,具备自我描述性(人类可读)和层级结构(支持值中值),不具备逻辑性(无逻辑编程语句),可通过JavaScript进行解析

格式:

键值对: {"名字":"流的华"}

数组:{"名字":["流的华","章学油"]}

数组(值中值,嵌套):  {"名字":[{"流的华":"长的帅","年龄":20}

                    {"章学油":"唱的好","年龄":21}

                   ]  

              }

规则:

-无论是数组还是单个键值对,都必须加"{}"

-数组,确定一个键名,值必须要用"[]"扩起来

-数组支持值中值模式,即定义了一个键,键里面仍然可以创建键值对,要求每一对键值对用"{}"扩起

-数字型不需要双引号扩扩起来

三、ansible-play案例

编写一个ansible-play剧本需要以下步骤:

定义组->创建并编写playbook剧本-->执行剧本

接下来我会举出若干个例子,在每个例子中你都会看到一些模块和play动作的具体使用方式

1.案例1-批量创建用户

要求:为所有主机添加用户zhangsan,设置密码123

1)创建组

在上一节我讲述了aansible配置文件查找顺序以及管理机分发证书文件,看不懂的请回顾上一篇文章(开头有连接)         

  1. [root@ansible ansible] cd /etc/ansible
  2. [root@ansible ansible] mkdir myansible
  3. [root@ansible ansible] vim myhosts
  4. [web]
  5. web1
  6. web2
  7. [all:vars]
  8. ansible_ssh_private_key_file="/root/.ssh/id_rsa"

2)编写playbook剧本

.yml文件必须严格遵守yaml格式,上节有讲.遵守层级规矩,相同层对齐,子层保证缩进至少一个空格,"-"和":"后要打一个空格,然后才能写值

执行playbook剧本的格式:ansible-playbook *.yml

这里有一个细节,那就是user模块的password参数,是不是看不懂?看不懂就对了,常规的创建密码命令应该是:echo 123 | passwd --stdin zhangsan(我完全可以用shell模块执行这条命令),而这里我用到了一个变量过滤器,事实上如果你使用常规的方式,ansible的shell模块会将password直接写入shadow,并没有用密码占位符,由于用户登录需要将密码加密之后核对,但是此时用于核对的密码是没有经过加密的,那么问题就来了,这肯定就对不上了,所以你无法登录

如下:

所以你需要用到变量过滤器(Linux采用sha512加密):

password_hash

格式{{'urpassword' | password_hash('sha512')}}

  1. [root@ansible ansible] vim createUsers.yml
  2. ---
    - hosts: web
      remote_user: root
      tasks:
        - user:
            name: zhangsan
            password: "{{'123456' | password_hash('sha512')}}"  
  3. [root@ansible ansible]# ansible-playbook createUsers.yml          
  4. PLAY [web] ******************************************************************
  5. TASK [Gathering Facts] ********************************************************
  6. ok: [web]
  7. TASK [create user zhangsan] ***********************************************
  8. changed: [web]
  9. TASK [command] ****************************************************************
  10. changed: [web]
  11. PLAY RECAP ********************************************************************
  12. cache : ok=4 changed=2 unreachable=0 failed=0

2.案例2-批量创建用户进阶,使用变量

案例1创建用户有一个局限性,就是一个脚本只能创建一个用户,下次要创建不同的用户只能修改脚本,用户和脚本的耦合性比较高,我们可以使用变量来解放这种耦合.以下提供四种方式来使用变量

首先我们要修改一下脚本,我们通过"{{key}}"来使用变量,双括号中放的是键名

---
- hosts: web
  remote_user: root
  tasks:
    - user:
        name: "{{user}}"
        password: "{{'123456' | password_hash('sha512')}}"

1)直接输入变量(外部)

格式:ansible-playbook *.yml -e "键=值"

ansible-playbook userCreate.yml -e "user=lisi"
 

2)引用json变量(外部)

首先要创建一个json文件,在里面写下数据

vim user.json

{"user":"zhangsan"} 

格式:ansible-playbook *.yml -e "@*.json"            #引用的时候前面要加一个@,别问为什么,规矩

ansible-playbook userCreate.yml -e "@user.json"

3)引用yml变量(外部)

首先要创建一个yml文件,在里面写下数据

vim user.yml

---

user: zhangsan 

格式:ansible-playbook *.yml -e "@*.yml"            #引用的时候前面要加一个@,别问为什么,规矩

ansible-playbook userCreate.yml -e "@user.yml"

4)使用脚本内置变量(内置)

 使用vars:

           键:值

---
- hosts: web
  remote_user: root
  vars :
    user: zhaoqiang
  tasks:
    - user:
        name: "{{user}}"
        password: "{{'123456' | password_hash('sha512')}}"

3.案例3-批量安装Apache服务

要求:用playbook安装Apache,修改端口,配置ServerName,修改主页,设置开机自启

组我就不定义了,参考案例1

1)编写playbook剧本

关于ansible模块的使用我在上一篇文章有描述,文章开头有链接

这里主要用到yum模块,lineinfile模块,copy模块和service模块

步骤:

1_安装apache

2_将apache的端口修改为8080,采用lineinfile模块

3_启动服务

4_将本地的index.html拷贝到每台托管机中

5_测试

  1. [root@ansible ansible]# echo "hello world" > index.html
  2. [root@ansible ansible]# vim http.yml
  3. ---
  4. - hosts: cache
  5.   remote_user: root
  6.   tasks:
  7.      - name: install one specific version of Apache
  8.        yum:
  9.           name: httpd                          //安装Apache
  10.           state: installed
  11.      - lineinfile:
  12.           path: /etc/httpd/conf/httpd.conf
  13.           regexp: '^Listen '
  14.           line: 'Listen 8080'                 //修改端口为8080
  15.      - service:
  16.           name: httpd
  17.           enabled: yes                    //开机自启
  18.           state: restarted
  19.      - copy:
  20.           src: /root/index.html        //修改主页,可以自己写个页面
  21.           dest: /var/www/html/index.html
  22. [root@ansible ansible]# ansible-playbook http.yml
  23. [root@ansible ansible]# curl 192.168.1.45:8080           //测试
  24. hello world

4.案例4-忽视报错,继续执行脚本

 ansible-playbook的对执行过程中报错的常规处理是停止执行脚本,但是很多情况我们不想让其停止执行,比如我们创建一个文件,如果该文件存在,那么这种时候ansible-playbook也会停止执行,可是我们不希望在这里停止执行,因为其对最终结果不会造成影响(如果文件本来就存在,那么即使我们不执行创建命令也会存在这个文件,所以整个过程的结果都是一样的,这就是程序的幂等性

想要脚本不中断执行很简单,只需要加入一条参数即可

ignoring_errors:True

我们创建一个用户并把它加入一个并不存在的组,这里会报错,我们忽视错误,可以看到忽视错误,脚本还将继续执行

---
- hosts: web
  remote_user: root
  tasks:
    - user:
        name: "{{user}}"

     group: abc
        password: "{{'123456' | password_hash('sha512')}}"

        ignoring_errors:True

...........

fatal: [web1]: FAILED! => {"changed": false, "msg": "Group iwq does not exist"}
...ignoring
 

对于何时该使用ignoring_errors:True是操作者需要加强锻炼的,一般需要有前瞻性,知道哪会出错,且这种错误不会在根本上影响最终结果.加强锻炼吧,萌新

5.案例5,重启apache服务,触发条件:配置文件被修改

 案例说明:我们在编写playbook剧本时,有的部分不一定需要每次都执行,我们可以给它写一个触发条件,即当触发了某个条件后才执行这一部分.如我们在批量修改apache配置文件时,将原端口80改为8080,而有些主机已经是8080了,那我们就不需要重启这台主机的服务.

 本例需要用到notify这个动作,notify可由于每个play的最后触发,copy有自检功能,它会比对你的文件与目标主机的文件,如果两者一样则不替换,如果内容不一致则将其替换,并且给出change提示.而notify会将change作为触发条件,选择是否执行.如果显示change,则调用接下来的handler动作,handler将执行定义好的的操作

执行顺序:

文件内容是否发生改变?

-没有改变,不触犯动作

-改变,nofity被触发,执行handle

本例采用copy模块,也可以使用lineinfile模块按行修改.如果使用copy你需要在管理主机上准备相应的文件

  1. [root@ansible ansible]# vim handers.yml
  2. ---
  3. - hosts: web
  4.   remote_user: root
  5.   tasks:
  6.     - copy:
  7.         src: httpd.conf
  8.         dest:  /etc/httpd/conf/httpd.conf
  9.         owner: apache
  10.         group: apache
  11.         mode: 0644
  12.       notify:
  13.         - restart httpd
  14.   handlers:
  15.     - name: restart httpd
  16.       service:
  17.           name: httpd
  18.           state: restarted

第一次执行,触发动作

第二次执行,不触犯动作

6.案例6,把系统负载太高的Apache服务停止

案例描述:使用uptime命令查看实时负载,当1分钟负载大于0.7的web服务器停掉

 uptime         #分别为1分钟负载,5分钟,10分钟
 15:22:02 up  3:38,  1 user,  load average: 0.48, 0.16, 0.09

本例要学习几个陌生的模块

register模块用来保存前一个命令的返回状态,可以在之后进行调用

格式:register: 键名

调用: 键名.stdout   (stdout标准化输出)

when模块用于在满足指定条件后触发一项操作

格式: when 条件

  1. [root@ansible ansible]# vim when.yml
  2. ---
  3. - hosts: web
  4.   remote_user: root
  5.   tasks:
  6.     - shell: uptime | awk '{printf("%.2f\n",$(NF-2))}'                  #NF从后面数,$.2f 占位符
  7.       register: result
  8.     - service:
  9.         name: httpd
  10.         state: stopped
  11.       when: result.stdout|float > 0.7          

#|float将标准化输出作为浮点数,因为register默认保存的是字符串,而字符串不能比较大小

使用awk 'BEGIN{while(1){}}'制造死循环增加负载

可以用watch -n 1 'uptime' 实时监控uptime的负载

7.案例7,一次性创建多个用户

本例需要用到with_items模块,用过item调用变量值

  1. ---
  2. - hosts: web
  3.   remote_user: root
  4.   tasks:
  5.     - user:
  6.         name: "{{item}}"
  7.         password: "{{'123456' | password_hash('sha512')}}"
  8.       with_items: ["wyf1","wyf2","wyf3","wyf4"]
     

进阶用法:with_items数组 

引用方式item.键名

  1. ---   
    - hosts: web2
      remote_user: root
      tasks:
        - name: add users
          user: 
            name: {{item.name}}
            group: {{item.group}}  
            password: {{'123456' | password_hash('sha512')}}
          with_items:
            - {name: 'nb',  group: 'root'}
            - {name: 'dd',  group: 'root'}
            - {name: 'plj', group: 'wheel'}
            - {name: 'lx',  group: 'wheel'                    

8.案例8,组合playbook

  在编写playbook的时候随着项目越来越大,playbook越来越复杂。可以把一些play、task 或 handler放到其他文件中,通过包含进来是一个不错的选择

本例需要学习include模块,它可以引入一个项目的文件和目录

格式: include: 文件路径

  1. ...
  2. tasks:
  3. - include: tasks/users.yml               #导入变量,可以通过{{ user }}来使用这些变量
  4. - include: tasks/useradd.yml                      #导入添加用户模块
  5. handlers:
  6. - include: handlers/handlers.yml    #导入handles条件触发的执行模块

9. 

猜你喜欢

转载自blog.csdn.net/ck784101777/article/details/102619042