Ansible学习-playbook基础部分(二)

Ansible-playbook基本介绍

playbook(剧本)

playbook 是由一个或者多个 play 组成的列表。 play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible 中task 定义好的角色。从根本上来讲,task就是调用 ansible 的一个 Module 。将多个play组织在一个playbook中,即可以让她们联动起来,按照事先编排的机制同唱一台大戏。

举例:

想象你要布置两间客房,给管家留了一张清单。每间客房都先检查床头有没有台灯,没有就放一盏。然后检查台灯有没有亮,没亮就打开。

这张清单就是 Playbook,管家就是 Ansible。

  • 主机清单 inventory 相当于房间名册,记录有哪些房间。
  • hosts 指定这次要布置哪几间房。
  • tasks 是要按顺序做的事,先确保有台灯,再确保灯亮着。

如果管家再检查一遍,发现两间房的台灯都已经亮着,就直接通过。这就是幂等。对应到刚才的例子安装Nginx,台灯就是 Nginx,「有台灯」对应已安装,「灯亮着」对应服务正在运行。

如果Nginx 已经安装并且已经在运行中,就不会重复安装或重启它。这就是 Ansible 里常说的幂等。

image-20261105150239957

1. YAML介绍

一种可读性高的表达资料序列的格式,很多语言都支持YAML文本,和脚本语言的交互性很好,使用实现语言的数据类型,有一个一致的信息模型;易于实现,可以基于流来处理,表达能力强,拓展性好。

YAML 入门教程 | 菜鸟教程

Ansible 大多数为标量

标量:单个不可再分的值

标量包括:字符串,布尔值,整数,浮点数,Null,时间,日期

标量的写法

name: wang

或者

name:
  wang

对象:键值对的集合,又称映射(mapping)/ 哈希(hashes)/ 字典(dictionary)

字典由多个key和value组成,key和value之间用: 分隔,冒号后必须有一个空格,所有k/v可以放在一行,或者每个k/v分别放在不同行

account: {name:wang,age:34}

或者

account:
  name: wang
  age: 18

数组(List列表):一组按次序排列的值,又称序列/列表

列表由多个元素组成,每个元素放在不同的行,且元素前均使用 -打头,并且-后面有一个空格,或者将所有元素用[]括起来,放在同一行

course: [linux,python,java]

或者

course:
  -linux: haowan
  -java: haixing

image-20261105145807205

2. playbook 核心组件

2.1 hosts:执行远程主机列表

---
- hosts: webservers
  remote_user: root       # 基于什么用户去跑,可不写,需要提权时要写,可不写
  gather_fast: no         # 可不写,不收集主机相关信息,可以提高效率
  						  # 如果用系统变量,一定要为yes
  ignore_errors: yes      # 忽略错误继续执行,也可以写再每一个tasks下,
  force_handlers: yes	  # 强制触发handler 

2.2 task:任务集

由多个 task 的元素组成的列表,实现每个 task 是一个字典,一个完整的代码块功能,最少元素需要 name 和 task,一个 name 只能包括一个 task。

检查语法是否有问题

---
- hosts: 192.168.155.120
  tasks:
  - name: this is ping
    ping:
  - name: this is shell command
    shell:  ls -l /
  - name: wall
    command: wall "hello wall"
  - name: httpd stats
    service:
      name: crond
      state: restarted
- hosts: 192.168.155.130
  tasks:
  - name: create User
    user:
      name: user1
      state: present
      uid: 1000
      group: root
      shell: /bin/bash
  - name: copy file to user1's home
    copy:
      src: /etc/hosts
      dest: /home/user1
ansible-playbook --syntax-check 1.yaml
ansible-playbook -C 1.yaml

image-20261110153659685

task 谁写再前面先执行谁。

2.3 handler:执行远程主机列表

当关注的资源发生变化是采取一定的操作,可以避免多次有改变时每次都执行指定的操作,取而代之,仅仅在所有的变化发射完成后一次性执行指定操作,在notify中调用handler中定义的操作。

注意:

  • 单独定义,然后基于notify中调用handler中定义的操作。
    - 如果多个task通知了相同的handlers,此 handlers 仅会在所有 task 结束之后运行一次。
  • handlers 是在前面的 task 都成功执行后才会执行,如果前面任何一个 task 失败,会导致handler 跳过执行。

安装 httpd → 改 Listen 8080 → state: started

# 探测服务是否存在
- hosts: 192.168.155.120
  tasks:
  - name: install httpd
    dnf:
      name: httpd
      state: installed
  - name: configure file change
    replace: 
      path: /etc/httpd/conf/httpd.conf
      regexp: '^Listen.*'
      replace: "Listen 8080"
  - name: httpd enable start 
    service:
      name: httpd
      state: started
      enable: yes

但是如果如果 httpd 已经在跑,改了配置文件它不会重启,Listen 8080 不会生效。

用 handler:配置变更时通知 restart,且只在变更时触发(幂等):

---
# 探测服务是否存在
# 安装 httpd → 改 Listen 8080 → state: started
- hosts: 192.168.155.120
  tasks:
  - name: install httpd
    dnf:
      name: httpd
      state: installed
  - name: configure file change
    replace: 
      path: /etc/httpd/conf/httpd.conf
      regexp: '^Listen.*'
      replace: "Listen 8080"
    notify: restart httpd # 如果本次这个任务真的改变了文件内容(状态为 changed),那就去触发名叫 restart httpd 的 handler。
    
  - name: httpd enable start 
    service:
      name: httpd
      state: started
      enable: yes
      
  handlers:
    - name: restart httpd
      service:
        name: httpd
        state: restarted

最后触发

2.4 tags:定义标签

​ 在 playbook 文件中,可以利用tags组件,为特定task指定标签,当执行playbook时,可以只执行特定tags

的task,而非整个 playbook 文件,可以一个 task 对应多个tag,也可以多个 task 对应一个 tag 。

​ 运行方式: ansible-playbook --list-tags file.yaml查看所有

---
- hosts: 192.168.155.120
  tasks:
  - name: install httpd
    dnf:
      name: httpd
      state: installed
  - name: configure file change
    replace:
      path: /etc/httpd/conf/httpd.conf
      regexp: '^Listen.*'
      replace: "Listen 8080"
    notify: restart httpd
  - name: httpd enable start
    service:
      name: httpd
      state: started
      enable: yes
  - name: check http configure
    shell: httpd -t
  - name: copy configure file
    copy:
      src: /root/anaconda-ks.cfg
      dest: /var/www/html/
    tags: file
  handlers:
    - name: restart httpd
      service:
        name: httpd
        state: restarted

image-20261111155349995

2.5 变量

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

变量来源:

  • ansible setup facts 远程主机的所有变量都可以直接调用

  • 在/etc/ansible/hosts 中定义

    ​ 普通变量:主机组中主机单独定义,优先级低于公共变量

    ​ 公共(组)变量:针对主机中所有主机定义统一变量

    [dbservers]
    ##
    ## db01.intranet.mydomain.net
    ## db02.intranet.mydomain.net
    ## 10.25.1.56
    192.168.155.120
    192.168.155.110 # ansible_connection=local 也就是这个变量
    
  • 通过命令行指定变量:优先级最高

    ansible-playbook -e varname=valie

    ---
    - hosts: 192.168.155.120
      tasks:
      - name: "install  pkname "
        dnf:
          name:  "{{ pkname }}"
          state: installed
      - name: start httpd
        service:
          name: "{{ pkname }}"
          state: started
    

    image-20261111175502125

  • 在 playbook 中定义(推荐)

    ---
    - hosts: 192.168.155.120
      vars:
      - pkname: httpd
      - src_path: /root/anaconda-ks.cfg
      tasks:
      - name: "install  pkname "
        dnf:
          name:  "{{ pkname }}"
          state: installed
      - name: start httpd
        service:
          name: "{{ pkname }}"
          state: started
      - name: copy file
        copy:
          src: "{{ src_path }}"
          dest: /tmp/
    
  • 在独立的变量YAML文件中定义(推荐)

    ---
    # vars.yaml
    pkname: httpd
    src_path: /root/anaconda-ks.cfg
    ---
    - hosts: 192.168.155.120
      vars_files:
      - vars.yaml # 默认同一个路径
      tasks:
      - name: "install  pkname "
        dnf:
          name:  "{{ pkname }}"
          state: installed
      - name: start httpd
        service:
          name: "{{ pkname }}"
          state: started
      - name: copy file
        copy:
          src: "{{ src_path }}"
          dest: /tmp/
    
  • 在 role 中定义

变量定义:

​ variable=value

​ variable: value

调用变量

{{ variable }} 有时候需要家双引号 "{{ variable }}"调用主机收集信息时
ansible-playbook -e  选项指定    # -e 的方式优先级高于 playbook 内部的vars 变量
举例:
	ansible-playbook test.yaml -e "hosts=www user=root"

1)Setup内置变量

setup 模块主要用来收集主机的信息,这些facts 信息可以直接以变量的形式调用,但是主机数量较多,会影响速度。

常用

ansible all -m setup -a "filter=ansible_processor_vcpus"                 # 逻辑CPU核心总数
ansible all -m setup -a "filter=ansible_all_ipv4_addresses"              # 所有IPv4地址列表
ansible all -m setup -a "filter=ansible_architecture"                    # 系统架构,如 x86_64
ansible all -m setup -a "filter=ansible_uptime_seconds"                  # 系统运行时间(秒)
ansible all -m setup -a "filter=ansible_processor"                       # CPU详细信息列表
ansible all -m setup -a "filter=ansible_env"                             # 系统环境变量

# 其他比较常用的 Facts 变量
ansible all -m setup -a "filter=ansible_os_family"                       # 系统家族,如 RedHat / Debian
ansible all -m setup -a "filter=ansible_distribution"                    # 发行版名称,如 CentOS / Ubuntu
ansible all -m setup -a "filter=ansible_kernel"                          # 内核版本号
ansible all -m setup -a "filter=ansible_fqdn"                            # 完整限定域名 FQDN
ansible all -m setup -a "filter=ansible_pkg_mgr"                         # 包管理工具,如 yum / apt
ansible all -m setup -a "filter=ansible_memtotal_mb"                     # 内存总量(MB)
ansible all -m setup -a "filter=ansible_memfree_mb"                      # 内存剩余量(MB)
ansible all -m setup -a "filter=ansible_swaptotal_mb"                    # Swap 总量(MB)
ansible all -m setup -a "filter=ansible_swapfree_mb"                     # Swap 剩余量(MB)
ansible all -m setup -a "filter=ansible_mounts"                          # 磁盘挂载信息列表
ansible all -m setup -a "filter=ansible_devices"                         # 磁盘设备信息字典
ansible all -m setup -a "filter=ansible_default_ipv4"                    # 默认IPv4路由/网卡信息
ansible all -m setup -a "filter=ansible_all_ipv6_addresses"              # 所有IPv6地址列表
ansible all -m setup -a "filter=ansible_python_version"                  # 被控主机 Python 版本
ansible all -m setup -a "filter=ansible_date_time"                       # 日期时间信息字典

# 通配符批量查看
ansible all -m setup -a "filter=ansible_*_mb"                            # 所有内存相关变量
ansible all -m setup -a "filter=ansible_processor*"                      # 所有CPU相关变量
ansible all -m setup -a "filter=ansible_*ipv*"                           # 所有IP相关变量
ansible all -m setup -a "filter=ansible_default_ipv4*"                   # 默认IPv4相关变量
---
- hosts: all
  remote_user: root
  gather_facts: yes   # 必须为 YES
  
  tasks:
  - name: show {{ ansible_nodename }}
    shell: echo {{ ansible_nodename }}

2)注册变量 register && debug

上面那种只能进行运行无法显示,只能用注册变量,注册变量必须跟shell绑定

- hosts: all
  tasks:
  - name: "show hostname"
    shell: echo "{{ ansible_nodename }}"
    register: name			# 讲shell命令执行的变量放在name变量中
  - name: "show value"
    debug:
      msg: "{{ name }}"		# 讲register里面的键显示出来

image-20261111185538815

上面那样显示太多,无法准确显示想要的信息

- hosts: all
  tasks:
  - name: "get message"
    shell: "awk -F: 'NR==1{print $1}' /etc/passwd"
    register: username
  - debug:
      var: username.stdout_lines

image-20261111191725192

安装httpd, 并且检测运行状态

---
- hosts: 192.168.155.120
  vars:
    pkname: httpd
    service_name: httpd

  tasks:
  - name: "install {{ pkname }}"
    dnf:
      name: "{{ pkname }}"
      state: present
  - name: "start {{ service_name }}"
    service:
      name: "{{ service_name }}"
      state: restarted
  - name: check status
    shell: ps -aux | grep {{ service_name }}
    register: check_service
  - name: debug
    debug:
      var: check_service.stdout_lines  # var: "{{ check_service.stdout_lines }}"

playbook一共七个模块,还剩template和role没有完成编写,这个文章的学习思路呢,就建议多写yaml文件,将其中的每个部分都自己纯手写一下。因为最重要的部分也就是这个剧本部分。

Snipaste_2026-11-11_20-24-30

posted @ 2026-11-11 20:07  DoomedWanderer  阅读(5)  评论(0)    收藏  举报