1
2
3
4
5
6
7
作者:李晓辉

联系方式:

1. 微信:Lxh_Chat

2. 邮箱:939958092@qq.com

Ansible自动化概述

Ansible 是个开源工具,特别厉害,好多 IT 任务都能搞定,比如部署基础设施、配置管理,还有给云平台搞各种配置任务。

Ansible 能帮你超快地把多层云应用搭起来。你可以用它创建计算、存储和网络组件,还能在实例上安装软件包,搞负载均衡,处理网络安全,这些在混合云环境里很常见的任务都能搞定。

有些任务是所有服务器都得执行的,比如安全加固或者基础系统配置。还有一些任务只有在特定条件下才会运行。Ansible Playbooks 就是用来安排这些多层部署和跨平台工作流的,而且它是用人类能读懂的格式写的,很容易复用。

OpenStack 模块

Ansible 现在可以很方便地操作 OpenStack,而且有很多模块可以直接跟 OpenStack 的服务交互,不管是管理员还是普通用户都能用。

认证方式

首先,Ansible 是通过一个叫 os-client-config 的东西来完成认证的。它可以从很多地方获取认证信息,比如环境变量、配置文件,或者直接在 playbook 里定义。这些方式都很灵活,你可以根据自己的需求选择。

  • 环境变量:如果你已经设置了像 OS_AUTH 这样的环境变量,Ansible 会直接用它们,不用在模块里再写一遍。

  • 配置文件:比如 /etc/ansible/openstack.yaml 或者 ~/.config/openstack/clouds.yaml,这些文件里也可以放认证信息。

  • Playbook:你可以在 playbook 里直接定义认证信息,甚至可以用 ansible-vault 加密,这样更安全。

  • 模块参数:如果某个任务需要以不同的用户身份运行,还可以在模块的 auth 参数里单独定义。

模块命名

还有一个很关键的点,就是现在新的 OpenStack 模块都以 os_ 开头了,比如 os_server 用来创建实例,os_network 用来创建网络。老的模块没有这个前缀,现在正在逐渐被废弃。而且现在模块的名字更贴近用户熟悉的组件名,而不是服务名(比如 nova),这样更容易理解。

信息收集模块

还有一些带 _info 后缀的模块,比如 os_network_info,它们可以用来从服务或组件中收集信息。你可以用过滤器和条件语句来优化搜索结果。

查看模块

如果你想看看都有哪些模块可以用,可以直接用命令 ansible-doc --list | grep ^os_,或者去 Ansible 官方文档 查看详细列表。

运⾏ OpenStack 模块

首先,运行 Ansible 命令的时候,你需要一个目标主机,而且这个主机需要有 SSH 密钥访问权限。在课堂环境里,我们一般用本地主机(localhost)作为目标,然后用 OpenStack 用户凭证进行认证。

比如,你可以先加载用户凭证文件(比如 developer1-finance-rc),然后运行一个简单的 Ansible 命令来创建一个密钥对:

1
2
3
4
5
(overcloud) [stack@director ~]$ ansible -m os_keypair -a 'name=key state=present \
public_key_file=/home/stack/.ssh/id_rsa.pub' localhost
localhost | CHANGED => {
"changed": true,
...

创建实例

创建实例的时候,需要定义一些关键参数,比如 flavorimagenetwork,这些参数是必须的,不然实例没法正确创建。Ansible 的模块默认值可能和 OpenStack 命令行工具的默认值不一样,所以有时候可能会出现一些意外行为。

比如,auto_ip 参数默认是开启的,它会自动给实例分配一个浮动 IP 地址。如果你的内部网络连接了多个外部网络,Ansible 会随机选择一个来分配浮动 IP,除非你指定了 floating_ip_pools。比如:

1
2
3
4
(overcloud) [stack@director ~]$ ansible -m os_server \ 
-a 'state=present name=instance01 flavor=default image=rhel8 \
nics="net-name=finance-network1" \
floating_ip_pools=provider-datacentre' localhost

如果 auto_ip 是开启的,但没有连接外部网络,命令就会失败,因为没法分配浮动 IP。这种情况下,你可以手动指定一个浮动 IP 地址,比如:

等待资源就绪

有些模块里有一个 wait 参数,比如 os_image 模块。如果你设置了 wait=yes,Ansible 会等待资源进入 ACTIVE 状态,这样它就可以被使用或者与其他资源交互了。还可以用 timeout 参数来设置等待的时间限制。比如:

1
2
3
(overcloud) [stack@director ~]$ ansible -m os_image \
-a 'name=rhel8.3 container_format=bare disk_format=qcow2 \
filename=rhel8.3.qcow2 wait=yes' localhost

创建和删除资源

如果你想创建一个资源,直接运行命令就行,默认情况下 state=present,不需要显式指定。如果资源已经存在,命令会返回 SUCCESS,但 changed 会是 false

如果你想删除一个资源,就把 state 设置为 absent,然后提供资源的名字或者 ID。比如,如果你想把一个叫 database1 的服务器从负载均衡池 database_pool 中移除,可以用:

1
2
(overcloud) [stack@director ~]$ ansible -m os_member \
-a 'name=database1 state=absent pool=database_pool' localhost

负载均衡模块

os_loadbalancer 模块比较特殊,因为它可以一次性声明多个子资源,比如浮动 IP、监听器、池和成员。这个模块用起来很强大,但需要注意参数的配置。

创建负载均衡器的时候,可以直接分配一个浮动 IP,而且这个浮动 IP 是在创建负载均衡器的时候一起生成的,不需要提前创建。这比 os_server 模块方便多了,因为 os_server 创建实例的时候,浮动 IP 必须提前存在。

比如,你可以这样创建一个负载均衡器,并且直接分配一个浮动 IP:

1
2
3
(overcloud) [stack@director ~]$ ansible -m os_loadbalancer \
-a 'name=my_balancer vip_subnet=finance-subnet1 auto_public_ip=yes \
wait=yes public_network=provider-datacentre' localhost

运行之后,OpenStack 会自动分配一个内部 VIP 地址(比如 192.168.1.100),并且绑定一个浮动 IP 地址(比如 172.25.250.181)。你可以用 OpenStack 命令行工具查看负载均衡器和浮动 IP 的详细信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
(overcloud) [stack@director ~]$ openstack loadbalancer show \
> my_balancer -c name -c vip_address
+-------------+---------------+
| Field | Value |
+-------------+---------------+
| name | my_balancer |
| vip_address | 192.168.1.100 |
+-------------+---------------+

(overcloud) [stack@director ~]$ openstack floating ip show \
> 172.25.250.181 -c floating_ip_address -c fixed_ip_address
+---------------------+----------------+
| Field | Value |
+---------------------+----------------+
| fixed_ip_address | 192.168.1.100 |
| floating_ip_address | 172.25.250.181 |
+---------------------+----------------+

删除负载均衡器的时候,浮动 IP 默认不会被删除。如果你想同时删除浮动 IP,需要设置 delete_public_ip=yes,比如:

1
2
(overcloud) [stack@director ~]$ ansible -m os_loadbalancer \
-a 'name=my_balancer state=absent delete_public_ip=yes' localhost

使用 Playbook 自动化操作

如果你需要操作多个资源,或者想自动化一系列操作,用 Playbook 是最好的选择。Ansible 的 Playbook 非常强大,可以用来定义复杂的任务序列,而且支持各种模块、参数、条件判断,几乎可以完成任何应用生命周期的操作。

SSH 密钥访问

在 Playbook 中,你需要确保目标主机有 SSH 密钥访问权限。你可以通过变量来定义 SSH 密钥的位置。这些变量可以定义在 Playbook 中、inventory 文件中、角色中,或者直接在命令行中指定。你甚至可以在 Playbook 运行过程中动态创建变量,或者通过注册返回值来使用变量。

比如,你可以这样定义一个 inventory 文件,指定主机的 SSH 密钥位置:

1
2
3
4
5
6
7
8
9
10
[production]
frontend1 ansible_host=172.25.250.151
frontend2 ansible_host=172.25.250.152

[data]
database1
database2

[production:vars]
ansible_ssh_private_key_file=/home/student/.ssh/example-keypair

这样,当你运行 Playbook 的时候,Ansible 会自动使用指定的 SSH 密钥去连接目标主机。

Ansible 中带有 _info 后缀的 OpenStack 模块可以用来查询和获取资源信息,这些信息可以保存下来,或者在后续任务中使用。比如 os_flavor_infoos_networks_infoos_server_info 等模块。

参数和缩进

  • Ansible 的参数(比如 with_itemsregister)和模块定义的缩进级别是一样的。

  • 模块参数(比如 waitstate)需要在模块定义内部进一步缩进。

过滤结果

有些模块可以通过资源属性值来过滤结果。不同模块的过滤方式可能有所不同。比如:

  • os_flavor_info:可以直接在参数中应用条件。比如:

    • ram: ">=1024":筛选内存大于 1024 MB 的 flavor。

    • ram: "MIN":筛选内存最小的 flavor。

    • vcpus: "2":筛选 vCPU 数量为 2 的 flavor。

示例 1:查询带有临时存储的 Flavor

以下是一个查询带有临时存储的 Flavor 的示例。认证信息直接在模块级别定义,优先级高于其他地方定义的认证信息:

1
2
3
4
5
6
7
8
9
10
11
- name: "Look for flavors that comply with the conditions"
os_flavor_info:
auth:
auth_url: http://172.25.250.50:5000/v3
username: admin
password: redhat
project_name: admin
project_domain_name: Default
user_domain_name: Default
ephemeral: ">0"
register: result

示例 2:查询特定租户的活动子网

以下是一个查询特定租户的活动子网的示例:

1
2
3
4
5
6
7
- name: "Gather active networks from tenant"
os_networks_info:
filters:
tenant_id: 50e6fca93606496b8a6c043957e4cb1d
status: ACTIVE
name: provider-storage
register: result

示例 3:查询匹配特定条件的实例

以下是一个查询实例名称中包含 web 并且状态为 active 的实例的示例:

1
2
3
4
5
6
7
8
9
- name: "Query and filter instance information"
os_server_info:
server: "*web*"
filters:
vm_state: active
register: result

- debug:
msg: "{{ result.openstack_servers | map(attribute='name') | list }}"

Ansible 提供了很多原生过滤器,可以用来操作数据,比如:

  • 将 JSON 数据转换为 YAML 格式。

  • 从 URL 中提取主机名。

  • 获取字符串的 SHA1 哈希值。

  • 对整数进行加法或乘法运算。

你可以根据需要使用这些过滤器来操作数据,让输出结果更符合你的需求。