介绍
Ansible 是一个强大的自动化工具,它有助于管理和配置服务器,而无需手动干预。然而,许多 Ansible 任务需要提升权限才能正确执行。当运行需要管理员权限的命令时,Ansible 使用 sudo 机制,这可能会提示输入密码。
在这个实验(Lab)中,你将学习如何在 Ansible playbook 中正确配置 sudo 密码设置,了解常见的 sudo 相关问题,并实施最佳实践,以确保你的自动化在具有必要权限的情况下顺利运行。
Ansible 是一个强大的自动化工具,它有助于管理和配置服务器,而无需手动干预。然而,许多 Ansible 任务需要提升权限才能正确执行。当运行需要管理员权限的命令时,Ansible 使用 sudo 机制,这可能会提示输入密码。
在这个实验(Lab)中,你将学习如何在 Ansible playbook 中正确配置 sudo 密码设置,了解常见的 sudo 相关问题,并实施最佳实践,以确保你的自动化在具有必要权限的情况下顺利运行。
在第一步中,我们将安装 Ansible 并创建一个需要 sudo 权限的简单 playbook。这将帮助我们了解使用提升权限运行 Ansible 任务的基本要求。
让我们从在系统上安装 Ansible 开始。打开一个终端并运行以下命令:
sudo apt update
sudo apt install -y ansible
安装完成后,验证 Ansible 是否已正确安装:
ansible --version
你应该看到类似这样的输出,显示 Ansible 的版本和配置信息:
ansible [core 2.12.x]
config file = /etc/ansible/ansible.cfg
configured module search path = ['/home/labex/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3/dist-packages/ansible
ansible collection location = /home/labex/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/bin/ansible
python version = 3.10.x (main, Ubuntu, linux/x86_64)
jinja version = 3.0.3
libyaml = True
现在,让我们创建一个需要 sudo 权限的简单 Ansible playbook。此 playbook 将在本地系统上安装 htop 包。
为你的 Ansible 项目创建一个新目录:
mkdir -p ~/project/ansible-sudo-lab
cd ~/project/ansible-sudo-lab
接下来,创建定义 Ansible 将要管理的 hosts 的 inventory 文件。对于这个实验(Lab),我们将使用 localhost:
echo "localhost ansible_connection=local" > inventory
现在,创建一个需要 sudo 权限的基本 playbook。打开 VSCode 编辑器并创建一个名为 basic_playbook.yml 的新文件:
---
- name: Basic sudo operation
hosts: localhost
become: true ## This enables sudo
tasks:
- name: Install htop
apt:
name: htop
state: present
update_cache: yes
~/project/ansible-sudo-lab/basic_playbook.yml此 playbook 具有 become: true 指令,该指令告诉 Ansible 使用 sudo 来运行任务。任务本身尝试使用 apt 模块安装 htop 包。
现在,让我们运行我们的 playbook 并观察会发生什么:
cd ~/project/ansible-sudo-lab
ansible-playbook -i inventory basic_playbook.yml
由于 labex 用户具有无密码 sudo 访问权限,因此 playbook 应该成功运行,而不会提示输入密码。你应该看到类似这样的输出:
PLAY [Basic sudo operation] ******************************************
TASK [Gathering Facts] **********************************************
ok: [localhost]
TASK [Install htop] ************************************************
ok: [localhost]
PLAY RECAP *********************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Playbook 运行成功,因为我们当前的用户 (labex) 已经配置了无密码 sudo 访问权限。在接下来的步骤中,我们将探讨如何处理需要 sudo 密码的场景。
在上一步中,我们创建了一个基本 playbook,它使用 sudo 权限而无需密码。然而,在许多实际场景中,你需要提供 sudo 密码才能执行特权命令。让我们探讨如何在 Ansible 中处理 sudo 密码。
当 Ansible 需要在远程系统上使用提升的权限运行命令时,它使用 become 功能。默认情况下,Ansible 使用 sudo 命令进行权限提升,但你可以将其配置为使用其他方法,如 su、pbrun 或 pfexec。
如果运行 Ansible 的用户需要密码才能使用 sudo,Ansible 需要知道这个密码。有几种方法可以向 Ansible 提供 sudo 密码:
-K 或 --ask-become-passbecome_passwordansible.cfg为了演示如何处理 sudo 密码,让我们创建一个测试用户,该用户需要密码才能进行 sudo 操作:
sudo adduser ansible_test
当提示时,输入密码 ansible123 并完成用户创建过程。
接下来,让我们给这个用户 sudo 权限,但需要密码:
echo "ansible_test ALL=(ALL) ALL" | sudo tee /etc/sudoers.d/ansible_test
此配置允许 ansible_test 用户使用 sudo,但每次都需要用户的密码。
现在,让我们创建一个 playbook,演示如何处理 sudo 密码。在 WebIDE 中创建一个名为 sudo_password_playbook.yml 的新文件:
---
- name: Playbook with sudo password handling
hosts: localhost
become: true
## We'll provide the become_password when running the playbook
tasks:
- name: Get current user
command: whoami
register: current_user
become: false ## This task doesn't need sudo
- name: Print current user
debug:
msg: "Current user is {{ current_user.stdout }}"
become: false ## This task doesn't need sudo
- name: Run a command with sudo
command: apt update
register: sudo_output
- name: Print sudo command result
debug:
msg: "Command ran with sudo: {{ sudo_output.rc == 0 }}"
将此文件保存为 ~/project/ansible-sudo-lab/sudo_password_playbook.yml
当你希望以需要 sudo 密码的用户身份运行 playbook 时,你可以使用 -K(或 --ask-become-pass)选项来提示输入密码:
ansible-playbook -i inventory sudo_password_playbook.yml -K
由于我们以具有无密码 sudo 的 labex 用户身份运行,因此实际上不会提示你输入密码。但是,在未配置无密码 sudo 的生产环境中,Ansible 会提示你输入 sudo 密码。
为了使用我们的测试用户模拟此场景,你可以运行以下命令(尽管由于缺少 SSH 设置,它在此实验环境中无法完全工作):
ansible-playbook -i inventory sudo_password_playbook.yml -u ansible_test -K
当提示输入 BECOME 密码时,你将输入 ansible123。
除了交互式输入密码之外,你还可以在运行 playbook 时将 sudo 密码作为变量提供:
ansible-playbook -i inventory sudo_password_playbook.yml -e "ansible_become_password=ansible123"
这种方法对于无法进行交互式输入的自动化脚本很有用。但是,它会在命令行历史记录中暴露密码,这是一种安全风险。在生产环境中,你应该使用 Ansible Vault 来安全地存储敏感信息。
在上一步中,我们探讨了向 Ansible playbooks 提供 sudo 密码的不同方法。然而,将密码存储在纯文本文件中或在命令行中传递它们是不安全的。在这一步中,我们将学习如何使用 Ansible Vault 来安全地管理敏感信息,例如 sudo 密码。
Ansible Vault 是一项功能,允许你加密敏感数据,例如密码、API 密钥或证书。加密后的文件可以安全地存储在版本控制系统中,而不会暴露敏感信息。Ansible 可以在 playbook 执行期间自动解密这些文件。
让我们创建一个加密文件来存储我们的 sudo 密码:
cd ~/project/ansible-sudo-lab
ansible-vault create vault.yml
系统将提示你创建一个新的 vault 密码。输入 vaultpassword123 并确认它。
设置 vault 密码后,将打开一个编辑器。在编辑器中输入以下内容:
---
vault_sudo_password: ansible123
保存文件并退出编辑器。
现在,如果你尝试查看 vault 文件的内容,你将看到它已被加密:
cat vault.yml
你应该看到类似这样的输出:
$ANSIBLE_VAULT;1.1;AES256
32623438613466396238613731623338376461653866353031313632316237613561393639613131
3562626166616332386265373761653835356134613561380a363761333362323238663136633439
32343032333832313562353261333530666639643239303436643363393630643639316232303564
3962356162356361370a313038333432353162333462323035323262396233333039326535356662
31363539613432656362326565613232336535393232653939323466323131393362
现在,让我们创建一个使用加密的 sudo 密码的 playbook。创建一个名为 secure_sudo_playbook.yml 的新文件:
---
- name: Playbook with secure sudo password
hosts: localhost
become: true
become_password: "{{ vault_sudo_password }}"
vars_files:
- vault.yml
tasks:
- name: Get sudo user
command: whoami
register: sudo_user
- name: Print sudo user
debug:
msg: "Running as {{ sudo_user.stdout }}"
- name: Check sudo access
command: apt update
register: apt_result
failed_when: false
- name: Print result
debug:
msg: "Sudo access successful: {{ apt_result.rc == 0 }}"
将此文件保存为 ~/project/ansible-sudo-lab/secure_sudo_playbook.yml
当你运行包含加密 vault 文件的 playbook 时,你需要提供 vault 密码。有几种方法可以做到这一点:
--ask-vault-pass 选项:ansible-playbook -i inventory secure_sudo_playbook.yml --ask-vault-pass
当提示时,输入 vault 密码:vaultpassword123
首先,创建一个包含 vault 密码的文件:
echo "vaultpassword123" > vault_password_file
chmod 600 vault_password_file
然后使用密码文件运行 playbook:
ansible-playbook -i inventory secure_sudo_playbook.yml --vault-password-file vault_password_file
你应该看到类似这样的输出:
PLAY [Playbook with secure sudo password] ***************************
TASK [Gathering Facts] **********************************************
ok: [localhost]
TASK [Get sudo user] ***********************************************
changed: [localhost]
TASK [Print sudo user] *********************************************
ok: [localhost] => {
"msg": "Running as root"
}
TASK [Check sudo access] *******************************************
changed: [localhost]
TASK [Print result] ************************************************
ok: [localhost] => {
"msg": "Sudo access successful: True"
}
PLAY RECAP *********************************************************
localhost : ok=5 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
以下是管理 Ansible 中 sudo 密码时要遵循的一些最佳实践:
在生产环境中,你可能还考虑使用 HashiCorp Vault 或 AWS Secrets Manager 等工具来实现更安全的密钥管理。
即使配置正确,你仍然可能在 Ansible 中遇到 sudo 密码问题。在这一步中,我们将探讨常见问题及其解决方案。
以下是使用 sudo 与 Ansible 时可能遇到的一些常见问题:
让我们探讨一下这些问题及其解决方案。
为了更好地理解这些问题,让我们创建一个需要 TTY 的 sudo 场景。编辑我们测试用户的 sudoers 文件:
sudo cp /etc/sudoers.d/ansible_test /etc/sudoers.d/ansible_test.bak
echo 'Defaults:ansible_test requiretty' | sudo tee -a /etc/sudoers.d/ansible_test
此配置使 ansible_test 用户运行 sudo 命令时需要 TTY,这可能会导致 Ansible 出现问题。
创建一个名为 troubleshoot_sudo.yml 的新 playbook,其中包含一些常见的 sudo 故障排除技术:
---
- name: Troubleshoot sudo issues
hosts: localhost
become: true
become_method: sudo
## We'll provide the become_password when running the playbook
tasks:
- name: Check sudo version
command: sudo --version
register: sudo_version
become: false
- name: Print sudo version
debug:
msg: "{{ sudo_version.stdout_lines[0] }}"
become: false
- name: Check sudo configuration
command: sudo -l
register: sudo_config
become: false
failed_when: false
- name: Print sudo configuration
debug:
msg: "{{ sudo_config.stdout_lines }}"
become: false
when: sudo_config.rc == 0
- name: Test sudo command with pty
command: apt update
register: sudo_test
failed_when: false
vars:
ansible_become_flags: "-H"
- name: Print sudo test result
debug:
msg: "Sudo command {{ 'succeeded' if sudo_test.rc == 0 else 'failed' }}"
将此文件保存为 ~/project/ansible-sudo-lab/troubleshoot_sudo.yml
运行故障排除 playbook:
ansible-playbook -i inventory troubleshoot_sudo.yml -K
由于我们以具有无密码 sudo 的 labex 用户身份运行,因此 playbook 应该成功执行。
以下是常见 sudo 密码问题的解决方案:
如果 Ansible 失败并显示类似“缺少 sudo 密码”的消息,你可以:
-K 选项提示输入 sudo 密码ansible_become_password 变量如果 sudo 密码不正确:
如果用户没有正确的 sudo 权限:
sudo -l 检查用户的 sudo 权限如果 sudo 需要 TTY:
ansible_become_flags: "-H" 添加到你的 playbook 或 inventoryrequiretty 选项pty: true 选项让我们恢复我们测试用户的原始 sudo 配置:
sudo cp /etc/sudoers.d/ansible_test.bak /etc/sudoers.d/ansible_test
sudo rm /etc/sudoers.d/ansible_test.bak
这将删除我们之前添加的 requiretty 选项。
在这个实验中,你已经学习了如何在 Ansible playbooks 中处理 sudo 密码,这是许多管理员和 DevOps 工程师面临的常见挑战。以下是你完成的总结:
这些技能将帮助你创建更安全、更可靠的 Ansible playbooks,这些 playbooks 能够处理不同环境中各种 sudo 配置。
本实验的主要收获:
有了这些技能,你现在可以自信地使用 Ansible 执行需要提升权限的任务,确保你的自动化运行平稳且安全。