本文介绍Ansible基础概念、安装配置、常用模块,以及实战批量部署案例。
前言
管理1台服务器,手工操作没问题。
管理10台服务器,写脚本能应付。
管理100台服务器,必须用自动化工具。
Ansible是最流行的自动化运维工具之一,无需在目标机器安装Agent,基于SSH即可工作。
今天来入门Ansible。
一、Ansible简介
1.1 为什么选择Ansible
| 特点 | 说明 |
|---|---|
| 无Agent | 基于SSH,目标机器无需安装客户端 |
| YAML语法 | Playbook易读易写 |
| 幂等性 | 多次执行结果一致 |
| 模块丰富 | 几千个现成模块 |
| 推送模式 | 从控制机推送到目标机 |
1.2 Ansible架构
┌─────────────────┐
│ 控制机 │
│ (Ansible) │
└────────┬────────┘
│ SSH
┌────────┴────────┐
│ │
↓ ↓
┌─────────┐ ┌─────────┐
│ 目标机1 │ │ 目标机2 │
│ (被管理) │ │ (被管理) │
└─────────┘ └─────────┘
核心组件:
- Inventory:主机清单
- Module:执行模块
- Playbook:剧本(任务编排)
- Role:角色(可复用的Playbook集合)
二、安装配置
2.1 安装Ansible
bash
# Ubuntu/Debian
apt update
apt install ansible
# CentOS/RHEL
yum install epel-release
yum install ansible
# pip安装(推荐,版本更新)
pip install ansible
# 验证
ansible --version
2.2 配置SSH免密登录
bash
# 生成密钥(如果没有)
ssh-keygen -t rsa -b 4096
# 复制公钥到目标机器
ssh-copy-id user@192.168.1.10
ssh-copy-id user@192.168.1.11
ssh-copy-id user@192.168.1.12
# 测试
ssh user@192.168.1.10
2.3 配置Inventory
ini
# /etc/ansible/hosts 或 ./inventory
# 单个主机
192.168.1.10
# 主机组
[webservers]
192.168.1.10
192.168.1.11
192.168.1.12
[dbservers]
192.168.1.20 ansible_user=mysql
# 带变量
[webservers:vars]
ansible_user=deploy
ansible_port=22
# 组嵌套
[production:children]
webservers
dbservers
2.4 ansible.cfg配置
ini
# ./ansible.cfg 或 /etc/ansible/ansible.cfg
[defaults]
inventory = ./inventory
remote_user = deploy
private_key_file = ~/.ssh/id_rsa
host_key_checking = False
timeout = 30
[privilege_escalation]
become = True
become_method = sudo
become_user = root
become_ask_pass = False
三、Ad-Hoc命令
3.1 基本语法
bash
ansible <主机/组> -m <模块> -a "<参数>"
3.2 常用示例
bash
# 测试连通性
ansible all -m ping
# 执行命令
ansible webservers -m shell -a "uptime"
# 查看内存
ansible webservers -m shell -a "free -h"
# 复制文件
ansible webservers -m copy -a "src=/tmp/file.txt dest=/tmp/file.txt"
# 安装软件
ansible webservers -m apt -a "name=nginx state=present" --become
# 管理服务
ansible webservers -m service -a "name=nginx state=started" --become
# 创建用户
ansible webservers -m user -a "name=deploy state=present" --become
四、常用模块
4.1 文件操作
yaml
# copy - 复制文件
- copy:
src: /local/file
dest: /remote/file
owner: root
mode: '0644'
# file - 文件/目录管理
- file:
path: /data/app
state: directory
owner: deploy
mode: '0755'
# template - 模板渲染
- template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
# lineinfile - 修改文件行
- lineinfile:
path: /etc/hosts
line: "192.168.1.100 myserver"
state: present
4.2 软件管理
yaml
# apt - Debian系
- apt:
name: nginx
state: present
update_cache: yes
# yum - RedHat系
- yum:
name: nginx
state: present
# pip - Python包
- pip:
name: flask
state: present
virtualenv: /opt/app/venv
4.3 服务管理
yaml
# service/systemd
- systemd:
name: nginx
state: started
enabled: yes
daemon_reload: yes
4.4 用户管理
yaml
# user
- user:
name: deploy
groups: sudo
shell: /bin/bash
state: present
# authorized_key
- authorized_key:
user: deploy
key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
五、Playbook编写
5.1 基本结构
yaml
# deploy.yml
---
- name: Deploy Web Application
hosts: webservers
become: yes
vars:
app_name: myapp
app_port: 8080
tasks:
- name: Install required packages
apt:
name:
- nginx
- python3
- python3-pip
state: present
update_cache: yes
- name: Create app directory
file:
path: /opt/{{ app_name }}
state: directory
owner: deploy
mode: '0755'
- name: Copy application files
copy:
src: ./app/
dest: /opt/{{ app_name }}/
owner: deploy
- name: Start nginx
systemd:
name: nginx
state: started
enabled: yes
5.2 执行Playbook
bash
# 执行
ansible-playbook deploy.yml
# 检查语法
ansible-playbook deploy.yml --syntax-check
# 预演(不真正执行)
ansible-playbook deploy.yml --check
# 指定主机
ansible-playbook deploy.yml --limit webservers
# 显示详细信息
ansible-playbook deploy.yml -v # -vv, -vvv更详细
5.3 变量
yaml
# 在Playbook中定义
vars:
http_port: 80
app_name: myapp
# 在变量文件中
vars_files:
- vars/main.yml
# 命令行传入
ansible-playbook deploy.yml -e "http_port=8080"
# 使用变量
tasks:
- name: Configure port
template:
src: config.j2
dest: /etc/app/config
vars:
port: "{{ http_port }}"
5.4 条件判断
yaml
tasks:
- name: Install nginx on Debian
apt:
name: nginx
when: ansible_os_family == "Debian"
- name: Install nginx on RedHat
yum:
name: nginx
when: ansible_os_family == "RedHat"
5.5 循环
yaml
tasks:
- name: Install packages
apt:
name: "{{ item }}"
state: present
loop:
- nginx
- vim
- git
- name: Create users
user:
name: "{{ item.name }}"
groups: "{{ item.groups }}"
loop:
- { name: 'user1', groups: 'sudo' }
- { name: 'user2', groups: 'docker' }
5.6 Handler
yaml
tasks:
- name: Update nginx config
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: Restart nginx
handlers:
- name: Restart nginx
systemd:
name: nginx
state: restarted
六、实战案例
6.1 批量初始化服务器
yaml
# init_server.yml
---
- name: Initialize Servers
hosts: all
become: yes
tasks:
- name: Update apt cache
apt:
update_cache: yes
cache_valid_time: 3600
- name: Install basic packages
apt:
name:
- vim
- curl
- wget
- htop
- git
- net-tools
state: present
- name: Set timezone
timezone:
name: Asia/Shanghai
- name: Configure sysctl
sysctl:
name: "{{ item.key }}"
value: "{{ item.value }}"
sysctl_set: yes
loop:
- { key: 'net.core.somaxconn', value: '65535' }
- { key: 'vm.swappiness', value: '10' }
- name: Create deploy user
user:
name: deploy
groups: sudo
shell: /bin/bash
- name: Set up SSH key for deploy user
authorized_key:
user: deploy
key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
6.2 部署Nginx + 应用
yaml
# deploy_app.yml
---
- name: Deploy Application
hosts: webservers
become: yes
vars:
app_name: myapp
app_port: 8080
tasks:
- name: Install Nginx
apt:
name: nginx
state: present
- name: Configure Nginx
template:
src: templates/nginx.conf.j2
dest: /etc/nginx/sites-available/{{ app_name }}
notify: Restart nginx
- name: Enable site
file:
src: /etc/nginx/sites-available/{{ app_name }}
dest: /etc/nginx/sites-enabled/{{ app_name }}
state: link
- name: Deploy application
copy:
src: app/
dest: /opt/{{ app_name }}/
- name: Install dependencies
pip:
requirements: /opt/{{ app_name }}/requirements.txt
virtualenv: /opt/{{ app_name }}/venv
handlers:
- name: Restart nginx
systemd:
name: nginx
state: restarted
6.3 组网批量部署
如果你的服务器分布在不同地点,可以先用组网软件(如星空组网)连接起来,然后通过组网的虚拟IP进行Ansible管理:
ini
# inventory
[remote_servers]
10.10.0.1 ansible_host=10.10.0.1 # 组网虚拟IP
10.10.0.2 ansible_host=10.10.0.2
10.10.0.3 ansible_host=10.10.0.3
[remote_servers:vars]
ansible_user=deploy
这样即使服务器没有公网IP,也能通过组网进行批量管理,非常方便。
七、Role组织
7.1 Role结构
roles/
└── nginx/
├── tasks/
│ └── main.yml
├── handlers/
│ └── main.yml
├── templates/
│ └── nginx.conf.j2
├── files/
├── vars/
│ └── main.yml
└── defaults/
└── main.yml
7.2 使用Role
yaml
# site.yml
---
- hosts: webservers
become: yes
roles:
- nginx
- php
- mysql
7.3 Ansible Galaxy
bash
# 搜索Role
ansible-galaxy search nginx
# 安装Role
ansible-galaxy install geerlingguy.nginx
# 列出已安装
ansible-galaxy list
八、最佳实践
8.1 目录结构
project/
├── ansible.cfg
├── inventory/
│ ├── production
│ └── staging
├── group_vars/
│ ├── all.yml
│ └── webservers.yml
├── host_vars/
│ └── 192.168.1.10.yml
├── roles/
│ ├── common/
│ └── nginx/
├── playbooks/
│ ├── deploy.yml
│ └── init.yml
└── templates/
8.2 安全建议
bash
# 使用Ansible Vault加密敏感信息
ansible-vault create secrets.yml
ansible-vault edit secrets.yml
# 使用加密变量
ansible-playbook deploy.yml --ask-vault-pass
# 或使用密码文件
ansible-playbook deploy.yml --vault-password-file ~/.vault_pass
8.3 调试技巧
yaml
# 打印变量
- debug:
var: ansible_facts
# 打印消息
- debug:
msg: "The value is {{ my_var }}"
# 注册结果
- shell: whoami
register: result
- debug:
var: result.stdout
九、总结
Ansible入门要点:
- 基础概念:Inventory、Module、Playbook、Role
- SSH免密:Ansible基于SSH,先配置好免密登录
- Ad-Hoc:简单任务用命令行
- Playbook:复杂任务用YAML编排
- 幂等性:多次执行结果一致
- 模块化:用Role组织可复用的配置
常用命令速查:
bash
# 测试连通性
ansible all -m ping
# 执行命令
ansible all -m shell -a "uptime"
# 执行Playbook
ansible-playbook deploy.yml
# 检查语法
ansible-playbook deploy.yml --syntax-check
# 预演
ansible-playbook deploy.yml --check
参考资料
- Ansible官方文档:https://docs.ansible.com/
- Ansible Galaxy:https://galaxy.ansible.com/
- 《Ansible权威指南》
💡 建议:从简单的Ad-Hoc命令开始,熟练后再写Playbook。不要一开始就追求完美的Role结构。