Ansible:从0到1自动化运维部署

主机条件:

192.168.88.139 安装ansible

192.168.88.140 node1

192.168.88.141 node2

🚀 第一阶段:环境搭建与初始配置(建议1天)

这是所有实践的基础,我们需要配置好Ansible的控制节点和被管理节点。

  1. 配置主机名与Hosts解析:为了方便管理,建议为三台机器设置清晰的主机名。

    • 控制节点 (Control Node) :建议命名为 ansible,IP为 192.168.88.139

    • 受管节点 (Managed Nodes) :可以命名为 node1 (140) 和 node2 (141)。

    • 在所有节点的 /etc/hosts 文件中,添加三台机器的IP和主机名映射。

  2. 安装Ansible :Ansible采用无代理架构,只需在控制节点 上安装即可。在CentOS 9上,官方推荐使用 dnf 包管理器。

配置SSH免密登录:Ansible通过SSH协议与受管节点通信。需要在控制节点生成SSH密钥对,并将公钥复制到两台受管节点上。

复制代码
ssh-keygen -t rsa   # 在控制节点生成RSA密钥对(公钥+私钥)
ssh-copy-id root@node1   # 将公钥复制到 node1,并设置免密登录
ssh-copy-id root@node2   # 将公钥复制到 node2

结果:

创建一个项目目录project

复制代码
mkdir project
cd project

创建主机清单(Inventory) :Inventory文件定义了Ansible要管理的主机。创建一个项目目录,并在其中创建 inventory.ini 文件:

进入到项目文件夹下:

执行:

vi inventory.ini

复制代码
[webservers]
node1 ansible_host=192.168.88.140 ansible_user=root
node2 ansible_host=192.168.88.141 ansible_user=root

# 如果需要使用非root用户,请修改 ansible_user 和 become 相关设置
复制代码
运行测试命令
复制代码
​​​​​​​ansible -i inventory.ini all -m ping

如果返回 "pong",说明一切就绪,可以开始愉快的自动化之旅了!

📚 第二阶段:Ansible核心概念与实战(建议1-2周)

这个阶段是学习的核心,需要掌握Ansible的常用模块和Playbook的编写。

  • Ad-Hoc命令(快速上手):先用简单的命令测试连通性和模块用法。

    ansible -i inventory.ini all -m ping
    ansible -i inventory.ini webservers -m command -a "df -h"

结果:

  • 常用模块学习:Ansible拥有丰富的模块库,建议优先掌握以下几个:

    • command / shell:在远程主机执行命令。

    • copy:从控制节点拷贝文件到受管节点。

    • file:管理文件和目录的属性。

    • yum / dnf:管理软件包。

    • service:管理服务状态。

    • user:管理用户账号。

    • debug:输出变量或信息,用于调试。

  • Playbook编写(核心技能):Playbook是Ansible的配置、部署、编排语言,使用YAML格式编写。

    • 基础语法 :理解Playbook的结构:---- hoststasksname

    • 第一个Playbook :创建一个 first_playbook.yml,包含安装nginx、启动服务、拷贝一个自定义主页的任务。

创建first_playbook.yml文件

复制代码
vi first_playbook.yml

粘贴内容:包含安装nginx、启动服务、拷贝一个自定义主页的任务。

复制代码
---
- name: My first playbook
  hosts: webservers
  become: yes  # 使用sudo权限

  tasks:
    - name: Install nginx
      dnf:
        name: nginx
        state: present

    - name: Start nginx
      service:
        name: nginx
        state: started
        enabled: yes

    - name: Copy index.html
      copy:
        src: ./index.html
        dest: /usr/share/nginx/html/index.html

/root/poject/ 目录下,创建一个 files 子目录,并在其中放入 index.html

复制代码
mkdir -p /root/poject/files
echo "Hello from GitOps!" > /root/poject/files/index.html

运行Playbook

复制代码
ansible-playbook -i inventory.ini first_playbook.yml

结果:

复制代码
[root@139 poject]# echo "Hello from GitOps!" > /root/poject/files/index.html
[root@139 poject]# ansible-playbook -i inventory.ini first_playbook.yml

PLAY [My first playbook] ****************************************************************************************************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************************************************************************************************************
ok: [node1]
ok: [node2]

TASK [Install nginx] ********************************************************************************************************************************************************************************************
ok: [node1]
ok: [node2]

TASK [Start nginx] **********************************************************************************************************************************************************************************************
ok: [node1]
ok: [node2]

TASK [Copy index.html] ******************************************************************************************************************************************************************************************
changed: [node1]
changed: [node2]

PLAY RECAP ******************************************************************************************************************************************************************************************************
node1                      : ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
node2                      : ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[root@139 poject]# 

变量与事实(Facts)

  • 变量(Variables):学习如何在Playbook、Inventory文件或独立的变量文件中定义和使用变量。

  • Facts:Ansible会自动收集受管节点的系统信息(如IP地址、操作系统版本等),这些信息可以作为变量使用。

    • name: Show OS family
      debug:
      msg: "The OS is {{ ansible_facts['os_family'] }}"
  • 任务控制

    • 条件判断(when) :只在特定条件下执行任务,例如只在Debian系系统上使用apt模块。

    • 循环(loop) :使用loop关键字重复执行任务,例如创建多个用户。

🏗️ 第三阶段:Playbook进阶与最佳实践(建议1周)

当基础Playbook熟练后,可以开始学习如何让代码更规范、更可复用。

  • Jinja2模板 :使用template模块和Jinja2模板语言动态生成配置文件。例如,根据不同的主机名或IP生成不同的nginx配置。

    yaml

    复制代码
    - name: Deploy nginx config from template
      template:
        src: ./nginx.conf.j2
        dest: /etc/nginx/nginx.conf
  • Roles(角色) :Roles是Ansible中用于组织Playbook的最佳实践,它将变量、任务、文件、模板、处理器等按规范的结构组织起来。可以使用 ansible-galaxy init <role_name> 命令创建一个角色骨架。

  • Handlers:Handlers是特殊的tasks,只在被notify时触发,通常用于在配置文件变更后重启服务。

接下来我们来做一个小项目:

🎯 第四阶段实践项目:使用角色部署带动态配置的 Nginx 网站

项目目标

  • node1node2 上安装 Nginx。

  • 利用 Jinja2模板 生成一个自定义的 index.html,页面内容显示该主机的IP地址和主机名。

  • 利用 Handler 在Nginx配置文件发生变更时自动重启服务。

  • 将所有任务、变量、模板、handler封装到一个 角色(Role) 中,以便将来复用。

目录结构:

~/ansible-role-nginx/

├── ansible.cfg # 可选,用于指定配置文件

├── inventory.ini # 你的主机清单

├── site.yml # 入口Playbook

└── roles/

└── nginx_role/ # 角色名

├── tasks/

│ └── main.yml

├── handlers/

│ └── main.yml

├── templates/

│ ├── nginx.conf.j2 # Nginx主配置模板

│ └── index.html.j2 # 网站首页模板

├── vars/

│ └── main.yml

└── meta/

└── main.yml # 依赖关系(可选)

🛠 第一步:创建目录和角色骨架

使用 ansible-galaxy 自动生成角色骨架(省去手动建目录的麻烦)

复制代码
cd ~
mkdir ansible-role-nginx && cd ansible-role-nginx
ansible-galaxy init roles/nginx_role

这会生成完整的目录结构,你只需保留需要的目录,删除示例文件或覆盖内容。

结果:

复制代码
[root@139 ~]# cd ~
mkdir ansible-role-nginx && cd ansible-role-nginx
ansible-galaxy init roles/nginx_role
- Role roles/nginx_role was created successfully
[root@139 ansible-role-nginx]#

在项目文件夹下创建:

检查并编辑 inventory.ini

复制代码
vi inventory.ini

[webservers]
node1 ansible_host=192.168.88.140 ansible_user=root
node2 ansible_host=192.168.88.141 ansible_user=root

# 可选:全局变量
[all:vars]
ansible_user=root

📝 第二步:编写模板文件

2.1 编写 index.html.j2(位于 roles/nginx_role/templates/

这是一个Jinja2模板,它会使用Ansible的 facts 变量动态生成内容

1. 进入项目根目录
复制代码
cd ~/ansible-role-nginx
2. 确认 templates 目录存在(如果不存在则创建)
复制代码
mkdir -p roles/nginx_role/templates
3. 创建并编辑 index.html.j2 文件

你可以使用任何文本编辑器(如 vinanovim):

复制代码
vi roles/nginx_role/templates/index.html.j2

将模板内容粘贴进去:

复制代码
<!DOCTYPE html>
<html>
<head>
    <title>Welcome to {{ ansible_facts['hostname'] }}</title>
</head>
<body>
    <h1>Server: {{ ansible_facts['hostname'] }}</h1>
    <p>IP Address: {{ ansible_facts['default_ipv4']['address'] }}</p>
    <p>OS: {{ ansible_facts['distribution'] }} {{ ansible_facts['distribution_version'] }}</p>
</body>
</html>

📄 第三步:编写任务(tasks/main.yml)

打开 roles/nginx_role/tasks/main.yml,填入以下内容:

复制代码
---
- name: Install Nginx
  dnf:
    name: nginx
    state: present
  notify: restart nginx   # 通知handler,在任务变化时重启

- name: Ensure nginx is enabled and started
  systemd:
    name: nginx
    state: started
    enabled: yes

- name: Deploy custom index.html from template
  template:
    src: index.html.j2
    dest: /usr/share/nginx/html/index.html
    owner: root
    group: root
    mode: '0644'
  notify: restart nginx   # 内容变化时重启

- name: Deploy nginx.conf from template (optional)
  template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
    owner: root
    group: root
    mode: '0644'
  notify: restart nginx
  when: use_custom_config | default(false) | bool   # 通过变量控制是否部署自定义配置

🔔 第四步:编写 Handler(handlers/main.yml)

Handlers 只有在被 notify 触发时才会执行,这里我们定义重启Nginx:

复制代码
cd ~/ansible-role-nginx

pwd   # 应该显示 /root/ansible-role-nginx 或类似路径

mkdir -p roles/nginx_role/handlers

vi roles/nginx_role/handlers/main.yml

粘贴 Handler 内容

进入编辑模式(按 i 键),粘贴以下内容:

复制代码
---
- name: restart nginx
  systemd:
    name: nginx
    state: restarted

📦 第五步:定义变量(vars/main.yml)

这里可以定义角色内部的默认变量,比如控制是否使用自定义配置:

复制代码
---
# 是否部署自定义 nginx.conf,默认不部署(false)
use_custom_config: false

📋 第六步:编写入口Playbook(site.yml)

在项目根目录创建 site.yml,它引用我们刚写的角色:

复制代码
---
- name: Apply Nginx configuration to web servers
  hosts: webservers
  become: yes

  roles:
    - nginx_role

🚀 第七步:运行Playbook

确保你的 inventory.ini 正确(注意不要有行尾注释),然后执行

复制代码
ansible-playbook -i inventory.ini site.yml

执行后,观察输出:

  • 每个任务的状态(okchanged)。

  • 如果模板内容变化,会触发 restart nginx handler。


🧪 第八步:验证结果

在浏览器中访问 http://192.168.88.140http://192.168.88.141,你应该看到显示各自主机名和IP的页面。查看响应头(用 curl -I 或浏览器开发者工具)