如何使用ansible循环挂载多个磁盘

问题描述 投票:0回答:3

我最近刚刚开始使用 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 变量未定义”错误。有什么方法可以将卷名称设置为全局,以便下一个剧本可以访问它或者我如何改进此代码?

azure ansible mount disk rhel7
3个回答
2
投票

首先,我不是 ansible 专家,但你想要做的是:

  • 对多个任务使用相同的循环。

我认为这是不可能的。另一件事是,

loop
变量仅适用于具有匹配缩进的任务,在您的情况下:
blockinfile

您可以做的是为您想要执行的任务创建一个自己的task文件,并将其包含在您的剧本中(循环包含)。 这是由 @Konstantin 在以下示例中完成的:具有相同循环的多个 ansible 任务

额外:
不可用的原因
如果可以使用单个

loop
来完成多个任务,那么您必须确保将其应用于所有任务,例如:

- block:
    task1
     ...
    task2
     ...
  loop:
    - { lun: 'lun0', mountpoint: '/apps/mysql/binlog', diskname: 'binlog' }
    - { lun: 'lun1', mountpoint: '/apps/mysql/innodb', diskname: 'innodb' }

示例:

(根据您的评论创建了一个示例,我认为这不是一个好的解决方案,但它是一个解决方案) 使用

set_fact
创建列表,然后将此列表传递到另一个 playbook。
使用我现有的例子:

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 }}"



1
投票

阅读文档后,我找到了实现此目的的方法。

正确的方法是使用 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
这样我就能够以 disk.lun 和 disk.mountpoint 的形式获取 lun 和挂载点。 注意:在使用 include_tasks 选项时,您需要在每个任务中单独传递标签关键字(如果您正在使用一个任务)。


0
投票

这里的一切都很棒。我添加了一些东西来使

parted
幂等,但很难将其脱离上下文发布,所以...这是我使用 OP 的脚本和 @shubham-jairath 的出色循环组合在一起的完整解决方案:

文件:plays/mountdisk.yml

---
# https://stackoverflow.com/questions/63100027/how-to-mount-multiple-disks-in-a-loop-using-ansible

- name: get volume name
  shell: echo "/dev/$(ls -l /dev/disk/azure/scsi1 | grep {{ item.lun }} | egrep -o "([^\/]+$)")"
  register: volumename

- name: get partition (if any)
  shell: blkid | grep "{{ volumename.stdout }}" || true
  register: partition

- meta: end_play
  when: partition.stdout != ""

- 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

文件:play/mountmyvmdisk.yml

---
- hosts: Mycoolhosts
  gather_facts: true
  become: true

  vars:
    disksToMount:
      - lun: "lun0"
        mountpoint: "/mnt/mycooldisk"

  tasks:
    - include_tasks: "mountdisk.yml"
      loop: "{{ disksToMount }}"
© www.soinside.com 2019 - 2024. All rights reserved.