介绍
在本篇综合实验中,你将掌握使用 Ansible 自动化关键的 Linux 管理任务。在你掌握了文件管理的基础后,你将探索如何管理系统管理的完整生命周期,从软件安装到用户管理、服务配置、存储配置和网络设置。
你将首先使用 ansible.builtin.dnf、ansible.builtin.yum_repository 和 ansible.builtin.rpm_key 等模块来自动化软件包管理和仓库配置。接下来,你将创建和管理用户账户,配置 SSH 访问,并设置 sudo 权限。本实验将逐步进行服务管理、使用 cron 和 systemd 进行计划任务,然后进阶到使用 LVM 和文件系统操作进行存储管理。最后,你将配置网络接口并收集系统信息。
本实验强调在企业 Linux 环境中常见的真实场景,帮助你有效地实施基础设施即代码(Infrastructure as Code)实践。
配置仓库和管理软件包
在本步骤中,你将学习如何使用 Ansible 在 RHEL 系统上自动化软件包管理。你将配置一个 Yum 仓库,管理 RPM GPG 密钥,并在托管主机上收集软件包信息。这对于在你的基础设施中维护一致的软件安装至关重要。
你将使用几个关键模块:ansible.builtin.yum_repository 用于仓库管理,ansible.builtin.rpm_key 用于 GPG 密钥处理,ansible.builtin.package_facts 用于收集软件包信息,以及 ansible.builtin.dnf 用于软件包安装。
首先,设置项目环境并安装 Ansible。
安装
ansible-core包并导航到项目目录。sudo dnf install -y ansible-core cd ~/project mkdir system-software cd system-software创建 Ansible inventory 文件 来定义我们的托管主机。在本实验中,我们将管理本地机器。
cat << EOF > inventory.ini [webservers] localhost ansible_connection=local [all:children] webservers EOF**创建主 playbook
repo_playbook.yml**,它将管理仓库配置和软件包安装。此 playbook 演示了一个完整的软件管理工作流程。nano repo_playbook.yml添加以下内容来创建一个全面的软件管理 playbook:
--- - name: Repository Configuration and Software Management hosts: all become: true vars: custom_pkg: httpd tasks: - name: Gather Package Facts ansible.builtin.package_facts: manager: auto - name: Show Package Facts for the custom package (initial check) ansible.builtin.debug: var: ansible_facts['packages'][custom_pkg] when: custom_pkg in ansible_facts['packages'] - name: Ensure EPEL repository is configured ansible.builtin.yum_repository: name: epel description: Extra Packages for Enterprise Linux 9 file: epel baseurl: https://download.fedoraproject.org/pub/epel/9/Everything/x86_64/ gpgcheck: yes gpgkey: https://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-9 enabled: yes state: present - name: Import EPEL GPG key ansible.builtin.rpm_key: state: present key: https://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-9 - name: Install the custom package ansible.builtin.dnf: name: "{{ custom_pkg }}" state: present - name: Gather Package Facts (after installation) ansible.builtin.package_facts: manager: auto - name: Show Package Facts for the custom package (post-installation) ansible.builtin.debug: var: ansible_facts['packages'][custom_pkg] when: custom_pkg in ansible_facts['packages'] - name: Display installed package version ansible.builtin.debug: msg: "{{ custom_pkg }} version {{ ansible_facts['packages'][custom_pkg][0]['version'] }} is installed" when: custom_pkg in ansible_facts['packages']注意: 本实验中的配置文件相当长,为了保持文档简洁,此处不提供详细解释。如果你需要任何部分的解释,请点击代码块左下角的“Explain Code”按钮,获取 Labby 提供的详细解释。
此 playbook 演示了几个重要概念:
- 软件包事实收集:展示了如何收集已安装软件包的信息
- 仓库管理:配置 EPEL 仓库并进行适当的 GPG 验证
- GPG 密钥管理:导入仓库的 GPG 密钥以确保安全
- 软件包安装:使用 dnf 模块安装指定的软件包
- 验证:通过更新的事实确认软件包安装
执行 playbook 以查看完整的软件管理工作流程。
ansible-playbook -i inventory.ini repo_playbook.yml你应该会看到输出显示:
- 初始软件包检查(由于 httpd 未安装,可能被跳过)
- 仓库配置
- GPG 密钥导入
- 软件包安装
- 最终验证显示已安装的软件包
验证仓库配置,通过检查创建的仓库文件。
cat /etc/yum.repos.d/epel.repo你应该会看到 EPEL 仓库配置,其中包含 baseurl、gpgcheck 和 gpgkey 设置。
测试软件包管理的幂等性,再次运行 playbook。
ansible-playbook -i inventory.ini repo_playbook.yml请注意,Ansible 会报告不需要更改的任务为“ok”,这展示了其幂等性。
你已成功使用 Ansible 自动化了软件软件包管理,包括仓库配置、GPG 密钥管理和软件包安装验证。
自动化用户管理和 SSH 配置
在本步骤中,你将学习如何使用 Ansible 自动化用户账户管理、SSH 配置和 sudo 权限。这对于在你的基础设施中维护一致的用户访问和安全策略至关重要。
你将使用诸如 ansible.builtin.user 用于用户管理,ansible.builtin.group 用于组创建,ansible.posix.authorized_key 用于 SSH 密钥管理,以及 ansible.builtin.lineinfile 用于配置文件修改等模块。
导航到新的项目目录以进行用户管理任务。
cd ~/project mkdir system-users cd system-users安装
ansible.posixcollection。ansible-galaxy collection install ansible.posix创建本次实验的 inventory 文件。
cat << EOF > inventory.ini [webservers] localhost ansible_connection=local EOF创建一个变量文件 来定义我们要管理的用户的组和用户。
mkdir vars nano vars/users_vars.yml添加以下内容来定义用户账户及其组的成员关系:
--- users: - username: webuser1 groups: webadmin - username: webuser2 groups: webadmin - username: devuser1 groups: webadmin为我们的用户生成 SSH 密钥对。在实际环境中,用户会提供他们的公钥。
mkdir files ## 为每个用户生成 SSH 密钥 ssh-keygen -t rsa -b 2048 -f files/webuser1.key -N "" -C "webuser1@example.com" ssh-keygen -t rsa -b 2048 -f files/webuser2.key -N "" -C "webuser2@example.com" ssh-keygen -t rsa -b 2048 -f files/devuser1.key -N "" -C "devuser1@example.com"**创建主用户管理 playbook
users.yml**。此 playbook 将创建组、用户,分发 SSH 密钥,并配置 sudo 访问。nano users.yml添加以下全面的用户管理 playbook:
--- - name: Create and manage user accounts hosts: webservers become: true vars_files: - vars/users_vars.yml tasks: - name: Create webadmin group ansible.builtin.group: name: webadmin state: present - name: Create user accounts ansible.builtin.user: name: "{{ item['username'] }}" groups: "{{ item['groups'] }}" shell: /bin/bash create_home: yes state: present loop: "{{ users }}" - name: Set up SSH authorized keys ansible.posix.authorized_key: user: "{{ item['username'] }}" key: "{{ lookup('file', 'files/' + item['username'] + '.key.pub') }}" state: present loop: "{{ users }}" - name: Configure sudo access for webadmin group ansible.builtin.lineinfile: path: /etc/sudoers.d/webadmin state: present create: yes mode: "0440" line: "%webadmin ALL=(ALL) NOPASSWD: ALL" validate: /usr/sbin/visudo -cf %s - name: Configure SSH to disable root login ansible.builtin.lineinfile: dest: /etc/ssh/sshd_config regexp: "^PermitRootLogin" line: "PermitRootLogin no" backup: yes notify: restart sshd - name: Configure SSH to disable password authentication ansible.builtin.lineinfile: dest: /etc/ssh/sshd_config regexp: "^PasswordAuthentication" line: "PasswordAuthentication no" backup: yes notify: restart sshd handlers: - name: restart sshd ansible.builtin.service: name: sshd state: restarted此 playbook 演示了几个用户管理最佳实践:
- 组管理:创建管理组
- 用户创建:设置用户账户及其正确的家目录
- SSH 密钥管理:分发公钥以进行基于密钥的认证
- Sudo 配置:安全地授予管理权限
- SSH 加固:禁用 root 登录和密码认证
- 服务管理:在配置更改时重启 SSH 服务
执行用户管理 playbook。
ansible-playbook -i inventory.ini users.ymlPlaybook 将创建用户,设置 SSH 密钥,配置 sudo 访问,并加固 SSH 配置。
验证用户创建和组的成员关系。
## 检查用户是否已创建 getent passwd webuser1 webuser2 devuser1 ## 检查组的成员关系 groups webuser1 groups webuser2 groups devuser1 ## 验证 webadmin 组是否存在 getent group webadmin测试其中一个已创建用户的 SSH 密钥认证。
## 测试 SSH 密钥认证(这将连接到 localhost) ssh -i files/webuser1.key webuser1@localhost "whoami"验证 sudo 配置,通过测试无密码的 sudo 访问。
## 测试 webuser1 的 sudo 访问 ssh -i files/webuser1.key webuser1@localhost "sudo whoami"检查 SSH 配置更改。
## 验证 SSH 配置 sudo grep "PermitRootLogin\|PasswordAuthentication" /etc/ssh/sshd_config ## 检查 sudo 配置 sudo cat /etc/sudoers.d/webadmin
你已成功使用 Ansible 自动化了用户账户创建、SSH 密钥分发和安全配置,为跨基础设施的安全用户管理奠定了基础。
自动化服务管理和任务调度
在本步骤中,你将学习如何使用 Ansible 管理 systemd 服务、调度 cron 作业以及配置系统启动目标。这对于维护服务可用性和自动化基础设施中的例行任务至关重要。
你将使用诸如 ansible.builtin.service 用于服务管理,ansible.builtin.cron 用于调度任务,ansible.posix.at 用于一次性任务,以及 ansible.builtin.systemd 用于系统目标管理等模块。
导航到新的项目目录以进行服务和进程管理。
cd ~/project mkdir system-process cd system-process创建本次实验的 inventory 文件。
cat << EOF > inventory.ini [webservers] localhost ansible_connection=local EOF创建一个 playbook 来管理 Apache HTTP 服务器服务。这将演示基本的服务管理。
nano service_management.yml添加以下内容:
--- - name: Manage Apache HTTP Server Service hosts: webservers become: true tasks: - name: Start and enable httpd service ansible.builtin.service: name: httpd state: started enabled: yes - name: Create a simple index.html ansible.builtin.copy: content: | <html> <head><title>Ansible Managed Server</title></head> <body> <h1>Welcome to Ansible Managed Apache Server</h1> <p>This server is configured and managed by Ansible.</p> <p>Service started at: $(date)</p> </body> </html> dest: /var/www/html/index.html owner: apache group: apache mode: "0644" - name: Verify httpd service is running ansible.builtin.service_facts: - name: Display httpd service status ansible.builtin.debug: var: ansible_facts.services['httpd.service']创建一个用于调度 cron 作业的 playbook。这演示了自动化任务调度。
nano create_crontab_file.yml添加以下内容:
--- - name: Schedule recurring cron jobs hosts: webservers become: true tasks: - name: Create labex user for cron jobs ansible.builtin.user: name: labex state: present create_home: yes - name: Schedule system monitoring cron job ansible.builtin.cron: name: System monitoring log job: "date >> /home/labex/system_monitor.log && df -h >> /home/labex/system_monitor.log" minute: "*/5" hour: "*" user: labex cron_file: system-monitoring state: present - name: Schedule daily log rotation ansible.builtin.cron: name: Daily log cleanup job: "find /home/labex -name '*.log' -mtime +7 -delete" minute: "0" hour: "2" weekday: "*" user: labex cron_file: log-cleanup state: present - name: Schedule weekly system update check ansible.builtin.cron: name: Weekly update check job: "dnf check-update > /home/labex/update_check.log 2>&1" minute: "0" hour: "3" weekday: "0" user: labex cron_file: update-check state: present创建一个使用
at调度一次性任务的 playbook。nano schedule_at_task.yml添加以下内容:
--- - name: Schedule one-time tasks with at hosts: webservers become: true become_user: labex tasks: - name: Schedule immediate system info collection ansible.posix.at: command: "uname -a > ~/system_info_$(date +%Y%m%d_%H%M%S).txt" count: 2 units: minutes unique: yes state: present - name: Schedule delayed service status check ansible.posix.at: command: "systemctl status httpd > ~/httpd_status_$(date +%Y%m%d_%H%M%S).txt" count: 5 units: minutes unique: yes state: present创建一个管理系统启动目标的 playbook。
nano boot_target_management.yml添加以下内容:
--- - name: Manage system boot targets hosts: webservers become: true tasks: - name: Check current default target ansible.builtin.command: cmd: systemctl get-default register: current_target changed_when: false - name: Display current boot target ansible.builtin.debug: msg: "Current default boot target: {{ current_target.stdout }}" - name: Set default boot target to multi-user ansible.builtin.systemd: name: multi-user.target enabled: yes when: current_target.stdout != "multi-user.target" - name: Verify the boot target change ansible.builtin.command: cmd: systemctl get-default register: new_target changed_when: false - name: Display new boot target ansible.builtin.debug: msg: "New default boot target: {{ new_target.stdout }}"执行服务管理 playbook。
ansible-playbook -i inventory.ini service_management.yml这将启动 httpd 服务并创建一个欢迎页面。
执行 cron 作业调度 playbook。
ansible-playbook -i inventory.ini create_crontab_file.yml这将为系统监控和维护创建几个计划任务。
执行一次性任务调度 playbook。
ansible-playbook -i inventory.ini schedule_at_task.yml这将使用
at命令调度即时任务。执行启动目标管理 playbook。
ansible-playbook -i inventory.ini boot_target_management.yml这将检查并可能修改系统的默认启动目标。
验证计划任务和服务。
## 检查 cron 作业 sudo cat /etc/cron.d/system-monitoring sudo cat /etc/cron.d/log-cleanup sudo cat /etc/cron.d/update-check ## 检查 at 作业 sudo atq ## 检查 httpd 服务状态 sudo systemctl status httpd ## 测试 Web 服务器 curl localhost ## 检查系统监控日志(等待几分钟让 cron 运行) sudo cat /home/labex/system_monitor.log创建一个清理 playbook 以在需要时删除计划任务。
nano remove_scheduled_tasks.yml添加以下内容:
--- - name: Remove scheduled tasks hosts: webservers become: true tasks: - name: Remove system monitoring cron job ansible.builtin.cron: name: System monitoring log user: labex cron_file: system-monitoring state: absent - name: Remove log cleanup cron job ansible.builtin.cron: name: Daily log cleanup user: labex cron_file: log-cleanup state: absent - name: Remove update check cron job ansible.builtin.cron: name: Weekly update check user: labex cron_file: update-check state: absent
你已成功使用 Ansible 自动化了服务管理、任务调度和系统配置,为自动维护和监控你的基础设施奠定了基础。
使用 LVM 和文件系统自动化存储管理
在本步骤中,你将学习如何使用 Ansible 自动化存储管理,包括创建 LVM 物理卷、卷组、逻辑卷和文件系统。这对于以一致且可扩展的方式管理基础设施中的存储资源至关重要。
你将使用诸如 ansible.builtin.lvg 用于卷组管理,ansible.builtin.lvol 用于逻辑卷创建,ansible.builtin.filesystem 用于文件系统创建,以及 ansible.posix.mount 用于挂载点管理等模块。
导航到新的项目目录以进行存储管理。
cd ~/project mkdir system-storage cd system-storage创建本次实验的 inventory 文件。
cat << EOF > inventory.ini [webservers] localhost ansible_connection=local EOF创建一个 loop device 来模拟额外的存储,因为我们是在虚拟环境中工作。
## 创建一个 1GB 的文件用作虚拟磁盘 sudo dd if=/dev/zero of=/tmp/virtual_disk bs=1M count=1024 ## 设置 loop device sudo losetup /dev/loop0 /tmp/virtual_disk ## 验证 loop device lsblk | grep loop0创建一个全面的存储管理 playbook。这将演示 LVM 操作和文件系统管理。
nano storage.yml添加以下内容:
--- - name: Configure LVM storage and filesystems hosts: webservers become: true vars: storage_device: /dev/loop0 volume_group: apache-vg content_lv: content-lv logs_lv: logs-lv backup_lv: backup-lv tasks: - name: Install LVM utilities ansible.builtin.dnf: name: lvm2 state: present - name: Create physical volume community.general.lvg: vg: "{{ volume_group }}" pvs: "{{ storage_device }}" state: present - name: Create logical volume for web content community.general.lvol: vg: "{{ volume_group }}" lv: "{{ content_lv }}" size: 256m state: present - name: Create logical volume for logs community.general.lvol: vg: "{{ volume_group }}" lv: "{{ logs_lv }}" size: 256m state: present - name: Create logical volume for backup community.general.lvol: vg: "{{ volume_group }}" lv: "{{ backup_lv }}" size: 256m state: present - name: Create XFS filesystem on content volume community.general.filesystem: fstype: xfs dev: "/dev/{{ volume_group }}/{{ content_lv }}" force: no - name: Create XFS filesystem on logs volume community.general.filesystem: fstype: xfs dev: "/dev/{{ volume_group }}/{{ logs_lv }}" force: no - name: Create ext4 filesystem on backup volume community.general.filesystem: fstype: ext4 dev: "/dev/{{ volume_group }}/{{ backup_lv }}" force: no - name: Create mount points ansible.builtin.file: path: "{{ item }}" state: directory mode: "0755" loop: - /var/www - /var/log/httpd - /backup - name: Mount web content volume ansible.posix.mount: path: /var/www src: "/dev/{{ volume_group }}/{{ content_lv }}" fstype: xfs opts: defaults state: mounted - name: Mount logs volume ansible.posix.mount: path: /var/log/httpd src: "/dev/{{ volume_group }}/{{ logs_lv }}" fstype: xfs opts: defaults state: mounted - name: Mount backup volume ansible.posix.mount: path: /backup src: "/dev/{{ volume_group }}/{{ backup_lv }}" fstype: ext4 opts: defaults state: mounted - name: Set appropriate ownership for web content ansible.builtin.file: path: /var/www owner: apache group: apache recurse: yes - name: Set appropriate ownership for httpd logs ansible.builtin.file: path: /var/log/httpd owner: apache group: apache recurse: yes - name: Create html directory for web content ansible.builtin.file: path: /var/www/html state: directory owner: apache group: apache mode: "0755" - name: Create sample web content ansible.builtin.copy: content: | <html> <head><title>Storage Management Demo</title></head> <body> <h1>LVM Storage Configuration</h1> <p>This content is served from an LVM logical volume managed by Ansible.</p> <p>Volume Group: {{ volume_group }}</p> <p>Logical Volume: {{ content_lv }}</p> <p>Filesystem: XFS</p> </body> </html> dest: /var/www/html/storage.html owner: apache group: apache mode: "0644"安装所需的 Ansible collection 以进行 LVM 管理。
ansible-galaxy collection install community.general执行存储管理 playbook。
ansible-playbook -i inventory.ini storage.yml这将创建 LVM 结构、文件系统和挂载点。
创建一个 playbook 来收集和显示存储信息。
nano get-storage.yml添加以下内容:
--- - name: Gather storage information hosts: webservers become: true tasks: - name: Gather disk facts ansible.builtin.setup: gather_subset: - hardware - name: Display volume group information ansible.builtin.command: cmd: vgdisplay apache-vg register: vg_info changed_when: false - name: Display logical volume information ansible.builtin.command: cmd: lvdisplay apache-vg register: lv_info changed_when: false - name: Display filesystem information ansible.builtin.command: cmd: df -h /var/www /var/log/httpd /backup register: fs_info changed_when: false - name: Display mount information ansible.builtin.command: cmd: cat /proc/mounts register: mount_info changed_when: false - name: Show volume group details ansible.builtin.debug: var: vg_info.stdout_lines - name: Show logical volume details ansible.builtin.debug: var: lv_info.stdout_lines - name: Show filesystem usage ansible.builtin.debug: var: fs_info.stdout_lines - name: Show fstab entries ansible.builtin.command: cmd: grep apache-vg /etc/fstab register: fstab_entries changed_when: false failed_when: false - name: Display fstab entries ansible.builtin.debug: var: fstab_entries.stdout_lines执行存储信息收集 playbook。
ansible-playbook -i inventory.ini get-storage.yml这将显示有关已创建存储结构的详细信息。
手动验证存储配置。
## 检查 LVM 结构 sudo vgs apache-vg sudo lvs apache-vg sudo pvs /dev/loop0 ## 检查文件系统 df -h /var/www /var/log/httpd /backup ## 检查挂载点 mount | grep apache-vg ## 检查 fstab 条目 grep apache-vg /etc/fstab ## 测试 Web 内容 cat /var/www/html/storage.html创建一个存储扩展 playbook 来演示扩展操作。
nano expand_storage.yml添加以下内容:
--- - name: Expand storage volumes hosts: webservers become: true vars: volume_group: apache-vg content_lv: content-lv tasks: - name: Extend content logical volume community.general.lvol: vg: "{{ volume_group }}" lv: "{{ content_lv }}" size: 400m state: present - name: Extend XFS filesystem community.general.filesystem: fstype: xfs dev: "/dev/{{ volume_group }}/{{ content_lv }}" resizefs: yes - name: Display updated filesystem size ansible.builtin.command: cmd: df -h /var/www register: new_size changed_when: false - name: Show new filesystem size ansible.builtin.debug: var: new_size.stdout_lines测试存储扩展。
## 在扩展前检查当前大小 df -h /var/www ## 运行扩展 playbook ansible-playbook -i inventory.ini expand_storage.yml ## 验证扩展 df -h /var/www sudo lvs apache-vg/content-lv
你已成功使用 Ansible 自动化了 LVM 存储管理,包括物理卷创建、逻辑卷管理、文件系统创建和挂载点配置。
自动化网络配置和信息收集
在最后一步中,你将学习如何使用 Ansible 自动化网络接口配置和收集全面的系统信息。这完成了从软件到存储再到网络的系统管理自动化的完整流程。
你将使用诸如 ansible.builtin.template 用于网络配置文件,收集网络事实,以及创建全面的系统报告等模块。
导航到新的项目目录以进行网络管理。
cd ~/project mkdir system-network cd system-network创建本次实验的 inventory 文件。
cat << EOF > inventory.ini [webservers] localhost ansible_connection=local EOF创建一个全面的网络和系统信息收集 playbook。
nano network_info.yml添加以下内容:
--- - name: Gather comprehensive system information hosts: webservers become: true tasks: - name: Gather all system facts ansible.builtin.setup: - name: Create system report directory ansible.builtin.file: path: /tmp/system_reports state: directory mode: "0755" - name: Generate system information report ansible.builtin.template: src: system_report.j2 dest: /tmp/system_reports/system_info_{{ ansible_facts['hostname'] }}.html mode: "0644" - name: Generate network configuration report ansible.builtin.template: src: network_report.j2 dest: /tmp/system_reports/network_info_{{ ansible_facts['hostname'] }}.html mode: "0644" - name: Collect network interface information ansible.builtin.command: cmd: ip addr show register: ip_info changed_when: false - name: Collect routing information ansible.builtin.command: cmd: ip route show register: route_info changed_when: false - name: Collect DNS configuration ansible.builtin.command: cmd: cat /etc/resolv.conf register: dns_info changed_when: false - name: Display network summary ansible.builtin.debug: msg: | System: {{ ansible_facts['hostname'] }} OS: {{ ansible_facts['distribution'] }} {{ ansible_facts['distribution_version'] }} Kernel: {{ ansible_facts['kernel'] }} Default IPv4: {{ ansible_facts['default_ipv4']['address'] | default('N/A') }} Default Interface: {{ ansible_facts['default_ipv4']['interface'] | default('N/A') }} Total Memory: {{ ansible_facts['memtotal_mb'] }}MB CPU Cores: {{ ansible_facts['processor_vcpus'] }}创建模板目录和文件以用于报告。
mkdir templates nano templates/system_report.j2为系统报告模板添加以下内容:
<!doctype html> <html> <head> <title>System Report - {{ ansible_facts['hostname'] }}</title> <style> body { font-family: Arial, sans-serif; margin: 20px; } .section { margin-bottom: 20px; padding: 10px; border: 1px solid #ccc; } .header { background-color: #f5f5f5; padding: 10px; } table { border-collapse: collapse; width: 100%; } th, td { border: 1px solid #ddd; padding: 8px; text-align: left; } th { background-color: #f2f2f2; } </style> </head> <body> <div class="header"> <h1>System Report for {{ ansible_facts['hostname'] }}</h1> <p> Generated on: {{ ansible_date_time.date }} {{ ansible_date_time.time }} </p> </div> <div class="section"> <h2>System Information</h2> <table> <tr> <th>Property</th> <th>Value</th> </tr> <tr> <td>Hostname</td> <td>{{ ansible_facts['hostname'] }}</td> </tr> <tr> <td>FQDN</td> <td>{{ ansible_facts['fqdn'] }}</td> </tr> <tr> <td>Operating System</td> <td> {{ ansible_facts['distribution'] }} {{ ansible_facts['distribution_version'] }} </td> </tr> <tr> <td>Kernel</td> <td>{{ ansible_facts['kernel'] }}</td> </tr> <tr> <td>Architecture</td> <td>{{ ansible_facts['architecture'] }}</td> </tr> <tr> <td>CPU Cores</td> <td>{{ ansible_facts['processor_vcpus'] }}</td> </tr> <tr> <td>Total Memory</td> <td>{{ ansible_facts['memtotal_mb'] }}MB</td> </tr> <tr> <td>Uptime</td> <td>{{ ansible_facts['uptime_seconds'] }} seconds</td> </tr> </table> </div> <div class="section"> <h2>Storage Information</h2> <table> <tr> <th>Mount Point</th> <th>Filesystem</th> <th>Size</th> <th>Used</th> <th>Available</th> </tr> {% for mount in ansible_facts['mounts'] %} <tr> <td>{{ mount.mount }}</td> <td>{{ mount.fstype }}</td> <td> {{ (mount.size_total / 1024 / 1024 / 1024) | round(2) }}GB </td> <td> {{ ((mount.size_total - mount.size_available) / 1024 / 1024 / 1024) | round(2) }}GB </td> <td> {{ (mount.size_available / 1024 / 1024 / 1024) | round(2) }}GB </td> </tr> {% endfor %} </table> </div> <div class="section"> <h2>Services Status</h2> <table> <tr> <th>Service</th> <th>Status</th> </tr> <tr> <td>httpd</td> <td> {{ ansible_facts.services['httpd.service']['state'] | default('not installed') }} </td> </tr> <tr> <td>sshd</td> <td> {{ ansible_facts.services['sshd.service']['state'] | default('unknown') }} </td> </tr> <tr> <td>NetworkManager</td> <td> {{ ansible_facts.services['NetworkManager.service']['state'] | default('unknown') }} </td> </tr> </table> </div> </body> </html>创建网络报告模板。
nano templates/network_report.j2添加以下内容:
<!doctype html> <html> <head> <title>Network Report - {{ ansible_facts['hostname'] }}</title> <style> body { font-family: Arial, sans-serif; margin: 20px; } .section { margin-bottom: 20px; padding: 10px; border: 1px solid #ccc; } .header { background-color: #f5f5f5; padding: 10px; } table { border-collapse: collapse; width: 100%; } th, td { border: 1px solid #ddd; padding: 8px; text-align: left; } th { background-color: #f2f2f2; } pre { background-color: #f9f9f9; padding: 10px; overflow-x: auto; } </style> </head> <body> <div class="header"> <h1>Network Configuration Report</h1> <p>Host: {{ ansible_facts['hostname'] }}</p> <p> Generated on: {{ ansible_date_time.date }} {{ ansible_date_time.time }} </p> </div> <div class="section"> <h2>Network Interfaces</h2> <table> <tr> <th>Interface</th> <th>IPv4 Address</th> <th>IPv6 Address</th> <th>MAC Address</th> <th>Status</th> </tr> {% for interface_name in ansible_facts['interfaces'] %} {% if interface_name != 'lo' %} {% set interface_facts = ansible_facts[interface_name] %} <tr> <td>{{ interface_name }}</td> <td> {{ interface_facts.get('ipv4', {}).get('address', 'N/A') }} </td> <td> {{ interface_facts.get('ipv6', [{}])[0].get('address', 'N/A') if interface_facts.get('ipv6') else 'N/A' }} </td> <td>{{ interface_facts.get('macaddress', 'N/A') }}</td> <td> {{ interface_facts.get('active', false) | ternary('Active', 'Inactive') }} </td> </tr> {% endif %} {% endfor %} </table> </div> <div class="section"> <h2>Default Gateway</h2> <table> <tr> <th>Property</th> <th>Value</th> </tr> <tr> <td>Default IPv4 Address</td> <td> {{ ansible_facts['default_ipv4']['address'] | default('N/A') }} </td> </tr> <tr> <td>Default Interface</td> <td> {{ ansible_facts['default_ipv4']['interface'] | default('N/A') }} </td> </tr> <tr> <td>Default Gateway</td> <td> {{ ansible_facts['default_ipv4']['gateway'] | default('N/A') }} </td> </tr> </table> </div> <div class="section"> <h2>DNS Configuration</h2> <table> <tr> <th>DNS Servers</th> </tr> {% for dns in ansible_facts['dns']['nameservers'] %} <tr> <td>{{ dns }}</td> </tr> {% endfor %} </table> </div> </body> </html>创建一个网络接口配置 playbook。
nano configure_network.yml添加以下内容:
--- - name: Configure network settings hosts: webservers become: true tasks: - name: Install NetworkManager if not present ansible.builtin.dnf: name: NetworkManager state: present - name: Ensure NetworkManager is running ansible.builtin.service: name: NetworkManager state: started enabled: yes - name: Configure hosts file with system information ansible.builtin.lineinfile: path: /etc/hosts line: "{{ ansible_facts['default_ipv4']['address'] }} {{ ansible_facts['hostname'] }}.lab.example.com {{ ansible_facts['hostname'] }}" regexp: ".*{{ ansible_facts['hostname'] }}.*" backup: yes - name: Create network monitoring script ansible.builtin.copy: content: | #!/bin/bash ## Network monitoring script generated by Ansible echo "=== Network Status Report ===" echo "Generated at: $(date)" echo echo "=== Interface Status ===" ip addr show echo echo "=== Routing Table ===" ip route show echo echo "=== DNS Configuration ===" cat /etc/resolv.conf echo echo "=== Network Connectivity Test ===" ping -c 3 8.8.8.8 dest: /usr/local/bin/network-status.sh mode: "0755" - name: Create network information gathering cron job ansible.builtin.cron: name: Network status monitoring job: "/usr/local/bin/network-status.sh >> /var/log/network-status.log 2>&1" minute: "*/15" user: root cron_file: network-monitoring state: present执行网络信息收集 playbook。
ansible-playbook -i inventory.ini network_info.yml这将生成全面的系统和网络报告。
执行网络配置 playbook。
ansible-playbook -i inventory.ini configure_network.yml这将配置网络设置和监控。
查看生成的报告。
## 列出生成的报告 ls -la /tmp/system_reports/ ## 查看系统报告(你也可以在浏览器中打开) cat /tmp/system_reports/system_info_*.html ## 检查网络监控脚本 cat /usr/local/bin/network-status.sh ## 测试网络监控脚本 sudo /usr/local/bin/network-status.sh ## 检查网络监控 cron 作业 sudo cat /etc/cron.d/network-monitoring创建一个最终的综合 playbook,将所有学到的概念结合起来。
nano complete_system_setup.yml添加以下内容:
--- - name: Complete system setup and configuration hosts: webservers become: true vars: admin_users: - webuser1 - webuser2 tasks: - name: Ensure all required packages are installed ansible.builtin.dnf: name: - httpd - lvm2 - NetworkManager - cronie state: present - name: Ensure all services are running ansible.builtin.service: name: "{{ item }}" state: started enabled: yes loop: - httpd - NetworkManager - crond - name: Generate final system status report ansible.builtin.template: src: system_report.j2 dest: /tmp/final_system_report.html mode: "0644" - name: Display completion message ansible.builtin.debug: msg: | ============================================ RHEL System Administration Automation Complete! ============================================ Summary of configured components: - Software: EPEL repository and packages installed - Users: {{ admin_users | length }} administrative users created - Services: httpd, NetworkManager, and crond configured - Storage: LVM volumes and filesystems configured - Network: Interface configuration and monitoring set up - Scheduling: Cron jobs and at tasks configured Reports available at: - /tmp/system_reports/ - /tmp/final_system_report.html Your RHEL system is now fully automated with Ansible!执行最终的综合设置。
ansible-playbook -i inventory.ini complete_system_setup.yml
你已成功完成了使用 Ansible 对 RHEL 系统管理任务的全面自动化,涵盖了软件管理、用户管理、服务管理、存储配置和网络设置。
在 Web 浏览器中预览生成的报告。
导航到报告目录:
cd /tmp/system_reports使用 Python 启动一个临时 Web 服务器:
python -m http.server 8000要在浏览器中预览报告:
- 点击顶部菜单栏的 + 按钮
- 选择 Web Service
- 输入端口号 8000
- 你现在可以在线查看生成的 HTML 报告了

Web 服务器将显示一个目录列表,你可以在其中点击 HTML 文件来查看由你的 Ansible playbook 生成的全面系统和网络报告。
注意: 查看完报告后,按
Ctrl+C停止 Web 服务器。
总结
在本次综合实验中,你已经掌握了使用 Ansible 自动化关键的 Red Hat Enterprise Linux (RHEL) 管理任务。你从软件软件包管理开始,学习了如何配置仓库、管理 GPG 密钥以及在收集软件包事实以获取系统信息的同时安装软件包。这为在你的基础设施中实现一致的软件部署奠定了基础。
接着,你进入了用户管理和身份验证环节,自动化了用户账户的创建、配置了基于 SSH 密钥的身份验证、设置了 sudo 权限,并加固了 SSH 配置。这建立了对企业环境至关重要的安全且标准化的用户访问策略。
实验继续进行服务管理和任务调度,你学习了如何管理 systemd 服务、创建周期性的 cron 作业、使用 at 调度一次性任务以及配置系统启动目标。这些技能对于维护服务可用性和自动化例行维护任务至关重要。
存储管理通过全面的 LVM 自动化进行了涵盖,包括物理卷创建、卷组管理、逻辑卷配置、文件系统创建和挂载点配置。你还学会了动态扩展存储卷,这对于可扩展的基础设施管理至关重要。
最后,你完成了网络配置自动化和全面的系统监控。你学习了如何收集网络事实、配置接口、使用 Jinja2 模板创建详细的系统报告,以及设置自动监控脚本。这提供了系统状态管理和报告的完整图景。
在整个实验过程中,你应用了基础设施即代码 (IaC) 原则,确保所有系统配置都是可复现的、版本可控的且可一致部署的。你现在已经掌握了自动化 RHEL 系统管理生命周期的技能,从初始部署到持续维护和监控。


