ansible

文章目录

Ansible 核心概念与优势

什么是 Ansible

Ansible 是一款 无代理架构的自动化运维工具,基于 Python 开发,核心用于批量执行命令、配置管理、应用部署、任务编排等场景,无需在被控节点安装客户端,通过 SSH 协议(默认)或 WinRM(Windows 节点)实现通信

核心优势

  • 无代理:被控节点无需安装 Ansible 客户端,仅需 SSH 服务(Linux)或 WinRM(Windows),部署成本极低;
  • 模块化:所有操作通过模块实现,支持自定义模块,扩展性强;
  • 声明式语法:Playbook 采用 YAML 格式,专注 "最终状态",无需编写复杂脚本逻辑;
  • 幂等性:重复执行同一操作,结果一致(不会因重复执行导致异常);
  • 轻量灵活:无需额外守护进程,依赖 Python 环境(2.7/3.5+),资源占用少。

环境部署与基础配置

安装方式

bash 复制代码
# 方式1:YUM 安装
yum install epel-release -y  # 安装 EPEL 源
yum install ansible -y

# 方式2:pip 安装
pip install ansible

# 验证安装
ansible --version  # 显示版本信息则安装成功

核心配置文件(优先级:低→高)

  • /etc/ansible/ansible.cfg:全局默认配置(系统级);
  • ~/.ansible.cfg:用户级配置(覆盖全局);
  • 项目目录下的 ansible.cfg:项目级配置(覆盖前两者,推荐使用)

inventory(主机清单)配置

Inventory 用于定义被控节点(目标主机),支持 INI 或 YAML 格式,默认路径 /etc/ansible/hosts。

示例 1:INI 格式(常用)

bash 复制代码
# 单个主机(IP 或域名)
192.168.1.100
web01.example.com

# 分组配置(同一组主机可批量操作)
[web_servers]  # 组名:web服务器组
web01 ansible_host=192.168.1.101 ansible_port=22 ansible_user=root ansible_ssh_pass=123456
web02 ansible_host=192.168.1.102  # 省略默认值(端口22、用户root)

[db_servers]  # 组名:数据库服务器组
db01 ansible_host=192.168.1.201
db02 ansible_host=192.168.1.202

# 嵌套分组(组包含组)
[all_servers:children]
web_servers
db_servers

示例 2:YAML 格式

bash 复制代码
all:
  children:
    web_servers:
      hosts:
        web01:
          ansible_host: 192.168.1.101
          ansible_ssh_pass: 123456
        web02:
          ansible_host: 192.168.1.102
    db_servers:
      hosts:
        db01:
          ansible_host: 192.168.1.201

免密登录配置

为避免每次执行命令输入密码,配置 SSH 免密登录

bash 复制代码
# 控制节点生成密钥对(已生成可跳过)
ssh-keygen -t rsa -P "" -f ~/.ssh/id_rsa

# 批量分发公钥到被控节点(需输入一次密码)
ansible all -m authorized_key -a "user=root key='{{ lookup('file', '~/.ssh/id_rsa.pub') }}' state=present" --ask-pass

Ansible 常用命令(Ad-Hoc 模式)

Ad-Hoc 模式用于执行 临时命令 (无需编写 Playbook),格式:ansible [目标] -m [模块] -a [模块参数]

基础测试命令

bash 复制代码
# 测试主机连通性(ping 模块,核心用于验证 SSH 通信)
ansible web_servers -m ping  # 测试 web_servers 组所有主机
ansible all -m ping  # 测试所有主机(all 为默认组)

# 执行shell命令(command 模块,默认模块,无需指定 -m)
ansible db_servers -a "df -h"  # 查看数据库组主机磁盘情况
ansible web01 -a "systemctl status nginx"  # 查看单个主机 nginx 状态

# 执行复杂shell命令(含管道、重定向,需用 shell 模块)
ansible web_servers -m shell -a "ps aux | grep nginx | wc -l"
ansible all -m shell -a "echo 'test' > /tmp/test.txt"

常用模块实战

命令常用参数

  • -i:指定自定义 inventory 文件(默认用 /etc/ansible/hosts)
bash 复制代码
ansible -i ./my_hosts web_servers -m ping
  • -u:指定执行用户(默认 root)
  • -k/--ask-pass:提示输入 SSH 密码
  • -b/--become:切换到其他用户(默认 root,需配置 sudo 权限)
  • -v: verbose 模式(-vvv 显示详细执行过程,排障用)

Playbook 核心语法(YAML 格式)

Playbook 是 Ansible 自动化的核心,用于编排多任务、多主机的复杂操作,本质是 YAML 格式的 "任务清单"

Playbook 基本结构

bash 复制代码
- name: 部署 Nginx 服务  # Play 名称(可选,便于阅读)
  hosts: web_servers  # 目标主机/组(必填)
  remote_user: root  # 执行用户(可选,默认 root)
  become: yes  # 是否提权(可选,如需 sudo)
  vars:  # 定义变量(可选)
    nginx_port: 80
    nginx_root: /usr/share/nginx/html
  tasks:  # 任务列表(必填,按顺序执行)
    - name: 安装 Nginx  # 任务名称(可选)
      yum:  # 模块名
        name: nginx  # 模块参数
        state: installed

    - name: 复制 Nginx 配置文件
      copy:
        src: ./nginx.conf  # 本地配置文件路径
        dest: /etc/nginx/nginx.conf  # 远程路径
      notify:  # 触发处理器(配置变更后执行)
        - 重启 Nginx

    - name: 创建网站根目录
      file:
        path: "{{ nginx_root }}"  # 引用变量(双大括号)
        state: directory
        mode: 755

    - name: 启动 Nginx 并设开机自启
      service:
        name: nginx
        state: started
        enabled: yes

  handlers:  # 处理器(仅被 notify 触发时执行,且只执行一次)
    - name: 重启 Nginx
      service:
        name: nginx
        state: restarted

核心语法规则

  • 缩进:YAML 依赖缩进(2 个空格,禁止用 Tab),同一层级缩进一致;
  • 变量:vars 中定义,使用 {{ 变量名 }} 引用;
  • 任务:每个任务必须指定 name(可选)和 模块名,模块参数用键值对;
  • 处理器(handlers):用于 "配置变更后需执行的操作"(如重启服务),仅在任务状态为 changed 时被 notify 触发;
  • 条件判断:when 关键字,满足条件才执行任务:
bash 复制代码
- name: 只在 CentOS 系统安装 yum 包
  yum: name=nginx state=installed
  when: ansible_distribution == "CentOS"
  • 循环:with_items/loop 关键字,批量执行同一任务:
bash 复制代码
- name: 安装多个依赖包
  yum:
    name: "{{ item }}"
    state: installed
  loop:  # 等价于 with_items
    - gcc
    - pcre-devel
    - zlib-devel

执行 Playbook

bash 复制代码
# 基本执行(-i 指定 inventory,-v 显示详细日志)
ansible-playbook -i ./my_hosts deploy_nginx.yml -v

# 检查语法(不执行任务)
ansible-playbook --syntax-check deploy_nginx.yml

# 模拟执行(Dry Run,不实际修改系统)
ansible-playbook -C deploy_nginx.yml

变量与模板(Jinja2)

变量来源(优先级:高→低)

  • 命令行传递:ansible-playbook -e "nginx_port=8080" deploy.yml(-e 指定额外变量);
  • Playbook 中 vars 定义;
  • Inventory 中定义(主机变量、组变量);
  • Facts(系统内置变量,如 ansible_ip_addresses、ansible_os_family):
bash 复制代码
# 查看目标主机的 Facts 信息
ansible web01 -m setup

模板文件(.j2)

使用 Jinja2 模板动态生成配置文件(如 Nginx 配置、MySQL 配置),模板文件后缀为 .j2

示例:Nginx 模板文件(nginx.conf.j2)

bash 复制代码
server {
    listen {{ nginx_port }};  # 引用变量
    server_name {{ ansible_fqdn }};  # 引用 Facts 变量

    root {{ nginx_root }};
    index index.html;

    {% if enable_ssl == true %}  # Jinja2 条件判断
    ssl on;
    ssl_certificate /etc/nginx/ssl/cert.pem;
    {% endif %}
}

Playbook 中使用 template 模块

bash 复制代码
- name: 部署 Nginx 配置文件(模板)
  template:
    src: ./nginx.conf.j2  # 本地模板文件
    dest: /etc/nginx/conf.d/default.conf  # 远程生成的配置文件
    mode: 644
  vars:
    nginx_port: 8080
    nginx_root: /var/www/html
    enable_ssl: false
  notify: 重启 Nginx

角色(Roles):Playbook 模块化拆分

当 Playbook 变得复杂时,使用 Roles 进行模块化拆分,便于复用和维护。Roles 是按特定目录结构组织的任务、变量、模板等的集合。

Roles 目录结构(标准)

bash 复制代码
roles/
├── nginx/  # 角色名:nginx
│   ├── tasks/  # 核心任务(必须,main.yml 为入口)
│   │   └── main.yml
│   ├── vars/  # 角色变量(可选,main.yml 为入口)
│   │   └── main.yml
│   ├── templates/  # 模板文件(可选)
│   │   └── nginx.conf.j2
│   ├── handlers/  # 处理器(可选,main.yml 为入口)
│   │   └── main.yml
│   ├── files/  # 静态文件(可选,如证书、脚本)
│   │   └── index.html
│   └── meta/  # 角色依赖(可选)
│       └── main.yml
└── mysql/  # 角色名:mysql(结构同上)

角色示例(nginx 角色)

  • roles/nginx/tasks/main.yml(任务入口):
bash 复制代码
- name: 安装 Nginx
  yum: name=nginx state=installed

- name: 复制静态首页文件
  copy: src=index.html dest={{ nginx_root }} mode=644

- name: 部署 Nginx 配置文件(模板)
  template: src=nginx.conf.j2 dest=/etc/nginx/conf.d/default.conf
  notify: 重启 Nginx

- name: 启动 Nginx 服务
  service: name=nginx state=started enabled=yes
  • roles/nginx/vars/main.yml(变量):
bash 复制代码
nginx_port: 80
nginx_root: /usr/share/nginx/html
  • roles/nginx/handlers/main.yml(处理器):
bash 复制代码
- name: 重启 Nginx
  service: name=nginx state=restarted

Playbook 中调用 Roles

bash 复制代码
- name: 部署 Web 服务(调用 nginx 角色)
  hosts: web_servers
  roles:
    - nginx  # 直接调用角色(默认读取 roles/nginx)
    # - { role: nginx, nginx_port: 8080 }  # 传递变量覆盖角色默认值

实战场景:批量部署 LAMP 架构

需求:

目标组:web_servers(CentOS 7);

部署组件:Apache(httpd)、MySQL、PHP;

实现:创建测试页面,验证 PHP 连接 MySQL。
Playbook(lamp_deploy.yml)

bash 复制代码
- name: 批量部署 LAMP 架构
  hosts: web_servers
  remote_user: root
  vars:
    mysql_root_pass: 123456
    test_db: testdb
    test_user: testuser
    test_user_pass: testpass123

  tasks:
    # 1. 安装依赖包
    - name: 安装 LAMP 相关包
      yum:
        name:
          - httpd
          - mariadb-server
          - mariadb
          - php
          - php-mysql
          - gcc
        state: installed

    # 2. 启动服务并设开机自启
    - name: 启动 httpd 服务
      service: name=httpd state=started enabled=yes

    - name: 启动 mariadb 服务
      service: name=mariadb state=started enabled=yes

    # 3. 配置 MySQL(创建数据库、用户、授权)
    - name: 初始化 MySQL 根密码
      shell: mysqladmin -u root password '{{ mysql_root_pass }}'
      ignore_errors: yes  # 避免已设置密码时报错

    - name: 创建测试数据库
      mysql_db:
        name: '{{ test_db }}'
        state: present
        login_user: root
        login_password: '{{ mysql_root_pass }}'

    - name: 创建测试用户并授权
      mysql_user:
        name: '{{ test_user }}'
        password: '{{ test_user_pass }}'
        priv: '{{ test_db }}.*:ALL'
        host: '%'
        state: present
        login_user: root
        login_password: '{{ mysql_root_pass }}'

    # 4. 创建 PHP 测试页面
    - name: 生成 PHP 测试文件
      copy:
        content: |
           = mysqli_connect('localhost', '{{ test_user }}', '{{ test_user_pass }}', '{{ test_db }}');
          if ($conn) {
              echo "LAMP 部署成功!PHP 连接 MySQL 正常!";
          } else {
              echo "连接失败:" . mysqli_connect_error();
          }
          mysqli_close($conn);
          ?>
        dest: /var/www/html/test.php
        mode: 644

    # 5. 开放 80 端口(防火墙)
    - name: 开放 80 端口
      firewalld:
        service: http
        permanent: yes
        state: enabled
        immediate: yes

执行与验证

bash 复制代码
# 执行 Playbook
ansible-playbook -i ./my_hosts lamp_deploy.yml

# 验证:访问测试页面(浏览器或 curl)
curl http://192.168.1.101/test.php

常见问题与排障技巧

  • SSH 连接失败:
    • 检查被控节点 SSH 服务是否启动(systemctl status sshd);
    • 验证 inventory 中主机 IP、端口、用户名、密码是否正确;
    • 关闭被控节点防火墙(systemctl stop firewalld)或开放 SSH 端口。
  • 模块执行报错:
    • 用 -vvv 查看详细日志(ansible-playbook -vvv deploy.yml);
    • 检查模块参数是否正确(参考 Ansible 官方模块文档);
    • 确保被控节点满足模块依赖(如 yum 模块仅支持 RHEL 系系统)。
  • Playbook 语法错误:
    • 用 ansible-playbook --syntax-check 检查语法;
    • 确认缩进为 2 个空格,无 Tab 字符;
    • 字符串含特殊字符时用引号包裹(单引号 / 双引号)。
相关推荐
脏脏a2 小时前
【Linux】进程地址空间
linux·运维·服务器·进程地址空间
无泪无花月隐星沉2 小时前
uos server 1070e部署Hadoop
大数据·运维·服务器·hadoop·分布式·uos·国产化os
tianyuanwo2 小时前
纵深防御:构建安全高效的 Ansible 自动化运维体系
运维·安全·ansible
阎*水2 小时前
docker教案
linux·运维
走向IT2 小时前
Python批量修改linux 密码脚本
linux·运维·服务器·python·批量·修改密码
阿方索2 小时前
Ansible
ansible
成为你的宁宁2 小时前
【Jenkins 与 Ansible 集成指南:从优势解析到实战落地(含本机配置、插件安装、工具配置及命令 / 剧本两种 Jenkins 调用方式全流程】
ansible·jenkins
2301_787328492 小时前
36.docker swarm
运维·docker·容器
甜甜不吃芥末2 小时前
GitLab 配置 SSH 密钥完整教程
运维·ssh·gitlab