最近自学 Ansible,感觉已经能写一些简单的自动化脚本了,但一到实际项目就发现文件配置、动态生成和大规模主机管理还是有点乱。于是又翻了资料,把文件操作、Jinja2 模板和 Playbook 拆分组织这些重点内容整理了一下,写成这份笔记,方便自己以后复习,也分享给同样在学的同学。


目录

  1. 文件管理模块常用操作

  2. Jinja2 模板生成动态配置

  3. 主机选择的高级模式

  4. Playbook 拆分与复用(import vs include)

  5. 总结与易错点记录

  6. 学习小结


1. 文件管理模块常用操作

Ansible 自带的文件模块超级好用,基本覆盖了日常的创建、复制、修改、删除需求,而且大部分是幂等的,跑多少次都不会乱改。

常用模块:

  • file:创建/删除文件或目录,改权限、所有者

  • copy:把本地文件推到远程主机

  • lineinfile:确保某一行存在(或删除)

  • stat:查看文件信息

  • synchronize:用 rsync 同步目录

几个常用例子

创建空文件并设置权限:

- name: 创建配置文件
  ansible.builtin.file:
    path: /etc/myapp/app.conf
    state: touch
    mode: '0640'
    owner: appuser
    group: appgroup

复制本地文件(建议开 backup):

- name: 推送配置
  ansible.builtin.copy:
    src: files/app.conf
    dest: /etc/myapp/app.conf
    mode: '0640'
    backup: yes

在文件末尾加一行:

- name: 添加环境变量
  ansible.builtin.lineinfile:
    path: /etc/profile
    line: 'export JAVA_HOME=/opt/jdk'
    state: present
    insertafter: EOF

清理目录:

- name: 删除旧数据
  ansible.builtin.file:
    path: /tmp/old_data
    state: absent
    recurse: yes

目录同步(备份网站时常用):

- name: 同步 html 目录
  ansible.posix.synchronize:
    src: /var/www/html/
    dest: /backup/html/
    delete: yes

小体会copy 适合静态文件,template 适合带变量的(后面会讲),先分清楚用哪个。


2. Jinja2 模板生成动态配置

静态文件用 copy 就行,但真实场景里配置经常要根据不同主机变化,这时候就得用 template 模块 + Jinja2 模板。

模板放 templates/ 目录,推荐用 .j2 后缀。

简单例子:生成 /etc/motd

templates/motd.j2:

欢迎登录 {{ ansible_hostname }}
当前时间:{{ ansible_date_time.date }}
内核:{{ ansible_kernel }}

Playbook:

- name: 生成动态 motd
  ansible.builtin.template:
    src: motd.j2
    dest: /etc/motd
    mode: '0644'

循环例子(生成 hosts 文件):

templates/hosts.j2:

127.0.0.1 localhost
{% for host in groups['webservers'] %}
{{ hostvars[host].ansible_default_ipv4.address }} {{ host }}
{% endfor %}

条件判断

{% if ansible_distribution == 'Ubuntu' %}
# Ubuntu 专用配置
{% endif %}

常用过滤器:

  • {{ list | unique }}

  • {{ value | default('默认值') }}

  • {{ data | to_json }}

我踩过的坑:如果循环的组为空,会多出一堆空行,加个判断就好了:

{% if groups['webservers'] | length > 0 %}
{% for host in groups['webservers'] %}
...
{% endfor %}
{% endif %}

3. 主机选择的高级模式

写 Playbook 时,hosts: 这行可以写得很灵活,尤其是机器多了以后。

基础:

  • 单机:web1

  • 组:webserversall

  • 通配:web*

高级:

  • 范围:web[01:10]

  • 并集:webservers,dbservers

  • 交集:production:&webservers

  • 排除:all:!web3

例子(灰度更新前5台生产web,跳过web3):

- hosts: web[1-5]:&production:!web3
  tasks:
    - ...

我现在做小项目时经常用交集+排除来控制滚动更新范围,挺好使的。


4. Playbook 拆分与复用(import vs include)

Playbook 写长了特别乱,最好拆成多个小文件。

  • import_tasks:静态导入,提前解析,条件可以作用到每个任务

  • include_tasks:动态包含,运行时决定,更灵活

通用任务文件 tasks/deploy.yml:

- name: 安装软件
  ansible.builtin.package:
    name: "{{ pkg_name }}"
    state: present

- name: 启动服务
  ansible.builtin.service:
    name: "{{ service_name }}"
    state: started
    enabled: yes

主 Playbook:

- hosts: webservers
  tasks:
    - import_tasks: deploy.yml
      vars:
        pkg_name: nginx
        service_name: nginx

区别

  • import:适合固定流程,调试时可以用 --start-at-task 跳进去

  • include:适合根据条件动态决定包含哪个文件

我现在习惯把常用操作(安装软件、创建用户、配置防火墙)都拆成独立 tasks 文件,主文件只管传参和流程,改起来方便多了。


5. 总结与易错点记录

知识点 主要用途 易错点提醒
copy vs template 静态 vs 动态文件 copy 不能用变量,template 必须 .j2
lineinfile 单行修改 正则写错会误删,记得 backup: yes
Jinja2 循环 动态生成 空组要判断,不然多空行
主机模式交集/排除 精准控制范围 逻辑容易搞混,多测试
import vs include 静态 vs 动态导入 import 更严格,include 更灵活
变量传参 任务复用 用 vars 块传,避免全局污染

6. 学习小结

这部分内容练下来,感觉 Ansible 从“能写脚本”变成了“能管大项目”。文件模块 + 模板基本能解决 80% 的配置问题,Playbook 拆分后代码也整洁多了。

下次打算继续写变量、loop、roles 和错误处理。建议大家也自己搭几台虚拟机多敲,边敲边 debug 进步最快。

如果有同学也在学 Ansible,欢迎交流~

(完)

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐