🐇明明跟你说过:个人主页
🏅个人专栏:《Linux :从菜鸟到飞鸟的逆袭》🏅
🔖行路有良友,便是天堂🔖
目录
一、引言
1、什么是Ansible
Ansible 是一个开源的自动化工具,广泛用于 IT 基础设施的配置管理、应用部署、任务自动化以及多节点系统的编排(Orchestration)。Ansible 由 Red Hat 维护,它以简洁、易用、无代理的设计理念受到广大开发者和运维人员的喜爱。
2、Ansible应用场景
1. 配置管理
Ansible 最常见的应用场景之一是 配置管理。它可以帮助自动化地配置服务器,确保系统和应用的配置一致。通过 Ansible Playbooks,我们可以定义系统的配置,安装软件包,修改文件内容,管理服务等。
示例场景:
- 在多台服务器上安装和配置 Web 服务器(如 Apache、Nginx)。
- 配置数据库服务器,确保配置一致性,如 MySQL、PostgreSQL。
- 配置和部署应用程序环境(如 Java 环境、Node.js 环境等)。
2. 应用部署
Ansible 可以自动化 应用部署,确保应用的版本一致性,并简化多环境的部署过程。它支持从开发到生产环境的自动化流程,减少了人工操作的错误,并提高了发布效率。
示例场景:
- 部署 Web 应用程序(如 Laravel、Django、Flask、Node.js 应用等)。
- 自动化部署微服务架构中的不同服务。
- 将应用程序自动发布到多个服务器或容器中。
3. 云资源管理
Ansible 能够与云平台(如 AWS、Azure、Google Cloud)集成,自动化云资源的创建、配置和管理。这使得云环境的资源部署变得更加高效和可重复。
示例场景:
- 在 AWS 上自动创建 EC2 实例、配置安全组、设置负载均衡器。
- 在 Azure 上管理虚拟机、存储账户和网络资源。
- 自动化管理 Kubernetes 集群和云中的容器服务。
4. 容器化部署
Ansible 支持与容器化技术(如 Docker、Kubernetes)集成,可以自动化容器的构建、部署和管理。
示例场景:
- 自动构建并部署 Docker 镜像。
- 在 Kubernetes 集群中自动创建 Pods、部署服务和配置卷。
- 管理 Docker Swarm 集群的节点和服务。
5. 基础设施自动化
Ansible 可以自动化基础设施的创建和配置,帮助管理员管理大规模基础设施,提升运维效率。
示例场景:
- 自动化配置负载均衡器(如 HAProxy、Nginx)。
- 自动配置网络设备、管理防火墙规则、配置 DNS。
- 自动安装和配置监控工具,如 Prometheus、Zabbix 等。
二、Ansible Playbook基础
1、YAML语法简介
YAML(YAML Ain't Markup Language)是一种简洁、可读性强的数据序列化格式,常用于配置文件、数据交换和自动化工具(如 Ansible、Kubernetes、Docker Compose 等)的配置。YAML 以其简洁性和易读性,成为了许多现代工具和应用程序的首选配置格式。
1. 基本结构
YAML 使用缩进来表示层级结构,缩进通常使用 2 或 4 个空格,不使用制表符(Tab)。
key: value
例如:
name: John Doe
age: 30
2. 键值对
YAML 文件的基本构成是 键值对。键和值之间用冒号 : 分隔,冒号后必须有空格。
name: Alice
age: 25
3. 列表(数组)
YAML 支持使用短横线 - 来表示列表(数组)。每个元素前面有一个短横线和一个空格。
fruits:
- Apple
- Banana
- Cherry
4. 嵌套结构
YAML 通过缩进来表示嵌套结构。缩进通常是 2 个空格,表示层级。
person:
name: John
age: 30
address:
street: "123 Main St"
city: "New York"
5. 多行字符串
YAML 提供了两种方式来表示多行字符串:
- |:保留换行符,将文本按行存储(每个换行会保留)。
- >:将换行符转换为空格,将文本合并为一行(多行文本会变成一个长字符串,换行会被转化为空格)。
text_with_newlines: |
This is a line.
This is another line.
This is the third line.
text_without_newlines: >
This is a very long line
that is actually split
into multiple lines.
6. 注释
YAML 支持使用 # 来添加注释。注释从 # 开始,直到行尾。
# This is a comment
name: Alice # This is an inline comment
2、Playbook的基本元素
在 Ansible 中,Playbook 是自动化流程的核心,它包含了一系列的 plays。每个 play 会执行一些任务(tasks),而任务的执行顺序由 Playbook 中定义的 handlers 来控制。
1. Play(剧本)
Play 是 Playbook 中的一个基本单元,表示你希望在目标主机上执行的操作。每个 Play 定义了:
- 目标主机:Playbook 中的主机(hosts)字段指定哪些主机将执行任务。
- 任务执行顺序:Playbook 中的任务(tasks)会按顺序在目标主机上执行。
- 权限:become 用来指定是否以超级用户(root)身份运行任务。
2. Task(任务)
Task 是 Play 中的具体操作,它定义了你希望在目标主机上执行的命令或动作。任务通常由一个模块(如 yum、apt、service、copy)执行。每个任务有以下组成部分:
- 任务名称(name):描述任务目的。
- 模块名称:任务中用来执行操作的模块(例如 yum、apt、copy、service 等)。
- 模块参数:指定模块的参数(例如,安装的软件包名、服务名、文件路径等)。
3. Handler(处理器)
Handler 是 Playbook 中的一种特殊类型的任务,它们通常用于执行某些需要在任务变化时触发的操作。与普通任务不同,handler 只有在被显式通知时才会执行。通常用于执行诸如重启服务、重新加载配置等操作。
- 触发条件:当任务执行导致某些变化时,才会通知相关的 handler。
- 通知触发:任务可以使用 notify 字段来通知 handler 执行某个操作。
3、playbook工作流程
1. 加载和解析 Playbook:
- Ansible 开始执行 Playbook 时,首先会加载并解析 Playbook 文件。Playbook 是 YAML 格式的文件,Ansible 会通过解析文件来理解里面定义的各个 Play 和任务(tasks)。
- 每个 Playbook 文件可以包含多个 Play,每个 Play 会指定需要在哪些主机上执行任务。
2. 加载清单(Inventory):
- Inventory(清单)是一个包含主机和主机组的文件(通常是一个INI或YAML格式文件)。Ansible 会根据清单文件来确定需要执行 Playbook 的目标主机。
- 清单文件可以是静态的(手动配置)或者动态的(由某些脚本或 API 动态生成)。
3. 进入每个 Play 的执行:
- Ansible 会逐个 Play 地执行 Playbook 文件中的每个 Play。
- 每个 Play 会指定 hosts(目标主机),也可以定义运行任务时是否需要 become(是否以超级用户身份运行)等相关属性。
4. 执行 Tasks:
- 在每个 Play 中,Ansible 会逐个执行 task。每个任务对应着在目标主机上执行的操作(例如安装软件、修改配置文件、启动服务等)。
- 每个任务执行时,Ansible 会使用相应的模块(如 yum、apt、service、file)来完成任务,并根据任务的状态(成功或失败)记录执行结果。
- 每个任务执行时会检查其状态,并根据任务的结果决定是否执行下一个任务。
5. 触发 Handlers:
- Handler 是 Ansible 中的一种特殊类型的任务。与普通任务不同,handler 只有在任务执行时发生变更(例如文件被修改、服务被重启等)时才会被触发。
- 如果某个任务成功地通知了 handler(通过 notify),handler 会在所有任务完成后执行(通常用于重启服务或重新加载配置等操作)。
6. 处理任务的状态:
- 每个任务执行后,Ansible 会检查任务的状态并记录其结果。任务可能的状态包括:
- changed:任务的执行导致目标主机的状态发生了变化(例如文件被更新、服务被启动)。
- ok:任务执行没有导致状态变化,但执行仍然成功(例如服务已经处于预期状态,无需更改)。
- failed:任务执行失败(例如软件包安装失败、服务启动失败)。
- skipped:任务被跳过,通常是因为条件语句(如 when)不满足。
7. 执行完所有 Plays:
- Playbook 中的所有 Play 执行完后,Ansible 会检查是否有未执行的 handlers。如果有,Ansible 会执行相应的 handler。
8. 结果报告:
- Playbook 执行完毕后,Ansible 会生成一个执行报告。报告包含了每个任务的执行状态、目标主机的状态以及每个任务是否发生了变化。你可以查看执行日志来确认每个任务的成功与失败。
三、Tasks与Commands
1、Task的基本结构
一个 Task 通常包含以下几部分:
- name:任务名称,用于描述这个任务的目的,通常是一个简短的文本。
- module_name:执行任务的模块。Ansible 提供了丰富的模块库,每个模块实现不同的功能。
- module_parameters:模块的参数,用来指定该任务所需的具体配置或操作细节。
- when:条件判断,只有满足某个条件时才会执行任务。
- notify:当任务发生变化时,通知触发 handler 执行。
- register:将任务的执行结果存储到一个变量中,可以在后续的任务中使用。
- tags:标签,用于给任务打标签,便于运行时选择性执行。
- become:是否以超级用户身份执行该任务。
Task 示例结构
- name: Install Nginx
apt:
name: nginx
state: present
become: yes
when: ansible_facts['distribution'] == 'Ubuntu'
notify:
- Restart Nginx
register: nginx_installation
tags:
- webserver
- name: Install Nginx 是任务的描述,用来标明该任务的目的。
- apt 是 Ansible 提供的模块,用来管理 Debian 系统上的软件包。在这个例子中,apt 模块用于安装 nginx 软件包。
- name: nginx 指定了要安装的软件包名称。
- state: present 表示确保软件包 nginx 已安装。如果已经安装,它不会进行任何更改。如果没有安装,它会安装该软件包。
- become: yes 表示该任务需要以 root 用户身份执行。如果没有该选项,任务将作为当前用户执行。
- when: ansible_facts['distribution'] == 'Ubuntu' 表示该任务仅在目标主机的操作系统为 Ubuntu 时才会执行。ansible_facts['distribution'] 是 Ansible 收集的主机事实信息,存储了关于目标主机的详细信息。
- notify: - Restart Nginx 表示如果该任务导致目标主机状态发生变化(例如软件包被安装),则会触发名为 Restart Nginx 的 handler 执行。
- register: nginx_installation 将该任务的执行结果保存到变量 nginx_installation 中。后续可以使用该变量判断任务是否执行成功或获取其输出。
- tags: [webserver] 给任务打上标签,便于在运行时选择性地执行特定的任务。例如,在执行 Playbook 时,可以使用 --tags webserver 参数只执行标记为 webserver 的任务。
2、循环(loops)在Tasks中的实现
loop 是现代版本的 Ansible 推荐使用的循环语法。它可以遍历任何类型的可迭代对象,例如列表、字典等。
示例:循环安装多个软件包
- name: Install multiple packages
apt:
name: "{{ item }}"
state: present
loop:
- nginx
- vim
- curl
在这个示例中,任务会循环安装列表中的软件包 nginx、vim 和 curl。item 是循环中的当前元素,它会依次取 nginx、vim 和 curl。
3、示例:管理用户账户与权限
目标
- 创建用户账户。
- 设置密码。
- 将用户添加到一个或多个组。
- 设置用户的主目录权限。
- 管理用户的 SSH 公钥。
Playbook 示例
---
- name: Manage user accounts and permissions
hosts: all
become: yes # 以 root 用户身份执行
tasks:
# 创建用户 user1 和 user2
- name: Ensure user user1 is present
user:
name: user1
state: present
shell: /bin/bash
comment: "User 1"
home: /home/user1
create_home: yes
password: "{{ 'password123' | password_hash('sha512') }}"
update_password: on_create # 仅在用户创建时设置密码
- name: Ensure user user2 is present
user:
name: user2
state: present
shell: /bin/bash
comment: "User 2"
home: /home/user2
create_home: yes
password: "{{ 'password456' | password_hash('sha512') }}"
update_password: on_create
# 创建一个用户组
- name: Ensure group developers exists
group:
name: developers
state: present
# 将用户添加到开发者组
- name: Add user user1 to developers group
user:
name: user1
group: developers
append: yes
- name: Add user user2 to developers group
user:
name: user2
group: developers
append: yes
# 设置用户的主目录权限
- name: Set permissions for user1's home directory
file:
path: /home/user1
owner: user1
group: developers
mode: '0755'
- name: Set permissions for user2's home directory
file:
path: /home/user2
owner: user2
group: developers
mode: '0755'
# 管理 SSH 公钥(可选)
- name: Add SSH public key for user1
authorized_key:
user: user1
state: present
key: "{{ lookup('file', '/path/to/user1_ssh_key.pub') }}" # 公钥的文件路径
- name: Add SSH public key for user2
authorized_key:
user: user2
state: present
key: "{{ lookup('file', '/path/to/user2_ssh_key.pub') }}" # 公钥的文件路径
解释
user 模块:
- 创建用户:使用 user 模块来确保 user1 和 user2 用户存在。
- state: present:确保用户存在。
- password: "{{ 'password123' | password_hash('sha512') }}":为用户设置密码,并使用 password_hash 过滤器对密码进行加密。
- create_home: yes:如果用户没有主目录,则会自动创建主目录。
- update_password: on_create:仅在用户创建时设置密码。
group 模块:
- 创建用户组:使用 group 模块创建一个名为 developers 的组,确保该组存在。
user 模块(添加用户到组):
- 使用 group: developers 参数将用户添加到 developers 组。
- append: yes 表示如果用户已经属于该组,不会移除其他组。
file 模块:
- 设置主目录权限:使用 file 模块设置用户主目录的权限,确保主目录的所有者是对应的用户,组是 developers,权限是 0755。
authorized_key 模块:
- 管理 SSH 公钥:使用 authorized_key 模块将 SSH 公钥添加到用户的 ~/.ssh/authorized_keys 文件中,从而允许用户通过 SSH 公钥认证登录。
- key 参数通过 lookup('file', 'path_to_key') 引用本地文件的内容。
💕💕💕每一次的分享都是一次成长的旅程,感谢您的陪伴和关注。希望这些关于Linux的文章能陪伴您走过技术的一段旅程,共同见证成长和进步!😺😺😺
🧨🧨🧨让我们一起在技术的海洋中探索前行,共同书写美好的未来!!!