AnsibleでLinuxサーバのSolidfire iSCSIボリューム マウント 自動化
インフラ構築・運用のフェーズで、繰り返し・定期的に実施する作業、対象サーバ数・ボリューム数が多数ある作業は、自動化をしておくと何かと便利かと思います。 今回は Ansibleのmoduleを利用して、Linuxサーバから Solidfire の iSCSIボリューム をマウントするためのLinuxサーバ上での作業をAnsibleで自動化してみたものを紹介します。
なお、 Ansible管理サーバは構築済みで、Storage側のiSCSIボリュームも作成・設定が完了済みの前提です。
Ansible導入・SolidFire ボリューム作成についてはAnsibleを利用したiSCSIボリューム作成の記事で触れているので、よろしければそちらもどうぞ。なお、「Ansibleを利用したiSCSIボリューム作成」の記事ではCHAP認証ではなくVAG認証方式を利用しています。ご注意ください。
前提
以下の環境で試しています
- Cent 7.7
- Solidfire 12.2
- Ansible 2.10
- Python 3.6.8
- solidfire-sdk-python 1.7.0.152
なお、この記事で書かれている 手順やPlayBookは動作を保証されたものではありません。
各環境に合わせてテスト・確認をしたうえで自己責任にて利用していただければと思います。
作業の流れ
- Ansible Collection & Package追加
- ディレクトリ構成準備
- インベントリファイル作成
- Playbookファイル作成
- Playbook実行
1. Ansible Collection & Package追加
Ansible 2.10からは、モジュールがCollectionで管理されるようになり、Ansible-baseと一緒に導入されるモジュール以外は必要に応じて明示的に追加する必要があります。
今回利用するモジュール用のCollectionをansible-galaxyコマンドで追加します。
また、今回は、ansible実行時の管理対象サーバへのsshアクセスはパスワード認証を利用するので、
必要なパッケージをyumで導入します。
$ ansible-galaxy collection install community.general
$ ansible-galaxy collection install ansible.posix
$ sudo yum install -y sshpass
- 出力は省略:必要に応じて "y" を入力 -
なお、NetAppモジュールのCollectionのリリースは、こちらで簡単に紹介されているので 興味ある方は確認してみてください。
2. ディレクトリ構成準備
ansibleの各種ファイルを配置するディレクトリを準備します。
~/ansible-lin
├─ hosts
| └─ hosts
├─ tasks
| └─ main.yaml
└─ vars
├─ sf-common.yaml
└─ chap-auth.yaml
$ mkdir -p ~/ansible-lin/hosts ~/ansible-lin/tasks ~/ansible-lin/vars
3. インベントリファイル作成
~/hosts/ディレクトリは配下にインベントリファイルを作成し、iSCSiボリュームマウント処理を行う対象サーバを登録します。
iscsi_clientというグループに、client01 , client02の2台のサーバを所属させます。
[iscsi_client]
client01 ansible_host=<< client01のIPアドレス >>
client02 ansible_host=<< client02のIPアドレス >>
[iscsi_client:vars]
ansible_ssh_port=22
ansible_ssh_user=<< sshユーザ >>
ansible_ssh_pass=<< sshユーザ パスワード >>
ansible_ssh_common_args='-o StrictHostKeyChecking=no'
4. Playbookファイル作成
次にPlaybookファイルを作成します。
利用するパラメータ値は以下となります。
パラメータ名 | 値 | 備考 |
---|---|---|
VG名 | vgnX | |
LV名 | lvnX | |
マウントポイント | /iscmntX |
※ Xは連番数字
パラメータファイルの準備
~/ansible/varsディレクトリ配下に、sf-common,yaml ,chap-authyaml の2つのパラメータファイルを作成します。
cluster_svip : "<< Solidfire Storage VIP >>"
chap_ps : << CHAP Initiator Secret >>
chap_ps_in : << CHAP Target Secret >>
Playbookファイルの準備
次に、~/ansible/tasksディレクトリ配下に main.yamlファイルを準備します。
以下の流れで設定をおこなうプレイブックになっています。
- iSCSIパッケージ導入
- /etc/iscsi.confファイル編集
- iSCSIボリューム検出&ログインしてデバイスとして認識
- iSCSIボリュームマウント
なお、このプレイブックの記述では、対象サーバが、"/dev/sda"デバイスをシステム領域用ディスクとして利用している前提で、"/dev/sda"デバイス以外は、ディスクを認識しておらず接続もされていない想定での記述となっています。
追加するiSCSIボリュームは/dev/sdb以降のデバイスとして認識される想定です。
認識したデバイスはLVMボリュームとして自動的にマウント・/etc/fstab登録まで実行されます。
---
- name: iscsi mount
hosts: iscsi_client
gather_facts: no
vars:
vgname : vgn
lvname : lvn
mntname : iscmnt
vars_files:
- ../vars/chap-auth.yaml
- ../vars/sf-common.yaml
tasks:
- name: yum install iscsi-initiator-utils
yum:
name: "{{ packages }}"
state: latest
update_cache: yes
vars:
packages:
- iscsi-initiator-utils
register: iscsi
### Setting iscsid.conf Phase
- name: set iscsid.conf file
blockinfile:
path: /etc/iscsi/iscsid.conf
block: |
node.session.auth.authmethod = CHAP
node.session.auth.username = {{ inventory_hostname }}
node.session.auth.password = {{ chap_ps }}
node.session.auth.username_in = {{ inventory_hostname }}
node.session.auth.password_in = {{ chap_ps_in }}
discovery.sendtargets.auth.authmethod = CHAP
discovery.sendtargets.auth.username = {{ inventory_hostname }}
discovery.sendtargets.auth.password = {{ chap_ps }}
discovery.sendtargets.auth.username_in = {{ inventory_hostname }}
discovery.sendtargets.auth.password_in = {{ chap_ps_in }}
register: iscsid_conf
- name: start iscsid
systemd:
name : iscsid.service
state: restarted
enabled: yes
### iSCSI discovery & connect Phase
- name: iscsi target discovery
community.general.open_iscsi:
show_nodes: yes
discover : yes
portal : '{{ cluster_svip }}'
register: iscsi_target
- name: iscsi targets connect
open_iscsi:
target: "{{ item }}"
login: yes
with_items: "{{ iscsi_target.nodes }}"
when: iscsi_target.changed
### iSCSI Mount Phase
- name: find all iscsi devices
find:
paths: /dev
file_type: any
patterns: "^sd[b-z]$"
use_regex: yes
register: found_devices
- name: create volume group
lvg:
vg : "{{ vgname }}{{ item.0 }}"
pvs: "{{ item.1.path }}"
with_indexed_items: '{{ found_devices.files }}'
- name: create logical volume
lvol:
vg : "{{ vgname }}{{ item.0 }}"
lv : "{{ lvname }}{{ item.0 }}"
size: +100%FREE
shrink: no
with_indexed_items: '{{ found_devices.files }}'
- name: make filesystem
filesystem:
fstype: xfs
dev: /dev/mapper/{{ vgname }}{{ item.0 }}-{{ lvname }}{{ item.0 }}
with_indexed_items: '{{ found_devices.files }}'
- name: mount disk
mount:
path: /{{ mntname }}{{ item.0 }}
src: /dev/{{ vgname }}{{ item.0 }}/{{ lvname }}{{ item.0 }}
fstype: xfs
opts: _netdev
state: mounted
with_indexed_items: '{{ found_devices.files }}'
5. Playbook実行
プレイブックを実行してみます。
実行時は"-i"オプションで明示的に利用するインベントリファイルを指定しています。
$ cd ~/ansible-lin/tasks
$ ansible-playbook -i ../hosts/hosts main.yaml
PLAY [iscsi mount] *****************************************************************************************************
TASK [yum install iscsi-initiator-utils] *******************************************************************************
changed: [client01]
changed: [client02]
TASK [set iscsid.conf file] ********************************************************************************************
changed: [client02]
changed: [client01]
TASK [start iscsid] ****************************************************************************************************
changed: [client02]
changed: [client01]
TASK [iscsi target discovery] ******************************************************************************************
changed: [client02]
changed: [client01]
TASK [iscsi targets connect] *******************************************************************************************
changed: [client01] => (item=iqn.2010-01.com.solidfire:wwnr.sfvol101.643)
changed: [client02] => (item=iqn.2010-01.com.solidfire:wwnr.sfvol201.645)
changed: [client02] => (item=iqn.2010-01.com.solidfire:wwnr.sfvol202.646)
changed: [client01] => (item=iqn.2010-01.com.solidfire:wwnr.sfvol102.644)
TASK [find all iscsi devices] ******************************************************************************************
ok: [client02]
ok: [client01]
TASK [create volume group] *********************************************************************************************
changed: [client02] => (item=[0, {'uid': 0, 'woth': False, 'mtime': 1614744046.6572943, 'inode': 24227, 'isgid': False, 'size': 0, 'roth': False, 'isuid': False, 'isreg': False, 'pw_name': 'root', 'gid': 6, 'ischr': False, 'wusr': True, 'xoth': False, 'rusr': True, 'nlink': 1, 'issock': False, 'rgrp': True, 'gr_name': 'disk', 'path': '/dev/sdc', 'xusr': False, 'atime': 1614744046.6572943, 'isdir': False, 'ctime': 1614744046.6572943, 'isblk': True, 'xgrp': False, 'dev': 5, 'wgrp': True, 'isfifo': False, 'mode': '0660', 'islnk': False}])
changed: [client01] => (item=[0, {'uid': 0, 'woth': False, 'mtime': 1614744046.6707006, 'inode': 28111, 'isgid': False, 'size': 0, 'roth': False, 'isuid': False, 'isreg': False, 'pw_name': 'root', 'gid': 6, 'ischr': False, 'wusr': True, 'xoth': False, 'rusr': True, 'nlink': 1, 'issock': False, 'rgrp': True, 'gr_name': 'disk', 'path': '/dev/sdc', 'xusr': False, 'atime': 1614744046.6707006, 'isdir': False, 'ctime': 1614744046.6707006, 'isblk': True, 'xgrp': False, 'dev': 5, 'wgrp': True, 'isfifo': False, 'mode': '0660', 'islnk': False}])
changed: [client02] => (item=[1, {'uid': 0, 'woth': False, 'mtime': 1614744045.3072782, 'inode': 24955, 'isgid': False, 'size': 0, 'roth': False, 'isuid': False, 'isreg': False, 'pw_name': 'root', 'gid': 6, 'ischr': False, 'wusr': True, 'xoth': False, 'rusr': True, 'nlink': 1, 'issock': False, 'rgrp': True, 'gr_name': 'disk', 'path': '/dev/sdb', 'xusr': False, 'atime': 1614744045.3072782, 'isdir': False, 'ctime': 1614744045.3072782, 'isblk': True, 'xgrp': False, 'dev': 5, 'wgrp': True, 'isfifo': False, 'mode': '0660', 'islnk': False}])
changed: [client01] => (item=[1, {'uid': 0, 'woth': False, 'mtime': 1614744045.2946823, 'inode': 28000, 'isgid': False, 'size': 0, 'roth': False, 'isuid': False, 'isreg': False, 'pw_name': 'root', 'gid': 6, 'ischr': False, 'wusr': True, 'xoth': False, 'rusr': True, 'nlink': 1, 'issock': False, 'rgrp': True, 'gr_name': 'disk', 'path': '/dev/sdb', 'xusr': False, 'atime': 1614744045.2946823, 'isdir': False, 'ctime': 1614744045.2946823, 'isblk': True, 'xgrp': False, 'dev': 5, 'wgrp': True, 'isfifo': False, 'mode': '0660', 'islnk': False}])
TASK [create logical volume] *******************************************************************************************
changed: [client02] => (item=[0, {'uid': 0, 'woth': False, 'mtime': 1614744046.6572943, 'inode': 24227, 'isgid': False, 'size': 0, 'roth': False, 'isuid': False, 'isreg': False, 'pw_name': 'root', 'gid': 6, 'ischr': False, 'wusr': True, 'xoth': False, 'rusr': True, 'nlink': 1, 'issock': False, 'rgrp': True, 'gr_name': 'disk', 'path': '/dev/sdc', 'xusr': False, 'atime': 1614744046.6572943, 'isdir': False, 'ctime': 1614744046.6572943, 'isblk': True, 'xgrp': False, 'dev': 5, 'wgrp': True, 'isfifo': False, 'mode': '0660', 'islnk': False}])
changed: [client01] => (item=[0, {'uid': 0, 'woth': False, 'mtime': 1614744046.6707006, 'inode': 28111, 'isgid': False, 'size': 0, 'roth': False, 'isuid': False, 'isreg': False, 'pw_name': 'root', 'gid': 6, 'ischr': False, 'wusr': True, 'xoth': False, 'rusr': True, 'nlink': 1, 'issock': False, 'rgrp': True, 'gr_name': 'disk', 'path': '/dev/sdc', 'xusr': False, 'atime': 1614744046.6707006, 'isdir': False, 'ctime': 1614744046.6707006, 'isblk': True, 'xgrp': False, 'dev': 5, 'wgrp': True, 'isfifo': False, 'mode': '0660', 'islnk': False}])
changed: [client02] => (item=[1, {'uid': 0, 'woth': False, 'mtime': 1614744045.3072782, 'inode': 24955, 'isgid': False, 'size': 0, 'roth': False, 'isuid': False, 'isreg': False, 'pw_name': 'root', 'gid': 6, 'ischr': False, 'wusr': True, 'xoth': False, 'rusr': True, 'nlink': 1, 'issock': False, 'rgrp': True, 'gr_name': 'disk', 'path': '/dev/sdb', 'xusr': False, 'atime': 1614744045.3072782, 'isdir': False, 'ctime': 1614744045.3072782, 'isblk': True, 'xgrp': False, 'dev': 5, 'wgrp': True, 'isfifo': False, 'mode': '0660', 'islnk': False}])
changed: [client01] => (item=[1, {'uid': 0, 'woth': False, 'mtime': 1614744045.2946823, 'inode': 28000, 'isgid': False, 'size': 0, 'roth': False, 'isuid': False, 'isreg': False, 'pw_name': 'root', 'gid': 6, 'ischr': False, 'wusr': True, 'xoth': False, 'rusr': True, 'nlink': 1, 'issock': False, 'rgrp': True, 'gr_name': 'disk', 'path': '/dev/sdb', 'xusr': False, 'atime': 1614744045.2946823, 'isdir': False, 'ctime': 1614744045.2946823, 'isblk': True, 'xgrp': False, 'dev': 5, 'wgrp': True, 'isfifo': False, 'mode': '0660', 'islnk': False}])
TASK [make filesystem] *************************************************************************************************
changed: [client01] => (item=[0, {'uid': 0, 'woth': False, 'mtime': 1614744046.6707006, 'inode': 28111, 'isgid': False, 'size': 0, 'roth': False, 'isuid': False, 'isreg': False, 'pw_name': 'root', 'gid': 6, 'ischr': False, 'wusr': True, 'xoth': False, 'rusr': True, 'nlink': 1, 'issock': False, 'rgrp': True, 'gr_name': 'disk', 'path': '/dev/sdc', 'xusr': False, 'atime': 1614744046.6707006, 'isdir': False, 'ctime': 1614744046.6707006, 'isblk': True, 'xgrp': False, 'dev': 5, 'wgrp': True, 'isfifo': False, 'mode': '0660', 'islnk': False}])
changed: [client02] => (item=[0, {'uid': 0, 'woth': False, 'mtime': 1614744046.6572943, 'inode': 24227, 'isgid': False, 'size': 0, 'roth': False, 'isuid': False, 'isreg': False, 'pw_name': 'root', 'gid': 6, 'ischr': False, 'wusr': True, 'xoth': False, 'rusr': True, 'nlink': 1, 'issock': False, 'rgrp': True, 'gr_name': 'disk', 'path': '/dev/sdc', 'xusr': False, 'atime': 1614744046.6572943, 'isdir': False, 'ctime': 1614744046.6572943, 'isblk': True, 'xgrp': False, 'dev': 5, 'wgrp': True, 'isfifo': False, 'mode': '0660', 'islnk': False}])
changed: [client01] => (item=[1, {'uid': 0, 'woth': False, 'mtime': 1614744045.2946823, 'inode': 28000, 'isgid': False, 'size': 0, 'roth': False, 'isuid': False, 'isreg': False, 'pw_name': 'root', 'gid': 6, 'ischr': False, 'wusr': True, 'xoth': False, 'rusr': True, 'nlink': 1, 'issock': False, 'rgrp': True, 'gr_name': 'disk', 'path': '/dev/sdb', 'xusr': False, 'atime': 1614744045.2946823, 'isdir': False, 'ctime': 1614744045.2946823, 'isblk': True, 'xgrp': False, 'dev': 5, 'wgrp': True, 'isfifo': False, 'mode': '0660', 'islnk': False}])
changed: [client02] => (item=[1, {'uid': 0, 'woth': False, 'mtime': 1614744045.3072782, 'inode': 24955, 'isgid': False, 'size': 0, 'roth': False, 'isuid': False, 'isreg': False, 'pw_name': 'root', 'gid': 6, 'ischr': False, 'wusr': True, 'xoth': False, 'rusr': True, 'nlink': 1, 'issock': False, 'rgrp': True, 'gr_name': 'disk', 'path': '/dev/sdb', 'xusr': False, 'atime': 1614744045.3072782, 'isdir': False, 'ctime': 1614744045.3072782, 'isblk': True, 'xgrp': False, 'dev': 5, 'wgrp': True, 'isfifo': False, 'mode': '0660', 'islnk': False}])
TASK [mount disk] ******************************************************************************************************
changed: [client01] => (item=[0, {'uid': 0, 'woth': False, 'mtime': 1614744046.6707006, 'inode': 28111, 'isgid': False, 'size': 0, 'roth': False, 'isuid': False, 'isreg': False, 'pw_name': 'root', 'gid': 6, 'ischr': False, 'wusr': True, 'xoth': False, 'rusr': True, 'nlink': 1, 'issock': False, 'rgrp': True, 'gr_name': 'disk', 'path': '/dev/sdc', 'xusr': False, 'atime': 1614744046.6707006, 'isdir': False, 'ctime': 1614744046.6707006, 'isblk': True, 'xgrp': False, 'dev': 5, 'wgrp': True, 'isfifo': False, 'mode': '0660', 'islnk': False}])
changed: [client02] => (item=[0, {'uid': 0, 'woth': False, 'mtime': 1614744046.6572943, 'inode': 24227, 'isgid': False, 'size': 0, 'roth': False, 'isuid': False, 'isreg': False, 'pw_name': 'root', 'gid': 6, 'ischr': False, 'wusr': True, 'xoth': False, 'rusr': True, 'nlink': 1, 'issock': False, 'rgrp': True, 'gr_name': 'disk', 'path': '/dev/sdc', 'xusr': False, 'atime': 1614744046.6572943, 'isdir': False, 'ctime': 1614744046.6572943, 'isblk': True, 'xgrp': False, 'dev': 5, 'wgrp': True, 'isfifo': False, 'mode': '0660', 'islnk': False}])
changed: [client01] => (item=[1, {'uid': 0, 'woth': False, 'mtime': 1614744045.2946823, 'inode': 28000, 'isgid': False, 'size': 0, 'roth': False, 'isuid': False, 'isreg': False, 'pw_name': 'root', 'gid': 6, 'ischr': False, 'wusr': True, 'xoth': False, 'rusr': True, 'nlink': 1, 'issock': False, 'rgrp': True, 'gr_name': 'disk', 'path': '/dev/sdb', 'xusr': False, 'atime': 1614744045.2946823, 'isdir': False, 'ctime': 1614744045.2946823, 'isblk': True, 'xgrp': False, 'dev': 5, 'wgrp': True, 'isfifo': False, 'mode': '0660', 'islnk': False}])
changed: [client02] => (item=[1, {'uid': 0, 'woth': False, 'mtime': 1614744045.3072782, 'inode': 24955, 'isgid': False, 'size': 0, 'roth': False, 'isuid': False, 'isreg': False, 'pw_name': 'root', 'gid': 6, 'ischr': False, 'wusr': True, 'xoth': False, 'rusr': True, 'nlink': 1, 'issock': False, 'rgrp': True, 'gr_name': 'disk', 'path': '/dev/sdb', 'xusr': False, 'atime': 1614744045.3072782, 'isdir': False, 'ctime': 1614744045.3072782, 'isblk': True, 'xgrp': False, 'dev': 5, 'wgrp': True, 'isfifo': False, 'mode': '0660', 'islnk': False}])
PLAY RECAP *************************************************************************************************************
client01 : ok=10 changed=9 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
client02 : ok=10 changed=9 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
$
これでclient01,02で、iSCSIボリュームがマウントされ、/etc/fstabに登録がされました。
client01,02にログインして、dfコマンド等でボリュームマウントしてみると
/iscmntXディレクトリとしてマウントされていることを確認できます。
まとめ
LinuxサーバでiSCSIボリュームをマウントする操作を自動化してみました。
今回はPlaybookファイルをあえて1ファイルで作成してみましたが、複数の処理要素を含んでいるのでファイル分割したり、Role化したりすることで利便性等があがるかと思います。また、インベントリファイルは、都度入力を省略するためにsshユーザ・パスワード等を記述しましたが、公開鍵認証方式にするとかAnsible Vault使うとか要件や環境に合わせて変更ができます。
そういった点は、実際に運用する際は考慮ポイントになって来るかと思います。