节点环境
管理节点
- 系统版本:Rocky Linux release 8.10 (Green Obsidian),最小化安装
- Python 环境:python3.12
- Ansible-core 版本:2.15.13
这里为了演示,安装的是
ansible-core
(只带基础模块),正常使用可以安装ansible
(带有一些扩展模块),更方便使用。本次安装通过
pip
安装。
被控节点
- 系统版本:Rocky Linux release 8.10 (Green Obsidian),最小化安装
- Python 环境:python3.6
三个节点地址分别为:192.168.221.142
、192.168.221.143
、192.168.221.144
。
Ansible 对 Python 版本会有要求,如果 Ansible 版本过高,而被控节点 Python 版本较低,可能会存在模块执行失败的情况。
配置基础环境
# 安装 Python 和 两个常用基础包
[root@ansible-controller ~]# dnf install -y vim bash-completion python3.12 python3.12-pip sshpass
# 升级 pip
[root@ansible-controller ~]# python3.12 -m pip install --upgrade pip
安装 Ansible
# 检查可用 Ansible-core 版本
[root@ansible-controller ~]# python3.12 -m pip index versions ansible-core
ansible-core (2.18.5)
Available versions: 2.18.5, 2.18.4, 2.18.3, 2.18.2, 2.18.1, 2.18.0, 2.17.11, 2.17.10, 2.17.9, 2.17.8, 2.17.7, 2.17.6, 2.17.5, 2.17.4, 2.17.3, 2.17.2, 2.17.1, 2.17.0, 2.16.14, 2.16.13, 2.16.12, 2.16.11, 2.16.10, 2.16.9, 2.16.8, 2.16.7, 2.16.6, 2.16.5, 2.16.4, 2.16.3, 2.16.2, 2.16.1, 2.16.0, 2.15.13, 2.15.12, 2.15.11, 2.15.10, 2.15.9, 2.15.8, 2.15.7, 2.15.6, 2.15.5, 2.15.4, 2.15.3, 2.15.2, 2.15.1, 2.15.0, 2.14.18, 2.14.17, 2.14.16, 2.14.15, 2.14.14, 2.14.13, 2.14.12, 2.14.11, 2.14.10, 2.14.9, 2.14.8, 2.14.7, 2.14.6, 2.14.5, 2.14.4, 2.14.3, 2.14.2, 2.14.1, 2.14.0, 2.13.13, 2.13.12, 2.13.11, 2.13.10, 2.13.9, 2.13.8, 2.13.7, 2.13.6, 2.13.5, 2.13.4, 2.13.3, 2.13.2, 2.13.1, 2.13.0, 2.12.10, 2.12.9, 2.12.8, 2.12.7, 2.12.6, 2.12.5, 2.12.4, 2.12.3, 2.12.2, 2.12.1, 2.12.0, 2.11.12, 2.11.11, 2.11.10, 2.11.9, 2.11.8, 2.11.7, 2.11.6, 2.11.5, 2.11.4, 2.11.3, 2.11.2, 2.11.1, 2.11.0
# 安装 Ansible-core
[root@ansible-controller ~]# python3.12 -m pip install ansible-core==2.15.13 argcomplete
...output omitted...
# 配置命令自动补全
[root@ansible-controller ansible]# activate-global-python-argcomplete --user
Adding shellcode to /root/.zshenv...
Added.
Adding shellcode to /root/.bash_completion...
Added.
Please restart your shell or source the installed file to activate it.
[root@ansible-controller ~]# exit
logout
# 重新打开一个命令行
# 查看安装的 Ansible
[root@ansible-controller ~]# ansible --version
ansible [core 2.15.13]
config file = /root/ansible_init/ansible.cfg
configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/local/lib/python3.12/site-packages/ansible
ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/local/bin/ansible
python version = 3.12.8 (main, Dec 12 2024, 16:30:29) [GCC 8.5.0 20210514 (Red Hat 8.5.0-22)] (/usr/bin/python3.12)
jinja version = 3.1.6
libyaml = True
# 可以看到只有 70 个基础模块
[root@ansible-controller ~]# ansible-doc -l | wc -l
74
配置 Ansible 初始化环境
这里主要是配置被控节点支持运行 Ansible 模块,主要是安装 Python 和 创建 Ansible 连接账户。
初始化被控节点模块执行环境
创建一个临时环境,用于给被控节点安装 Python 和创建 Ansible 连接账户。
# 创建 ansible 主目录
[root@ansible-controller ~]# mkdir ansible_init
[root@ansible-controller ~]# cd ansible_init/
# 创建配置文件
[root@ansible-controller ansible_init]# cat ansible.cfg
[defaults]
inventory=./inventory
become=false
host_key_checking=False
# 配置初始化配置的主机清单
[root@ansible-controller ansible_init]# cat inventory
master1 ansible_ssh_host=192.168.221.142 HOSTNAME=master1.example.com
worker1 ansible_ssh_host=192.168.221.143 HOSTNAME=worker1.example.com
worker2 ansible_ssh_host=192.168.221.144 HOSTNAME=worker2.example.com
[all:vars]
ansible_ssh_user=root
ansible_ssh_password=redhat
# 测试
[root@ansible-controller ansible_init]# ansible all -m raw -a id
worker1 | CHANGED | rc=0 >>
uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
Shared connection to 192.168.221.143 closed.
master1 | CHANGED | rc=0 >>
uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
Shared connection to 192.168.221.142 closed.
worker2 | CHANGED | rc=0 >>
uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
Shared connection to 192.168.221.144 closed.
# 安装 python3
[root@ansible-controller ansible_init]# ansible all -m raw -a 'dnf install -y python3'
...output omitted...
# 测试模块
[root@ansible-controller ansible_init]# ansible all -m ping
...output omitted...
添加 Ansible 管理用户
# 添加 Ansible 用户
[root@ansible-controller ~]# openssl passwd -6 -salt randomsalt redhat
$6$randomsalt$nyZMZWZT9mAsW3O4fAAX66nk/RagLSUr4vq921cGE/hsqskAzcOJvaF4uvHUFxYnT1vBB9tGbR7UhEAhuVWu/0
[root@ansible-controller ansible_init]# ansible all -m user \
-a 'name=ansible uid=10000 groups=wheel append=true password=$6$randomsalt$nyZMZWZT9mAsW3O4fAAX66nk/RagLSUr4vq921cGE/hsqskAzcOJvaF4uvHUFxYnT1vBB9tGbR7UhEAhuVWu/0'
...output omitted...
配置 Ansible 自动化环境
这里是在被控节点具备 Ansible 模块运行环境后开始对被控节点进行配置的步骤。
创建自动化环境相关配置
创建一个新的环境目录,用于主机管理。
# 创建一个新的 Ansible 目录并进入
[root@ansible-controller ansible_init]# cd
[root@ansible-controller ~]# mkdir ansible
[root@ansible-controller ~]# cd ansible
# 创建 Ansible 配置文件
[root@ansible-controller ansible]# ansible-config init --disabled -t all > ansible.cfg
# 配置文件按需修改
[root@ansible-controller ansible]# grep -Ev "^#|^$|^;" ansible.cfg
[defaults]
fact_caching=jsonfile
fact_caching_connection=./cache
inventory=./inventory
remote_user=ansible
host_key_checking=False
[privilege_escalation]
become=True
become_ask_pass=True
become_method=sudo
become_user=root
[persistent_connection]
[connection]
[colors]
[selinux]
[diff]
[galaxy]
[inventory]
[netconf_connection]
[paramiko_connection]
[jinja2]
[tags]
[runas_become_plugin]
[su_become_plugin]
[sudo_become_plugin]
[callback_tree]
[ssh_connection]
[winrm]
[inventory_plugins]
[inventory_plugin_script]
[inventory_plugin_yaml]
[url_lookup]
[powershell]
[vars_host_group_vars]
# 准备主机清单
[root@ansible-controller ansible]# cat inventory
master1 ansible_ssh_host=192.168.221.142 HOSTNAME=master1.example.com
worker1 ansible_ssh_host=192.168.221.143 HOSTNAME=worker1.example.com
worker2 ansible_ssh_host=192.168.221.144 HOSTNAME=worker2.example.com
[all:vars]
ansible_ssh_user=ansible
ansible_ssh_password=redhat
准备一个初始化配置的 Playbook
- 可以使用
ansible-doc -l
命令查看有哪些模块 - 可以使用
ansible-doc <模块名>
来查看模块文档,通过输入/EXAMPLE
来搜索模块使用模板
搜索模板内容以 ansible.builtin.dnf
模块举例:
EXAMPLES:
- name: Install the latest version of Apache
ansible.builtin.dnf:
name: httpd
state: latest
- name: Install Apache >= 2.4
ansible.builtin.dnf:
name: httpd >= 2.4
state: present
- name: Install the latest version of Apache and MariaDB
ansible.builtin.dnf:
name:
- httpd
- mariadb-server
state: latest
- name: Remove the Apache package
ansible.builtin.dnf:
name: httpd
state: absent
- name: Install the latest version of Apache from the testing repo
ansible.builtin.dnf:
name: httpd
enablerepo: testing
state: present
- name: Upgrade all packages
ansible.builtin.dnf:
name: "*"
state: latest
Playbook 内容:
[root@ansible-controller ansible]# cat init.yaml
---
- name: Initial configuration
hosts: all
tasks:
- name: Installing System Packages
ansible.builtin.dnf:
name:
- vim
- bash-completion
- python3-pip
- epel-release
state: present
- name: Upgrading system packages
ansible.builtin.dnf:
name: '*'
state: latest
- name: Set hostname
ansible.builtin.hostname:
name: "{{ HOSTNAME }}"
- name: Set up SSH to disable root login
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regex: "^#?PermitRootLogin"
line: "PermitRootLogin no"
notify: restart sshd
handlers:
- name: Restart SSH Service
ansible.builtin.systemd:
name: sshd
state: restarted
listen: restart sshd
...output omitted...
这个 Playbook 干了四件事:
- 安装一些基础软件包
- 升级系统所有软件包
- 设置主机名
- 关闭 SSH 的 root 登录
执行自动化任务
[root@ansible-controller ansible]# ansible-playbook init.yaml
BECOME password:
...output omitted...
# 检查配置
[root@ansible-controller ansible]# ansible all -m command -a "dnf upgrade"
BECOME password:
worker2 | CHANGED | rc=0 >>
Last metadata expiration check: 3:12:13 ago on Tue 20 May 2025 07:36:03 PM CST.
Dependencies resolved.
Nothing to do.
Complete!
worker1 | CHANGED | rc=0 >>
Last metadata expiration check: 3:10:43 ago on Tue 20 May 2025 07:37:33 PM CST.
Dependencies resolved.
Nothing to do.
Complete!
master1 | CHANGED | rc=0 >>
Last metadata expiration check: 0:18:26 ago on Tue 20 May 2025 10:29:50 PM CST.
Dependencies resolved.
Nothing to do.
Complete!
[root@ansible-controller ansible]# ansible all -m command -a 'grep -E "^#?PermitRootLogin no" /etc/ssh/sshd_config'
BECOME password:
master1 | CHANGED | rc=0 >>
PermitRootLogin no
worker1 | CHANGED | rc=0 >>
PermitRootLogin no
worker2 | CHANGED | rc=0 >>
PermitRootLogin no
[root@ansible-controller ansible]# ansible all -m command -a 'hostname'
BECOME password:
worker1 | CHANGED | rc=0 >>
worker1.example.com
worker2 | CHANGED | rc=0 >>
worker2.example.com
master1 | CHANGED | rc=0 >>
master1.example.com
使用集合来扩展 Ansible 的功能
安装集合
ansible-core
只具备一些核心模块,有时候需要一些额外的模块来扩展 Ansible 的功能,通过安装集合可以拓展 Ansible 的功能,比方说 ansible.posix.selinux
用于管理 SELinux。
# 下载集合
[root@ansible-controller ansible]# ansible-galaxy collection install ansible.posix
Starting galaxy collection install process
Process install dependency map
Starting collection install process
Downloading https://galaxy.ansible.com/api/v3/plugin/ansible/content/published/collections/artifacts/ansible-posix-2.0.0.tar.gz to /root/.ansible/tmp/ansible-local-111554mi8iz9y/tmpjgw4dlat/ansible-posix-2.0.0-fc5mr3e5
Installing 'ansible.posix:2.0.0' to '/root/.ansible/collections/ansible_collections/ansible/posix'
ansible.posix:2.0.0 was installed successfully
使用新安装的模块
# 检查新安装的模块
[root@ansible-controller ansible]# ansible-doc -l | grep ansible.posix
ansible.posix.acl Set and retrieve file ACL informatio...
ansible.posix.at Schedule the execution of a command ...
ansible.posix.authorized_key Adds or removes an SSH authorized ke...
ansible.posix.firewalld Manage arbitrary ports/services with...
ansible.posix.firewalld_info Gather information about firewalld
ansible.posix.mount Control active and configured mount ...
ansible.posix.patch Apply patch files using the GNU patc...
ansible.posix.rhel_facts Facts module to set or override RHEL...
ansible.posix.rhel_rpm_ostree Ensure packages exist in a RHEL for ...
ansible.posix.rpm_ostree_upgrade Manage rpm-ostree upgrade transactio...
ansible.posix.seboolean Toggles SELinux booleans
ansible.posix.selinux Change policy and state of SELinux
ansible.posix.synchronize A wrapper around rsync to make commo...
ansible.posix.sysctl Manage entries in sysctl.conf
# 查看 ansible.posix.selinux 模块文档
[root@ansible-controller ansible]# ansible-doc ansible.posix.selinux
# 输入 /EXAMPLE 搜索使用模板
# 根据模板准备配置 SELinux 的 YAML 文件
---
- name: Disable SELinux
hosts: all
gather_facts: false
tasks:
- name: Disable SELinux
ansible.posix.selinux:
policy: targeted
state: permissive
# 执行 Playbook
[root@ansible-controller ansible]# ansible-playbook selinux.yml
# 验证
[root@ansible-controller ansible]# ansible all -m command -a 'grep SELINUX= /etc/selinux/config'
BECOME password:
master1 | CHANGED | rc=0 >>
# SELINUX= can take one of these three values:
SELINUX=permissive
worker1 | CHANGED | rc=0 >>
# SELINUX= can take one of these three values:
SELINUX=permissive
worker2 | CHANGED | rc=0 >>
# SELINUX= can take one of these three values:
SELINUX=permissive
如果执行的时候报错
The error was: ModuleNotFoundError: No module named 'selinux'
,表示被控主机没有安装python3-libselinux
软件包。
重启节点并验证功能
[root@ansible-controller ansible]# ansible all -m reboot
BECOME password:
worker1 | CHANGED => {
"changed": true,
"elapsed": 14,
"rebooted": true
}
worker2 | CHANGED => {
"changed": true,
"elapsed": 14,
"rebooted": true
}
master1 | CHANGED => {
"changed": true,
"elapsed": 15,
"rebooted": true
}
[root@ansible-controller ansible]# ssh [email protected]
[email protected]'s password:
Permission denied, please try again.
[email protected]'s password:
[root@ansible-controller ansible]# ssh [email protected]
[email protected]'s password:
Last login: Wed May 21 01:32:06 2025 from 192.168.221.141
[ansible@master1 ~]$
[ansible@master1 ~]$ hostname
master1.example.com
[ansible@master1 ~]$ sudo dnf upgrade
[sudo] password for ansible:
Last metadata expiration check: 0:19:34 ago on Wed 21 May 2025 01:14:37 AM CST.
Dependencies resolved.
Nothing to do.
Complete!