介绍
Ansible 是一个强大的 IT 自动化工具,它简化了基础设施管理。在这个实践实验(hands-on lab)中,你将学习如何使用 Ansible 在目标系统上创建具有特定内容的文件。通过完成这个实验,你将理解 Ansible 文件管理的基础知识,并能够在自己的基础设施中实现自动化的文件创建。
Ansible 是一个强大的 IT 自动化工具,它简化了基础设施管理。在这个实践实验(hands-on lab)中,你将学习如何使用 Ansible 在目标系统上创建具有特定内容的文件。通过完成这个实验,你将理解 Ansible 文件管理的基础知识,并能够在自己的基础设施中实现自动化的文件创建。
在开始使用 Ansible 创建文件之前,我们需要在系统上安装和配置它。让我们设置我们的环境:
首先,我们将更新软件包列表并在我们的 Ubuntu 22.04 系统上安装 Ansible:
sudo apt update
sudo apt install -y ansible
运行这些命令后,你应该看到输出,表明 Ansible 已经成功安装。让我们验证安装:
ansible --version
你应该看到类似这样的输出:
ansible [core 2.12.0]
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 (default, ...) [GCC 11.2.0]
jinja version = 3.0.3
libyaml = True
Ansible 使用一个 inventory 文件来定义它将要管理的 hosts(主机)。对于这个实验,我们将创建一个本地 inventory,其中包括我们自己的机器:
mkdir -p ~/project/ansible-files
cd ~/project/ansible-files
~/project/ansible-files
目录inventory
[local]
localhost ansible_connection=local
这个 inventory 文件告诉 Ansible 在本地机器上运行命令,而无需使用 SSH。
ansible.cfg
文件:
~/project/ansible-files
目录ansible.cfg
[defaults]
inventory = ./inventory
host_key_checking = False
cd ~/project/ansible-files
ansible local -m ping
你应该看到类似这样的输出:
localhost | SUCCESS => {
"changed": false,
"ping": "pong"
}
这确认了 Ansible 已正确安装并配置为在你的本地机器上运行命令。
现在我们已经设置好了 Ansible,让我们学习如何创建带有内容的文件。Ansible 提供了几个用于管理文件的模块,在这个步骤中,我们将重点关注 copy
模块。
Ansible Playbook 是 YAML 文件,描述了要在目标主机上执行的一组任务。每个任务都使用一个特定的 Ansible 模块来执行一个操作。
让我们创建第一个 playbook 来创建一个带有内容的文件:
~/project/ansible-files
目录中创建一个新文件:
create_file.yml
---
- name: Create a file with content
hosts: local
tasks:
- name: Create a simple text file
copy:
dest: "~/project/hello.txt"
content: |
Hello from Ansible!
This file was created using the Ansible copy module.
Current date: {{ ansible_date_time.date }}
让我们理解一下这个 playbook 的作用:
hosts: local
行指定此 playbook 将在 inventory 中的 local
组的主机上运行。tasks
部分包含要执行的任务列表。copy
模块用于创建带有内容的文件。dest
参数指定文件的目标路径。content
参数包含将要写入文件的文本内容。{{ ansible_date_time.date }}
是一个变量,当 playbook 运行时,它将被替换为当前日期。cd ~/project/ansible-files
ansible-playbook create_file.yml
你应该看到类似这样的输出:
PLAY [Create a file with content] ***********************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [Create a simple text file] ***********************************************
changed: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
cat ~/project/hello.txt
你应该看到类似这样的输出:
Hello from Ansible!
This file was created using the Ansible copy module.
Current date: 2023-08-15
日期将反映你运行 playbook 时的当前日期。
幂等性是 Ansible 的一个关键特性——多次运行同一个 playbook 应该产生相同的结果。让我们再次运行 playbook,看看幂等性是如何发挥作用的:
ansible-playbook create_file.yml
这次,你应该看到 "changed" 计数为 0:
PLAY [Create a file with content] ***********************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [Create a simple text file] ***********************************************
ok: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
这表明 Ansible 识别到文件已经存在,并且内容正确,因此它不会再次修改它。
在这一步中,我们将探讨如何使用变量和模板,通过 Ansible 创建更具动态性的文件。
变量使你的 playbooks 更加灵活和可重用。让我们创建一个使用变量来创建配置文件的 playbook:
~/project/ansible-files
目录中创建一个新文件:
variables_demo.yml
---
- name: Create files using variables
hosts: local
vars:
app_name: "MyApplication"
app_version: "1.0.0"
port_number: 8080
log_level: "INFO"
tasks:
- name: Create config file with variables
copy:
dest: "~/project/app_config.ini"
content: |
## Configuration for {{ app_name }}
## Generated by Ansible
[application]
name = {{ app_name }}
version = {{ app_version }}
[server]
port = {{ port_number }}
log_level = {{ log_level }}
在这个 playbook 中:
vars
部分定义了可以在整个 playbook 中使用的变量。{{ variable_name }}
语法引用。copy
模块用于创建包含这些变量内容的文件。cd ~/project/ansible-files
ansible-playbook variables_demo.yml
你应该看到类似这样的输出:
PLAY [Create files using variables] ********************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [Create config file with variables] ***************************************
changed: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
cat ~/project/app_config.ini
你应该看到类似这样的输出:
## Configuration for MyApplication
## Generated by Ansible
[application]
name = MyApplication
version = 1.0.0
[server]
port = 8080
log_level = INFO
对于更复杂的文件内容,Ansible 支持 Jinja2 模板。让我们创建一个模板文件并在 playbook 中使用它:
mkdir -p ~/project/ansible-files/templates
~/project/ansible-files/templates
目录web_config.j2
## Web Server Configuration
## Generated by Ansible on {{ ansible_date_time.date }}
server {
listen {{ web_port }};
server_name {{ server_name }};
location / {
root {{ doc_root }};
index index.html;
}
{% if enable_ssl %}
## SSL Configuration
ssl_certificate {{ ssl_cert }};
ssl_certificate_key {{ ssl_key }};
{% endif %}
}
~/project/ansible-files
目录template_demo.yml
---
- name: Create files using templates
hosts: local
vars:
web_port: 80
server_name: "example.com"
doc_root: "/var/www/html"
enable_ssl: true
ssl_cert: "/etc/ssl/certs/example.com.crt"
ssl_key: "/etc/ssl/private/example.com.key"
tasks:
- name: Create web server config from template
template:
src: templates/web_config.j2
dest: ~/project/web_server.conf
在这个 playbook 中:
template
模块代替 copy
。src
参数指向我们的模板文件。dest
参数指定创建输出文件的位置。vars
部分中定义的变量将在模板中使用。cd ~/project/ansible-files
ansible-playbook template_demo.yml
你应该看到类似这样的输出:
PLAY [Create files using templates] ********************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [Create web server config from template] **********************************
changed: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
cat ~/project/web_server.conf
你应该看到类似这样的输出:
## Web Server Configuration
## Generated by Ansible on 2023-08-15
server {
listen 80;
server_name example.com;
location / {
root /var/www/html;
index index.html;
}
## SSL Configuration
ssl_certificate /etc/ssl/certs/example.com.crt;
ssl_certificate_key /etc/ssl/private/example.com.key;
}
注意 Jinja2 模板是如何使用我们的变量呈现的,并且由于 enable_ssl
设置为 true
,因此包含了 SSL 的条件部分。
在最后一步中,我们将探索一些使用 Ansible 的高级文件管理技术,包括文件权限、条件性文件创建以及使用多个与文件相关的模块。
创建文件时,你通常需要设置特定的权限和所有权。让我们创建一个演示此功能的 playbook:
~/project/ansible-files
目录file_permissions.yml
---
- name: Manage file permissions and ownership
hosts: local
tasks:
- name: Create a script file with execute permissions
copy:
dest: ~/project/script.sh
content: |
#!/bin/bash
echo "This script was created by Ansible"
echo "Current user: $(whoami)"
echo "Current directory: $(pwd)"
mode: "0755"
- name: Create a read-only configuration file
copy:
dest: ~/project/readonly.conf
content: |
## This is a read-only configuration file
setting1 = value1
setting2 = value2
mode: "0444"
在这个 playbook 中:
mode
参数用于设置文件权限。0755
表示所有者具有读、写和执行权限,组和其他用户具有读和执行权限。0444
表示对所有人只读。cd ~/project/ansible-files
ansible-playbook file_permissions.yml
你应该看到类似这样的输出:
PLAY [Manage file permissions and ownership] **********************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [Create a script file with execute permissions] **************************
changed: [localhost]
TASK [Create a read-only configuration file] **********************************
changed: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
ls -l ~/project/script.sh ~/project/readonly.conf
你应该看到类似这样的输出:
-rwxr-xr-x 1 labex labex 118 Aug 15 12:34 /home/labex/project/script.sh
-r--r--r-- 1 labex labex 73 Aug 15 12:34 /home/labex/project/readonly.conf
~/project/script.sh
你应该看到类似这样的输出:
This script was created by Ansible
Current user: labex
Current directory: /home/labex/project/ansible-files
有时你只需要在满足特定条件时才创建文件。让我们创建一个演示条件性文件创建的 playbook:
~/project/ansible-files
目录conditional_file.yml
---
- name: Conditional file creation
hosts: local
vars:
environment: "development"
create_debug_file: true
create_backup: false
tasks:
- name: Create environment-specific configuration
copy:
dest: "~/project/{{ environment }}_config.yml"
content: |
## Configuration for {{ environment }} environment
debug: {{ 'enabled' if environment == 'development' else 'disabled' }}
log_level: {{ 'DEBUG' if environment == 'development' else 'INFO' }}
- name: Create debug log file
copy:
dest: ~/project/debug.log
content: |
## Debug log file
## Created: {{ ansible_date_time.iso8601 }}
mode: "0644"
when: create_debug_file
- name: Create backup directory
file:
path: ~/project/backup
state: directory
mode: "0755"
when: create_backup
在这个 playbook 中:
when
指令用于任务的条件执行。file
模块用于创建目录。cd ~/project/ansible-files
ansible-playbook conditional_file.yml
你应该看到类似这样的输出:
PLAY [Conditional file creation] **********************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [Create environment-specific configuration] ******************************
changed: [localhost]
TASK [Create debug log file] **************************************************
changed: [localhost]
TASK [Create backup directory] ************************************************
skipped: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=3 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
请注意,"Create backup directory"(创建备份目录)任务被跳过,因为 create_backup
设置为 false
。
cat ~/project/development_config.yml
cat ~/project/debug.log
ls -la ~/project/ | grep backup
你应该看到已创建的两个文件的内容,并确认没有创建备份目录。
Ansible 提供了几个用于文件管理的模块。让我们创建一个演示使用多个与文件相关的模块的 playbook:
~/project/ansible-files
目录file_modules.yml
---
- name: Demonstrate file-related modules
hosts: local
tasks:
- name: Create a directory
file:
path: ~/project/ansible_demo
state: directory
mode: "0755"
- name: Create a file using the copy module
copy:
dest: ~/project/ansible_demo/copied.txt
content: "This file was created using the copy module.\n"
- name: Create a symbolic link
file:
src: ~/project/ansible_demo/copied.txt
dest: ~/project/ansible_demo/link_to_copied.txt
state: link
- name: Create a file with blockinfile module
blockinfile:
path: ~/project/ansible_demo/block.txt
create: true
block: |
This is a block of text
that will be inserted
as a single unit.
marker: "## {mark} ANSIBLE MANAGED BLOCK"
在这个 playbook 中:
file
模块与 state: directory
一起使用来创建一个目录。file
模块与 state: link
一起使用来创建一个符号链接。blockinfile
模块用于创建一个包含由标记注释包围的文本块的文件。cd ~/project/ansible-files
ansible-playbook file_modules.yml
你应该看到类似这样的输出:
PLAY [Demonstrate file-related modules] ***************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [Create a directory] *****************************************************
changed: [localhost]
TASK [Create a file using the copy module] ************************************
changed: [localhost]
TASK [Create a symbolic link] *************************************************
changed: [localhost]
TASK [Create a file with blockinfile module] **********************************
changed: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
ls -la ~/project/ansible_demo/
cat ~/project/ansible_demo/copied.txt
cat ~/project/ansible_demo/link_to_copied.txt
cat ~/project/ansible_demo/block.txt
你应该看到:
ansible_demo
的目录copied.txt
的文件,其中包含指定的内容link_to_copied.txt
的符号链接,指向 copied.txt
block.txt
的文件,其中包含由标记注释包围的文本块最后一个命令的输出应该类似于:
## BEGIN ANSIBLE MANAGED BLOCK
This is a block of text
that will be inserted
as a single unit.
## END ANSIBLE MANAGED BLOCK
这演示了 Ansible 文件管理功能的通用性。
祝贺你完成了这个 Ansible 文件管理实验。你已经学习了几个重要的概念和技术:
copy
模块创建具有特定内容的文件这些技能为自动化你的基础设施中的文件管理任务奠定了坚实的基础。借助 Ansible,你可以确保在多台服务器上保持一致的文件内容,以受控的方式应用更改,并维护可审计的配置记录。
要继续你的 Ansible 学习之旅,请考虑探索更高级的主题,例如角色(roles)、playbook 组织以及将 Ansible 与其他 DevOps 工具集成。