1
0
wiki/Tech/operating-system/Automation/Ansible.md
2024-06-14 15:13:31 +08:00

1635 lines
46 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: Ansible
description: Ansible 自动化运维管理
keywords:
- Ansible
- 自动化运维
- DevOps
tags:
- 技术/操作系统
- 自动化/Linux
- Linux/安装
author: 仲平
date: 2024-05-15
---
## 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 架构概述
![](https://static.7wate.com/2024%2F05%2F16%2F60b689d609a756040c7d4bcbc25ab74a-Understanding-Ansible-Architecture-using-diagram3.png)
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**:通过 WSLWindows 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 进行安装:
```shell
sudo apt update
sudo apt install ansible
```
##### CentOS
在 CentOS 上,可以通过 EPELExtra Packages for Enterprise Linux库安装 Ansible
```shell
sudo yum install epel-release
sudo yum install ansible
```
##### macOS
在 macOS 上,可以使用 Homebrew 来安装 Ansible
```shell
brew install ansible
```
#### 通过 Python Pip 安装
可以使用 Python 的包管理器 pip 来安装 Ansible这种方法适用于任何支持 Python 的操作系统:
```shell
pip install ansible
```
#### 从源代码安装
从源代码安装适用于需要最新功能或定制 Ansible 的场景:
```shell
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` 文件结构如下:
```ini
[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 密钥对**
```shell
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
```
生成的密钥文件通常存储在 `~/.ssh/` 目录下。
1. **将公钥添加到被管理节点**
```shell
ssh-copy-id user@remote_host
```
或者手动将公钥添加到被管理节点的 `~/.ssh/authorized_keys` 文件中。
1. **配置 SSH 代理(可选)** 使用 SSH 代理可以管理多个 SSH 密钥,提高连接效率:
```shell
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa
```
通过上述步骤Ansible 可以无密码地通过 SSH 访问被管理节点,从而实现自动化操作。
## Ansible 自动化管理基础
### Ansible Playbooks
#### Playbook 的基本结构
Playbook 是 Ansible 的核心配置文件,用于定义一系列自动化任务。它使用 YAML 格式编写,主要由 Plays 和 Tasks 组成。一个典型的 Playbook 结构如下:
```yaml
- 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`
```yaml
- 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**
```bash
ansible-playbook first_playbook.yml
```
在此示例中Playbook 定义了一个 Play包含两个任务一个用于安装 Apache Web 服务器,另一个用于启动 Apache 服务。`hosts` 指定了目标主机组为 `webservers`,并通过 `become: yes` 启用权限提升(通常是 sudo
#### 多 Play 和任务的组织
一个 Playbook 可以包含多个 Play每个 Play 针对不同的主机组或执行不同的任务。这种结构有助于在一个 Playbook 中管理复杂的部署场景。
```yaml
- 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` 模块的常用参数包括 `path`、`state`、`owner`、`group` 等。
#### 自定义模块
如果内置模块不能满足需求,可以编写自定义模块。自定义模块可以使用 Python 编写,并放置在库路径中。
示例自定义模块(`my_module.py`
```python
#!/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()
```
运行自定义模块:
```yaml
- name: Use custom module
hosts: localhost
tasks:
- name: Call custom module
my_module:
name: Ansible
```
### Ansible 变量和模板
#### 变量的定义与使用
变量可以在多个地方定义,如 Playbook、清单文件、角色等
```yaml
- 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`
```jinja2
## 变量替换
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`
```yaml
- 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`
```nginx
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 和相关文件(如任务、处理程序、变量、模板等)结构化和模块化。角色的目录结构通常如下:
```css
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. **创建角色**
```bash
ansible-galaxy init my_role
```
这条命令会生成上述结构的角色目录。
1. **定义任务**`roles/my_role/tasks/main.yml`
```yaml
- name: Install Apache
apt:
name: apache2
state: present
- name: Start Apache service
service:
name: apache2
state: started
```
在这个例子中,定义了两个任务:一个用于安装 Apache另一个用于启动 Apache 服务。
1. **在 Playbook 中使用角色**
```yaml
- name: Apply my role
hosts: webservers
roles:
- my_role
```
在 Playbook 中,通过 `roles` 关键字引用角色。
#### 角色的共享与重用Ansible Galaxy
Ansible Galaxy 是 Ansible 官方的角色分享平台,用户可以在上面发布和下载角色,方便角色的共享与重用。
1. **安装角色**
```shell
ansible-galaxy install username.role_name
```
可以从 Galaxy 下载并安装角色。安装的角色通常会存放在 Ansible 的角色路径中(默认是 `/etc/ansible/roles``~/.ansible/roles`)。
1. **使用已安装的角色**
```yaml
- 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`
```ini
[webservers]
web1.example.com
web2.example.com
[dbservers]
db1.example.com
db2.example.com
```
#### 动态 Inventory 脚本编写
动态 Inventory 脚本可以用任何语言编写,只要它能输出 JSON 格式的主机和组信息。例如,使用 Python 编写一个简单的动态 Inventory 脚本(`my_inventory.py`
```python
#!/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 时使用该脚本:
```bash
ansible-playbook -i my_inventory.py my_playbook.yml
```
#### 常用的动态 Inventory 插件(如 AWS、Azure
Ansible 提供了多种动态 Inventory 插件,支持 AWS、Azure、GCP 等云平台。
1. **AWS 动态 Inventory** 安装 `boto3`
```shell
pip install boto3
```
创建 `aws_ec2.yml` 配置文件,使用 `aws_ec2` 插件:
```yaml
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
```bash
ansible-playbook -i aws_ec2.yml my_playbook.yml
```
1. **Azure 动态 Inventory** 安装 `azure-cli``azure-mgmt`
```bash
pip install azure-cli azure-mgmt
```
使用 `azure_rm` 插件:
```yaml
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-auth``google-api-python-client` 库:
```bash
pip install google-auth google-api-python-client
```
创建 `gcp_compute.yml` 配置文件,使用 `gcp_compute` 插件:
```yaml
plugin: gcp_compute
projects:
- my-gcp-project
filters:
- status = RUNNING
auth_kind: serviceaccount
service_account_file: /path/to/service-account.json
```
使用该配置文件运行 Playbook
```bash
ansible-playbook -i gcp_compute.yml my_playbook.yml
```
通过动态 Inventory可以自动发现和管理云环境中的资源提高自动化程度和灵活性。这在动态变化的基础设施中尤其有用确保 Ansible 的管理目标始终是最新的。
### Ansible Vault
#### 使用 Vault 加密敏感数据
Ansible Vault 用于加密敏感数据,如密码、密钥等,确保这些信息在存储和传输过程中不会被泄露。以下是 Ansible Vault 的基本使用方法:
```shell
# 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 时无需每次手动输入密码:
```ini
[defaults]
vault_password_file = /path/to/.vault_pass.txt
```
`/path/to/.vault_pass.txt` 文件中应只包含 Vault 密码,且该文件应设置为仅有文件所有者可读写:
```shell
chmod 600 /path/to/.vault_pass.txt
```
如果不希望将密码写入文件,也可以使用命令行参数 `--ask-vault-pass`
```shell
ansible-playbook --ask-vault-pass my_playbook.yml
```
#### 在 Playbooks 中集成 Vault
在 Playbook 中使用 Vault 加密的变量文件时,可以通过 `vars_files` 引用这些文件:
```yaml
- 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
```yaml
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 的变量文件:
```yaml
- 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 和密码文件:
```yaml
ansible-playbook --vault-id dev@prompt --vault-id prod@/path/to/prod_vault_pass.txt my_playbook.yml
```
通过 Ansible Vault可以有效地保护敏感数据确保自动化流程的安全性同时保持操作的便捷性和高效性。
## Ansible 与其他自动化工具的比较
| 维度 | Ansible | Puppet | Chef |
| -------------- | ------------------------------------------------------- | ----------------------------------------------------- | ----------------------------------------------------- |
| **架构** | 无代理架构,通过 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 资源。
```shell
pip install boto3
```
配置 Ansible Inventory 使用 AWS 动态库存插件 `aws_ec2`
```ini
plugin: aws_ec2
regions:
- us-east-1
filters:
instance-state-name: running
```
示例 Playbook创建和管理 EC2 实例。
```yaml
- 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-cli``azure-mgmt` 库,使用 `azure_rm` 模块管理 Azure 资源。
```shell
pip install azure-cli azure-mgmt
```
配置 Ansible Inventory 使用 Azure 动态库存插件 `azure_rm`
```yaml
plugin: azure_rm
include_vm_resource_groups:
- myResourceGroup
```
示例 Playbook创建和管理 Azure VM 实例。
```yaml
- 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 文件。
```yaml
- name: List EC2 instances
hosts: localhost
tasks:
- name: List instances
ec2_instance_facts:
region: us-east-1
```
##### 自动化部署
使用 Ansible Playbook 实现云资源的自动化部署和配置,简化操作流程。
```yaml
- 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 容器和镜像。
```yaml
- 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 资源和集群。
```yaml
- 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 部署和管理容器化应用,实现自动化运维。
```yaml
- 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 集群,实现应用编排和服务发现。
```yaml
- 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 管理数据中心服务器的配置,确保一致性和自动化。
```yaml
- 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 配置。
```yaml
- name: Manage hardware
hosts: datacenter
become: yes
tasks:
- name: Upgrade firmware
command: /usr/bin/upgrade_firmware.sh
```
#### 网络设备配置
##### 网络设备管理
使用 Ansible 管理网络设备配置,自动化网络设备的部署和更新。
```yaml
- 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 自动化网络拓扑的配置和管理,确保网络配置的一致性。
```yaml
- 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。
```yaml
- 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 实现跨平台应用的自动化部署,确保各平台的一致性。
```yaml
- 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 实践案例
### 常见使用案例
#### 系统用户和组管理
创建用户和组,设置权限和密码。
```yaml
- name: Create a new user
hosts: all
become: yes
tasks:
- name: Add a user
user:
name: john
state: present
password: "{{ 'password' | password_hash('sha512') }}"
```
#### 软件安装和更新
使用包管理器安装和更新软件包。
```yaml
- 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
```
#### 服务管理
启动、停止和重启服务。
```yaml
- name: Manage services
hosts: all
become: yes
tasks:
- name: Ensure nginx is running
service:
name: nginx
state: started
```
#### 文件和目录管理
创建、删除文件和目录,设置权限和所有者。
```yaml
- 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'
```
#### 网络配置
配置网络接口和防火墙规则。
```yaml
- 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配置虚拟主机和数据库。
```yaml
- 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启动容器部署应用。
```yaml
- 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` 选项
提供详细的输出信息,帮助定位问题。
```yaml
ansible-playbook -i inventory myplaybook.yml -vvv
```
#### 调试模块
使用 `debug` 模块输出变量信息。
```yaml
- name: Debug variables
hosts: all
tasks:
- name: Show variable value
debug:
var: my_variable
```
#### 条件执行
使用 `when` 条件语句,避免在不满足条件时执行任务。
```yaml
- name: Conditional execution
hosts: all
tasks:
- name: Only run when condition is met
command: /usr/bin/somecommand
when: ansible_os_family == "Debian"
```
#### 查看日志文件
查看 Ansible 生成的日志文件,分析错误信息。
```yaml
tail -f /var/log/ansible.log
```
## Ansible 性能优化
### 大规模部署的性能优化
#### 并行执行
增加并行任务的数量,默认值为 5可以通过 `forks` 参数调整。
```shell
ansible-playbook -i inventory myplaybook.yml -f 10
```
#### SSH 连接复用
启用 SSH 连接复用,提高效率。
```ini
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
```
#### 使用缓存
使用事实缓存减少收集远程主机信息的时间。
```ini
[defaults]
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_cache
```
### 高效编写 Playbooks 的技巧
#### 避免重复
使用角色和 include 机制,避免重复代码。
```yaml
- name: Include common tasks
import_tasks: common.yml
```
#### 变量和模板
使用变量和模板简化配置文件。
```yaml
- name: Use variables in tasks
hosts: all
vars:
my_var: "value"
tasks:
- name: Print variable
debug:
msg: "The value is {{ my_var }}"
```
#### 条件和循环
使用条件和循环减少代码冗余。
```yaml
- 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 连接速度。
```ini
[ssh_connection]
pipelining = True
```
#### 冗余任务执行
使用 `check_mode` 检查任务是否需要执行,避免不必要的任务执行。
```yaml
- name: Check mode example
hosts: all
tasks:
- name: Ensure nginx is installed
apt:
name: nginx
state: present
check_mode: yes
```
#### 过多事实收集
禁用不必要的事实收集,提高效率。
```yaml
- 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。
```shell
ansible-playbook -i inventory myplaybook.yml
```
### Nagios
使用 Ansible 安装和配置 Nagios部署监控插件。
```yaml
- 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收集和监控指标。
```yaml
- 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 的使用,从而实现自动化部署和管理,提高工作效率。