ansible那点事——playbook知识


一、ansible-play

  playbook是由一个或多个play组成的列表。play的主要作用是将事先归位一组的主机通过预先的编排来实现批量操作。也可以理解是一个简单的剧本,由多个task组成的剧本,格式为YAML,遵循YAML语法。

基本组件:

name:定义playbook或者task的名称  

hosts:playbook中的每一个play的目的都是为了让某个或某些以某个指定用户的身份执行任务。hosts用于指定要执行指定任务的主机,其可以是一个或多个由冒号分割主机组。与命令模式下的ansible匹配规则一样  

user:remote_user则用于指定远程主机上的执行任务的用户,也可以使用user  

tasks:任务列表。play的主体部分是task list. task list中的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后再开始第二个。  

vars:定义变量  

vars_files:定义变量文件 

notify:任务执行结果如果是发生更改了的则触发定义在handler的任务执行  

handlers:用于当前关注的资源发生变化时采取一定指定的操作  

include:能包含的包括task,handler和playbook  ,可以在include的时候传递变量

一个简答的play demo,apache安装,如果httpd.conf发生改变则重启httpd

- hosts: node-2 # 操作的主机
  user: root   # 操作用户
  tasks: # 任务
  - name: install apache # 任务名称,自定义
    yum: name=httpd state=present # yum模块
  - name: start apache # 任务名称,自定义
    service: name=httpd state=started # service模块
  - name: change apache # 任务名称,自定义
    copy: src=./httpd.conf dest=/etc/httpd/conf/httpd.conf # copy模块
    notify: restart apache # 触发。如果change apache任务执行成功则会执行 restart apache任务
  handlers: # 触发操作,与notify同用
  - name: restart apache # 触发任务的名称
    service: name=httpd state=restarted # service模块

二、ansible-playbook

  playbook是将多个play组织在一个playbook中,即可以让他们联通起来按事先编排的机制共同“表演”。playbook由YMAL(YAML Ain’t Makup Language)语言编写。

  相较于play来说,playbook有了元素的概念,以下为核心元素:
  - Variables 变量元素,可传递给Tasks/Templates使用;
  - Tasks 任务元素,由模块定义的操作的列表,即调用模块完成任务;
  - Templates 模板元素,使用了模板语法的文本文件,可根据变量动态生成配置文件;
  - Handlers 处理器元素,通常指在某事件满足时触发的操作;
  - Roles 角色元素

1、playbook demo 批量部署nginx

  1. 创建目录结构,并准备index.html文件及nginx.conf文件
mkdir -p roles/nginx/{files,handlers,tasks,templates,vars} 

touch roles/site.yaml roles/nginx/{handlers,tasks,vars}/main.yaml

echo "<h1>Ansible-playbook test</h1>" >/etc/ansible/test/roles/nginx/files/index.html

cp /etc/nginx/nginx.conf /etc/ansible/test/roles/nginx/templates/nginx.conf.j2 # 程序的模板配置文件以.j2结尾


目录结构:
    roles/
    ├── nginx
    │   ├── files
    │   │     └── index.html
    │   ├── handlers
    │   │     └── main.yaml
    │   ├── tasks
    │   │     └── main.yaml
    │   ├── templates
    │   │     └── nginx.conf.j2
    │   └── vars
    │         └── main.yaml
    └── site.yaml

  1. 编写tasks/main.yaml
# 所有需要执行的task都放在这个文件下

- name: install nginx
  yum: name={{ item }} state=latest
  with_items:
  - nginx

- name: copy index.html
  copy: src=/etc/ansible/test/roles/nginx/files/index.html dest=/usr/share/nginx/html/index.html

- name: copy nginx.conf
  template: src=/etc/ansible/test/roles/nginx/templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf
  notify: restart nginx

- name: run nginx
  service: name=nginx state=started enabled=yes
  1. 编写handlers/main.yaml
# 这个文件下对应的task都对应着 tasks/main.yaml 下的 notify

- name: restart nginx
    service: name=nginx state=restarted
  1. 修改templates/nginx.conf.j2
worker_processes  {{ ansible_processor_cores }};# 调用内部已知变量,setup模块获取
worker_connections {{ worker_connections }};# 自定义变量 在vars/main.yaml里定义
  1. 编写vars/main.yaml
worker_connections: 10240 # 变量赋值
  1. 编写site.yaml
 - hosts: node-2   # 目标主机(组)
   roles:   # 调用roles中的nginx
   - nginx
  1. 执行playbook
ansible-playbook site.yaml --syntax-check  # playbook语法测试

ansible-playbook site.yaml # 执行playbook

2、playbook常用的参数、操作

1)tags标记
#给task做个标记,可以控制任务执行

- hosts: all     #注意-后面的空格   指定执行本play的主机组
  user: root     # 指定运行本play的远程主机用户
  tasks:                         
  - name: playbook_test   # 任务描述
    shell: touch /tmp/playbook.txt  # shell模块
    tags: suibian         # 这是一个任务标记,可用来控制此任务
    
    
# 只运行指定标记的任务:-t tags
ansible-playbook  -t 标记名称 test.yml 

# 跳过某一个被标记的任务:--skip-tags=SKIP_TAGS 
ansible-playbook  --skip-tags=标记名称 test.yml 

# 从某一个任务开始往下运行:--start-at-task 任务名称
ansible-playbook  --start-at-task "start httpd service" test.yml 
2)playbook包含多个play
- hosts: all    # play1
  remote_user: root
  tasks:
  - name: install a group
    group: name=mygrp system=true

- hosts: webservers  # play2
  remote_user: root
  tasks:
  - name: install httpd package
    yum: name=httpd
3)变量的使用
- name: create_user    # 剧本描述信息
  hosts: node-2
  user: root
  gather_facts: false
  vars:
  - user: "liang"     # 变量值一定要用引号引住
  tasks:
  - name: create user
    user: name="{{ user }}"

基于字典列表给出元素示例:
- hosts: all
  remote_user: root
  tasks:
  - name: create groups
    group: name={{ item }} state=present
    with_items:
    - groupx1
    - groupx2
    - groupx3
    - name: create users
    user: name={{ item.name }} group={{ item.group }} state=present
    with_items:
    - {name: 'userx1', group: 'groupx1'}
    - {name: 'userx2', group: 'groupx2'}
    - {name: 'userx3', group: 'groupx3'}
4)条件判断 when
# 条件判断,当满足when条件时才会执行task

- name: use when
  shell: touch /tmp/when.txt
  when: ansible_hostname == "node-2" # 如果主机名为node-2才创建文件

- name: use when
  shell: touch /tmp/when.txt
  when: ansible_all_ipv4_addresses[0] == "192.168.93.137" # 如果ip地址为192.168.93.137才会创建文件
  
- hosts: webservers
  tasks:
   - name: haha
     command: /bin/uname
     register: result         # uname结果赋给result
     ignore_errors: True      # 忽略errors
   - command: /bin/df
     when: result|failed      # 如果result(uname)失败,则执行df
     register: aaa            # df结果赋给aaa
   - command: /bin/ls
     when: result|success     # 如果result(uname)成功,则执行ls
   - command: /bin/lsblk
     when: aaa|skipped        # 如果aaa被跳过,则执行lsblk
5)include参数
# 避免编写重复的yaml,我们把重复功能的yaml单独拿出来。类似于shell中function,脚本中调用function

- hosts: node-2
  name: create_user
  vars:
  - user: "liang"
  tasks:
  - name: create user
    user: name="{{ user }}"
- include: handlers.yml    # 2.8版本之后includd被遗弃,使用import_playbook代替
- import_playbook: handlers.yml
6)register参数
# register类似shell中的变量的用法,可以将task获取的信息赋值通过register参数赋值给一个变量

- hosts: all
  tasks:
    - shell: hostname
      register: Hostname
      ignore_errors: True
    - name: print pwd_status value
      file: name=/tmp/{{ Hostname.stdout }} state=touch # 在/tmp下创建一个以主机名命名的文件
7)应用vars变量
#vars,可以在playbook中直接声明的变量,在task中使用变量

- hosts: all
  vars:
    user:
      name: haha
      groups: haha
  tasks:
    - name: create file haha
      file: path=/tmp/{{ user.name }} state=touch # touch /tmp/haha
8)交互式 prompt参数
# prompt 类似shell中的except,实现交互式的playbook

- hosts: 192.195.23.51
  vars_prompt: # 引用交互式,类似except
    - name: "Name"
      prompt: "please enter your name:"   # prompt 与用户交互
      private: no
    - name: "sex"
      prompt: "please enter your sex: \n
      A: man\n
      B: woman\n"
      private: no                        # private no为显示用户输入 yes为隐藏
      default: man
  tasks:
    - name: print information
      debug: msg="{{ Name }} his sex is {{ sex }}"
    - name: touch file
      file: path=/tmp/{{ Name }} state=touch

三、playbook报错

   一般playbook除了语法及逻辑的错误,其他很少有错误信息,不过在使用shell模块时有一种特殊的情况。

- hosts: 192.168.93.128
  tasks:
    - name: found process
      shell: ps -ef |grep java |egrep -v "grep|snc-agent"

执行ansible-play返回错误:
192.168.93.128 | FAILED | rc=1 >>
non-zero return code

报错信息是因为shell返回结果为空,ansible就以为shell出错了,然后返回错误,也就是我们的 ps 命令没有查出来任何进程。这实际上对于我们的逻辑来说是没有问题的。比如我们没有查到某个进程才去启动它。

解决方案:
1、忽略这个错误,在task中添加 ignore_errors 不会因为这个task影响整个playbook,可以保证playbook的完整运行,不过前台还是会返回错误。
2、使用shell模块时,在命令后面加|cat 将命令命令通过管道符给cat
shell: ps -ef |grep java |egrep -v "grep|snc-agent" |cat
或者使用wc -l的方式去判断进程数
shell: ps -ef |grep java |egrep -v "grep|snc-agent" |wc -l

推荐方案2的第一种方法,可以满足我们的需求还避免shell返回控制。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

偷学技术的梁胖胖yo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值