Ansible

Ansible 是一个开源的自动化工具,主要用于配置管理、应用部署、编排(Orchestration)等。由 Michael DeHaan 于 2012 年创建,Ansible 的设计理念是简单易用、无代理(Agentless)和基于推送的模型。通过简单的 YAML 文件(称为剧本,Playbooks)定义自动化任务,Ansible 能帮助系统管理员和开发人员在大量服务器上快速、可靠地执行各种操作。

Ansible 历史与发展

Ansible 由 Michael DeHaan 创建,并在 2012 年发布首个版本。它迅速在 DevOps 社区中获得了广泛的关注和使用,因其易用性和强大的功能。2015 年,Ansible 被 Red Hat 收购,这使其发展得更为迅速和稳定。如今,Ansible 已成为业界领先的自动化工具之一,被广泛应用于各类企业和组织中。

为什么选择 Ansible

  1. 简单易用:Ansible 采用 YAML 作为配置语言,简单明了,易于理解和编写。
  2. 无代理架构:Ansible 不需要在被管理的节点上安装任何代理软件,减少了维护成本和复杂性。
  3. 强大的模块支持:Ansible 提供了数百个模块,支持多种操作系统、云平台、网络设备等。
  4. 声明式配置:Ansible 允许用户通过声明式配置文件定义所需状态,确保系统的一致性。
  5. 社区活跃:Ansible 拥有一个活跃的开源社区,丰富的文档和资源,支持广泛。

Ansible 架构概述

Ansible 的架构设计非常简洁,主要包括以下几个组件:

  • 控制节点(Control Node):运行 Ansible 的机器,通常是管理员的工作站或管理服务器。所有的 Ansible 命令和 Playbook 都从控制节点执行。
  • 被管理节点(Managed Nodes):通过 SSH 或 WinRM 连接并由 Ansible 控制的机器,这些节点可以是物理服务器、虚拟机、容器,或网络设备等。
  • 剧本(Playbooks):使用 YAML 编写的配置文件,定义了一系列的任务和操作,用于配置、部署和编排多个被管理节点上的资源。
  • 模块(Modules):Ansible 的基本执行单元,每个模块都实现了特定的功能,如安装软件包、管理文件、执行命令等。Ansible 提供了数百个内置模块,并允许用户编写自定义模块。
  • 插件(Plugins):扩展 Ansible 功能的小程序,包括连接插件(connection plugins)、回调插件(callback plugins)、过滤插件(filter plugins)等,增强 Ansible 的灵活性和功能。
  • 清单(Inventory):定义被管理节点及其分组信息的文件,可以是静态文件(如 INI 或 YAML 格式)或动态生成的脚本,支持定义主机变量和组变量。
  • 角色(Roles):将剧本、任务、处理程序、变量、模板和文件等组织在一起的目录结构,用于复用和共享配置,实现配置管理的模块化和标准化。

Ansible 主要特性

无代理架构

Ansible 采用无代理架构,这意味着它不需要在被管理的节点上安装任何软件或代理。Ansible 通过 SSH 进行通信,简化了管理和维护工作,并提高了系统的安全性和可靠性。

基于 YAML 的配置

Ansible 使用 YAML 作为其配置语言。YAML 简洁直观,易于阅读和编写,特别适合用来编写配置文件。通过 YAML 文件,用户可以定义各种自动化任务,轻松实现复杂的操作。

以声明式为中心

Ansible 采用声明式配置模型,用户只需定义期望的系统状态,Ansible 会自动计算并执行所需的操作,确保系统达到期望状态。这种方式减少了配置错误,提高了系统的一致性和可维护性。

广泛的模块支持

Ansible 提供了丰富的内置模块,涵盖了几乎所有常见的系统管理和应用部署任务。此外,Ansible 还支持用户编写自定义模块,满足特殊需求。模块可以通过官方 Ansible Galaxy 平台共享和下载,进一步扩展了 Ansible 的功能和应用范围。

Ansible 应用场景

配置管理

Ansible 可以用于配置管理,自动化配置服务器和网络设备。通过剧本定义配置细节,Ansible 能够确保大规模环境中所有设备的一致性,简化了系统维护和升级工作。

应用部署

Ansible 支持自动化应用部署,从代码拉取、编译、安装到配置,均可以通过剧本实现。无论是简单的单机应用,还是复杂的多节点分布式系统,Ansible 都能有效管理和部署。

编排(Orchestration)

Ansible 不仅可以执行单个任务,还可以编排复杂的工作流程。通过定义依赖关系和执行顺序,Ansible 能够协调多个服务和系统的协同工作,确保在多步骤操作中各个环节的正确执行。

Ansible 安装与配置

系统要求

Ansible 设计为跨平台运行,支持多种操作系统,包括但不限于以下几种:

  • Linux:支持绝大多数发行版,如 Ubuntu、CentOS、Debian、Red Hat Enterprise Linux (RHEL) 等。
  • macOS:可以在 macOS 上安装并运行 Ansible,用于开发和测试环境。
  • Windows:通过 WSL(Windows Subsystem for Linux)或在 Windows 上安装 Cygwin,可以在 Windows 上运行 Ansible。

Ansible 运行时需要以下基本依赖项:

  • Python:Ansible 需要 Python 2.7 或 Python 3.5 及以上版本。
  • SSH:Ansible 通过 SSH 与被管理节点通信,需要在控制节点和被管理节点上配置 SSH。
  • 其他依赖:根据具体模块需求,可能需要额外安装一些依赖包,例如用于云平台管理的 SDK。

Ansible 安装步骤

在不同操作系统上的安装

Ubuntu

在 Ubuntu 上安装 Ansible 非常简单,可以通过官方的包管理器 APT 进行安装:

sudo apt update
sudo apt install ansible
CentOS

在 CentOS 上,可以通过 EPEL(Extra Packages for Enterprise Linux)库安装 Ansible:

sudo yum install epel-release
sudo yum install ansible
macOS

在 macOS 上,可以使用 Homebrew 来安装 Ansible:

brew install ansible

通过 Python Pip 安装

可以使用 Python 的包管理器 pip 来安装 Ansible,这种方法适用于任何支持 Python 的操作系统:

pip install ansible

从源代码安装

从源代码安装适用于需要最新功能或定制 Ansible 的场景:

git clone https://github.com/ansible/ansible.git
cd ansible
source ./hacking/env-setup

这种方法需要额外的依赖包,具体可以参考 Ansible 官方文档。

Ansible 配置方法

Ansible 配置文件结构(ansible.cfg)

Ansible 的配置文件 ansible.cfg 允许用户自定义 Ansible 的运行参数。该文件通常位于以下位置之一:

  1. 当前目录下的 ansible.cfg
  2. 用户主目录下的 .ansible.cfg
  3. 全局配置文件 /etc/ansible/ansible.cfg

一个典型的 ansible.cfg 文件结构如下:

[defaults]
inventory = ./hosts
remote_user = ansible
private_key_file = ~/.ssh/id_rsa
host_key_checking = False
 
[privilege_escalation]
become = True
become_method = sudo
become_user = root
become_ask_pass = False
 
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
pipelining = True

Ansible 配置文件优先级

Ansible 允许在多个位置定义配置文件,并根据以下优先级顺序应用配置:

  1. 命令行参数:直接在命令行上指定的参数优先级最高。
  2. 环境变量:通过环境变量设置的配置次高优先级。
  3. ansible.cfg 文件:
    1. 当前目录下的 ansible.cfg
    2. 用户主目录下的 .ansible.cfg
    3. 全局配置文件 /etc/ansible/ansible.cfg
  4. 模块参数:模块内部的参数配置。
  5. 默认值:Ansible 内部的默认值。

常用配置选项

配置选项说明
inventory定义主机清单文件的位置。
remote_user指定远程主机的默认用户。
private_key_file定义用于 SSH 连接的私钥文件。
host_key_checking是否检查 SSH 主机密钥,默认启用。
retry_files_enabled是否生成重试文件,默认启用。
log_path指定 Ansible 运行日志的存储路径。
become是否启用权限提升(如 sudo)。
become_method权限提升的方法(如 sudo 或 su)。
become_user权限提升后的目标用户。
become_ask_pass是否提示输入密码用于权限提升。
ssh_args定制 SSH 连接参数。
pipelining启用管道以提高性能。

SSH 密钥和认证配置

Ansible 通过 SSH 与被管理节点通信,配置 SSH 密钥认证可以提高安全性和自动化程度。

  1. 生成 SSH 密钥对
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

生成的密钥文件通常存储在 ~/.ssh/ 目录下。

  1. 将公钥添加到被管理节点
ssh-copy-id user@remote_host

或者手动将公钥添加到被管理节点的 ~/.ssh/authorized_keys 文件中。

  1. 配置 SSH 代理(可选): 使用 SSH 代理可以管理多个 SSH 密钥,提高连接效率:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa

通过上述步骤,Ansible 可以无密码地通过 SSH 访问被管理节点,从而实现自动化操作。

Ansible 自动化管理基础

Ansible Playbooks

Playbook 的基本结构

Playbook 是 Ansible 的核心配置文件,用于定义一系列自动化任务。它使用 YAML 格式编写,主要由 Plays 和 Tasks 组成。一个典型的 Playbook 结构如下:

- name: Describe the purpose of the playbook
  hosts: target_hosts_group
  become: yes
  vars:
    variable_name: value
  tasks:
    - name: Describe the task
      module_name:
        module_option: value

Playbook 的常用关键字

关键字说明
name描述 Play 或 Task 的名称,便于阅读和调试。
hosts指定目标主机或主机组,可以是一个或多个主机组名。
become是否启用权限提升(如 sudo),默认值为 no
vars定义在 Play 级别的变量,适用于整个 Play。
tasks任务列表,每个任务调用一个模块执行特定操作。
roles指定在 Play 中包含的角色,角色是一个组织良好的任务集合。
handlers定义事件触发的任务,当其他任务通知这些处理程序时执行。
environment指定任务或 Play 级别的环境变量。
gather_facts是否在 Play 开始时收集远程主机的信息,默认值为 yes
notify通知一个或多个处理程序在任务完成时执行。
when条件语句,用于在特定条件下执行任务。
with_items循环语句,用于在任务中迭代一个列表。
register捕获任务的输出结果并存储在变量中。
tags为任务或 Play 打标签,便于选择性地运行特定任务或 Play。
ignore_errors是否忽略任务执行中的错误,继续执行后续任务。
delegate_to将任务委派给指定的主机执行,而不是在目标主机上执行。
serial控制任务并行执行的主机数量或批次大小。
max_fail_percentage允许的最大失败百分比,超过此比例时停止 Play。

编写和运行第一个 Playbook

  1. 编写 Playbook 文件(如 first_playbook.yml):
- name: Install and start Apache web server
  hosts: webservers
  become: yes
  tasks:
    - name: Install Apache
      apt:
        name: apache2
        state: present
    - name: Start Apache service
      service:
        name: apache2
        state: started
  1. 运行 Playbook
ansible-playbook first_playbook.yml

在此示例中,Playbook 定义了一个 Play,包含两个任务:一个用于安装 Apache Web 服务器,另一个用于启动 Apache 服务。hosts 指定了目标主机组为 webservers,并通过 become: yes 启用权限提升(通常是 sudo)。

多 Play 和任务的组织

一个 Playbook 可以包含多个 Play,每个 Play 针对不同的主机组或执行不同的任务。这种结构有助于在一个 Playbook 中管理复杂的部署场景。

- name: Setup web servers
  hosts: webservers
  become: yes
  tasks:
    - name: Install Apache
      apt:
        name: apache2
        state: present
 
    - name: Start Apache service
      service:
        name: apache2
        state: started
 
- name: Setup database servers
  hosts: dbservers
  become: yes
  tasks:
    - name: Install MySQL
      apt:
        name: mysql-server
        state: present
 
    - name: Start MySQL service
      service:
        name: mysql
        state: started

在此示例中,Playbook 包含两个 Play:第一个 Play 针对 webservers 主机组,安装并启动 Apache Web 服务器;第二个 Play 针对 dbservers 主机组,安装并启动 MySQL 数据库服务。

通过组织多个 Play 和任务,可以在一个 Playbook 中处理多种部署需求,提高配置管理的灵活性和可维护性。

Ansible 模块

常用模块

模块名称用途示例
file管理文件和目录yaml\n- name: Create a directory\n file:\n path: /path/to/directory\n state: directory\n
service管理服务yaml\n- name: Start a service\n service:\n name: nginx\n state: started\n
command执行命令yaml\n- name: Run a command\n command: /usr/bin/uptime\n
shell执行 shell 命令yaml\n- name: Run a shell command\n shell: echo "Hello, world!" > /tmp/hello.txt\n
copy复制文件到远程主机yaml\n- name: Copy a file\n copy:\n src: /local/path/to/file\n dest: /remote/path/to/file\n
template使用 Jinja2 模板渲染并复制文件到远程主机yaml\n- name: Deploy configuration file from template\n template:\n src: /path/to/template.j2\n dest: /path/to/destination\n
yum使用 YUM 包管理器安装、卸载包(适用于 RHEL 系)yaml\n- name: Install a package using yum\n yum:\n name: httpd\n state: present\n
apt使用 APT 包管理器安装、卸载包(适用于 Debian 系)yaml\n- name: Install a package using apt\n apt:\n name: apache2\n state: present\n
user管理用户yaml\n- name: Create a user\n user:\n name: username\n state: present\n password: password_hash\n
group管理用户组yaml\n- name: Create a group\n group:\n name: groupname\n state: present\n
cron管理 cron 作业yaml\n- name: Add a cron job\n cron:\n name: "backup script"\n minute: "0"\n hour: "2"\n job: "/path/to/backup.sh"\n
git管理 Git 仓库yaml\n- name: Clone a Git repository\n git:\n repo: "https://github.com/repo.git"\n dest: "/path/to/destination"\n

每个模块都有特定的参数和选项,可以在 Ansible 官方文档中查找详细信息。例如,file 模块的常用参数包括 pathstateownergroup 等。

自定义模块

如果内置模块不能满足需求,可以编写自定义模块。自定义模块可以使用 Python 编写,并放置在库路径中。

示例自定义模块(my_module.py):

#!/usr/bin/python
 
from ansible.module_utils.basic import AnsibleModule
 
def run_module():
    module_args = dict(
        name=dict(type='str', required=True)
    )
 
    module = AnsibleModule(
        argument_spec=module_args,
        supports_check_mode=True
    )
 
    result = dict(
        changed=False,
        message=''
    )
 
    name = module.params['name']
    result['message'] = f'Hello, {name}!'
 
    if module.check_mode:
        module.exit_json(**result)
 
    module.exit_json(**result)
 
def main():
    run_module()
 
if __name__ == '__main__':
    main()

运行自定义模块:

- name: Use custom module
  hosts: localhost
  tasks:
    - name: Call custom module
      my_module:
        name: Ansible

Ansible 变量和模板

变量的定义与使用

变量可以在多个地方定义,如 Playbook、清单文件、角色等:

- name: Example with variables
  hosts: localhost
  vars:
    http_port: 80
  tasks:
    - name: Display variable
      debug:
        msg: "HTTP port is {{ http_port }}"

变量优先级

Ansible 变量的优先级从低到高依次为:

  1. 角色默认变量(role defaults)
  2. 组变量(group vars)
  3. 主机变量(host vars)
  4. 播放(Play)中的变量
  5. 任务(Task)中的变量
  6. 命令行定义的变量(使用 -e 参数)

这个优先级决定了当同一个变量在多个地方定义时,哪个值会被使用。

Jinja2 模板语法

Ansible 使用 Jinja2 作为模板引擎,支持复杂的模板生成。模板文件通常以 .j2 结尾,放置在 templates 目录下。

示例模板文件(config.j2):

## 变量替换
Hello, {{ name }}!
 
## 条件语句
{% if http_port == 80 %}
  server {
      listen 80;
  }
{% else %}
  server {
      listen {{ http_port }};
  }
{% endif %}
 
## 循环语句
{% for user in users %}
  user {{ user.name }} with id {{ user.id }}
{% endfor %}

使用模板生成配置文件

可以使用 template 模块将 Jinja2 模板渲染为实际配置文件,并部署到目标主机上。

示例 Playbook(deploy_config.yml):

- name: Deploy configuration file
  hosts: webservers
  become: yes
  vars:
    http_port: 80
    server_name: example.com
    proxy_url: 127.0.0.1:8080
  tasks:
    - name: Deploy nginx configuration
      template:
        src: templates/nginx.conf.j2
        dest: /etc/nginx/sites-available/default
      notify:
        - restart nginx
 
  handlers:
    - name: restart nginx
      service:
        name: nginx
        state: restarted

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

server {
    listen {{ http_port }};
    server_name {{ server_name }};
    
    location / {
        proxy_pass http://{{ proxy_url }};
    }
}

在此 Playbook 中,template 模块会将 templates/nginx.conf.j2 文件渲染为实际的配置文件,并部署到 /etc/nginx/sites-available/default。如果模板内容发生变化,通知部分会触发 restart nginx 处理程序,重启 nginx 服务以应用新的配置。

通过这种方式,可以使用 Ansible 自动化生成和部署配置文件,大大简化了系统配置管理的工作,并确保配置的一致性和可重复性。

Ansible 高级应用技巧

Ansible 角色

角色的结构与组成

角色(Roles)是 Ansible 中的一种组织方式,用于将 Playbooks 和相关文件(如任务、处理程序、变量、模板等)结构化和模块化。角色的目录结构通常如下:

roles/
  └── role_name/
      ├── tasks/
      │   └── main.yml
      ├── handlers/
      │   └── main.yml
      ├── templates/
      │   └── template_file.j2
      ├── files/
      │   └── file_name
      ├── vars/
      │   └── main.yml
      ├── defaults/
      │   └── main.yml
      ├── meta/
      │   └── main.yml
      └── README.md
  • tasks:存放主要任务列表(main.yml 是入口文件)。
  • handlers:存放处理程序(main.yml 是入口文件)。
  • templates:存放 Jinja2 模板文件。
  • files:存放需要复制到远程主机的静态文件。
  • vars:存放角色专用变量。
  • defaults:存放默认变量。
  • meta:存放角色的元数据,如依赖关系。
  • README.md:角色的说明文档,描述角色的用途、用法等。

创建和使用角色

  1. 创建角色
ansible-galaxy init my_role

这条命令会生成上述结构的角色目录。

  1. 定义任务roles/my_role/tasks/main.yml):
- name: Install Apache
  apt:
    name: apache2
    state: present
 
- name: Start Apache service
  service:
    name: apache2
    state: started

在这个例子中,定义了两个任务:一个用于安装 Apache,另一个用于启动 Apache 服务。

  1. 在 Playbook 中使用角色
- name: Apply my role
  hosts: webservers
  roles:
    - my_role

在 Playbook 中,通过 roles 关键字引用角色。

角色的共享与重用(Ansible Galaxy)

Ansible Galaxy 是 Ansible 官方的角色分享平台,用户可以在上面发布和下载角色,方便角色的共享与重用。

  1. 安装角色
ansible-galaxy install username.role_name

可以从 Galaxy 下载并安装角色。安装的角色通常会存放在 Ansible 的角色路径中(默认是 /etc/ansible/roles~/.ansible/roles)。

  1. 使用已安装的角色
- name: Use a role from Ansible Galaxy
  hosts: webservers
  roles:
    - username.role_name

在 Playbook 中通过 roles 关键字引用已经安装的角色。

通过使用 Ansible 角色,可以将复杂的 Playbook 结构化、模块化,使得配置管理更为清晰、可维护。同时,通过 Ansible Galaxy 平台,可以方便地共享和重用角色,提升团队协作和生产效率。

Ansible 动态 Inventory

静态 Vs 动态 Inventory

静态 Inventory 是一个简单的文本文件,列出所有被管理节点及其分组。动态 Inventory 则是通过脚本或插件生成的,适用于云环境或动态变化的基础设施。

示例静态 Inventory(hosts):

[webservers]
web1.example.com
web2.example.com
 
[dbservers]
db1.example.com
db2.example.com

动态 Inventory 脚本编写

动态 Inventory 脚本可以用任何语言编写,只要它能输出 JSON 格式的主机和组信息。例如,使用 Python 编写一个简单的动态 Inventory 脚本(my_inventory.py):

#!/usr/bin/env python
 
import json
 
inventory = {
    "webservers": {
        "hosts": ["web1.example.com", "web2.example.com"],
    },
    "dbservers": {
        "hosts": ["db1.example.com", "db2.example.com"],
    }
}
 
print(json.dumps(inventory))

运行 Playbook 时使用该脚本:

ansible-playbook -i my_inventory.py my_playbook.yml

常用的动态 Inventory 插件(如 AWS、Azure)

Ansible 提供了多种动态 Inventory 插件,支持 AWS、Azure、GCP 等云平台。

  1. AWS 动态 Inventory: 安装 boto3
pip install boto3

创建 aws_ec2.yml 配置文件,使用 aws_ec2 插件:

plugin: aws_ec2
regions:
  - us-east-1
filters:
  instance-state-name: running
keyed_groups:
  - key: tags.Name
    prefix: tag
  - key: tags.Environment
    prefix: env

使用该配置文件运行 Playbook:

ansible-playbook -i aws_ec2.yml my_playbook.yml
  1. Azure 动态 Inventory: 安装 azure-cliazure-mgmt
pip install azure-cli azure-mgmt

使用 azure_rm 插件:

plugin: azure_rm
include_vm_resource_groups:
  - myResourceGroup
auth_source: auto

使用该配置文件运行 Playbook:

ansible-playbook -i azure_rm.yml my_playbook.yml
  1. GCP 动态 Inventory

安装 google-authgoogle-api-python-client 库:

pip install google-auth google-api-python-client

创建 gcp_compute.yml 配置文件,使用 gcp_compute 插件:

plugin: gcp_compute
projects:
  - my-gcp-project
filters:
  - status = RUNNING
auth_kind: serviceaccount
service_account_file: /path/to/service-account.json

使用该配置文件运行 Playbook:

ansible-playbook -i gcp_compute.yml my_playbook.yml

通过动态 Inventory,可以自动发现和管理云环境中的资源,提高自动化程度和灵活性。这在动态变化的基础设施中尤其有用,确保 Ansible 的管理目标始终是最新的。

Ansible Vault

使用 Vault 加密敏感数据

Ansible Vault 用于加密敏感数据,如密码、密钥等,确保这些信息在存储和传输过程中不会被泄露。以下是 Ansible Vault 的基本使用方法:

# 1.加密文件
ansible-vault encrypt secret.yml
 
# 2.解密文件
ansible-vault decrypt secret.yml
 
# 3.编辑加密文件
ansible-vault edit secret.yml
 
# 4.查看加密文件
ansible-vault view secret.yml
 
# 5.重新加密文件(更改加密密码)
ansible-vault rekey secret.yml

Vault 的管理和使用

为了更方便地管理 Vault,可以在 ansible.cfg 中指定 Vault 密码文件,这样在运行 Playbook 时无需每次手动输入密码:

[defaults]
vault_password_file = /path/to/.vault_pass.txt

/path/to/.vault_pass.txt 文件中应只包含 Vault 密码,且该文件应设置为仅有文件所有者可读写:

chmod 600 /path/to/.vault_pass.txt

如果不希望将密码写入文件,也可以使用命令行参数 --ask-vault-pass

ansible-playbook --ask-vault-pass my_playbook.yml

在 Playbooks 中集成 Vault

在 Playbook 中使用 Vault 加密的变量文件时,可以通过 vars_files 引用这些文件:

- name: Deploy with Vault
  hosts: webservers
  vars_files:
    - secret.yml
  tasks:
    - name: Use encrypted variable
      debug:
        msg: "The secret is {{ vault_secret }}"

在这个示例中,secret.yml 是一个加密的变量文件,其中包含敏感数据。Ansible 会在运行 Playbook 时解密并加载这些变量。

Vault ID 和多 Vault 支持

Ansible Vault 支持使用多个 Vault ID 来加密不同级别或类型的敏感数据。使用 --vault-id 选项可以指定不同的 Vault 密码文件或密码提示命令。

例如,加密文件时指定 Vault ID:

ansible-vault encrypt --vault-id dev@prompt secret_dev.yml
ansible-vault encrypt --vault-id prod@/path/to/prod_vault_pass.txt secret_prod.yml

在 Playbook 中引用不同 Vault ID 的变量文件:

- name: Deploy with Vault IDs
  hosts: webservers
  vars_files:
    - vault_id: dev
      file: secret_dev.yml
    - vault_id: prod
      file: secret_prod.yml
  tasks:
    - name: Use dev encrypted variable
      debug:
        msg: "Dev secret is {{ dev_secret }}"
    - name: Use prod encrypted variable
      debug:
        msg: "Prod secret is {{ prod_secret }}"

运行 Playbook 时,指定 Vault ID 和密码文件:

ansible-playbook --vault-id dev@prompt --vault-id prod@/path/to/prod_vault_pass.txt my_playbook.yml

通过 Ansible Vault,可以有效地保护敏感数据,确保自动化流程的安全性,同时保持操作的便捷性和高效性。

Ansible 与其他自动化工具的比较

维度AnsiblePuppetChef
架构无代理架构,通过 SSH 或 WinRM 与被管理节点通信有代理架构,需要在被管理节点上安装 Puppet Agent有代理架构,需要在被管理节点上安装 Chef Client
通信模型基于推送模型,由控制节点推送任务到被管理节点执行基于拉取模型,被管理节点定期向 Puppet Master 拉取配置基于拉取模型,被管理节点定期向 Chef Server 拉取配置
配置语言使用 YAML 编写 Playbook,直观易读使用 Puppet 自定义的声明式语言编写清单(Manifest)使用 Ruby 编写食谱(Cookbooks),脚本式语言,灵活性高
学习曲线简单易用,适合快速上手学习曲线较为陡峭学习曲线较陡,需要掌握 Ruby
适用场景临时和一次性任务、多平台支持、快速部署和小型团队大规模配置管理、复杂依赖管理、企业级功能复杂和大型环境管理、需要复杂逻辑和自定义的场景
模块支持内置丰富的模块,适用于多种场景提供丰富的模块和企业级工具提供灵活的配置和扩展能力
依赖管理依赖管理能力相对较弱强大的资源依赖管理能力灵活的依赖管理和配置能力
企业级功能提供一些企业级功能,社区活跃,资源丰富提供丰富的企业级功能和工具,如报告、审计、合规管理等提供强大的企业级功能和支持
性能由于采用 SSH 推送模型,在大规模环境中性能可能会受到限制性能较好,适合大规模环境性能较好,适合复杂和大型环境
维护成本无代理架构,减少了管理和维护成本需要管理和维护 Puppet Master 和 Agent需要管理和维护 Chef Server 和 Client
社区和支持拥有庞大且活跃的社区,提供丰富的资源和支持社区活跃,企业级支持完善社区活跃,企业级支持完善

Ansible 在云环境中的应用

AWS 集成

安装并配置 boto3 库,使用 ec2 模块管理 AWS 资源。

pip install boto3

配置 Ansible Inventory 使用 AWS 动态库存插件 aws_ec2

plugin: aws_ec2
regions:
  - us-east-1
filters:
  instance-state-name: running

示例 Playbook:创建和管理 EC2 实例。

- name: Launch EC2 instance
  hosts: localhost
  tasks:
    - name: Launch an instance
      ec2:
        key_name: my-key
        instance_type: t2.micro
        image: ami-0abcdef1234567890
        wait: yes
        region: us-east-1
        group: my-security-group

Azure 集成

安装并配置 azure-cliazure-mgmt 库,使用 azure_rm 模块管理 Azure 资源。

pip install azure-cli azure-mgmt

配置 Ansible Inventory 使用 Azure 动态库存插件 azure_rm

plugin: azure_rm
include_vm_resource_groups:
  - myResourceGroup

示例 Playbook:创建和管理 Azure VM 实例。

- name: Launch Azure VM
  hosts: localhost
  tasks:
    - name: Create a VM
      azure_rm_virtualmachine:
        resource_group: myResourceGroup
        name: myVM
        vm_size: Standard_DS1_v2
        admin_username: azureuser
        admin_password: Password123!
        image:
          offer: UbuntuServer
          publisher: Canonical
          sku: 18.04-LTS
          version: latest

云资源管理和部署

动态库存管理

使用动态库存插件自动发现和管理云资源,无需手动更新 Inventory 文件。

   - name: List EC2 instances
     hosts: localhost
     tasks:
       - name: List instances
         ec2_instance_facts:
           region: us-east-1
自动化部署

使用 Ansible Playbook 实现云资源的自动化部署和配置,简化操作流程。

- name: Deploy web application on AWS
  hosts: tag_Environment_web
  become: yes
  tasks:
    - name: Install Nginx
      yum:
        name: nginx
        state: present
    - name: Start Nginx
      service:
        name: nginx
        state: started

Ansible 在容器化环境中的应用

Docker 集成

使用 community.docker 集成 Docker,管理 Docker 容器和镜像。

- name: Manage Docker
  hosts: all
  become: yes
  tasks:
    - name: Install Docker
      apt:
        name: docker.io
        state: present
    - name: Run a Docker container
      community.docker.docker_container:
        name: mycontainer
        image: nginx
        state: started
        ports:
          - "80:80"

Kubernetes 集成

使用 kubernetes.core 集成 Kubernetes,管理 Kubernetes 资源和集群。

- name: Manage Kubernetes
  hosts: localhost
  tasks:
    - name: Create a namespace
      kubernetes.core.k8s:
        state: present
        definition:
          apiVersion: v1
          kind: Namespace
          metadata:
            name: mynamespace
    - name: Deploy a pod
      kubernetes.core.k8s:
        state: present
        definition:
          apiVersion: v1
          kind: Pod
          metadata:
            name: mypod
            namespace: mynamespace
          spec:
            containers:
            - name: nginx
              image: nginx

容器部署

使用 Ansible 部署和管理容器化应用,实现自动化运维。

- name: Deploy Dockerized application
  hosts: all
  become: yes
  tasks:
    - name: Pull Docker image
      community.docker.docker_image:
        name: myapp
        tag: latest
        source: pull
    - name: Run Docker container
      community.docker.docker_container:
        name: myapp
        image: myapp:latest
        state: started
        ports:
          - "8080:8080"

Kubernetes 应用编排

使用 Ansible 管理 Kubernetes 集群,实现应用编排和服务发现。

- name: Deploy Kubernetes application
  hosts: localhost
  tasks:
    - name: Create deployment
      kubernetes.core.k8s:
        state: present
        definition:
          apiVersion: apps/v1
          kind: Deployment
          metadata:
            name: myapp
            namespace: default
          spec:
            replicas: 3
            selector:
              matchLabels:
                app: myapp
            template:
              metadata:
                labels:
                  app: myapp
              spec:
                containers:
                - name: myapp
                  image: myapp:latest
                  ports:
                  - containerPort: 8080
    - name: Expose service
      kubernetes.core.k8s:
        state: present
        definition:
          apiVersion: v1
          kind: Service
          metadata:
            name: myapp-service
            namespace: default
          spec:
            selector:
              app: myapp
            ports:
            - protocol: TCP
              port: 80
              targetPort: 8080

Ansible 在传统 IT 环境中的应用

数据中心管理

服务器配置管理

使用 Ansible 管理数据中心服务器的配置,确保一致性和自动化。

- name: Configure data center servers
  hosts: datacenter
  become: yes
  tasks:
    - name: Update all packages
      apt:
        upgrade: dist
    - name: Ensure NTP is installed
      apt:
        name: ntp
        state: present
    - name: Configure NTP
      copy:
        src: templates/ntp.conf.j2
        dest: /etc/ntp.conf
      notify:
        - restart ntp
 
  handlers:
    - name: restart ntp
      service:
        name: ntp
        state: restarted
硬件管理

使用 Ansible 自动化硬件管理,如固件升级和 BIOS 配置。

- name: Manage hardware
  hosts: datacenter
  become: yes
  tasks:
    - name: Upgrade firmware
      command: /usr/bin/upgrade_firmware.sh

网络设备配置

网络设备管理

使用 Ansible 管理网络设备配置,自动化网络设备的部署和更新。

- name: Configure network devices
  hosts: switches
  become: yes
  tasks:
    - name: Update switch firmware
      ios_command:
        commands:
          - copy tftp://192.0.2.1/new_firmware.bin flash:
          - reload
网络拓扑管理

使用 Ansible 自动化网络拓扑的配置和管理,确保网络配置的一致性。

- name: Configure network topology
  hosts: routers
  become: yes
  tasks:
    - name: Configure OSPF
      ios_config:
        lines:
          - router ospf 1
          - network 10.0.0.0 0.255.255.255 area 0

跨平台管理

多操作系统管理

使用 Ansible 管理多种操作系统,包括 Linux、Windows 和 macOS。

- name: Manage multiple OS
  hosts: all
  become: yes
  tasks:
    - name: Install packages on Linux
      apt:
        name: nginx
        state: present
      when: ansible_os_family == "Debian"
 
    - name: Install packages on Windows
      win_feature:
        name: Web-Server
        state: present
      when: ansible_os_family == "Windows"
 
    - name: Install packages on macOS
      homebrew:
        name: nginx
        state: present
      when: ansible_os_family == "Darwin"
跨平台应用部署

使用 Ansible 实现跨平台应用的自动化部署,确保各平台的一致性。

- name: Deploy application across platforms
  hosts: all
  become: yes
  tasks:
    - name: Deploy app on Linux
      command: /usr/local/bin/deploy_app.sh
      when: ansible_os_family == "Debian"
 
    - name: Deploy app on Windows
      win_command: C:\Deploy\deploy_app.bat
      when: ansible_os_family == "Windows"
 
    - name: Deploy app on macOS
      command: /usr/local/bin/deploy_app.sh
      when: ansible_os_family == "Darwin"

Ansible 实践案例

常见使用案例

系统用户和组管理

创建用户和组,设置权限和密码。

- name: Create a new user
  hosts: all
  become: yes
  tasks:
    - name: Add a user
      user:
        name: john
        state: present
        password: "{{ 'password' | password_hash('sha512') }}"

软件安装和更新

使用包管理器安装和更新软件包。

- name: Install and update software packages
  hosts: all
  become: yes
  tasks:
    - name: Install nginx
      apt:
        name: nginx
        state: present
    - name: Update all packages
      apt:
        upgrade: dist

服务管理

启动、停止和重启服务。

- name: Manage services
  hosts: all
  become: yes
  tasks:
    - name: Ensure nginx is running
      service:
        name: nginx
        state: started

文件和目录管理

创建、删除文件和目录,设置权限和所有者。

- name: Manage files and directories
  hosts: all
  become: yes
  tasks:
    - name: Create a directory
      file:
        path: /etc/myapp
        state: directory
    - name: Copy a configuration file
      copy:
        src: files/myapp.conf
        dest: /etc/myapp/myapp.conf
        owner: root
        group: root
        mode: '0644'

网络配置

配置网络接口和防火墙规则。

- name: Configure network interfaces
  hosts: all
  become: yes
  tasks:
    - name: Configure eth0
      network:
        name: eth0
        state: up
        address: 192.168.1.100
        netmask: 255.255.255.0
        gateway: 192.168.1.1

真实场景的 Playbook 编写

LAMP 堆栈部署

安装 Apache、MySQL 和 PHP,配置虚拟主机和数据库。

- name: Deploy LAMP stack
  hosts: webservers
  become: yes
  tasks:
    - name: Install Apache
      apt:
        name: apache2
        state: present
 
    - name: Install MySQL
      apt:
        name: mysql-server
        state: present
 
    - name: Install PHP
      apt:
        name: php
        state: present
 
    - name: Configure Apache virtual host
      template:
        src: templates/vhost.conf.j2
        dest: /etc/apache2/sites-available/000-default.conf
      notify:
        - restart apache
 
  handlers:
    - name: restart apache
      service:
        name: apache2
        state: restarted

Docker 容器管理

安装 Docker,启动容器,部署应用。

- name: Manage Docker containers
  hosts: all
  become: yes
  tasks:
    - name: Install Docker
      apt:
        name: docker.io
        state: present
 
    - name: Ensure Docker is running
      service:
        name: docker
        state: started
 
    - name: Run a web application container
      docker_container:
        name: mywebapp
        image: nginx
        state: started
        ports:
          - "80:80"

故障排除与调试技巧

使用 -vvv 选项

提供详细的输出信息,帮助定位问题。

ansible-playbook -i inventory myplaybook.yml -vvv

调试模块

使用 debug 模块输出变量信息。

- name: Debug variables
  hosts: all
  tasks:
    - name: Show variable value
      debug:
        var: my_variable

条件执行

使用 when 条件语句,避免在不满足条件时执行任务。

- name: Conditional execution
  hosts: all
  tasks:
    - name: Only run when condition is met
      command: /usr/bin/somecommand
      when: ansible_os_family == "Debian"

查看日志文件

查看 Ansible 生成的日志文件,分析错误信息。

tail -f /var/log/ansible.log

Ansible 性能优化

大规模部署的性能优化

并行执行

增加并行任务的数量,默认值为 5,可以通过 forks 参数调整。

ansible-playbook -i inventory myplaybook.yml -f 10

SSH 连接复用

启用 SSH 连接复用,提高效率。

[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s

使用缓存

使用事实缓存减少收集远程主机信息的时间。

[defaults]
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_cache

高效编写 Playbooks 的技巧

避免重复

使用角色和 include 机制,避免重复代码。

- name: Include common tasks
  import_tasks: common.yml

变量和模板

使用变量和模板简化配置文件。

- name: Use variables in tasks
  hosts: all
  vars:
    my_var: "value"
  tasks:
    - name: Print variable
      debug:
        msg: "The value is {{ my_var }}"

条件和循环

使用条件和循环减少代码冗余。

- name: Install multiple packages
  hosts: all
  become: yes
  tasks:
    - name: Install packages
      apt:
        name: "{{ item }}"
        state: present
      loop:
        - nginx
        - mysql-server
        - php

常见性能问题及解决方案

SSH 连接瓶颈

使用 pipelining 提升 SSH 连接速度。

[ssh_connection]
pipelining = True

冗余任务执行

​ 使用 check_mode 检查任务是否需要执行,避免不必要的任务执行。

- name: Check mode example
  hosts: all
  tasks:
    - name: Ensure nginx is installed
      apt:
        name: nginx
        state: present
      check_mode: yes

过多事实收集

禁用不必要的事实收集,提高效率。

- name: Disable fact gathering
  hosts: all
  gather_facts: no
  tasks:
    - name: Ensure nginx is installed
      apt:
        name: nginx
        state: present

Ansible 集成

Jenkins

  1. 安装 Jenkins 插件

    安装 Ansible 插件和 SSH 插件,以便 Jenkins 可以运行 Ansible 任务。

  2. 配置 Jenkins 作业

    创建一个 Jenkins 作业,配置源代码管理、构建触发器等。

  3. 在 Jenkins 中运行 Playbook

    在 Jenkins 作业中添加构建步骤,运行 Ansible Playbook。

   ansible-playbook -i inventory myplaybook.yml

Nagios

使用 Ansible 安装和配置 Nagios,部署监控插件。

   - name: Install Nagios
     hosts: all
     become: yes
     tasks:
       - name: Install Nagios packages
         apt:
           name: nagios3
           state: present
       - name: Configure Nagios
         template:
           src: templates/nagios.cfg.j2
           dest: /etc/nagios3/nagios.cfg
         notify:
           - restart nagios
   
     handlers:
       - name: restart nagios
         service:
           name: nagios3
           state: restarted

Prometheus

使用 Ansible 部署 Prometheus 和 Node Exporter,收集和监控指标。

   - name: Install Prometheus
     hosts: all
     become: yes
     tasks:
       - name: Download Prometheus
         get_url:
           url: https://github.com/prometheus/prometheus/releases/download/v2.26.0/prometheus-2.26.0.linux-amd64.tar.gz
           dest: /tmp/prometheus.tar.gz
   
       - name: Extract Prometheus
         unarchive:
           src: /tmp/prometheus.tar.gz
           dest: /opt/
           remote_src: yes
   
       - name: Configure Prometheus
         template:
           src: templates/prometheus.yml.j2
           dest: /opt/prometheus-2.26.0.linux-amd64/prometheus.yml
   
       - name: Create systemd service
         template:
           src: templates/prometheus.service.j2
           dest: /etc/systemd/system/prometheus.service
         notify:
           - reload systemd
           - start prometheus
   
     handlers:
       - name: reload systemd
         command: systemctl daemon-reload
       - name: start prometheus
         service:
           name: prometheus
           state: started

通过以上系统全面的内容,您可以更好地理解和掌握 Ansible 的使用,从而实现自动化部署和管理,提高工作效率。