如何使用 ansible 在一个循环中挂载多个磁盘
Posted
技术标签:
【中文标题】如何使用 ansible 在一个循环中挂载多个磁盘【英文标题】:How to mount multiple disks in a loop using ansible 【发布时间】:2020-11-15 21:09:06 【问题描述】:我最近才开始使用 Ansible。我正在尝试在使用 terraform 附加的 azure VM 上安装 4 个磁盘。每个磁盘都带有一个 LUN 编号,我正在使用该 LUN 编号和 grep 获取每个磁盘的设备名称(sdc、sdd 等)。
- name: get volume name
shell: echo "/dev/$(ls -l /dev/disk/azure/scsi1 |grep item.lun |egrep -o "([^\/]+$)")"
register: volumename
- parted:
device: " volumename.stdout "
number: 1
state: present
- filesystem:
fstype: xfs
dev: " volumename.stdout "
- mount:
fstype: xfs
opts: noatime
src: " volumename.stdout "
path: " item.mountpoint "
state: mounted
- command: blkid -s UUID -o value volumename.stdout
register: volumename_disk
- blockinfile:
path: /etc/fstab
state: present
block: |
UUID= volumename_disk.stdout volumename.stdout xfs defaults,noatime,nofail 0 0
loop:
- lun: 'lun0', mountpoint: '/apps/mysql/binlog', diskname: 'binlog'
- lun: 'lun1', mountpoint: '/apps/mysql/innodb', diskname: 'innodb'
- lun: 'lun2', mountpoint: '/apps/mysql/data', diskname: 'data'
- lun: 'lun3', mountpoint: '/apps/mysql', diskname: 'backup'
tags: test
我不断收到 volumename 变量未定义错误。有没有办法将volumename设置为全局以便下一个剧本可以访问它或者我如何改进这个代码?
【问题讨论】:
【参考方案1】:首先,我不是 ansible 的专家,但看起来你想要做的是:
对多个任务使用相同的循环。我认为这是不可能的。另一件事是 loop
-variables 仅适用于具有匹配缩进的任务,在您的情况下:blockinfile
。
您可以做的是为您要执行的任务创建一个自己的任务-文件,并将其包含在您的剧本中(循环包含)。 这已由@Konstantin 在以下示例中完成:Multiple ansible task with same loop
额外:Reason why it is NOT available
如果可以将单个 loop
用于多个任务,那么您必须确保将其应用于所有任务,例如:
- block:
task1
...
task2
...
loop:
- lun: 'lun0', mountpoint: '/apps/mysql/binlog', diskname: 'binlog'
- lun: 'lun1', mountpoint: '/apps/mysql/innodb', diskname: 'innodb'
示例:
(根据您的评论创建了一个示例,我认为这不是一个好的解决方案,但它是一个解决方案)
使用set_fact
创建一个列表,然后将此列表传递给另一个剧本。
使用我现有的示例:
my_tasks.yml:
---
- command: echo " item.lun"
register: volumename
- set_fact:
volumenames: " volumenames|default([]) + [ 'name': volumename.stdout ] "
- debug:
msg: "VOLUMENAME is: volumename.stdout "
playbook.yml:
---
- hosts: localhost
tasks:
- include_tasks: my_tasks.yml
loop:
- lun: 'lun0', mountpoint: '/apps/mysql/binlog', diskname: 'binlog'
- lun: 'lun1', mountpoint: '/apps/mysql/innodb', diskname: 'innodb'
- lun: 'lun2', mountpoint: '/apps/mysql/data', diskname: 'data'
- lun: 'lun3', mountpoint: '/apps/mysql', diskname: 'backup'
- import_playbook: playbook2.yml myvar=' volumenames '
playbook2.yml
---
- hosts: localhost
tasks:
- debug:
msg: " myvar "
【讨论】:
谢谢,我刚试过,是的,你是对的 include_tasks 只是循环多个任务的方法,但问题仍然是循环传递动态变量,如“lun”并构建一个变量volumename 需要在任务中进一步使用,而 Ansible 似乎并不擅长。不确定是否有更好的方法来做到这一点。 不确定我是否关注。您当然可以使用 set_fact 创建一个新变量,该变量可以被另一个剧本使用。 (我可以使用调试添加一个不太有用的示例,看看它是否可以理解)- 您下面的解决方案要好得多。谢谢。【参考方案2】:通读文档后,我找到了实现这一目标的方法。
正确的方法是使用 Ansible 的字典变量。
raid_config:
- lun: " backup_lun "
mountpoint: " backup_mountpoint "
- lun: " data_lun "
mountpoint: " data_mountpoint "
- lun: " binlog_lun "
mountpoint: " binlog_mountpoint "
- lun: " innodb_lun "
mountpoint: " innodb_mountpoint "
将任务移动到单独的文件 mountdisk.yml 并将字典传递给这样的任务
- include_tasks: "mountdisk.yml"
loop: " raid_config "
loop_control:
loop_var: disk
tags: test
这样我就能够获取 lun 和挂载点作为 disk.lun 和 disk.mountpoint。
注意:在使用 include_tasks 选项时,您需要在每个任务中分别传递标签关键字(如果您使用的是一个)。
【讨论】:
以上是关于如何使用 ansible 在一个循环中挂载多个磁盘的主要内容,如果未能解决你的问题,请参考以下文章