Ansible题目全解析与答案

Ansible题目全解析与答案

一、安装和配置 ansible 环境

题目要求

  1. 安装所需软件包;

  2. /home/student/ansible/inventory文件中设置主机清单,

  3. 要求:

    node1 属于 test01 主机组,

    node2 属于 test02 主机组,

    node3 和 node4 属于 web 主机组,

    node5 属于 test05 主机组,

    web 组属于 webtest 主机组;

  4. /home/student/ansible目录中创建 ansible.cfg,满足以下需求:主机清单文件为/home/student/ansible/inventory,playbook 中角色位置为/home/student/ansible/roles,collection 位置为/home/student/ansible/collections

1. 安装所需软件包(控制机 master 操作)

2. 创建主机清单(/home/student/ansible/inventory

mkdir ansible

vim inventory

mkdir collections

ansible all -m ping

答案
yaml 复制代码
[test01]
node1
[test02]
node2
[web]
node3
node4
[test05]
node5
[webtest:children]
web

3. 创建 ansible.cfg 配置文件(/home/student/ansible/ansible.cfg

答案
yaml 复制代码
cd /etc/ansible/ansible.cfg
ansible-config init --disabled > ansible.cfg
##复制到/home/student/ansible/

# /home/student/ansible/ansible.cfg
[defaults]
# 文档要求:主机清单文件路径
inventory = /home/student/ansible/inventory

# 文档要求:角色存放路径
roles_path = /home/student/ansible/roles

# 文档要求:Collection 存放路径
collections_paths = /home/student/ansible/collections

# 补充配置:远程执行用户(文档预设受管机 sudo 用户为 student)
remote_user = student
host_key_checking=False


# 补充配置:开启 sudo 提权(系统操作需 root 权限)
become = yes
become_ask_pass=False
become_method=sudo
# 补充配置:sudo 目标用户(默认 root,满足系统配置需求)
become_user = root

# 补充配置:简化输出格式(便于查看任务执行结果)
stdout_callback = yaml
说明
  • 核心配置项(inventory、roles_path、collections_paths)完全按文档路径设置,确保 Ansible 能正确加载资源;
  • 补充remote_userbecome配置:适配文档"受管机预设 sudo 用户 student"的环境,通过student远程登录后提权为root,既符合权限规范,又能执行系统级任务。

二、创建和运行 Ansible 任务(编写yum.yml

题目要求

编写脚本/home/student/ansible/yum.yml,为所有受管机配置 yum 仓库:

  1. 仓库 1:名称为 BASEOS,描述为 software base,URL 为http://ansible.example.com/rhel9/BaseOS,GPG 签名启用,GPG 密钥 URL 为http://ansible.example.com/rhel9/RPM-GPG-KEY-redhat-release,仓库为启用状态;
  2. 仓库 2:名称为 APPSTREAM,描述为 software stream,URL 为http://ansible.example.com/rhel9/AppStream,GPG 签名启用,GPG 密钥 URL 为http://ansible.example.com/rhel9/RPM-GPG-KEY-redhat-release,仓库为启用状态。

答案

yaml 复制代码
# /home/student/ansible/yum.yml
---
- name: 为所有受管机配置 BASEOS 和 APPSTREAM 仓库(文档要求)
  hosts: all  # 目标:所有受管机
  tasks:
    # 配置仓库 1:BASEOS(完全匹配文档参数)
    - name: 配置 BASEOS Yum 仓库
      yum_repository:
        file: rhel9_repos  # 统一存储到 /etc/yum.repos.d/rhel9_repos.repo
        name: BASEOS       # 文档要求:仓库名称
        description: software base  # 文档要求:仓库描述
        baseurl: http://ansible.example.com/rhel9/BaseOS  # 文档要求:仓库 URL
        enabled: yes  # 文档要求:启用仓库
        gpgcheck: yes  # 文档要求:启用 GPG 签名验证
        gpgkey: http://ansible.example.com/rhel9/RPM-GPG-KEY-redhat-release 
        state: present  # 确保仓库配置存在

    # 配置仓库 2:APPSTREAM(完全匹配文档参数)
    - name: 配置 APPSTREAM Yum 仓库
      yum_repository:
        file: rhel9_repos  # 与 BASEOS 共用配置文件,减少冗余
        name: APPSTREAM    # 文档要求:仓库名称
        description: software stream  # 文档要求:仓库描述
        baseurl: http://ansible.example.com/rhel9/AppStream  # 文档要求:仓库 URL
        enabled: yes  # 文档要求:启用仓库
        gpgcheck: yes  # 文档要求:启用 GPG 签名验证
        gpgkey: http://ansible.example.com/rhel9/RPM-GPG-KEY-redhat-release  
        state: present  # 确保仓库配置存在

    # 补充任务:清理并更新 Yum 缓存(确保新仓库立即生效)
    - name: 清理 Yum 旧缓存并更新新缓存
      yum:
        clean: all
        update_cache: yes
说明
  • 两个仓库的所有参数(名称、描述、URL、GPG 配置)均严格按文档填写,无任何偏差;
  • 共用rhel9_repos.repo文件,避免生成多个独立配置文件,便于后续统一管理;
  • 补充"清理缓存"任务:新仓库配置后需更新缓存,否则 Yum 无法识别新仓库的软件包,确保后续安装任务正常执行。

三、编写剧本远程安装软件(创建tools.yml

题目要求

创建名为/home/student/ansible/tools.yml的 playbook,能够实现以下目的:

  1. 将 php 和 tftp 软件包安装到 test01、test02 和 web 主机组中的主机上;
  2. 将 RPM Development Tools 软件包组安装到 test01 主机组中的主机上;
  3. 将 test01 主机组中的主机上所有软件包升级到最新版本。

答案

yaml 复制代码
# /home/student/ansible/tools.yml
---
# Play 1:为 test01、test02、web 组安装 php 和 tftp(文档要求 1)
- name: 安装 php 和 tftp 到目标主机组
  hosts: test01:test02:web  # 多组并集,匹配文档指定范围
  tasks:
    - name: 确保 php 和 tftp 已安装
      yum:
        name:
          - php
          - tftp
        state: present

# Play 2:为 test01 组安装软件包组并升级(文档要求 2、3)
- name: 为 test01 组安装软件包组并升级所有软件
  hosts: test01  # 仅针对 test01 组
  tasks:
    # 文档要求 2:安装 RPM Development Tools 软件包组
    - name: 安装 RPM Development Tools 软件包组
      yum:
        name: "@RPM Development Tools"  # 软件包组需加 @ 前缀
        state: present

    # 文档要求 3:升级 test01 组所有软件包到最新版
    - name: 升级所有软件包到最新版本
      yum:
        name: '*'  # 匹配所有已安装软件包
        state: latest
说明
  • 拆分两个 Play 逻辑:Play 1 处理多组的基础软件安装,Play 2 处理 test01 组的特殊需求(软件包组+全量升级),边界清晰,便于排查问题;
  • 软件包组安装需加@前缀:这是 Yum 识别软件包组的专用语法,不加会导致"找不到软件包"错误;
  • 全量升级用name: '*':确保 test01 组所有软件包均升级到最新版,完全满足"所有软件包升级"的要求。

四、配置计划任务(编写jihua.yml

题目要求

编写剧本/home/student/ansible/jihua.yml

  1. 在 test02 组中的被管理主机运行;
  2. 为用户 student 创建计划任务:student 用户每隔 5 分钟执行echo "hello tarena"

答案

yaml 复制代码
# /home/student/ansible/jihua.yml
---
- name: 为 test02 组 student 用户配置计划任务(文档要求)
  hosts: test02  # 文档要求 1:仅在 test02 组执行
  tasks:
    - name: 创建 5 分钟执行一次的 cron 任务(文档要求 2)
      cron:
        name: "student-echo-task"  # 任务名称,便于识别
        user: student  # 文档要求:任务归属 student 用户
        minute: "*/5"  # 文档要求:每隔 5 分钟执行(cron 表达式)
        job: 'echo "hello tarena"'  # 文档要求:执行的命令
        state: present  # 确保任务存在
说明
  • hosts: test02严格限定执行范围,避免任务在其他组误执行;
  • minute: "*/5"是 cron 标准表达式,表示"每 5 分钟",完全匹配"每隔 5 分钟"的需求;
  • 命令用单引号包裹:防止双引号内的空格被解析为语法分隔符,确保命令原样执行。

五、安装并使用系统角色(timesync)(创建timesync.yml

题目要求

安装 RHEL 角色软件包,并创建剧本/home/student/ansible/timesync.yml,满足以下要求:

  1. 在 test01 组中的被管理主机运行;
  2. 使用 timesync 角色;
  3. 配置该角色,使用时间服务器ansible.example.com,并启用 iburst 参数。

答案

步骤 1:安装 RHEL 系统角色(控制机操作)
bash 复制代码
# 1. 切换 root 用户(安装系统软件包需 root 权限)
su - root

# 2. 安装含 timesync 角色的 rhel-system-roles 包
sudo yum -y install rhel-system-roles

# 3. 复制 timesync 角色到文档指定路径(确保 Ansible 能找到)
cp -r /usr/share/ansible/roles/rhel-system-roles.timesync -p /home/student/ansible/roles/timesync
步骤 2:编写timesync.yml剧本
yaml 复制代码
# /home/student/ansible/timesync.yml
#/home/student/ansible/roles/timesync/README.md可以找模板
---
- name: 为 test01 组配置时间同步(文档要求)
  hosts: test01  # 文档要求 1:仅在 test01 组运行
  vars:
    # 文档要求 3:配置时间服务器及 iburst 参数
    timesync_ntp_servers:
      - hostname: ansible.example.com  # 文档指定的时间服务器
        iburst: yes  # 文档要求:启用 iburst(加速初始同步)
    # 补充配置:自动选择 NTP 服务(chronyd/ntpd)
    timesync_ntp_provider: auto
  roles:
    - timesync  # 文档要求 2:使用 timesync 角色
说明
  • 系统角色默认路径为/usr/share/ansible/roles,需复制到文档指定的/home/student/ansible/roles,否则 Ansible 无法加载角色;
  • iburst: yes的作用:初始同步时发送多个 NTP 请求,缩短时间同步耗时,完全满足文档要求;
  • timesync_ntp_provider: auto:让角色自动适配系统默认的 NTP 服务(RHEL9 默认 chronyd),无需手动指定,提升兼容性。

六、通过 galaxy 安装角色与 collection

题目要求

  1. 创建剧本/home/student/ansible/roles/down.yml,用来从以下 URL 下载角色,并安装到/home/student/ansible/roles目录下:http://ansible.example.com/roles/haproxy.tar(角色名为 haproxy)、http://ansible.example.com/roles/myphp.tar(角色名为 myphp);
  2. http://ansible.example.com/materials/下载如下 collection 并安装到/home/student/ansible/collections目录下:ansible-posix-1.5.1.tar.gzcommunity-general-6.3.0.tar.gz

答案

1. 安装角色(创建down.yml并执行)
步骤 1:创建角色安装清单(down.yml
yaml 复制代码
# /home/student/ansible/roles/down.yml
---
# 文档要求:安装 haproxy 角色
- name: haproxy  # 文档指定角色名
  src: http://ansible.example.com/roles/haproxy.tar  # 文档指定角色 URL
  
# 文档要求:安装 myphp 角色
- name: myphp  # 文档指定角色名
  src: http://ansible.example.com/roles/myphp.tar  # 文档指定角色 URL
步骤 2:执行角色安装
bash 复制代码
# 在控制机执行,从清单文件安装角色
ansible-galaxy install -r roles/down.yml -p roles/
2. 安装 Collection
yaml 复制代码
# 步骤 1:下载 Collection 到控制机指定目录
cd /home/student/ansible/
wget http://ansible.example.com/materials/ansible-posix-1.5.1.tar.gz
wget http://ansible.example.com/materials/community-general-6.3.0.tar.gz

# 步骤 2:安装 Collection 到文档指定路径
ansible-galaxy collection install ansible-posix-1.5.1.tar.gz -p /home/student/ansible/collections/
ansible-galaxy collection install community-general-6.3.0.tar.gz -p /home/student/ansible/collections/

# 验证安装结果
ansible-galaxy collection list -p /home/student/ansible/collections/

方法二:
cd /home/student/ansible/
ansible-galaxy collection install http://ansible.example.com/materials/ansible-posix-1.5.1.tar.gz -p collections/

ansible-galaxy collection install http://ansible.example.com/materials/community-general-6.3.0.tar.gz -p collections/
说明
  • 角色安装通过ansible-galaxy install -r实现:从down.yml清单读取角色信息,自动下载并安装到指定路径;
  • Collection 安装用-p指定路径:确保安装到文档要求的/home/student/ansible/collections,而非默认路径;
  • 验证步骤必不可少:通过ansible-galaxy collection list确认 Collection 已正确安装。

七、创建及使用自定义角色(httpd 角色与myrole.yml

题目要求

根据下列要求,在/home/student/ansible/roles中创建名为 httpd 的角色:

  1. 安装 httpd 软件,并能够开机自动运行;
  2. 开启防火墙,并允许 httpd 通过;
  3. 使用模板 index.html.j2,用来创建/var/www/html/index.html网页,内容如下(HOSTNAME 是受管理节点的完全域名,IPADDRESS 是 IP 地址):Welcome to HOSTNAME on IPADDRESS
    然后创建剧本 /home/student/ansible/myrole.yml,为 webtest 主机组启用 httpd 角色。

答案

步骤 1:创建 httpd 角色目录结构(控制机操作)
bash 复制代码
# 切换到角色目录,用 ansible-galaxy 自动生成标准化结构
cd /home/student/ansible/roles/
ansible-galaxy init httpd
步骤 2:编写角色核心文件
(1)任务文件(httpd/tasks/main.yml)------ 实现核心功能
yaml 复制代码
# /home/student/ansible/roles/httpd/tasks/main.yml
---
# 任务 1:安装 httpd 软件(文档要求 1)
- name: 安装 httpd 软件包
  yum:
    name: 
      - httpd
      - firewalld
    
    state: present  # 确保软件已安装

# 任务 2:设置 httpd 开机自启并启动(文档要求 1)
- name: 启动 httpd 服务并设置开机自启
  service:
    name: "{{ item }}"
    state: started  # 确保服务运行中
    enabled: yes  # 确保开机自启
  loop:
    - httpd
    - firewalld


- name: 允许 http 服务通过防火墙
  firewalld:
    service: http  # 对应 httpd 的默认服务名
    state: enabled
    permanent: yes  # 永久生效(重启防火墙不失效)
    immediate: yes  # 立即生效(无需重启防火墙)

# 任务 4:使用模板生成首页(文档要求 3)
- name: 从模板生成 /var/www/html/index.html
  template:
    src: index.html.j2  # 模板文件(存放在 roles/httpd/templates/ 下)
    dest: /var/www/html/index.html  # 目标文件路径
(2)模板文件(httpd/templates/index.html.j2)------ 动态生成网页
jinja2 复制代码
# /home/student/ansible/roles/httpd/templates/index.html.j2
# 文档要求:显示完全域名(HOSTNAME)和 IP 地址(IPADDRESS)
Welcome to {{ ansible_fqdn }} on {{ ansible_default_ipv4.address }}
  • 说明:ansible_fqdn 是 Ansible 内置 Facts 变量,自动获取受管机完全域名;ansible_default_ipv4.address 自动获取默认网卡的 IP 地址,完全匹配"HOSTNAME"和"IPADDRESS"的需求。
步骤 3:创建调用角色的剧本(myrole.yml
yaml 复制代码
# /home/student/ansible/myrole.yml
---
- name: 为 webtest 主机组启用 httpd 角色(文档要求)
  hosts: webtest  # 目标主机组(文档指定)
  roles:
    - httpd  # 调用自定义的 httpd 角色
执行与验证
bash 复制代码
# 1. 执行剧本,为 webtest 组部署 httpd 服务
ansible-playbook /home/student/ansible/myrole.yml

# 2. 验证(在控制机访问 webtest 组节点,如 node3)
curl http://node3.example.com
# 预期输出:Welcome to node3.example.com on 192.168.122.30(与节点实际信息匹配)
说明
  • 角色目录结构通过 ansible-galaxy init 生成,确保符合 Ansible 标准化规范,避免手动创建目录遗漏;
  • 模板文件中直接使用 Ansible 内置 Facts 变量,无需额外定义,实现"动态获取主机信息"的需求;
  • 剧本中 hosts: webtest 严格匹配文档"为 webtest 主机组启用角色"的要求,确保任务仅在目标组执行。

八、使用之前通过 galaxy 下载的角色(创建web.yml

题目要求

创建剧本/home/student/ansible/web.yml,满足下列需求:

  1. 该剧本中包含一个 play,可以在 test05 主机组运行 haproxy 角色(此角色已经配置好网站的负载均衡服务);
  2. 多次访问 http://node5.example.com 可以输出不同主机的欢迎页面;
  3. 该剧本中包含另一个 play,可以在 webtest 主机组运行 myphp 角色(此角色已经配置好网站的 php 页面);
  4. 多次访问 http://node5.example.com/index.php 也输出不同主机的欢迎页面。

答案

yaml 复制代码
# /home/student/ansible/web.yml
---
# Play 1:在 test05 组运行 haproxy 角色(文档要求 1)
- name: get fact
  hosts: webtest
- name: 为 test05 主机组部署 haproxy 负载均衡(文档要求 1)
  hosts: test05  # 文档指定目标组:test05
  become: yes
  roles:
    - haproxy  # 调用之前通过 Galaxy 下载的 haproxy 角色
  # 说明:haproxy 角色已预设负载均衡配置,指向 webtest 组节点,满足"访问 node5 输出不同页面"(文档要求 2)

# Play 2:在 webtest 组运行 myphp 角色(文档要求 3)
- name: 为 webtest 主机组部署 myphp 服务(文档要求 3)
  hosts: webtest  # 文档指定目标组:webtest
  roles:
    - myphp  # 调用之前通过 Galaxy 下载的 myphp 角色
  # 说明:myphp 角色已配置 PHP 页面,结合 haproxy 负载均衡,满足"访问 index.php 输出不同页面"(文档要求 4)
执行与验证
bash 复制代码
# 1. 执行剧本,部署 haproxy 和 myphp 角色
ansible-playbook /home/student/ansible/web.yml

# 2. 验证文档要求 2:访问 http://node5.example.com 输出不同页面
curl http://node5.example.com
# 预期输出:交替显示 node3 和 node4 的欢迎页面(haproxy 负载均衡生效)

# 3. 验证文档要求 4:访问 http://node5.example.com/index.php 输出不同页面
curl http://node5.example.com/index.php\
# 预期输出:交替显示 node3 和 node4 的 PHP 欢迎页面(myphp 角色+负载均衡生效)
说明
  • 两个 Play 严格按文档要求拆分:Play 1 处理 test05 组的 haproxy 负载均衡,Play 2 处理 webtest 组的 myphp 服务,逻辑边界清晰;
  • 负载均衡效果依赖 haproxy 角色预设配置(默认指向 webtest 组节点),无需额外编写负载均衡规则,符合文档"角色已配置好"的前提;
  • 多次访问验证是关键:通过循环访问确认负载均衡生效,满足"输出不同主机页面"的需求。

九、编写剧本远程管理逻辑卷(创建lvm.yml

题目要求

创建剧本 /home/student/ansible/lvm.yml,用来为所有受管机完成以下部署:

  1. 在卷组 search 中创建名为 mylv 的逻辑卷,大小为 1000MiB;
  2. 使用 ext4 文件系统格式化该逻辑卷;
  3. 如果无法创建要求的大小,应显示错误信息 insufficient free space,并改为 500MiB;
  4. 如果卷组 search 不存在,应显示错误信息 VG not found;
  5. 不需要挂载逻辑卷。

答案

yaml 复制代码
# /home/student/ansible/lvm.yml
---
- name: 管理逻辑卷(在 search 卷组创建 mylv)(文档要求)
  hosts: all  # 目标:所有受管机
  tasks:
    # 任务 1:检查卷组 search 是否存在(文档要求 4)
    - name: 检查卷组 search 的存在性
      command: vgdisplay search
      register: vg_check_result
      ignore_errors: yes  # 忽略卷组不存在的错误,避免剧本中断

    # 任务 2:卷组不存在时显示错误信息(文档要求 4)
    - name: 卷组 search 不存在,输出错误信息
      debug:
        msg: "ERROR: VG not found"  # 文档要求的错误信息
      when: vg_check_result.rc != 0  # 命令返回码非 0 表示卷组不存在

    # 任务 3:卷组存在时,尝试创建 1000MiB 的逻辑卷(文档要求 1)
    - name: 尝试在 search 卷组创建 1000MiB 的 mylv
      lvol:
        vg: search
        lv: mylv
        size: 1000MiB
        state: present
      register: lv_create_result
      ignore_errors: yes  # 忽略空间不足的错误
      when: vg_check_result.rc == 0  # 仅卷组存在时执行

    # 任务 4:空间不足时,显示错误并创建 500MiB 逻辑卷(文档要求 3)
    - name: 空间不足,显示错误并创建 500MiB 的 mylv
      block:
        # 显示空间不足错误
        - name: 输出空间不足错误信息
          debug:
            msg: "ERROR: insufficient free space"  # 文档要求的错误信息

        # 创建 500MiB 逻辑卷
        - name: 创建 500MiB 的 mylv 逻辑卷
          lvol:
            vg: search
            lv: mylv
            size: 500MiB
            state: present
      when:
        - vg_check_result.rc == 0  # 卷组存在
        - lv_create_result.rc != 0  # 1000MiB 创建失败(空间不足)

    # 任务 5:格式化逻辑卷为 ext4(文档要求 2)
    - name: 用 ext4 格式化 mylv 逻辑卷
      filesystem:
        fstype: ext4
        dev: /dev/search/mylv  # 逻辑卷设备路径
      when:
        - vg_check_result.rc == 0  # 卷组存在
        - (lv_create_result.rc == 0 or "created" in lv_create_result.msg)  # 逻辑卷已创建
说明
  • vgdisplay search 检查卷组存在性:通过命令返回码判断,而非依赖 Facts,避免 Facts 未更新导致误判;
  • 分条件处理逻辑:卷组不存在→输出"VG not found";空间不足→输出"insufficient free space"并创建 500MiB 卷;正常情况→创建 1000MiB 卷,完全匹配文档要求;
  • block 模块用于批量执行任务:将"显示错误+创建小卷"打包,避免重复写 when 条件,简化代码。
yaml 复制代码
---
- name: cerate lv
  hosts: all
  tasks: 
    - name: create lv1
      block:
        - name: create 1000 lv
          lvol:
            vg: search
            lv: mylv
            size: 1000
      rescue:
        - name: print message
          debug:
            msg: insufficient free space
        - name: create 500 lv
          lvol:
            vg: search
            lv: mylv
            size: 500
      always:
        - name: format lv
          filesystem:
            dev: /dev/search/mylv
            fstype: ext4
      when: "'search' in ansible_lvm.vgs"
    - name: print failed message
      debug:
        msg: VG not found
      when: "'search' not in ansible_lvm.vgs "

十、根据模板部署主机文件(创建newhosts.yml

题目要求

http://ansible.example.com/materials/newhosts.j2 下载模板文件,完成该模板文件,用来生成新主机清单(主机的显示顺序没有要求),结构如下:

复制代码
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.122.10 node1.example.com node1
192.168.122.20 node2.example.com node2
192.168.122.30 node3.example.com node3
192.168.122.40 node4.example.com node4
192.168.122.50 node5.example.com node5

创建剧本/home/student/ansible/newhosts.yml,它将使用上述模板在 test01 主机组的主机上生成文件/etc/newhosts

答案

步骤 1:下载并完善模板文件(控制机操作)
bash 复制代码
# 1. 下载模板到指定目录
cd /home/student/ansible/
curl -O  http://ansible.example.com/materials/newhosts.j2
vim newhost.j2

{% for i in groups.all %}
{{ hostvars[i].ansible_default_ipv4.address }} {{ hostvars[i].ansible_fqdn }} {{ hostvars[i].ansible_hostname }}
{% endfor %}
步骤 2:编写剧本(newhosts.yml
yaml 复制代码
# /home/student/ansible/newhosts.yml
---
- name: get fact
  hosts: all
- name: 为 test01 组生成 /etc/newhosts 文件(文档要求)
  hosts: test01  # 文档要求:仅在 test01 组运行
  gather_facts: no  # 模板为固定内容,无需收集主机信息,加快执行速度
  tasks:
    - name: 使用 newhosts.j2 模板生成 /etc/newhosts
      template:
        src: /home/student/ansible/newhosts.j2  # 本地模板路径
        dest: /etc/newhosts  # 文档要求的目标文件路径
执行与验证
bash 复制代码
# 1. 执行剧本
ansible-playbook /home/student/ansible/newhosts.yml

# 2. 验证(在 test01 组节点 node1 执行)
cat /etc/newhosts
# 预期输出与模板内容完全一致,包含所有主机的 IP 与主机名映射
说明
  • 模板为固定内容:因文档要求的主机清单结构是静态的(IP 和主机名已明确),无需使用 Jinja2 变量,直接写入固定内容即可;
  • gather_facts: no 优化执行效率:避免收集不必要的主机信息,减少剧本执行时间;
  • 权限设置符合系统规范:/etc/newhosts 作为系统配置文件,权限设为 0644,确保root可修改、其他用户可读取。

十一、编写剧本修改远程文件内容(创建newissue.yml

题目要求

创建剧本 /home/student/ansible/newissue.yml,满足下列要求:

  1. 在所有清单主机上运行,替换/etc/issue的内容;
  2. 对于 test01 主机组中的主机,/etc/issue 文件内容为 test01;
  3. 对于 test02 主机组中的主机,/etc/issue 文件内容为 test02;
  4. 对于 web 主机组中的主机,/etc/issue 文件内容为 Webserver。

答案

yaml 复制代码
# /home/student/ansible/newissue.yml
---
- name: Configure /etc/issue based on host group
  hosts: all  # 在所有清单主机上执行
  tasks:
    - name: Set /etc/issue content by host group
      copy:
        content: |
          {% if 'test01' in group_names %}
          test01
          {% elif 'test02' in group_names %}
          test02
          {% elif 'web' in group_names %}
          Webserver
          {% endif %}
        dest: /etc/issue  # 目标文件路径
yaml 复制代码
[student@master ansible]$ ansible node1 -m shell -a "cat /etc/issue"
node1 | CHANGED | rc=0 >>
test01

十二、编写剧本部署远程 Web 目录(创建webdev.yml

题目要求

创建剧本/home/student/ansible/webdev.yml,满足下列要求:

  1. 在 test01 主机组运行;
  2. 创建目录/webdev,属于 webdev 组,权限为 rwxrwxr-x,具有 SetGID 特殊权限;
  3. 使用符号链接/var/www/html/webdev链接到/webdev目录;
  4. 创建文件/webdev/index.html,内容是 It's works!;
  5. 查看 test01 主机组的 web 页面 http://node1/webdev/ 将显示 It's works!。

答案

yaml 复制代码
# /home/student/ansible/webdev.yml
---
- name: 为 test01 组部署 Web 目录(文档要求)
  hosts: test01  # 文档要求 1:仅在test01组运行
  tasks:
    - name: install httpd
      yum:
        name: 
          - httpd
          - firewalld
        state: present

    - name: 创建 webdev 用户组
      group:
        name: webdev
        state: present

    - name: 创建 /webdev 目录(rwxrwxr-x + SetGID)
      file:
        path: /webdev
        state: directory
        group: webdev 
        mode: '2775'   # 2=SetGID,775=rwxrwxr-x,完全匹配权限要求
        setype: httpd_sys_content_t

    - name: 创建符号链接 /var/www/html/webdev
      file:
        src: /webdev  
        dest: /var/www/html/webdev  
        state: link  

   
    - name: 创建 /webdev/index.html,写入内容 It's works!
      copy:
        content: "It's works!\n"
        dest: /webdev/index.html
        mode: '0644'
        setype: httpd_sys_content_t
   
    - name: 启动 httpd 服务并设置开机自启
      service:
        name: "{{ item }}"
        state: restarted
        enabled: yes
      loop: 
        - httpd
        - firewalld
    - name: set firewalld
      firewalld:
        service: http
        state: enabled
        permanent: yes
        immediate: yes
执行与验证
bash 复制代码
# 1. 执行剧本部署Web目录
ansible-playbook /home/student/ansible/webdev.yml
curl http://node1/webdev/  # 预期输出:It's works!
说明
  • 目录权限2775的含义:2代表SetGID(确保后续在该目录创建的文件自动继承目录组权限),775对应rwxrwxr-x,完全匹配文档权限要求;
  • 符号链接用state: link创建:Ansiblefile模块的link类型专门用于创建符号链接,需明确src(源路径)和dest(目标路径);
  • 补充httpd服务启动任务:若之前未部署httpd,需确保服务运行才能访问Web页面,满足文档"查看web页面"的最终需求。

十三、编写剧本为受管机生成硬件报告(创建hardware.yml

题目要求

创建名为/home/student/ansible/hardware.yml的 playbook,满足下列要求:

  1. 使所有受管理节点从以下 URL 下载文件:http://ansible.example.com/materials/hardware.empty
  2. 并用来生成以下硬件报告信息,存储在各自的/root/hardware.txt文件中:清单主机名称inventory_hostname、以 MB 表示的总内存大小ansible_memtotal_mb、BIOS 版本ansible_bios_version、硬盘 vda 的大小ansible_devices.vda.size、硬盘 vdb 的大小ansible_devices.vdb.size;如果这些硬件信息不存在的话,则改成 NONE 字符串。

答案

yaml 复制代码
# /home/student/ansible/hardware.yml
---
- name: 为所有受管机下载文件并生成硬件报告(文档要求)
  hosts: all  # 目标:所有受管机
  become: yes
  tasks:
    # 任务 1:下载 hardware.empty 文件(文档要求 1)
    - name: 从远程 URL 下载 hardware.empty 到 /tmp
      get_url:
        url: http://ansible.example.com/materials/hardware.empty  # 文档指定URL
        dest: /tmp/hardware.empty  # 下载到临时目录
        mode: '0644'
        owner: root
        group: root
        force: yes  # 若文件已存在,强制覆盖

    # 任务 2:生成硬件报告 /root/hardware.txt(文档要求 2)
    - name: 生成硬件报告到 /root/hardware.txt
      copy:
        content: |
          清单主机名称: {{ inventory_hostname | default('NONE') }}
          总内存大小(MB): {{ ansible_memtotal_mb | default('NONE') }}
          BIOS版本: {{ ansible_bios_version | default('NONE') }}
          硬盘vda大小: {{ ansible_devices.vda.size | default('NONE') if 'vda' in ansible_devices else 'NONE' }}
          硬盘vdb大小: {{ ansible_devices.vdb.size | default('NONE') if 'vdb' in ansible_devices else 'NONE' }}
        dest: /root/hardware.txt  # 文档指定的报告路径
        mode: '0600'  # 仅root可读写,保护硬件信息
        owner: root
        group: root
执行与验证
bash 复制代码
# 1. 执行剧本(需收集Facts,默认开启)
ansible-playbook /home/student/ansible/hardware.yml

# 2. 验证硬件报告(在任意受管机执行,如node1)
ssh student@node1 "sudo cat /root/hardware.txt"
# 预期输出示例:
# 清单主机名称: node1.example.com
# 总内存大小(MB): 1982
# BIOS版本: 1.16.0
# 硬盘vda大小: 20.00 GB
# 硬盘vdb大小: NONE(若vdb不存在)
说明
  • default('NONE')处理变量缺失:对于inventory_hostnameansible_memtotal_mb等简单变量,直接用default过滤器指定默认值为NONE
  • if 'vda' in ansible_devices处理设备不存在:ansible_devices是存储设备信息的字典,需先判断vda/vdb是否在字典中,再获取大小,避免"键不存在"报错;
  • 报告权限设为0600/root/hardware.txt存储硬件敏感信息,仅允许root读写,符合安全规范;
  • get_url模块下载文件:自动处理HTTP下载,force: yes确保下载最新文件,避免旧文件干扰。

方法二:

创建名为/home/student/ansible/hardware.yml的 playbook,满足下列要求:

  1. 使所有受管理节点从以下 URL 下载文件:http://ansible.example.com/materials/hardware.empty

  2. 并用来生成以下硬件报告信息,存储在各自的/root/hardware.txt文件中:

    清单主机名称inventory_hostname

    以 MB 表示的总内存大小ansible_memtotal_mb

    BIOS 版本ansible_bios_version

    硬盘 vda 的大小ansible_devices.vda.size

    硬盘 vdb 的大小ansible_devices.vdb.size

    如果这些硬件信息不存在的话,则改成 NONE 字符串。

yaml 复制代码
curl -O http://ansible.example.com/materials/hardware.empty

vim hardware.empty
hostname=inventoryhostname
mem=memory_in_MB
bios=BIOS_version
vdasize=disk_vda_size
vdbsize=disk_vdb_size

## 查看信息的事实变量
ansible node1 -m setup > a
vim a

vim hardware.yml
--- 
- name: test
  hosts: all
  tasks:
    - name: test2
      get_url:
        url: http://ansible.example.com/materials/hardware.empty
        dest: /root/hardware.txt
        
    - name: hostname
      replace:
        path: /root/hardware.txt
        regexp: inventoryhostname
        replace: "{{ inventory_hostname }}"
        
    - name: men
      replace:
        path: /root/hardware.txt
        regexp: memory_in_MB
        replace: "{{ ansible_memtotal_mb }}"
        
    - name: bios
      replace:
        path: /root/hardware.txt
        regexp: BIOS_version
        replace: "{{ ansible_bios_version }}"
        
    - name: vda
      replace:
        path: /root/hardware.txt
        regexp: disk_vda_size
        replace: "{{ ansible_devices.vda.size if ansible_devices.vda is defined else 'NONE' }}"
    - name: vdb
      replace:
        path: /root/hardware.txt
        regexp: disk_vdb_size
        replace: "{{ ansible_devices.vdb.size if ansible_devices.vdb is defined else 'NONE'}}"

十四、创建保险库文件(passdb.yml

题目要求

创建 ansible 保险库 /home/student/ansible/passdb.yml,其中有 2 个变量:

  1. pw_dev,值为 ab1234;
  2. pw_man,值为 cd5678;
    加密和解密该库的密码是 pwd@1234,密码存在/home/student/ansible/secret.txt中。

答案

步骤 1:创建密码文件(存储保险库密码)
bash 复制代码
# 在控制机创建 secret.txt,写入保险库密码
echo "pwd@1234" > /home/student/ansible/secret.txt

# 设置权限为 0600,仅student可读写(避免密码泄露)
chmod 0600 /home/student/ansible/secret.txt
步骤 2:创建未加密的变量文件
bash 复制代码
# 创建 passdb.yml,写入 2 个变量(文档要求)
---
pw_dev: ab1234
pw_man: cd5678
步骤 3:用密码文件加密保险库
bash 复制代码
# 使用 secret.txt 中的密码加密 passdb.yml
ansible-vault encrypt passdb.yml --vault-id secret.txt

# 验证加密状态(尝试查看文件,需解密)
ansible-vault view passdb.yml --vault-id secret.txt
# 预期输出:解密后的变量内容(pw_dev: ab1234;pw_man: cd5678)
  • 密码文件权限0600:确保只有student用户能读取密码,避免其他用户获取保险库解密权限;
  • ansible-vault encrypt加密文件:加密后文件内容变为乱码,需通过--vault-password-file指定密码文件才能解密;
  • ansible-vault view验证加密:解密查看文件内容,确认变量正确且加密生效,避免后续使用时因变量错误或加密失败导致问题。

十五、编写剧本为受管机批量创建用户(创建users.yml

题目要求

从以下 URL 下载用户列表,保存到/home/student/ansible目录下:http://ansible.example.com/materials/name_list.yml

创建剧本/home/student/ansible/users.yml的 playbook,满足下列要求:

  1. 使用之前题目中的 passdb.yml 保险库文件提供的密码做用户密码;
  2. 职位描述为 dev 的用户应在 test01、test02 主机组的受管机上创建,使用 pw_dev 变量分配密码,是补充组 devops 的成员;
  3. 职位描述为 man 的用户应在 web 主机组的受管机上创建,使用 pw_man 变量分配密码,是补充组 opsmgr 的成员;
  4. 密码应采用 SHA512 哈希格式,这几个用户的密码最大有效时间为30天;
  5. 该 playbook 可以使用之前题目创建的 secret.txt 密码文件运行。

答案

步骤 1:下载用户列表(控制机操作)
bash 复制代码
# 下载 name_list.yml 到指定目录
cd /home/student/ansible/
curl -O http://ansible.example.com/materials/name_list.yml
vim name_list.yml
users:
  - name: tom
    job: dev
  - name: jerry
    job: man
步骤 2:编写users.yml剧本
yaml 复制代码
vim users.yml
 
---
- name: test1
  hosts: test01:test02
  vars_files:
    - /home/student/ansible/passdb.yml
    - /home/student/ansible/name_list.yml
  tasks:
    - name: test2
      group:
        name: devops
        state: present
    - name: create user
      user:
        name: "{{ item.name }}"
        state: present
        groups: devops
        password: "{{ pw_dev | password_hash('sha512') }}"
        password_expire_max: 30
      loop: "{{ users }}"
      when: item.job == 'dev'


- name: test2
  hosts: web
  vars_files:
    - /home/student/ansible/passdb.yml
    - /home/student/ansible/name_list.yml
  tasks:
    - name: test3
      group:
        name: opsmgr
        state: present
    - name: create user1
      user:
        name: "{{ item.name }}"
        state: present
        groups: opsmgr
        password: "{{ pw_man | password_hash('sha512') }}"
        password_expire_max: 30
      loop: "{{ users }}"
      when: item.job == 'man'
复制代码
##执行
ansible-playbook users.yml --vault-id secret.txt
##验证
ssh root@node1
vi /etc/shadow
yaml 复制代码
# vim users.yml
---
# Play 1:为 test01、test02 组创建 dev 职位用户(文档要求 2)
- name: 为 test01/test02 组创建 dev 职位用户
  hosts: test01:test02  # 文档指定的目标组
  become: yes
  # 引用保险库文件和用户列表(文档要求 1、5)
  vars_files:
    - /home/student/ansible/passdb.yml  # 保险库文件(含pw_dev)
    - /home/student/ansible/name_list.yml  # 用户列表(含职位描述)
  tasks:
    # 先创建补充组 devops(文档要求 2)
    - name: 创建 devops 补充组
      group:
        name: devops
        state: present

    # 批量创建 dev 职位用户
    - name: 创建 dev 职位用户(补充组 devops)
      user:
        name: "{{ item.name }}"  # 从用户列表获取用户名
        comment: "{{ item.desc | default('Dev User') }}"  # 职位描述(默认值)
        # 文档要求 4:SHA512 哈希密码(pw_dev 来自保险库)
        password: "{{ pw_dev | password_hash('sha512') }}"
        groups: devops  # 文档要求 2:补充组 devops
        append: yes  # 不覆盖用户原有补充组
        # 文档要求 4:密码最大有效时间 30 天
        password_expire_max: 30
        state: present
      loop: "{{ user_list }}"  # 假设用户列表变量名为 user_list(需与 name_list.yml 一致)
      when: item.job == "dev"  # 文档要求 2:仅职位为 dev 的用户

# Play 2:为 web 组创建 man 职位用户(文档要求 3)
- name: 为 web 组创建 man 职位用户
  hosts: web  # 文档指定的目标组
  become: yes
  vars_files:
    - /home/student/ansible/passdb.yml  # 保险库文件(含pw_man)
    - /home/student/ansible/name_list.yml  # 用户列表
  tasks:
    # 先创建补充组 opsmgr(文档要求 3)
    - name: 创建 opsmgr 补充组
      group:
        name: opsmgr
        state: present

    # 批量创建 man 职位用户
    - name: 创建 man 职位用户(补充组 opsmgr)
      user:
        name: "{{ item.name }}"
        comment: "{{ item.desc | default('Man User') }}"
        # 文档要求 4

十六、重设保险库密码

从以下 URL 下载保险库文件到/home/student/ansible 目录:

http://ansible.example.com/materials/topsec.yml

当前的库密码是 banana,新密码是 big_banana,请更新该库密码

yaml 复制代码
curl -O  http://ansible.example.com/materials/topsec.yml
ansible-vault rekey topsec.yml
ansible-vault view topsec.yml
相关推荐
程序员清风4 小时前
贝壳一面:年轻代回收频率太高,如何定位?
java·后端·面试
考虑考虑4 小时前
Java实现字节转bcd编码
java·后端·java ee
软件开发-NETKF88884 小时前
JSP到Tomcat特详细教程
java·开发语言·tomcat·jsp·项目运行
渣哥5 小时前
为什么 JDK 1.8 要给 HashMap 加红黑树?
java
我登哥MVP5 小时前
Java 网络编程学习笔记
java·网络·学习
大厂码农老A5 小时前
面试官:“聊聊你最复杂的项目?” 为什么90%的候选人第一句就栽了?
java·面试
小欣加油5 小时前
leetcode 912 排序数组(归并排序)
数据结构·c++·算法·leetcode·排序算法
爱读源码的大都督5 小时前
Java已死?别慌,看我如何用Java手写一个Qwen Code Agent,拯救Java
java·人工智能·后端
lssjzmn5 小时前
性能飙升!Spring异步流式响应终极指南:ResponseBodyEmitter实战与架构思考
java·前端·架构