Ansible 自动化工具经验分享

SHELL BASH LINUX

Posted by gomyck on May 19, 2023

目的

  • 了解知道 ansible 的使用场景, 掌握已有 ansible 工程结构, 明确各模块功能并且熟练使用

Ansible 介绍

Ansible是 Redhat 收购并开源的一个非常简单的IT运维自动化工具,通过 SSH 协议对远程主机实现批量操作,包括配置管理、应用程序部署、任务编排、系统监控等功能。

Ansible 不需要在被管理的主机上安装任何代理程序, 只需要被管理机器支持 SSH 连接即可

为什么要学习 ansible

  • 1.自动化运维
    • 帮助开发团队快速构建和管理生产环境,包括服务器配置、应用程序部署、监控和日志分析等过程。
  • 2.跨平台支持
    • Ansible 可以在Linux MacOS windows 等多个操作系统上运行
  • 3.灵活性高
    • Ansible 的 playbook 和 roles 可以一次性完成多个任务,而无需使用脚本或其他工具。此外,Ansible 还提供了各种模块和插件,可以扩展其功能,从而满足不同的需求。

Ansible 可以解决的现有问题

  • 1.工具标准化
    • 以往在进行基础设施制备的过程中, 因软硬件, 系统版本, 系统类型的差异性, 所带来的实施过程差异性, 无法用统一有效的方式来解决, 在事后的生产资料整理过程中, 也很难把各种差异性相容, 通过 ansible 标准化工程, 可以把流程模块化, 为每个步骤定制对应的部署文件, 在生产过程中, 实施有选择性针对性的部署方案
  • 2.减少重复性工作
    • Ansible 可以接收一组服务器作为远程节点, 并行的执行命令 (exp: 需要在刚刚安装好系统的若干台服务器上安装基本的软件环境)
    • Ansible 可以简化周期性的重复工作 (exp: 本地打包项目, 部署到远程机器并重启服务, 在本地打印日志)
  • 3.操作幂等性
    • Ansible 原生命令具备操作幂等性, 如 file 命令, 它可以使远程主机上的文件永远与预期的保持一致, 并且可以忽略已存在且一致的文件
  • 4.工程化
    • 通过创建标准的 ansible 工程, 运维人员可以非常清晰明了的掌握并理解每个模块内的文件作用, 同时使用版本控制系统, 使工程具备了可维护性和可读性
  • 5.结果一致性
    • 使用 ansible 规范化部署和配置, 可以确保所有服务器都具备相同一致的配置和版本, 提升了一致性和可靠性

适用人群

  1. 运维工程师:Ansible可以帮助运维工程师自动化服务器的部署、配置和管理,从而降低手动操作的错误率,提高效率和可靠性。

  2. 开发人员:Ansible可以帮助开发人员自动化应用程序的部署和管理,从而降低开发过程中的工作量,提高部署效率和可靠性。

  3. 系统管理员:Ansible可以帮助系统管理员管理整个基础架构,包括云平台、容器平台和物理服务器,从而简化管理工作,提高可靠性和一致性。

  4. DevOps工程师:Ansible是DevOps工程师必备的自动化工具之一,可以帮助他们打造自动化流水线,实现快速部署和交付。

Ansible 的基本架构

Ansible 的基本架构包括以下几个部分:

  • 控制节点: 运行 Ansible 的主机,可以是 Linux,MacOS 或者 Windows Subsystem for Linux。
  • 托管节点: 被 Ansible 管理的主机,需要能够被控制节点通过 SSH 访问。
  • Inventory: 定义了托管节点的分组和变量,可以是静态的 INI 文件,也可以是动态的脚本或程序。
  • 模块: 执行具体的任务的代码片段,可以是核心模块,额外模块或者自定义模块。
  • Playbook: 定义了一系列任务和执行顺序的 YAML 文件,是 Ansible 的核心组件。
  • Role: 将 Playbook 分解为可复用的角色,方便共享和组织。

Ansible 的安装和配置

Ansible 可以通过多种方式安装,例如使用 pip,yum,apt 等包管理工具,或者从源码编译安装。具体的安装步骤可以参考 Ansible 文档

Ansible 的配置文件默认位于 /etc/ansible/ansible.cfg,也可以在当前目录或者用户目录下创建配置文件。配置文件中可以设置一些选项,例如默认的 Inventory 文件路径,SSH 连接参数,输出格式等。具体的配置选项可以参考 Ansible 文档

Ansible 的基本用法

Ad-hoc 命令

Ad-hoc 命令是一种在命令行中直接执行单个任务的方式,适合一些简单临时的操作。Ad-hoc 命令的基本语法是:

1
2
3
4
# host-pattern 可以直接定义主机列表 如: 192.168.3.*  或 inventory 里主机分组, 如: nfsClient
$ ansible <host-pattern> -m <module-name> -a <module-arguments> -u root

$ ansible all -m copy -a "src=/etc/hosts dest=/etc/hosts backup=yes"

Playbook

Playbook 是一种在 YAML 文件中定义一系列任务和执行顺序的方式,适合一些复杂持久的操作。Playbook 的基本语法是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
---
- hosts: <host-pattern>
  vars:
    <variable-name>: <variable-value>
  tasks:
    - name: <task-name>
      <module-name>:
        <module-arguments>
      register: <variable-name>
      when: <condition>
      notify: <handler-name>
  handlers:
    - name: <handler-name>
      <module-name>:
        <module-arguments>

使用 ansible-playbook 命令来执行 Playbook

1
$ ansible-playbook xxx.yaml

role

Role 是一种将 Playbook 分解为可复用的角色的方式,方便共享和组织。Role 的基本结构是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
role/
  defaults/
    main.yml  # 角色默认变量
  files/      # 角色相关文件
  handlers/
    main.yml  # 角色相关 handler
  meta/
    main.yaml # 角色元数据,例如作者,依赖等
  README.md   # 角色说明文档
  tasks/
    main.yml  # 角色主要任务
  templates/  # 角色相关模板文件
  tests/      # 角色测试用例
  vars/
    main.yml  # 角色相关变量

标准 role 目录创建可以使用, 执行之后会自动创建一个名为 xxx 的目录, 其中包含上述标准目录结构

1
$ ansible-galaxy init xxx

更多的 Role 的用法和示例,可以参考 Ansible 文档

ansible inventory 内置变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
ansible_ssh_host
      将要连接的远程主机名.与你想要设定的主机的别名不同的话,可通过此变量设置.

ansible_ssh_port
      ssh端口号.如果不是默认的端口号,通过此变量设置.

ansible_ssh_user
      默认的 ssh 用户名

ansible_ssh_pass
      ssh 密码(这种方式并不安全,我们强烈建议使用 --ask-pass 或 SSH 密钥)

ansible_sudo_pass
      sudo 密码(这种方式并不安全,我们强烈建议使用 --ask-sudo-pass)

ansible_sudo_exe (new in version 1.8)
      sudo 命令路径(适用于1.8及以上版本)

ansible_connection
      与主机的连接类型.比如:local, ssh 或者 paramiko. Ansible 1.2 以前默认使用 paramiko.1.2 以后默认使用 'smart','smart' 方式会根据是否支持 ControlPersist, 来判断'ssh' 方式是否可行.

ansible_ssh_private_key_file
      ssh 使用的私钥文件.适用于有多个密钥,而你不想使用 SSH 代理的情况.

ansible_shell_type
      目标系统的shell类型.默认情况下,命令的执行使用 'sh' 语法,可设置为 'csh' 或 'fish'.

ansible_python_interpreter
      目标主机的 python 路径.适用于的情况: 系统中有多个 Python, 或者命令路径不是"/usr/bin/python",比如  \*BSD, 或者 /usr/bin/python
      不是 2.X 版本的 Python.我们不使用 "/usr/bin/env" 机制,因为这要求远程用户的路径设置正确,且要求 "python" 可执行程序名不可为 python以外的名字(实际有可能名为python26).

      与 ansible_python_interpreter 的工作方式相同,可设定如 ruby 或 perl 的路径....

常用 playbook 模块

  • command 用于在远程主机上执行命令,不支持管道和重定向
    • command: command arguments
  • shell 用于在远程主机上执行命令,支持管道和重定向
    • shell: command arguments
  • script 用于在远程主机上执行本地脚本,支持传递参数
    • script: script arguments
  • copy 用于在远程主机上复制文件或者目录,支持设置权限和备份
1
2
3
4
5
6
- name: copy a configuration file
  copy:
    src: /etc/nginx/nginx.conf
    dest: /etc/nginx/nginx.conf.bak
    mode: 0644
    backup: yes
  • file 用于在远程主机上管理文件或者目录,支持设置状态,权限,所有者,链接等
1
2
3
4
5
6
7
8
- name: create a directory
  file:
    path: /opt/data
    state: directory
    mode: 0755
    owner: root
    group: root

  • service 用于在远程主机上管理服务,支持启动,停止,重启,重载等
1
2
3
4
5
- name: start httpd service
  service:
    name: httpd
    state: started
    enabled: yes
  • yum 用于在远程主机上管理 yum 包,支持安装,卸载,更新等
1
2
3
4
5
6
7
8
9
- name: install mysql-server package
  yum:
    name: mysql-server
    state: present

- name: update all packages
  yum:
    name: "*"
    state: latest
  • debug 于在远程主机上打印调试信息,支持使用变量和表达式
1
2
3
4
5
6
7
- name: print hello world
  debug:
    msg: "Hello, world!"

- name: print the hostname
  debug:
    var: ansible_hostname
  • assert 用于在远程主机上断言某个条件是否成立,如果不成立,终止 playbook 的执行
1
2
3
4
5
6
7
- name: assert the system is CentOS 7
  assert:
    that:
      - ansible_distribution == "CentOS"
      - ansible_distribution_major_version == "7"
    fail_msg: "The system is not CentOS 7"
    success_msg: "The system is CentOS 7"

playbook 的内置变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1.gourps 和 group_names
groups是一个全局变量,它会打印出Inventory文件里面的所有主机以及主机组信息,它返回的是一个JSON字符串
使用格式调用。也可以使用引用其中一个的数据。
变量会打印当前主机所在的groups名称,如果没有定义会返回ungrouped,它返回的组名是一个list列表。

2.hostvars
hostvars是用来调用指定的主机变量,需要传入主机信息,返回结果也是一个JSON字符串,同样,也可以直接引用JSON字符串内的指定信息。

3.inventory_hostname 和 inventory_hostname_short
inventory_hostname返回的是Inventory文件里面定义的主机名,inventory_hostname_short返回的是Inventory文件里面定义的主机名的第一部分。

4.play_hosts 和 inventory_dir
play_hosts变量时用来返回当前playbook运行的主机信息,返回格式是主机list结构,inventory_dir变量时返回当前playbook使用的Inventory目录。

5. ansible_facts
一个字典,包含通过setup模块收集到的当前主机的facts信息,比如操作系统,网络,硬件等。 需要在 playbook 中声明 gather_facts: true

Ansible 的一些关键字

关键字 描述
hosts 用于指定目标主机或主机组。
tasks 定义要执行的任务列表。
vars 定义变量。
roles 定义角色,角色是可重用的任务和变量集合。
includes 包含另一个剧本或任务文件。
handlers 定义处理程序,用于在任务完成时运行操作。
when 定义一个条件,只有在满足特定条件时才执行任务。
become 使用sudo或类似的特权升级工具运行任务。
ignore_errors 忽略错误继续执行任务。
gather_facts 收集主机信息,比如操作系统版本、IP地址等。
delegate_to 把任务委托给指定的主机去执行。
local_action 在控制节点上执行本地操作。
wait_for 等待特定条件的达成。
run_once 仅在第一个目标主机上运行一次任务。
with_items 循环执行一组任务,遍历一个变量或列表。
blockinfile 在文件中插入一段文本块或替换文本。
apt/yum/pip 安装、更新或删除软件包。
lineinfile 在文件中插入行、修改行或删除行。
user/group 创建或删除用户或组。
copy/template 复制文件或模板文件到目标主机。
service/system 启动、停止或重启系统服务或服务单元。