Ansible-playbook

假如我们现在要部署nginx代理服务器或者图片服务器,把nginx服务启动起来需要几步呢?

  1. 安装nginx程序包
  2. 通常默认配置文件是不够用的,我们还需要做好一个模板,给它复制配置文件,有可能配置文件还不只有一个
  3. 启动服务并且设置为开机自启
  4. 用命令设置好以后,nginx坏了一台,要重新把它拿回来,还需要重新从头到尾去设定一下这个命令到底当时用的什么,

因此我们应该把它定义成playbook,我们让ansible基于palybook(剧本)当中所定义的内容(一出出唱下来)执行即可,只要把playbook保存好,可以随时使用。所以我们接下来说一下怎么把上述所定义的内容给他保存在playbook中,使用一个配置文件,然后让ansible-playbook来自动完成上述所指的一步步操作。这里我们就需要用到yaml格式的配置文件。

 

1、Playbook:yaml格式(docker、ansible用的都是yaml格式)

        1)Yaml:YAML 语言(发音 /ˈjæməl/ 尾音类似于camel骆驼)是一个可读性高,用来表达数据系列的格式。Yaml参考了其他多种语言,包括C语言、python、perl,并从XML,电子邮件的数据格式(RPC 2822)中获得灵感。Clark  Evans在2001首次发表了这种语言,另外Ingy Dot Net和Oren Ben-Kiki也是这种语言的共同设计者,目前已经有数种编程语言或脚本语言支持(或者解析)这种语言。

          2)YAML是“Ain't Markup Language,” (即YAML不是XML。不是一种标记语言)的递归缩写。不过,在开发的这种语言时,YAML的意思其实是:"Yet Another Markup Language"(仍是一种标记语言)。但为了强调这种语言以数据作为中心,而不是以标记语言为重点,而用反向缩略语重命名。

          3)Yaml的语言和其他高级语言类似。并且可以简单表达清单、散列表、标量等数据形态,它使用空白符号缩进使用缩进表示层级关系缩进时不允许使用Tab键,只允许使用空格缩进的空格数目不重要,只要相同层级的元素左侧对齐即可和大量依赖外观的特色,特别适合用来表达编辑数据结构、各种配置文件、倾印除错内容、文件大纲(例如:许多电子邮件标题格式和YAML非常接近),yaml文件以"---"作为文档的开始,"..."作为文档的结束。

 

2、Yaml 支持的数据格式有三种:标量、数组、关联数组

对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字(dictionary)
数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)
纯量(scalars):单个的、不可再分的值

Ansible的playbook在执行某个任务时,也使用yaml来表达或者表现它的各种元素,对playbook来讲,我们需要表达的核心单元包含以下几项

 

3、Playbook的核心元素:

     Host:指明需要执行这个playbook的主机(这出戏,应该有哪几个演员来唱)

     Tasks:指明任务列表(有几个任务,都是什么,playbook的核心(有哪几出戏,每出戏都唱什么,列出来))

     Variables:定义playbook时,之所以把yaml叫语言,是因为他支持变量(当一个对应的数据可能被使用多次,而且将来有可能会发生修改,我们使用变量来一次性表示,而后修改变量值,让所有引用变量的地方都能够做出同时修改来实现以后简化配置的有效手段)

      templates:包含了模板语言的文本文件(类似于php)

      Handlers:由特定条件触发的任务(处理器就是task,但是它需要特定条件触发(处理器就是task,就是要唱的每一出戏,但是处理器跟每一出的唱法不同,他需要条件式触发,每一出戏,轮到你,该你唱你就要唱,但处理器是指只有特定条件满足时,才会唱的戏。如:我们通过一出戏已经唱完了,唱完以后,过一会儿,我们把nginx配置文件改了,改完以后,是启动nginx么?你发现在创建也没用,因为它已经改动了,服务已经启动了,在创建一变,只会不一样的配置文件复制过去,但不会重启,因为它一看nginx是启动的,他就不会在启动了。所以这个时候,如果是某一个被监控的资源状态发生改变,它可以当做条件去触发其他资源,刷新。而handler就是被监控的资源,触发实践的时候,通知我,我在去执行,如果没通知,就不需要))


我们写入代码,使用shell脚本,写shell脚本的过程当中,如果有一段代码可以被重复,可能被多次执行到,我们最好把它定义成函数,用到哪,就调用到哪,这样可以实现模块化编程,就叫结构化编程,代码模块比较清晰,这样我们改的时候,也只需要改被调用的部分。那如果我们不做这种结构化编程,就是所有的代码用的时候,都写一遍,无论是改,或者其他的操作,都会很麻烦,对我们的ansible-playbook也是一样的道理,因此,如果某个playbook可能会被多次用到(如;我们现在有两组nginx服务器,应该有三组需要安装,第一个组是调度器,第二组是Tomcat的每一个主机前端的单击的反向代理,第三组图片服务器,这三组nginx的配置都不同,如果我们为三组主机各自定义playbook时,你会发现,安装这个包、启动服务都要写三遍,这样很麻烦,代码无法通用,其实无非就是安装nginx配置文件、启动服务么。那么我们可以不可以安装服务、启动服务都一样呢?不同配置文件时,我们给调节时,它复制不同的配置文件就好了 。就是把安装和启动服务的功能复用,这是一种思路;那么还有一种(比较好理解的),我们现在只有三台服务器,需要装八个应用程序,A服务器需要安装1、2、3、4,B服务器需要装3、4、5、6,C服务器需要装5、6、7、8,我们会发现要安装第3、4应用程序时,A服务器和B服务器都需要安装,我们必须分开定义两个playbook才可以,因为第一个playbook是1、2、3、4,第二个playbook是3、4、5、6,这样分开我们就会比较麻烦的是3、4要写两遍,如果要写到一块也是不行,因为它们本身还有不一样的地方,那这个时候我们应该把每一个应用程序的安装、部署、启动功能做到一块,做成单独的功能模块,谁装这个应用程序和启动服务的话,直接调用这个模块就行,而这个就叫角色(roles)

 

4、一般来讲,playbook的基础组件有:

    1)Hosts:运行指定的目标主机(定义playbook需要指明,有哪几出戏需要谁来唱)

    Remote_user:在远程主机上执行任务的用户(唱戏的时候,有哪些用户的身份来唱)

   Sudo_user:(可以用管理员的身份来做,也可以用普通用户的身份来做,但是遇到管理权限时,需要sudo)

   2)Tasks:任务列表(有哪几出戏唱呢)

而制定每个任务的格式有两种:

(1)action(指明行为) :module(模块名) arguments(传递给模块的参数)

(2)module(直接制定模块): arguments(模块的各参数)

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

举例:我们在如果期望每一节点上,创建组叫memcached,创建用户叫memcached或者,在这个三个节点都安装memcached,提供安装memcached的配置文件,并启动memcached,这三个任务,由此,我们简单做个设定,定义一个playbook,只需要哪几个节点运行的时候,我们就要写明host为哪几个节点。

 

注:一个“剧本”当中可能为“n出戏”,指明要唱的内容,所以host应该是一个列表

Ansible-playbook_第1张图片

注:在写playbook的时候,一定要记住在 hosts,yum(模块儿名)等后带空格,否则会报错。

(1) 测试

ansible-playbook --check :只检测可能会发生的改变,但不真正执行操作;

Ansible-playbook_第2张图片

注:TASK [Gathering Facts] :收集facts(如果需要用到模板的话,如果需要模板主机应用模板的话,那也就意味着,我们需要收集目标主机的主机名、ip地址,以便套用在模板中,所以为了实现这个功能,每一次在任何一个主机上,执行任务之前,都要先把这个主机的各类各样的信息给他收集过来,收集过来我们才能往模板中用,就算没有模板,也需要要收集,我们无法判定哪次用哪次不用,所以收集这个功能是任何一主机必然要做的)

把配置文件里面hosts改为all

Ansible-playbook_第3张图片

 

它的执行方式:从输出结果中,不是在一个主机上执行完所有任务,再去执行另外一个主机,而是在所有主机上执行第一个任务,都完了以后,再在所有主机上执行第二个任务,以此类推。(其中任何一个步骤出现故障,那么它都会停下来,这样所有主机都没有完成(都出现故障停止))

ansible-playbook --list-hosts :列出运行任务的主机

Ansible-playbook_第4张图片

ansible-playbook --list-tasks:列出要运行的任务列表

 

Ansible-playbook --syntax--check:语法检查

(1)执行

Ansible-playbook memcached.yaml

Ansible-playbook_第5张图片

验证:在node2节点验证

Ansible-playbook_第6张图片

3)Handlers:由特定条件触发的任务,接收到其它任务的通知时被触发; notify: HANDLER TASK NAME

举例:我们去更新一下memcached的配置文件,编辑复制以后的V2的配置文件,这次我们让这个配置文件里面再多一个任务,除了安装程序包,启动服务以外,中间加一步复制配置文件。

Ansible-playbook_第7张图片Ansible-playbook_第8张图片

 

 

编辑 memcached-v2.yaml 配置文件

Ansible-playbook_第9张图片

 

现在的情况是,通过上面的执行的,第一个和第三个任务已经执行完了 ,第二个任务还没有执行过,而且配置文件的原名目标发生了改变,所以第二个文件会被复制过去

Ansible-playbook_第10张图片

我们可以看到第一个和第三个任务,都是OK,但是第二个任务不满足条件,所以它是会改变这个文件内容的,无论你改了多少次,都不会导致第三个任务重启或者重新执行。所以它的监听端口是不会改变的。

验证:

Ansible-playbook_第11张图片

Ansible-playbook_第12张图片

 

为了使每一次配置文件发生修改以后,都能去重启触发memcached,这里我们就需要用到notify: HANDLER TASK NAME(先重新定义配置文件,假设他要触发重启,就需要给别人发通知(重启任务的通知) notify: 'restart memcached service')

那么问题是“restart memcached service”是什么呢?它是需要我们在配置文件里面额外定义的,也就是playbook的另外一个组件handlers。在handlers,我们去定义一个新的handler,那么name那里必须与notify这个名字保持一致,别人通知它,就相当于通知这个处理器了,notify就是调用一个处理器的名字说,如果这个文件发生改变,那么就触发这个handlers去执行一变。那这个handler要做的就是重启服务了。

Ansible-playbook_第13张图片

 

修改完配置文件以后,可以检查一下语法,现在改一下模板,我们在复制一次他是没有任何改变的,我们必须要有一定的改变,以便触发执行。

Ansible-playbook_第14张图片

检测一下它是否发生了改变:

Ansible-playbook_第15张图片

Ansible-playbook_第16张图片

验证:可以知道它的监听端口发生了改变 

Ansible-playbook_第17张图片

4)variables:在playbook当中还可以使用变量,在playbook中可用的变量有两种:(11:48)

(1) facts:可直接调用; (没一个节点它的属性或者环境信息,包括像操作系统版本、操作系统名称、以及网络接口、ip地址主机名称、内存大小、cpu核心数等都称为facts,它们是系统环境的“事实”,那么这些环境设定的数据都可以被在模块中或者yaml中直接调用)

注意:可使用setup模块直接获取目标主机的facters;

补充模块:setup模块:

Ansible 192.168.171.151 -m setup |less 分页查看收集到的facts信息(比如有:这个节点ipv4、ipv6的地址;系统平台架构;当前系统BIOS的日期与版本;ansible自己的命令行用的什么组件(可以理解为这个不是ansible的command,而是启用系统操作时传递给内核的参数)等)

Ansible-playbook_第18张图片

(2) 用户自定义变量的方式 

(a) ansible-playbook命令的命令行中的

-e VARS, (每一个‘-e’引用一个变量,所以‘-e’可以使用多次)--extra-vars=VARS

(b) 在playbook中定义变量的方法:

vars:

- var1: value1

- var2: value2

 

变量引用:{{ variable }}(花括号两次要用空格)

举例:我们安装一个程序包,但是并不确定安装哪个程序包,希望它可以不停的被复用,在这里我们用名称来引用变量值(vars、变量名:pkgname、安装的程序包:tree)

Ansible-playbook_第19张图片

Ansible-playbook_第20张图片

以httpd服务为例:

Ansible-playbook_第21张图片

Ansible-playbook_第22张图片

这就是变量,上述我们用的是自定义变量,我们在check时,使用-e 定义“pkgname=nginx”,我们就会发现它安装的nginx,所以在命令行中可以直接传变量,它比在playbook中的优先级要高.

Ansible-playbook_第23张图片

传递变量:

(3) 通过roles传递变量;

(4) Host Inventory

举例:以分组的方式定义主机:

Ansible-playbook_第24张图片

验证:

Ansible-playbook_第25张图片

一个主机可以出现多次,使用ansible all时命令,主机不会重复出现,每一个主机只会出现一次。

Ansible-playbook_第26张图片

(a) 用户自定义变量

(i) 向不同的主机传递不同的变量; IP/HOSTNAME varaiable=value var2=value2

(ii) 向组中的主机传递相同的变量;

[groupname:vars]

variable=value

(b) invertory参数

用于定义ansible远程连接目标主机时使用的参数,而非传递给playbook的变量;

使用这些来指联系每一个主机时,使用的账号和密码。

Ansible主机连接每一个被管理的主机时,要使用ssh连接,所以我们必须事先做好基于密钥的认证,这样就避免了,每一次连接时,都输入密码。那如果我们不做基于密钥的认证,就可以使用下面的方式。在每一个主机背后,直接指明在连接某一台主机时的用什么账号,用什么密码、哪个端口。(注:很多时候为了安全,我们通常会把SSH服务器的端口修改)

注:https://blog.csdn.net/sl_qcy/article/details/107721908(该链接中有相关实验)

ansible_ssh_host

ansible_ssh_port

ansible_ssh_user

ansible_ssh_pass

ansbile_sudo_pass

举例:

Ansible-playbook_第27张图片

Ansible-playbook_第28张图片

 

 

你可能感兴趣的:(ansible)