ansible之playbook&角色

本文详细介绍了Ansible的Playbook和Role概念。Playbook是Ansible持久化操作的方式,由一个或多个Play组成,每个Play包含Tasks,用于执行模块操作。Role是自1.2版本引入的特性,用于层次化组织Playbook,方便管理和包含变量、任务和处理器。文中通过实例展示了如何创建和使用Role部署Nginx服务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

playbook-剧本

简介

Playbook与ad-hoc相比,是一种完全不同的运用ansible的方式,类似与saltstack的state状态文件。ad-hoc无法持久使用,playbook可以持久使用。
playbook是由一个或多个play组成的列表,play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的task定义好的角色。从根本上来讲,所谓的task无非是调用ansible的一个module。将多个play组织在一个playbook中,即可以让它们联合起来按事先编排的机制完成某一任务

Playbook核心元素
Hosts执行的远程主机列表
Tasks任务集
Varniables内置变量或自定义变量在playbook中调用
Templates模板,即使用模板语法的文件,比如配置文件等
Handlers 和notity结合使用由特定条件触发的操作,满足条件方才执行,否则不执行
tags 标签指定某条任务执行,用于选择运行playbook中的部分代码。

Playbook语法

playbook使用yaml语法格式,后缀可以是yaml,也可以是yml。

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

ansible-playbook参数

–check or -C只检测可能会发生的改变,但不真正执行操作
–list-hosts列出运行任务的主机
–list-tags列出playbook文件中定义所有的tags
–list-tasks列出playbook文件中定义的所以任务集
–limit主机列表 只针对主机列表中的某个主机或者某个组执行
-f指定并发数,默认为5个
-t指定tags运行,运行某一个或者多个tags。(前提playbook中有定义tags)
-v显示过程 -vv -vvv更详细

playbook组件用法

tasks

每一个task必须有一个名称name,这样在运行playbook时,从其输出的任务执行信息中可以很清楚的辨别是属于哪一个task的,如果没有定义name,action的值将会用作输出信息中标记特定的task。

每一个playbook中可以包含一个或者多个tasks任务列表,每一个tasks完成具体的一件事,(任务模块)比如创建一个用户或者安装一个软件等,在hosts中定义的主机或者主机组都将会执行这个被定义的tasks。

tasks: 
  - name: run df -h
    sudo_user: test  #定义要执行的用户组
    sudo: yes        #配置sudo
    shell: name=df -h
tasks:
  - name: create new file
    file: path=/tmp/test01.txt state=touch
  - name: create new user
    user: name=test001 state=present

tags

useradd.yml
hosts: websrvs
remote_user: root 
tasks :
name: create new file
file: name=/data/newfile state=touch
name: create new user
user: name=test2 system=yes shel1=/sbin/nologin 
name: instal1 package
yum: name=httpd
name: copy html
copy: src=/van/www/htm1/index.htm] dest=/var /www/htm1/
name: start service
service: name=httpd state=started enab led=yes


ansible-playbook -t tagsname useradd.yml
- hosts: 192.168.1.31
  remote_user: root

  tasks:
    - name: install httpd
      yum: name=httpd state=installed
      tags: inhttpd

    - name: start httpd
      service: name=httpd state=started
      tags: sthttpd

    - name: restart httpd
      service: name=httpd state=restarted
      tags: 
        - rshttpd
        - rs_httpd

#通过-t指定tags名称,多个tags用逗号隔开
ansible-playbook -t rshttpd httpd.yml 
#通过--skip-tags选项排除不执行的tags
ansible-playbook --skip-tags inhttpd httpd.yml

play的主体部分是task list。task list中的各任务按次序逐个在hosts中指定的所有主机_上执行,即在所有主机上完成第一个任务后再开始第 二个。在运行自下而下某playbook时,如果中途发生错误,所有已执行任务都将回滚,因此在更正playbook后重新执行一次即可

➢task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致

➢每个task都应该有其name ,用于playbook的执行结果输出,建议其内容尽可 能清晰地描述任务执行步骤。如果未提供name,则action的结果将用于输出

如果命令或脚本的退出码不为零, 可以使用ignore_ errors来忽略错误信息

#如果命令或脚本的退出码不为零, 可以使用ignore_ errors来忽略错误信息

name: run this command and ignore the result
shell: /usr/bin/somecommand || /bin/true  
tasks: .
name: run this command and ignore the result
shell: /usr/bin/somecommand
ignore_errors: True

Handlers

是task列表,这些task与前述的task并没有本质上的不同,用于当关注的资源发生化时,才会采取一定的操作
Notify此action可用于在每个play的最后被触发,这样可避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作称为handler
,也即notify中调用handler中定义的操作。

#可以定义多个
- hosts: websrvs
  remote_user: root
  tasks:
  - name: add group nginx
    tags: user
    user: name= nginx state= present
  - name: add user nginx
    user: name=nginx state=present group=nginx
  - name: Install Nginx
    yum: name=nginx state=present
  - name: config
    copy: src=/root/config.txt dest=/etc/nginx/nginx.conf
    notify:
    - Restart Nginx
    - Check Nginx Progess
handlers:
  - name: Restart Nginx
    service: name=nginx state=restarted enabled=yes
  - name: Check Nginx process
    shell: kllall -0 nginx > /tmp/nginx.log

template

该模板为我们提供了动态配置服务,使用jinja2语言,里面支持多种条件判断、循环、逻辑运算、比较操作等。其实说白了也就是一个文件,和之前配置文件使用copy一样,只是使用copy,不能根据服务器配置不一样进行不同动态的配置。这样就不利于管理。

1、多数情况下都将template文件放在和playbook文件同级的templates目录下(手动创建),这样playbook文件中可以直接引用,会自动去找这个文件。如果放在别的地方,也可以通过绝对路径去指定。
2、模板文件后缀名为.j2。

playbook变量

变量名:仅能由字母、数字和下划线组成,且只能以字母开头

变量来源:

➢ansible setup facts远程主机的所有变量都可直接调用
➢在/etc/ansible/hosts中定义,
➢在role中定义
➢在playbook中定义
➢在命令行中定义,优先级最高

#优先级从下到上依次降低,其中,在/etc/ansible/hosts文件中主机组中主机单独定义,优先级高于公共变量
cat app.yml

- hosts: appsrvs
  remote_user: root
  tasks:
  - name :install package
    yum: name={{ pkname }}
  - name: start service
    service: name={{ pkname }} state=started enab led=yes

ansible-playbook -e ' pkname=vsftpd' app.yml 
#执行playbook时候通过参数-e传入变量,这样传入的变量在整个playbook中都可以被调用,属于全局变量
#playbook中变量的定义
- hosts: all
  remote_user: root
  vars:                #定义变量
    pkg: nginx         #变量1
    dir: /tmp/test1    #变量2
/etc/ansible/hosts文件中的变量
[websrvs]        
192.168.30.101 http_ port=81   #每个主机的变量
192.168.30.102 http_ .port=82
[websrvs:vars ]        #该组的公共变量
nodename=www
domai nname=magedu . com

playbook语句

when

条件测试:如果需要根据变量、facts或此前任务的执行结果来做为某task执行与否的前提时要用到条件测试,通过when语句执行,
在task中使用jinja2的语法格式、
when语句:在task后添加when子句即可使用条件测试;when语句支持jinja2表达式语法。

- hosts: all
  remote_user: root
  vars:
    - listen_port: 88

  tasks:
    - name: Install Httpd
      yum: name=httpd state=installed
    - name: Config System6 Httpd
      template: src=httpd6.conf.j2 dest=/etc/httpd/conf/httpd.conf
      when: ansible_distribution_major_version == "6"   #判断系统版本,为6便执行上面的template配置6的配置文件
      notify: Restart Httpd
    - name: Config System7 Httpd
      template: src=httpd7.conf.j2 dest=/etc/httpd/conf/httpd.conf
      when: ansible_distribution_major_version == "7"   #判断系统版本,为7便执行上面的template配置7的配置文件
      notify: Restart Httpd
    - name: Start Httpd
      service: name=httpd state=started

  handlers:
    - name: Restart Httpd
      service: name=httpd state=restarted

with_items

with_items迭代,当有需要重复性执行的任务时,可以使用迭代机制。
对迭代项的引用,固定变量名为“item”,要在task中使用with_items给定要迭代的元素列表。
列表格式:   
字符串   
字典

- hosts: all
  remote_user: root

  tasks:
    - name: Install Package
      yum: name={{ item }} state=installed   #引用item获取值
      with_items:     #定义with_items
        - httpd
        - vsftpd
        - nginx
#with_items嵌套子变量
---
- hosts: all
  remote_user: root

  tasks:
    - name: Create New Group
      group: name={{ item }} state=present
      with_items: 
        - group1
        - group2
        - group3 

    - name: Create New User
      user: name={{ item.name }} group={{ item.group }} state=present
      with_items:
        - { name: 'user1', group: 'group1' } 
        - { name: 'user2', group: 'group2' } 
        - { name: 'user3', group: 'group3' }

for if

通过使用for,if可以更加灵活的生成配置文件等需求,还可以在里面根据各种条件进行判断,然后生成不同的配置文件、或者服务器配置相关等。

cat templates/nginx.conf.j2 
{% for port in nginx_vhost_port %}
server{
     listen: {{ port }};
     server_name: localhost;
}
{% endfor %}

#执行效果
ansible-playbook testfor01.yml

# 去到一个节点看下生成的结果发现自动生成了三个虚拟主机
cat /tmp/nginx_test.conf 
server{
     listen: 81;
     server_name: localhost;
}
server{
     listen: 82;
     server_name: localhost;
}
server{
     listen: 83;
     server_name: localhost;
}
cat templates/nginx.conf.j2 
{% for vhost in nginx_vhosts %}
server{
     listen:    {{ vhost.listen }};
     server_name:    {{ vhost.server_name }};
     root:   {{ vhost.root }}; 
}
{% endfor %}

#执行效果
cat /tmp/nginx_vhost.conf 
server{
     listen:    8081;
     server_name:    web1.example.com;
     root:   /var/www/nginx/web1; 
}
server{
     listen:    8082;
     server_name:    web2.example.com;
     root:   /var/www/nginx/web2; 
}
server{
     listen:    8083;
     server_name:    web3.example.com;
     root:   /var/www/nginx/web3; 
}

在这里插入图片描述

roles-角色

简介

角色(roles)是ansible自1.2版本开始引入的新特性,用于层次性,结构化地组织playbook。roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。简单的说,roles就是通过分别将变量、文件、任务、模块及处理器放置于单独的目录中、并可以便捷地include他们的一种机制。角色一般用于基于主机构建服务的场景中、但也可以是用于构建守护进程等场景中。

yml文件用于定义此角色用到的各handler:在handler中使用include包含的其他的handler文件也应该位于此目录中;
files目录存放由copy或script等模块调用的文件;
templates目录templates模块会自动在此目录中寻找Jinja2模板文件;
tasks目录至少应该包含一个名为main.yml的文件,其定义了此角色的任务列表;此文件可以使用include包含其他的位于此目录中的task文件;
handlers目录此目录中应当包含一个main;
vars目录应当包含一个main.yml文件,用于定义此角色用到的变量;
meta目录应当包含一个main.yml文件,用于定义此角色的特殊设定及其依赖关系;ansible 1.3及其以后的版本才支持
default目录为当前角色设定默认变量时使用此目录;应当包含一个main.yml文件;

用法

角色中一个playbook就可以这样写

---
 - hosts: webservers
  roles:
     - common
     - webservers

这个 playbook 为一个角色 ‘x’ 指定了如下的行为:
如果 roles/x/tasks/main.yml 存在, 其中列出的 tasks 将被添加到 play 中
如果roles/x/handlers/main.yml 存在, 其中列出的 handlers 将被添加到 play 中
如果roles/x/vars/main.yml 存在, 其中列出的 variables 将被添加到 play 中
如果roles/x/meta/main.yml 存在, 其中列出的 “角色依赖” 将被添加到 roles 列表中 (1.3 andlater)
所有 copy tasks 可以引用 roles/x/files/ 中的文件,不需要指明文件的路径。
所有 scripttasks 可以引用 roles/x/files/ 中的脚本,不需要指明文件的路径。
所有 template tasks 可以引用roles/x/templates/ 中的文件,不需要指明文件的路径。
所有 include tasks 可以引用roles/x/tasks/ 中的文件,不需要指明文件的路径。
如果 roles 目录下有文件不存在,这些文件将被忽略。比如 roles 目录下面缺少了 ‘vars/’ 目录,这也没关系。

注意:你仍然可以在 playbook 中松散地列出 tasks,vars_files 以及 handlers,这种方式仍然可用,但 roles 是一种很好的具有组织性的功能特性,我们强烈建议使用它。
如果你在 playbook 中同时使用 roles 和 tasks,vars_files 或者 handlers,roles 将优先执行。
而且,也可以使用参数化的 roles,这种方式通过添加变量来实现,比如:

- hosts: webservers
  roles:
    - common
    - { role: foo_app_instance, dir: '/opt/a',  port: 5000 }
    - { role: foo_app_instance, dir: '/opt/b',  port: 5001 }
当一些事情不需要频繁去做时,也可以为 roles 设置触发条件,像这样:

---
- hosts: webservers
  roles:
    - { role: some_role, when: "ansible_os_family == 'RedHat'" }

它的工作方式是:将条件子句应用到 role 中的每一个 task 上。


也可以给role分配指定的标签,比如
---

- hosts: webservers
  roles:
    - { role: foo, tags: ["bar", "baz"] }
如果 play 仍然包含有 ‘tasks’ section,这些 tasks 将在所有 roles 应用完成之后才被执行。

也可定义一些 tasks,让它们在 roles 之前以及之后执行,可以这样做:

---

- hosts: webservers
  pre_tasks:
    - shell: echo 'hello'
  roles:
    - { role: some_role }
  tasks:
    - shell: echo 'still busy'
  post_tasks:
    - shell: echo 'goodbye'

实战

部署nginx

建立目录架构

cd /etc/ansible
mkdir -p roles/nginx
cd /roles/nginx
mkdir tasks templates

编写任务文件

cd tasks
vim group.yml
- name: create group
  group: name=nginx gid=80

vim user.yml
- name: create user
  user: name=nginx uid=80 group=nginx system=yes shell=/sbin/nologin  

vim yum.yml
- name: install package
  yum: name=nginx

vim start.yml
- name: start service
  service: name=nginx state=started enabled=yes 

vim restart.yml
- name: restart service
  service: name=nginx state=restarted 

vim template.yml
- name: copy conf
  template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf

vim main.yml
- include: group.yml
- include: user.yml
- include: yum.yml
- include: template.yml
- include: start.yml

编写模板文件

cd templates
cp /etc/nginx/nginx.conf nginx.conf.j2
vim nginx.conf.j2
worker_processes {{  ansible_processor_vcpus+2 }};

编写执行文件
注意该文件和roles目录是同级的,即都在/etc/ansible下

cd /etc/ansible
vim nginx.yml
- host: webserver
  remote_user: root
  roles:
  - role: nginx


ansible-playbook nginx.yml
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值