Ansible 常用模块详解

Ansible 常用模块详解

模块概述

Ansible 模块是执行特定任务的独立单元。Ansible 提供了数百个内置模块,涵盖了系统管理、软件包管理、云服务管理等各个方面。

系统管理模块

package 模块

通用的软件包管理模块,支持多种 Linux 发行版。

# 安装软件包
- name: 安装 Nginx
  package:
    name: nginx
    state: present

# 安装多个包
- name: 安装常用工具
  package:
    name:
      - vim
      - git
      - curl
      - wget
    state: present

# 卸载软件包
- name: 卸载 Apache
  package:
    name: apache2
    state: absent

# 更新软件包
- name: 更新所有软件包
  package:
    name: '*'
    state: latest

apt 模块(Debian/Ubuntu)

# 更新缓存并安装
- name: 更新缓存并安装 Nginx
  apt:
    name: nginx
    update_cache: yes
    state: present

# 从 PPA 安装
- name: 添加 PPA 并安装
  apt_repository:
    repo: ppa:deadsnakes/ppa
    state: present

- name: 安装 Python 3.10
  apt:
    name: python3.10
    state: present

# 安装 .deb 文件
- name: 安装本地 deb 包
  apt:
    deb: /tmp/myapp_1.0_amd64.deb
    state: present

# 清理旧包
- name: 清理旧包
  apt:
    autoremove: yes
    autoclean: yes

yum 模块(CentOS/RHEL)

# 安装软件包
- name: 安装 Nginx
  yum:
    name: nginx
    state: present

# 从特定仓库安装
- name: 从 EPEL 安装
  yum:
    name: htop
    state: present
    enablerepo: epel

# 安装 RPM 文件
- name: 安装本地 RPM
  yum:
    name: /tmp/myapp-1.0-1.x86_64.rpm
    state: present

# 更新所有包
- name: 更新系统
  yum:
    name: '*'
    state: latest
    exclude: kernel*,python*

service 模块

管理系统服务。

# 启动服务
- name: 启动 Nginx
  service:
    name: nginx
    state: started
    enabled: yes

# 停止服务
- name: 停止 Apache
  service:
    name: apache2
    state: stopped
    enabled: no

# 重启服务
- name: 重启 MySQL
  service:
    name: mysql
    state: restarted

# 重载配置
- name: 重载 Nginx 配置
  service:
    name: nginx
    state: reloaded

systemd 模块

管理 systemd 服务。

# 启用并启动服务
- name: 启动自定义服务
  systemd:
    name: myapp
    state: started
    enabled: yes

# 重新加载 systemd
- name: 重新加载 systemd
  systemd:
    daemon_reload: yes

# 停止并禁用服务
- name: 停止服务
  systemd:
    name: oldservice
    state: stopped
    enabled: no
    masked: yes

文件管理模块

copy 模块

复制文件到远程主机。

# 复制文件
- name: 复制配置文件
  copy:
    src: /local/path/config.conf
    dest: /remote/path/config.conf
    owner: root
    group: root
    mode: '0644'
    backup: yes
    validate: 'nginx -t -c %s'

# 使用 content 直接写入
- name: 写入文件内容
  copy:
    content: |
      server {
          listen 80;
          server_name localhost;
      }
    dest: /etc/nginx/conf.d/default.conf
    mode: '0644'

# 复制目录
- name: 复制整个目录
  copy:
    src: /local/dir/
    dest: /remote/dir/

file 模块

管理文件、目录、符号链接。

# 创建文件
- name: 创建空文件
  file:
    path: /tmp/test.txt
    state: touch
    mode: '0644'

# 创建目录
- name: 创建目录
  file:
    path: /opt/myapp
    state: directory
    owner: appuser
    group: appgroup
    mode: '0755'

# 创建符号链接
- name: 创建符号链接
  file:
    src: /opt/myapp/current
    dest: /var/www/myapp
    state: link

# 删除文件或目录
- name: 删除文件
  file:
    path: /tmp/old_file
    state: absent

# 递归设置权限
- name: 设置目录权限
  file:
    path: /opt/myapp
    state: directory
    mode: '0755'
    recurse: yes

template 模块

使用 Jinja2 模板部署配置文件。

# 部署模板文件
- name: 部署 Nginx 配置
  template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
    owner: root
    group: root
    mode: '0644'
    backup: yes
    validate: 'nginx -t -c %s'

# nginx.conf.j2
user {{ nginx_user }};
worker_processes {{ nginx_worker_processes }};
error_log {{ nginx_log_dir }}/error.log;
pid {{ nginx_pid_file }};

events {
    worker_connections {{ nginx_worker_connections }};
}

http {
    include /etc/nginx/mime.types;
    server {
        listen {{ server_port }};
        server_name {{ server_name }};
    }
}

fetch 模块

从远程主机获取文件到本地。

# 获取日志文件
- name: 获取系统日志
  fetch:
    src: /var/log/syslog
    dest: /tmp/logs/{{ inventory_hostname }}-syslog
    flat: yes

# 获取目录
- name: 获取配置目录
  fetch:
    src: /etc/myapp/
    dest: /backup/{{ inventory_hostname }}/

synchronize 模块

使用 rsync 同步文件。

# 同步目录
- name: 同步应用目录
  synchronize:
    src: /local/app/
    dest: /remote/app/
    delete: yes
    recursive: yes
    perms: yes
    times: yes
    compress: yes

用户和组管理

user 模块

# 创建用户
- name: 创建部署用户
  user:
    name: deploy
    comment: "部署用户"
    shell: /bin/bash
    home: /home/deploy
    create_home: yes
    groups: sudo,docker
    append: yes

# 删除用户
- name: 删除测试用户
  user:
    name: testuser
    state: absent
    remove: yes

# 设置 SSH 密钥
- name: 为用户添加 SSH 公钥
  authorized_key:
    user: deploy
    state: present
    key: "{{ lookup('file', '/path/to/public_key.pub') }}"

# 修改密码
- name: 设置用户密码
  user:
    name: deploy
    password: "{{ password | password_hash('sha512') }}"

group 模块

# 创建组
- name: 创建应用组
  group:
    name: appgroup
    state: present
    system: yes
    gid: 1000

# 删除组
- name: 删除旧组
  group:
    name: oldgroup
    state: absent

命令执行模块

command 模块

执行命令(不通过 shell)。

# 执行命令
- name: 获取内核版本
  command: uname -r
  register: kernel_version
  changed_when: false

- name: 显示内核版本
  debug:
    msg: "{{ kernel_version.stdout }}"

# 使用参数
- name: 创建目录
  command: mkdir -p /tmp/mydir
  args:
    creates: /tmp/mydir

shell 模块

通过 shell 执行命令。

# 使用 shell 特性
- name: 检查磁盘空间
  shell: df -h / | tail -1 | awk '{print $5}'
  register: disk_usage
  changed_when: false

- name: 检查服务状态
  shell: |
    if systemctl is-active nginx > /dev/null 2>&1; then
      echo "running"
    else
      echo "stopped"
    fi
  register: nginx_status

# 使用管道和重定向
- name: 统计日志行数
  shell: wc -l /var/log/nginx/access.log
  register: log_lines

raw 模块

直接执行命令,不依赖 Python。

# 安装 Python(当目标没有 Python 时)
- name: 在没有 Python 的主机上安装
  raw: yum install -y python2

网络模块

uri 模块

与 Web 服务交互。

# GET 请求
- name: 检查 API 端点
  uri:
    url: http://api.example.com/health
    method: GET
    status_code: 200
  register: api_response

- name: 显示响应
  debug:
    var: api_response.json

# POST 请求
- name: 发送数据
  uri:
    url: http://api.example.com/data
    method: POST
    body_format: json
    body:
      name: test
      value: 123
    headers:
      Content-Type: application/json

# 认证
- name: 带认证的请求
  uri:
    url: https://api.example.com/data
    user: admin
    password: secret
    force_basic_auth: yes

get_url 模块

下载文件。

# 下载文件
- name: 下载安装包
  get_url:
    url: https://example.com/app-1.0.tar.gz
    dest: /tmp/app-1.0.tar.gz
    mode: '0644'
    checksum: sha256:abc123...

# 下载到指定目录
- name: 下载到目录
  get_url:
    url: https://example.com/file.txt
    dest: /opt/files/

# 使用代理
- name: 通过代理下载
  get_url:
    url: https://example.com/file.zip
    dest: /tmp/file.zip
    environment:
      http_proxy: http://proxy.example.com:8080
      https_proxy: http://proxy.example.com:8080

数据库模块

mysql_db 模块

# 创建数据库
- name: 创建数据库
  mysql_db:
    name: myapp
    state: present
    encoding: utf8mb4
    collation: utf8mb4_unicode_ci

# 删除数据库
- name: 删除测试数据库
  mysql_db:
    name: test_db
    state: absent

# 导入数据库
- name: 导入数据库
  mysql_db:
    name: myapp
    state: import
    target: /tmp/myapp.sql

mysql_user 模块

# 创建用户
- name: 创建数据库用户
  mysql_user:
    name: appuser
    password: "secure_password"
    host: localhost
    priv: "myapp.*:ALL"
    state: present

# 删除用户
- name: 删除旧用户
  mysql_user:
    name: olduser
    state: absent

# 修改权限
- name: 授予只读权限
  mysql_user:
    name: readonly_user
    priv: "myapp.*:SELECT"
    state: present

postgresql_db 模块

# 创建 PostgreSQL 数据库
- name: 创建数据库
  postgresql_db:
    name: myapp
    state: present
    encoding: UTF8
    lc_collate: en_US.UTF-8
    lc_ctype: en_US.UTF-8

# 删除数据库
- name: 删除数据库
  postgresql_db:
    name: test_db
    state: absent

postgresql_user 模块

# 创建用户
- name: 创建 PostgreSQL 用户
  postgresql_user:
    db: myapp
    name: appuser
    password: "secure_password"
    priv: "ALL"
    state: present

# 删除用户
- name: 删除用户
  postgresql_user:
    name: olduser
    state: absent

其他常用模块

debug 模块

# 输出消息
- name: 显示消息
  debug:
    msg: "应用部署完成"

# 输出变量
- name: 显示变量
  debug:
    var: app_config

# 输出详细变量
- name: 显示 facts
  debug:
    var: ansible_facts

# 条件输出
- name: 条件输出
  debug:
    msg: "服务器在生产环境"
  when: deployment_env == "production"

stat 模块

# 检查文件状态
- name: 检查文件是否存在
  stat:
    path: /etc/nginx/nginx.conf
  register: config_file

- name: 文件信息
  debug:
    msg:
      - "存在: {{ config_file.stat.exists }}"
      - "类型: {{ config_file.stat.islnk | ternary('链接', '文件') }}"
      - "大小: {{ config_file.stat.size }} 字节"
      - "修改时间: {{ config_file.stat.mtime }}"

# 根据状态执行
- name: 文件不存在时创建
  copy:
    content: "config content"
    dest: /etc/myapp/config.conf
  when: not config_file.stat.exists

lineinfile 模块

# 确保行存在
- name: 确保 SSH 配置存在
  lineinfile:
    path: /etc/ssh/sshd_config
    line: "PermitRootLogin no"
    state: present

# 删除行
- name: 删除配置行
  lineinfile:
    path: /etc/ssh/sshd_config
    line: "#PermitRootLogin yes"
    state: absent

# 使用正则表达式
- name: 修改配置
  lineinfile:
    path: /etc/myapp/config.conf
    regexp: '^max_connections'
    line: 'max_connections = 200'

blockinfile 模块

# 添加配置块
- name: 添加 Nginx 配置块
  blockinfile:
    path: /etc/nginx/nginx.conf
    block: |
      server {
          listen 8080;
          server_name localhost;
          location / {
              root /var/www/html;
          }
      }
    marker: "# {mark} ANSIBLE MANAGED BLOCK"

# 删除块
- name: 删除配置块
  blockinfile:
    path: /etc/nginx/nginx.conf
    state: absent
    marker: "# {mark} ANSIBLE MANAGED BLOCK"

find 模块

# 查找文件
- name: 查找旧日志文件
  find:
    paths: /var/log
    patterns: "*.log"
    age: 30d
    file_type: file
  register: old_logs

- name: 删除旧日志
  file:
    path: "{{ item.path }}"
    state: absent
  loop: "{{ old_logs.files }}"

cron 模块

# 添加定时任务
- name: 添加备份任务
  cron:
    name: "数据库备份"
    minute: "0"
    hour: "2"
    job: "/usr/local/bin/backup_db.sh"
    user: postgres

# 删除定时任务
- name: 删除定时任务
  cron:
    name: "旧任务"
    state: absent

# 环境变量
- name: 带环境变量的任务
  cron:
    name: "清理任务"
    job: "/usr/local/bin/cleanup.sh"
    environment:
      PATH: /usr/local/bin:/usr/bin:/bin

firewalld 模块

# 开放端口
- name: 开放 HTTP 端口
  firewalld:
    service: http
    permanent: yes
    state: enabled

- name: 开放自定义端口
  firewalld:
    port: 8080/tcp
    permanent: yes
    state: enabled

# 重载防火墙
- name: 重载防火墙
  systemd:
    name: firewalld
    state: reloaded

selinux 模块

# 设置 SELinux 模式
- name: 设置 SELinux 为宽容模式
  selinux:
    policy: targeted
    state: permissive

# 设置文件上下文
- name: 设置文件上下文
  selinux:
    path: /var/www/html
    context: httpd_sys_content_t
    state: present

云服务模块

ec2 模块

# 启动 EC2 实例
- name: 启动 EC2 实例
  ec2:
    key_name: my-key
    instance_type: t2.micro
    image: ami-12345678
    region: us-east-1
    count: 1
    vpc_subnet_id: subnet-123456
    assign_public_ip: yes
    wait: yes
    group: default
  register: ec2_result

- name: 显示实例 ID
  debug:
    var: ec2_result.instance_ids

总结

通过本教程,你已经了解了 Ansible 常用模块的使用方法:

  • 系统管理模块:package、service、systemd
  • 文件管理模块:copy、file、template
  • 用户和组管理模块:user、group
  • 命令执行模块:command、shell
  • 网络模块:uri、get_url
  • 数据库模块:mysql、postgresql
  • 其他常用模块:debug、stat、lineinfile

发表回复

后才能评论