跳到主要内容

Ansible配置管理

1. 概念

Ansible = 用 SSH 在远程服务器执行命令,状态收敛到 yaml 描述。无 agent,安装即用。

适合:

  • 服务器初始化(装包、配防火墙、加用户)
  • 配置文件分发
  • 批量运维(重启服务、补丁、备份)
  • 不上容器的传统部署

不适合:

  • K8s 资源(用 Helm)
  • 云资源创建(用 Terraform)

2. 起步

brew install ansible

# 不需要 server,控制机本机就行
ansible --version

2.1 inventory(主机清单)

# inventory.ini
[web]
web1.example.com ansible_user=ubuntu
web2.example.com ansible_user=ubuntu

[db]
db1.example.com

[all:vars]
ansible_python_interpreter=/usr/bin/python3
ansible_ssh_private_key_file=~/.ssh/id_rsa

或 yaml:

all:
hosts:
web1.example.com:
web2.example.com:
vars:
ansible_user: ubuntu
children:
web:
hosts:
web1.example.com:
web2.example.com:

2.2 验证连通

ansible all -i inventory.ini -m ping
ansible web -i inventory.ini -a "uptime"

3. Playbook 示例

# deploy-nginx.yml
- name: Deploy Nginx
hosts: web
become: yes # sudo
vars:
nginx_version: 1.24
tasks:
- name: Install nginx
apt:
name: nginx=}} nginx_version }}*
state: present
update_cache: yes

- name: Copy nginx config
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
owner: root
mode: '0644'
notify: Reload nginx

- name: Ensure nginx running
service:
name: nginx
state: started
enabled: yes

handlers:
- name: Reload nginx
service:
name: nginx
state: reloaded
ansible-playbook -i inventory.ini deploy-nginx.yml

# 干跑
ansible-playbook -i inventory.ini deploy-nginx.yml --check

# 限制主机
ansible-playbook ... --limit web1.example.com

# 限制 task
ansible-playbook ... --tags nginx

4. 常用模块

模块用途
apt / yum装包
service / systemd服务管理
copy复制文件
template渲染 Jinja2 模板
file文件 / 目录 / 链接
lineinfile修改文件单行
user / group用户
cron定时任务
git拉代码
shell / command执行命令
docker_container管理 Docker 容器

5. 模板(Jinja2)

# templates/nginx.conf.j2
worker_processes }} ansible_processor_vcpus }};

events {
worker_connections }} nginx_worker_connections | default(1024) }};
}

http {
{% for upstream in upstreams %}
upstream }} upstream.name }} {
{% for server in upstream.servers %}
server }} server }};
{% endfor %}
}
{% endfor %}
}
- template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
vars:
nginx_worker_connections: 4096
upstreams:
- name: backend
servers: [10.0.0.1:8080, 10.0.0.2:8080]

6. Role(复用单元)

roles/
├── nginx/
│ ├── defaults/main.yml # 默认变量
│ ├── tasks/main.yml # 任务
│ ├── handlers/main.yml # 处理器
│ ├── templates/ # 模板
│ ├── files/ # 静态文件
│ └── vars/main.yml # 内部变量
└── nodejs/
# playbook.yml
- hosts: web
roles:
- nginx
- nodejs

社区 role:Ansible Galaxy

ansible-galaxy install geerlingguy.nginx

7. Vault(加密 secret)

ansible-vault encrypt secret-vars.yml
# 输入密码

ansible-vault edit secret-vars.yml
ansible-vault decrypt secret-vars.yml

# playbook 用
ansible-playbook playbook.yml --ask-vault-pass
ansible-playbook playbook.yml --vault-password-file ~/.vault-pass

加密后可以提交 git。

8. 幂等性

Ansible 模块大多幂等(重复跑结果一样):

# ✓ 幂等
- apt: { name: nginx, state: present }
- file: { path: /etc/app, state: directory, mode: '0755' }

# ✗ 非幂等
- shell: echo "done" >> /var/log/app.log
- command: useradd alice

shell / command 必要时加 creates / changed_when

- shell: ./install.sh
args:
creates: /usr/local/bin/myapp # 文件存在则跳过

9. 部署前端示例

- name: Deploy frontend
hosts: web
become: yes
vars:
app_dir: /var/www/frontend
release_url: https://github.com/myorg/frontend/releases/download/}} version }}/dist.tar.gz

tasks:
- name: Download release
get_url:
url: "}} release_url }}"
dest: /tmp/dist.tar.gz

- name: Backup current
copy:
src: "}} app_dir }}"
dest: "}} app_dir }}.bak.}} ansible_date_time.epoch }}"
remote_src: yes
ignore_errors: yes

- name: Extract new version
unarchive:
src: /tmp/dist.tar.gz
dest: "}} app_dir }}"
remote_src: yes
owner: nginx
group: nginx

- name: Test nginx config
command: nginx -t
changed_when: false

- name: Reload nginx
service:
name: nginx
state: reloaded

10. 何时用 Ansible vs 容器

传统 VM 部署:用 Ansible 配 OS + 跑应用
容器部署:用 Dockerfile 而非 Ansible
K8s:用 Helm,不要 Ansible 装应用

新项目优先容器化,老项目 / 物理机用 Ansible。

11. 常见反模式

  • shell 模块滥用:失去幂等
  • 不分 role:单文件 1000 行
  • secret 明文:用 vault
  • inventory 写 IP:换机器要改全部,用域名
  • 不做 dry-run:直接 apply 灾难
  • all hosts 一次推:分批(serial: 5)防雪崩
  • handler 不用 notify:每次都重启

12. 延伸阅读