Ansible 完整中文使用指南
📚 目录
-
Ansible 简介
-
环境准备
-
基础配置
-
基础概念
-
Ad-hoc 命令使用
-
Playbook 编写指南
-
常用模块详解
-
实战示例
-
高级功能
-
最佳实践
-
故障排查
Ansible 简介
Ansible 是一个开源的自动化工具,用于配置管理、应用部署、任务编排和基础设施管理。它具有以下特点:
核心优势
核心组件
-
控制节点(Control Node):运行 Ansible 的机器
-
被管理节点(Managed Nodes):被 Ansible 管理的服务器
-
清单(Inventory):定义被管理节点的文件
-
模块(Modules):执行具体任务的代码单元
-
剧本(Playbooks):定义自动化任务的 YAML 文件
环境准备
1. 生成 SSH 密钥对
ssh-keygen -t rsa -f deployer-key.pem -q -N ""
|
2. 部署基础设施
terraform init
terraform apply
|
3. 环境配置
基础设施包括:
4. SSH 连接配置
scp -i ./deployer-key.pem deployer-key.pem ec2-user@<ansible_server_ip>:~/.ssh
ssh -i ./deployer-key.pem ec2-user@<ansible_server_ip>
vim ~/.ssh/config
|
SSH 配置内容:
Host <client_ip>
User ubuntu
IdentityFile ~/.ssh/deployer-key.pem
|
基础配置
ansible.cfg 配置文件
在项目目录创建 ansible.cfg
文件:
[defaults]
host_key_checking = False
inventory = hosts
remote_user = ubuntu
private_key_file = ~/.ssh/deployer-key.pem
forks = 5
timeout = 30
log_path = ./ansible.log
|
清单文件 (hosts)
创建 hosts
文件定义被管理的主机:
[tag_node]
192.168.1.100
[webservers]
web1 ansible_host=192.168.1.100 ansible_user=ubuntu
web2 ansible_host=192.168.1.101 ansible_user=ubuntu
[webservers:vars]
http_port=80
max_clients=200
[production:children]
webservers
databases
|
基础概念
YAML 语法基础
---
name: "Ansible Tutorial"
version: 2.9
packages:
- nginx
- mysql
- php
database:
host: localhost
port: 3306
name: myapp
description: |
这是一个多行
字符串示例
保持换行格式
enabled: true
debug: false
|
Ansible 变量
变量定义方式
---
- hosts: webservers
vars:
http_port: 80
server_name: example.com
tasks:
- name: 使用变量
debug:
msg: "服务器 {{ server_name }} 监听端口 {{ http_port }}"
|
变量优先级(从高到低)
-
命令行变量 (-e
)
-
任务变量
-
剧本变量
-
主机变量
-
组变量
-
默认变量
Ad-hoc 命令使用
Ad-hoc 命令用于执行简单的一次性任务,非常适合开发和调试阶段。
基本语法
ansible [主机模式] -m [模块名] -a "[模块参数]" [其他选项]
|
常用 Ad-hoc 命令示例
1. 连通性测试
ansible all -m ping
ansible webservers -m ping
ansible web1 -m ping
|
2. 收集系统信息
ansible all -m setup
ansible all -m setup -a "filter=ansible_os_family"
ansible all -m setup -a "filter=ansible_memory_mb"
|
3. 包管理
ansible all -b -m apt -a "name=nginx state=present"
ansible all -b -m apt -a "name=nginx,mysql-server state=present"
ansible all -b -m apt -a "update_cache=yes"
ansible all -b -m apt -a "name=nginx state=absent"
|
4. 服务管理
ansible all -b -m systemd -a "name=nginx state=started"
ansible all -b -m systemd -a "name=nginx state=stopped"
ansible all -b -m systemd -a "name=nginx state=restarted"
ansible all -b -m systemd -a "name=nginx enabled=yes"
|
5. 用户管理
ansible all -b -m user -a "name=testuser shell=/bin/bash"
ansible all -b -m user -a "name=testuser password={{ 'password123' | password_hash('sha512') }}"
ansible all -b -m user -a "name=testuser state=absent remove=yes"
|
6. 文件操作
ansible all -m copy -a "src=/etc/hosts dest=/tmp/hosts"
ansible all -m file -a "path=/tmp/testdir state=directory mode=0755"
ansible all -m file -a "path=/tmp/testfile state=absent"
ansible all -m file -a "path=/tmp/testfile mode=0644 owner=ubuntu group=ubuntu"
|
7. 命令执行
ansible all -m command -a "uptime"
ansible all -m shell -a "ps aux | grep nginx"
ansible all -m command -a "ls -la" -a "chdir=/tmp"
|
重要选项说明
Playbook 编写指南
Level 1: 基础 Playbook
1. 第一个 Playbook (first.yaml
)
---
- name: "我的第一个 Playbook"
hosts: localhost
tasks:
- name: "测试连通性"
ping:
|
运行命令:
ansible-playbook first.yaml
|
2. Hello World 示例 (helloworld.yaml
)
---
- name: 我的第二个 Playbook
hosts: localhost
tasks:
- name: 打印 Hello World
debug:
msg: "Hello World"
|
3. 多任务 Playbook (mtask.yaml
)
---
- name: 运行多个任务
hosts: localhost
tasks:
- name: 测试连通性
ping:
- name: 打印 Hello World
debug:
msg: "Hello World"
|
Level 2: 远程主机 Playbook
远程连通性测试 (rfirst.yaml
)
---
- name: "远程主机测试"
hosts: all
tasks:
- name: "测试远程连通性"
ping:
|
Playbook 结构说明
---
- name: "剧本描述"
hosts: target_hosts
become: yes
become_user: root
user: ubuntu
gather_facts: yes
vars:
variable_name: value
tasks:
- name: "任务描述"
module_name:
parameter: value
register: result
when: condition
notify: handler_name
handlers:
- name: "处理器名称"
module_name:
parameter: value
|
常用模块详解
1. 包管理模块 (apt
)
基础用法示例 (1-builtin-apt.yml
)
---
- hosts: tag_node
become: yes
become_user: root
user: ubuntu
tasks:
- name: 安装 nginx
ansible.builtin.apt:
name: nginx
state: present
update_cache: yes
- name: 安装软件包列表
ansible.builtin.apt:
pkg:
- apt-transport-https
- ca-certificates
- lsb-release
- gnupg
- zip
state: latest
- name: 卸载 zip 包
ansible.builtin.apt:
name: zip
state: absent
- name: 添加 Docker GPG 密钥
ansible.builtin.apt_key:
url: "https://download.docker.com/linux/{{ ansible_distribution | lower }}/gpg"
state: present
- name: 添加 Docker 软件源
ansible.builtin.apt_repository:
repo: "deb [arch={{ ansible_architecture }}] https://download.docker.com/linux/{{ ansible_distribution | lower }} {{ ansible_distribution_release }} stable"
state: present
filename: docker
- name: 安装 Docker
ansible.builtin.apt:
name:
- docker
- docker.io
- docker-compose
- docker-registry
state: latest
update_cache: true
|
apt 模块参数说明
2. 用户和组管理模块
示例 (2-builtin-user-group.yml
)
---
- hosts: tag_node
become: yes
become_user: root
user: ubuntu
tasks:
- name: 创建 devops 组
ansible.builtin.group:
name: devops
state: present
- name: 删除 docker 组
ansible.builtin.group:
name: docker
state: absent
- name: 添加用户 zhangsan
ansible.builtin.user:
name: zhangsan
shell: /bin/bash
group: devops
- name: 添加用户 william
ansible.builtin.user:
name: william
comment: William
uid: 1040
groups: sudo,admin,devops
append: yes
- name: 删除用户 zhangsan
ansible.builtin.user:
name: zhangsan
state: absent
remove: yes
- name: 为 william 生成 SSH 密钥
ansible.builtin.user:
name: william
generate_ssh_key: yes
ssh_key_bits: 2048
ssh_key_file: .ssh/id_rsa
|
user 模块主要参数
3. 文件和目录管理模块
示例 (3-builtin-file-copy.yml
)
---
- hosts: tag_node
become: yes
become_user: root
user: ubuntu
vars:
demo_files:
- /home/ubuntu/ansible/demo1.conf
- /home/ubuntu/ansible/demo2.conf
- /home/ubuntu/ansible/demo3.conf
demo_directories:
- /home/ubuntu/ansible/1
- /home/ubuntu/ansible/2
tasks:
- name: 创建目录
ansible.builtin.file:
path: "{{ item }}"
state: directory
mode: "0755"
loop: "{{ demo_directories }}"
- name: 创建文件
ansible.builtin.file:
path: "{{ item }}"
state: touch
mode: u=rw,g=r,o=r
loop: "{{ demo_files }}"
- name: 递归修改目录所有权
ansible.builtin.file:
path: /home/ubuntu/ansible/
state: directory
recurse: yes
owner: ubuntu
group: ubuntu
- name: 修改文件权限
ansible.builtin.file:
path: /home/ubuntu/ansible/demo2.conf
owner: william
group: devops
mode: "0644"
- name: 删除文件
ansible.builtin.file:
path: /home/ubuntu/ansible/demo2.conf
state: absent
- name: 复制本地文件到远程
ansible.builtin.copy:
src: /etc/zshrc
dest: /home/ubuntu/ansible/
owner: william
group: devops
mode: "0644"
- name: 远程文件复制
ansible.builtin.copy:
src: /home/ubuntu/ansible/zshrc
dest: /home/ubuntu/ansible/zshrc.backup
remote_src: yes
- name: 递归删除目录
ansible.builtin.file:
path: /home/ubuntu/ansible/
state: absent
|
file 模块参数说明
copy 模块参数说明
-
src
:源文件路径
-
dest
:目标路径
-
remote_src
:源文件是否在远程主机
-
backup
:是否备份原文件
-
force
:是否强制覆盖
4. 服务管理模块
示例 (4-builtin-service-systemd.yml
)
---
- hosts: tag_node
become: yes
become_user: root
user: ubuntu
tasks:
- name: 停止 nginx 服务
ansible.builtin.service:
name: nginx
state: stopped
- name: 禁用 nginx 服务
ansible.builtin.service:
name: nginx
enabled: no
- name: 启动 nginx 服务
ansible.builtin.service:
name: nginx
state: started
- name: 启用 nginx 服务
ansible.builtin.service:
name: nginx
enabled: yes
|
service 模块参数
5. 命令执行模块
示例 (5-builtin-command-shell.yml
)
---
- hosts: tag_node
user: ubuntu
tasks:
- name: 在指定目录创建文件
ansible.builtin.command: touch 2.txt
args:
chdir: /home/ubuntu/ansible/2/
- name: 执行 shell 命令
ansible.builtin.shell:
cmd: |
echo "Hello"
ls -la ./2
chdir: /home/ubuntu/ansible
|
command vs shell 模块对比
| 特性 | command | shell |
| -------- | ------- | ----- |
| 管道支持 | ❌ | ✅ |
| 重定向 | ❌ | ✅ |
| 环境变量 | ❌ | ✅ |
| 安全性 | 更高 | 较低 |
| 性能 | 更快 | 较慢 |
实战示例
完整的 Web 服务器部署 Playbook
---
- name: 部署 Web 服务器
hosts: webservers
become: yes
vars:
web_user: www-data
web_group: www-data
site_name: example.com
document_root: /var/www/{{ site_name }}
tasks:
- name: 更新包缓存
apt:
update_cache: yes
cache_valid_time: 3600
- name: 安装 Web 服务器软件
apt:
pkg:
- nginx
- php-fpm
- mysql-server
- git
state: latest
- name: 创建网站目录
file:
path: "{{ document_root }}"
state: directory
owner: "{{ web_user }}"
group: "{{ web_group }}"
mode: "0755"
- name: 创建测试页面
copy:
content: |
<!DOCTYPE html>
<html>
<head>
<title>{{ site_name }}</title>
</head>
<body>
<h1>欢迎访问 {{ site_name }}</h1>
<p>服务器时间: {{ ansible_date_time.iso8601 }}</p>
</body>
</html>
dest: "{{ document_root }}/index.html"
owner: "{{ web_user }}"
group: "{{ web_group }}"
mode: "0644"
- name: 配置 Nginx 虚拟主机
template:
src: nginx-site.conf.j2
dest: "/etc/nginx/sites-available/{{ site_name }}"
notify: restart nginx
- name: 启用 Nginx 站点
file:
src: "/etc/nginx/sites-available/{{ site_name }}"
dest: "/etc/nginx/sites-enabled/{{ site_name }}"
state: link
notify: restart nginx
- name: 启动并启用服务
systemd:
name: "{{ item }}"
state: started
enabled: yes
loop:
- nginx
- mysql
- php7.4-fpm
handlers:
- name: restart nginx
systemd:
name: nginx
state: restarted
|
Nginx 配置模板 (templates/nginx-site.conf.j2
)
server {
listen 80;
server_name {{ site_name }};
root {{ document_root }};
index index.html index.php;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
error_log /var/log/nginx/{{ site_name }}_error.log;
access_log /var/log/nginx/{{ site_name }}_access.log;
}
|
高级功能
1. Ansible Vault - 敏感数据加密
创建加密文件
ansible-vault create secret.yml
ansible-vault edit secret.yml
ansible-vault view secret.yml
ansible-vault encrypt plain.yml
ansible-vault decrypt secret.yml
|
在 Playbook 中使用加密变量
---
- hosts: localhost
vars_files:
- secret.yml
tasks:
- name: 使用加密的密码
debug:
msg: "数据库密码是: {{ db_password }}"
|
运行使用加密文件的 Playbook
ansible-playbook --ask-vault-pass playbook.yml
ansible-playbook --vault-password-file .vault_pass playbook.yml
|
2. 模板 (Templates)
Jinja2 模板示例
# 配置文件模板 (templates/app.conf.j2)
[database]
host = {{ db_host | default('localhost') }}
port = {{ db_port | default(3306) }}
name = {{ db_name }}
user = {{ db_user }}
password = {{ db_password }}
[web]
listen_port = {{ web_port | default(80) }}
workers = {{ ansible_processor_vcpus * 2 }}
debug = {{ debug_mode | default(false) | bool }}
# 生成配置文件的任务
- name: 生成应用配置文件
template:
src: app.conf.j2
dest: /etc/myapp/app.conf
owner: myapp
group: myapp
mode: '0600'
|
3. 条件执行
---
- hosts: all
tasks:
- name: 在 Ubuntu 上安装包
apt:
name: nginx
state: present
when: ansible_os_family == "Debian"
- name: 在 CentOS 上安装包
yum:
name: nginx
state: present
when: ansible_os_family == "RedHat"
- name: 仅在生产环境执行
service:
name: nginx
state: started
when: environment == "production"
- name: 复杂条件示例
debug:
msg: "执行此任务"
when:
- ansible_memory_mb.real.total > 1024
- ansible_processor_vcpus >= 2
- inventory_hostname in groups['webservers']
|
4. 循环 (Loops)
---
- hosts: all
vars:
users:
- name: alice
groups: [sudo, developers]
- name: bob
groups: [developers]
packages:
- git
- vim
- curl
tasks:
- name: 安装包列表
apt:
name: "{{ item }}"
state: present
loop: "{{ packages }}"
- name: 创建用户
user:
name: "{{ item.name }}"
groups: "{{ item.groups | join(',') }}"
append: yes
loop: "{{ users }}"
- name: 创建目录
file:
path: "/tmp/dir{{ item }}"
state: directory
loop: "{{ range(1, 6) | list }}"
- name: 复制配置文件
copy:
src: "{{ item }}"
dest: "/etc/myapp/"
with_fileglob:
- "configs/*.conf"
|
5. 错误处理
---
- hosts: all
tasks:
- name: 可能失败的任务
command: /some/command
ignore_errors: yes
- name: 检查返回码
command: /some/command
register: result
failed_when: result.rc != 0 and result.rc != 2
- name: 重试下载
get_url:
url: http://example.com/file.zip
dest: /tmp/file.zip
retries: 3
delay: 5
- name: 主要任务
block:
- name: 尝试执行的任务
command: /risky/command
rescue:
- name: 失败时执行的任务
debug:
msg: "主要任务失败,执行救援任务"
always:
- name: 总是执行的任务
debug:
msg: "清理工作"
|
6. Roles - 代码重用
Role 目录结构
roles/
└── nginx/
├── tasks/
│ └── main.yml
├── handlers/
│ └── main.yml
├── templates/
│ └── nginx.conf.j2
├── files/
├── vars/
│ └── main.yml
├── defaults/
│ └── main.yml
└── meta/
└── main.yml
|
Role 使用示例
---
- hosts: webservers
roles:
- nginx
- mysql
- { role: php, version: 7.4 }
|
最佳实践
1. 目录结构组织
ansible-project/
├── inventories/
│ ├── production/
│ │ ├── hosts
│ │ └── group_vars/
│ └── staging/
│ ├── hosts
│ └── group_vars/
├── roles/
├── playbooks/
├── group_vars/
├── host_vars/
├── ansible.cfg
└── requirements.yml
|
2. 变量管理
按环境组织变量
inventories/production/group_vars/all.yml
inventories/production/group_vars/webservers.yml
inventories/staging/group_vars/all.yml
inventories/staging/group_vars/webservers.yml
|
敏感数据处理
ansible-vault encrypt group_vars/all/vault.yml
db_password: "{{ vault_db_password }}"
api_key: "{{ vault_api_key }}"
|
3. Playbook 编写规范
良好的 Playbook 结构
---
- name: 清晰的 Playbook 描述
hosts: webservers
become: yes
vars:
app_name: myapp
app_version: 1.0.0
pre_tasks:
- name: 更新包缓存
apt:
update_cache: yes
roles:
- common
- nginx
tasks:
- name: 每个任务都有清晰的描述
template:
src: config.j2
dest: /etc/myapp/config.conf
notify: restart myapp
post_tasks:
- name: 验证服务状态
uri:
url: http://{{ inventory_hostname }}
status_code: 200
handlers:
- name: restart myapp
systemd:
name: myapp
state: restarted
|
4. 安全考虑
安全配置清单
-
[ ] 使用 Ansible Vault 加密敏感数据
-
[ ] 限制 sudo 权限,只在必要时使用 become
-
[ ] 使用 SSH 密钥而非密码认证
-
[ ] 定期轮换密钥和密码
-
[ ] 在生产环境启用 host_key_checking
-
[ ] 使用防火墙限制 SSH 访问
-
[ ] 定期审计 Playbook 和 Role
安全配置示例
[defaults]
host_key_checking = True
ask_pass = False
ask_sudo_pass = False
remote_user = ansible
private_key_file = ~/.ssh/ansible_key
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=yes
|
故障排查
1. 调试技巧
启用调试模式
ansible-playbook -v playbook.yml
ansible-playbook -vv playbook.yml
ansible-playbook -vvv playbook.yml
|
使用 debug 模块
- name: 调试变量
debug:
var: ansible_facts
- name: 调试消息
debug:
msg: "主机名是 {{ inventory_hostname }}"
- name: 条件调试
debug:
msg: "这是生产环境"
when: environment == "production"
|
检查模式
ansible-playbook --check playbook.yml
ansible-playbook --check --diff playbook.yml
|
2. 常见问题解决
SSH 连接问题
ansible all -m ping
ansible all -m ping --private-key ~/.ssh/mykey
ansible all -m ping -e 'ansible_ssh_common_args="-o StrictHostKeyChecking=no"'
|
权限问题
ansible all -m command -a "whoami" --become
ansible all -m command -a "whoami" --become --become-user root
ansible all -m command -a "whoami" --become --ask-become-pass
|
语法检查
ansible-playbook --syntax-check playbook.yml
pip install ansible-lint
ansible-lint playbook.yml
|
3. 日志分析
启用日志
[defaults]
log_path = /var/log/ansible.log
|
分析失败任务
grep FAILED /var/log/ansible.log
grep "host1" /var/log/ansible.log
|
4. 性能优化
并发控制
[defaults]
forks = 10
host_key_checking = False
[ssh_connection]
pipelining = True
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
|
事实缓存
[defaults]
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_facts_cache
fact_caching_timeout = 3600
|
减少 SSH 连接
- hosts: all
gather_facts: no
tasks:
- name: 简单任务
ping:
|
扩展资源
官方文档
社区资源
学习建议
-
逐步学习:从简单的 ad-hoc 命令开始,逐步学习 Playbook 和 Role
-
动手实践:在测试环境中实际操作,验证理论知识
-
阅读他人代码:研究 Ansible Galaxy 中的优秀 Role
-
关注最佳实践:始终考虑安全性、可维护性和可读性
-
持续学习:Ansible 在不断发展,保持学习新功能和改进
总结
Ansible 是一个功能强大且易于学习的自动化工具。通过本指南,您应该能够:
✅ 理解 Ansible 的核心概念和架构
✅ 搭建 Ansible 环境并进行基本配置
✅ 编写和执行 Playbook
✅ 使用常用模块完成系统管理任务
✅ 应用高级功能如变量、模板、条件执行等
✅ 遵循最佳实践,编写高质量的自动化代码
✅ 排查和解决常见问题
记住,熟练掌握 Ansible 需要时间和实践。建议您从简单的任务开始,逐步增加复杂性,并始终关注代码的可读性和可维护性。
祝您 Ansible 学习愉快! 🚀