Ansible剧本playbooks详解

一、playbook简介

playbook是ansible用于配置,部署和管理托管主机剧本,通过playbook的详细描述,执行其中一系列tasks,playbook字面意思是剧本,现实中由演员按剧本表演,在ansible中由计算机进行安装,部署应用,提供对外服务,以及组织计算机处理各种各样的事情。

ansible使用playbook来管理自动化task,playbook是yaml格式的文件,其基本内容可以认为是多条ansible的ad-hoc的语句组成。我们完成一个任务,例如安装部署一个httpd服务,我们需要多个模块(一个模块也可以称之为task)提供功能来完成。而playbook就是组织多个task的容器,他的实质就是一个文件,是用yaml(Yet Another Markup Language)语言编写的文件,有着特定的组织格式。YAML 是专门用来写配置文件的语言,非常简洁和强大,远比 JSON 格式方便,YAML语法能够简单的表示散列表,字典等数据结构。

playbook命令根据自上而下的顺序依次执行。同时,playbook开创了很多特性,它可以允许你传输某个命令的状态到后面的指令,如你可以从一台机器的文件中抓取内容并附为变量,然后在另一台机器中使用,这使得你可以实现一些复杂的部署机制,这是ansible命令无法实现的。

二、Playbook核心元素 

模块名

注释

Hosts

执行的远程主机列表

Tasks

任务集,即通过 task 调用 ansible 的模板将多个操作组织在一个 playbook 中运行

Variables

内置变量或自定义变量在playbook中调用

Templates

模板,使用模板语法的文件,比如配置文件等

Handlers

处理器,当changed状态条件满足时,(notify)触发执行的操作,和notity结合使用

tags

标签,指定某条任务执行,用于选择运行playbook中的部分代码

Roles

角色

 三、Playbook语法

playbook使用yaml语法格式,后缀可以是yaml,也可以是yml,文件中有多个play,一个play中只能有一个tasks,一个tasks中可以有多个name任务。

  • 在一个playbook文件中,可以连续三个连子号(---)区分多个play。还有选择性的连续三个点好(...)用来表示play的结尾,也可省略
  • 次行开始正常写playbook的内容,一般都会写上描述该playbook的功能
  • 使用#号注释代码
  • 缩进必须统一,不能空格和tab混用
  • 缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行实现的
  • YAML文件内容和Linux系统大小写判断方式保持一致,是区分大小写的,k/v的值均需大小写敏感
  • k/v的值可同行写也可以换行写。同行使用:分隔
  • v可以是个字符串,也可以是一个列表
  • 一个完整的代码块功能需要最少元素包括 name: task

四、playbook 运行方式

ansible-playbook <filename.yml> ... [options]

#检测文件配置
ansible-playbook test.yaml  --syntax-check
#执行文件
ansible-playbook test.yaml
ansible-playbook filename.yml [options]
 
# ssh 连接的用户名
-u REMOTE_USER, --user=REMOTE_USER
 
# ssh登录认证密码
-k, --ask-pass    
 
# sudo 到root用户,相当于Linux系统下的sudo命令
-s, --sudo       
    
# sudo 到对应的用户
-U SUDO_USER, --sudo-user=SUDO_USER   
 
# 用户的密码(—sudo时使用)
-K, --ask-sudo-pass     
 
# ssh 连接超时,默认 10 秒
-T TIMEOUT, --timeout=TIMEOUT
 
# 指定该参数后,执行 playbook 文件不会真正去执行,而是模拟执行一遍,然后输出本次执行会对远程主机造成的修改
-C, --check      
 
# 设置额外的变量如:key=value 形式 或者 YAML or JSON,以空格分隔变量,或用多个-e
-e EXTRA_VARS, --extra-vars=EXTRA_VARS    
 
# 进程并发处理,默认 5
-f FORKS, --forks=FORKS    
 
# 指定 hosts 文件路径,默认 default=/etc/ansible/hosts
-i INVENTORY, --inventory-file=INVENTORY   
 
# 指定一个 pattern,对- hosts:匹配到的主机再过滤一次
-l SUBSET, --limit=SUBSET    
 
# 只打印有哪些主机会执行这个 playbook 文件,不是实际执行该 playbook
--list-hosts  
 
# 列出该 playbook 中会被执行的 task
--list-tasks   
 
# 私钥路径
--private-key=PRIVATE_KEY_FILE   
 
# 同一时间只执行一个 task,每个 task 执行前都会提示确认一遍
--step    
 
# 只检测 playbook 文件语法是否有问题,不会执行该 playbook
--syntax-check  
 
# 当 play 和 task 的 tag 为该参数指定的值时才执行,多个 tag 以逗号分隔
-t TAGS, --tags=TAGS   
 
# 当 play 和 task 的 tag 不匹配该参数指定的值时,才执行
--skip-tags=SKIP_TAGS   
 
# 输出更详细的执行过程信息,-vvv可得到所有执行过程信息。
-v, --verbose 

检查文件是否有误:

ansible-playbook test.yaml --syntax-check

执行文件:

ansible-playbook test1.yaml

 六、变量

- name: test
  hosts: test
  remote_user: root
  vars:                 #定义变量
   - groupname: testgroup   
   - username: testuser
  tasks:
   - name: create group
     group: name={{groupname}} system=yes gid=600    #使用 {{key}} 引用变量的值
   - name: create user
     user: name={{username}} uid=600 group={{groupname}} 
   - name: copy file
     copy: content="{{ansible_default_ipv4}}" dest=/opt/vars.txt    #在setup模块中可以获取facts变量信息

七、常用模块

1、when 模块

在Ansible中,提供的唯一一个通用的条件判断是when指令,当when指令的值为true时,则该任务执行,否则不执行该任务。

when一个比较常见的应用场景是实现跳过某个主机不执行任务或者只有满足条件的主机执行任务

---
- hosts: all
  remote_user: root
  tasks:
   - name: test when  
    service: name=httpd state=stopped
     when: ansible_default_ipv4.address == "192.168.0.1"      #when指令中的变量名不需要手动加上 {{}}
# 或 
     when: inventory_hostname == "<主机名>"

当主机 IP 是 192.168.0.1 才会启动 httpd ,否则不启动

2、with_items 模块

Ansible提供了很多种循环结构,一般都命名为with_items,作用等同于 loop 循环;案例中with_item 相当于提供了2个变量,循环被调用执行任务

---
- name: play
  hosts: test
  gather_facts: false
  tasks:
    - name: create directories
      file:
        path: "{{item}}"
        state: directory
      with_items:
        - /tmp/test1
        - /tmp/test2
    - name: add users
      user: name={{item.name}} state=present groups={{item.groups}}
      with_items:
        - name: test1
          groups: wheel
        - name: test2
          groups: root
或
      with_items:
        - {name:'test1', groups:'wheel'}
        - {name:'test2', groups:'root'}

3、template(模板)

Ansible 模板是一种强大的工具,可用于在自动化任务中以动态方式生成配置、文件和其他工件。模板使用 Jinja2 模板语言,这是一种功能强大的模板语言,可用于创建复杂的模板。

Jinja2 模板语言:使用字面量,有下面形式。

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

数字:整数、浮点数

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

元组:[item1、item2、......]

字典:[key1:value1,key2:value2,......]

布尔型:true/false

算数运算:+ ,-, *, /,/ /,%,**

比较操作:==, !=, >, >=, <, <=

逻辑运算:and、or、not

流表达式:If For When

template功能:根据模块文件动态生成对应的配置文件

template文件必须存放于templates目录下,且命名为 .j2 结尾 yaml/yml 文件需和templates目录平级,目录结构如下:

./

├── temnginx.yml

└── templates

        └── nginx.conf.j2

---
- hosts: 10.0.0.1
  remote_user: root
  tasks:
    - name: install package
      yum: nginx
    - name: copy template
      template: 
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
    - name: service start
      service: name=nginx state=started enabled=yes

4、Playbooks中tasks语法使用

4.1、tags

如果写了一个很长的playbook,其中有很多的任务,这并没有什么问题,不过在实际使用这个剧本时,可能只是想要执行其中的一部分任务而已,或者,你只想要执行其中一类任务而已,而并非想要执行整个剧本中的全部任务,这个时候我们就可以借助 tags 标签实现这个需求。

tags可以帮助我们对任务进行’打标签’的操作,与模块名同级,当任务存在标签以后,我们就可以在执行playbook时,借助标签,指定执行哪些任务,或者指定不执行哪些任务了。

为playbook 添加标签的方式有如下几种:

  • 对一个 task 打一个标签
  • 对一个 task 打多个标签
  • 对多个 task 打一个标签

使用标签的方式:

  • -t 执行指定tag标签对用的任务
  • --skip-tags 执行除 --skip-tags 标签之外的所有任务
---
- hosts: web
  remote_user: root
 
  tasks:
  - name: test1
    file:
      path: /tmp/abc1.txt
      state: touch
    tags: t1,t4
 
  - name: test2
    file:
      path: /tmp/abc2.txt
      state: touch
    tags: t2
 
  - name: test3
    file:
      path: /tmp/abc3.txt
      state: touch
    tags: t3,t4

借助标签,除了能够指定“需要执行的任务”,还能够指定“不执行的任务” 使用--skip-tags 选项

ansible-playbook --skip-tags=t2 tags-test1.yaml

其实,ansible预置了5个特殊的标签,分别是

always :总是会被执行

never :总是不执行

tagged :表示只执行有标签的任务,没有标签的任务不会被执行。

untagged :只执行没有标签的任务,但是如果某些任务包含always标签,那么这些任务也会被执行。

all :特殊标签all表示所有任务会被执行,不用指定,默认情况下就是使用这个标签。

---
- hosts: web
  remote_user: root
 
  tasks:
  - name: test1
    file:
      path: /tmp/abc1.txt
      state: absent
    tags: t1
 
  - name: test2
    file:
      path: /tmp/abc2.txt
      state: absent
    tags: t2
 
  - name: test3
    file:
      path: /tmp/abc3.txt
      state: absent
    tags: t3,always


# task3的标签有两个,t3和always,在执行剧本时候,不指定t3,但是也会被执行,这就是always的作用。
如果不想执行标签中包含always的任务,可以使用--skip-tags=always 跳过他们。

4.2、file

file模块主要用于远程主机上的文件操作,file模块包含如下选项:

force

需要在两种情况下强制创建软链接,一种是源文件不存在但之后会建立的情况下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,选项:yes/no

group

定义文件/目录的属组

mode

定义文件/目录的权限

owner

定义文件/目录的属主

path

必选项,定义文件/目录的路径

recurse

递归的设置文件的属性,只对目录有效

src

要被链接的源文件的路径,只应用于state=link的情况

dest

被链接到的目标路径,只应用于state=link的情况

state

directory:表示目录,如果目录不存在,则创建目录。

link:创建软链接

hard:创建硬链接

touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间

absent:删除目录、文件或者取消链接文件。

举例:

- hosts: 192.168.0.1
  remote_user: tomcat
  tasks:
   - name: mkdir data directory
     file: path=/opt/data state=directory mode=0755
   - name: chmod bin
     file: dest=/opt/bigdata/jdk/bin mode=0755 recurse=yes
   - name: link files
     file: src=/etc/ssh/sshd_config dest=/mnt/sshd_config  owner=sshd state=link
   - name: delete files
     file: path=/tmp/tomcat.tar.gz state=absent
   - name: chown files
     file: path=/mnt/test.txt owner=nobody  group=nobody mode=0644

4.3、lineinfile

修改文件某一行文本

常用参数:

path

必须参数,指定要操作的文件

regexp

使用正则表达式匹配对应的行,当替换文本时,如果有多行文本都能被匹配,则只有最后面被匹配到的那行文本才会被替换,当删除文本时,如果有多行文本都能被匹配,这么这些行都会被删除。

line

指定修改后的文本内容

state

当想要删除对应的文本时,需要将state参数的值设置为absent,absent为缺席之意,表示删除,state的默认值为present

backrefs

默认情况下,当根据正则替换文本时,即使regexp参数中的正则存在分组,在line参数中也不能对正则中的分组进行引用,除非将backrefs参数的值设置为yes,backrefs=yes表示开启后向引用,这样,line参数中就能对regexp参数中的分组进行后向引用了,这样说不太容易明白,参考下面的示例命令比较直观一点,backrefs=yes除了能够开启后向引用功能,还有另一个作用,默认情况下,当使用正则表达式替换对应行时,如果正则没有匹配到任何的行,那么line对应的内容会被插入到文本的末尾,不过,如果使用了backrefs=yes,情况就不一样了,当使用正则表达式替换对应行时,同时设置了backrefs=yes,那么当正则没有匹配到任何的行时,则不会对文件进行任何操作,相当于保持原文件不变,如果没有理解,就按照下面的示例命令,动手操作一下吧,那样更加直观

insertafter

借助insertafter参数可以将文本插入到“指定的行”之后,insertafter参数的值可以设置为EOF或者正则表达式,EOF为End Of File之意,表示插入到文档的末尾,默认情况下insertafter的值为EOF,如果将insertafter的值设置为正则表达式,表示将文本插入到匹配到正则的行之后,如果正则没有匹配到任何行,则插入到文件末尾,当使用backrefs参数时,此参数会被忽略

insertbefore

借助insertbefore参数可以将文本插入到“指定的行”之前,insertbefore参数的值可以设置为BOF或者正则表达式,BOF为Begin Of File之意,表示插入到文档的开头,如果将insertbefore的值设置为正则表达式,表示将文本插入到匹配到正则的行之前,如果正则没有匹配到任何行,则插入到文件末尾,当使用backrefs参数时,此参数会被忽略

backup

是否在修改文件之前对文件进行备份

create

操作的文件不存在时是否创建

示例:

1、替换文件中匹配到得最后一个 SELINUX=,替换成 SELINUX=enforcing

- name: seline modify enforcing
   lineinfile:
      dest: /etc/selinux/config
      regexp: '^SELINUX='
      line: 'SELINUX=enforcing'

2、 insertbefore匹配内容在前面添加

- name: httpd.conf modify 8080
      lineinfile:
         dest: /opt/playbook/test/http.conf
         regexp: '^Listen'
         insertbefore: '^#Port'   
         line: 'Listen 8080'
      tags:
       - http8080

3、修改文件内容以及权限

 - name: modify hosts
      lineinfile:
         dest: /opt/playbook/test/hosts
         regexp: '^127\.0\.0\.1'
         line: '127.0.0.1 localhosts'
         owner: root
         group: root
         mode: 0644
      tags:
       - hosts

4、删除一行内容

- name: delete 192.168.0.1
      lineinfile:
         dest:  /opt/playbook/test/hosts
         state: absent
         regexp: '^192\.'
      tags:
       - delete192

4.4、replace

replace 模块根据指定得正则表达式替换文件中得字符串,文件中所有被正则匹配到得字符串都会被替换

- name: 替换配置文件中的文本
  hosts: service
  tasks:
 - name: 替换单个文本
      replace:
        path: /etc/test/config.conf
        regexp: 'old_text'
        replace: 'new_text'

 - name: 替换多个文本
      replace:
        path: /etc/test/config.conf
        regexp: '(old_text1|old_text2)'
        replace: 'new_text'

 - name: 使用正则表达式替换
      replace:
        path: /etc/test/config.conf
        regexp: 'pattern(.*)'
        replace: 'replacement\1'
        backrefs: yes

使用正则表达式替换:通过regexp参数指定一个正则表达式,使用括号捕获匹配的内容。通过replace参数指定替换的文本,并使用\1表示捕获的内容。replace模块会在文件中查找匹配的文本并进行替换。

4.5、shell

执行命令

- shell: mkdir /tmp/mytest
- shell: echo "export JAVA_HOME=/opt/jdk" >> /etc/profile

4.6、pause

暂停一定时间

常用参数:

  • minutes:暂停多少分钟
  • seconds:暂停多少秒
  • prompt:打印一串信息提示用户操作
- name: 等待用户30s用于输入
  pause: seconds=30 prompt="ENTER to continue CTRL-C a to quit"

4.7、local_action

本地操作功能,在运行ansible命令机器上执行操作

4.8、ignore_errors

忽略错误,通常情况执行失败时 ansible 会停止运行,有时候需要继续执行,则需要添加次参数

- name: 删除临时目录
  shell: rm /tmp/data
  ignore_errors:yes

4.9、user/group

用户组管理

常用参数:

  • name:指定组名称
  • gid:指定GID
  • state:动作参数

present:增加
absent:删除

4.10、yum

软件包管理

常用参数:

name:指定需要管理的软件包名

state:参数非常灵活,可以包含的值及含义如下

present:确保软件包已经安装了

installed:安装

latest:安装最新的软件包

removed/absent:删除对应的软件包

disable_gpg_check:用于禁用对rpm包公钥验证,默认值no表示不禁用验证,yes表示禁用验证

---
- name: install package
  hosts: all
  tasks:
  - name: install php and mariaDB
    yum:
      name:
      - php
      - mariadb
      state: present
    when: ansible_hostname in groups['dev']  

  - name: install the 'Development tools' package group
    yum:
      name: "@Development tools"
      state: present
    when: ansible_hostname in groups['dev']

  - name: upgrade all packages
    yum:
      name: "*"
      state: latest
- name:安装httpd服务
  yum: name=httpd state=latest
  - name: 删除旧版gcc
    yum: name = {{ item }} state=removed
    with_items:
      - gcc
      - httpd
      - php

4.11、cron

定时任务,相当于crontab

常用参数:

name:任务名称
minute:分, hour:时,day:天,month:月,weekday:周
job:指定要执行的命令或者脚本
state:当设置为absent代表删除任务

- name: 新增一个定时查看路径任务
  cron: name=check minute=5 job='pwd'

5、wars 变量

- name: second play
  hosts: dbservers
  remote_user: root
  vars:                 #定义变量
   - groupname: testgroup   #格式为 key: value
   - username: testuser
  tasks:
   - name: create group
     group: name={{groupname}} system=yes gid=308    #使用 {{key}} 引用变量的值
   - name: create user
     user: name={{username}} uid=309 group={{groupname}} 
   - name: copy file
     copy: content="{{ansible_default_ipv4}}" dest=/opt/vars.txt    #在setup模块中可以获取facts变量信息

  • 27
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值