zaki work log

作業ログやら生活ログやらなんやら

[Ansible] CentOSのswap無効化を行う (check_mode / changed_when / ignore_errors)

Kubernetesのシステム要件に「swapがオフであること」というのがあるので、Ansibleつかってノードの準備を行う際に「swapが有効の場合には無効にする」というのを冪等になるようにやってみた。

対象はCentOS 7

taskの例

Ansibleモジュールに「swapのon/off」というのが見つからなかったので、手作業で無効にするときの操作をそのままPlaybookにしてみました。
だいたいこんな感じ

    - name: get swap state
      shell: swapon -v
      register: swap_state
      check_mode: false
      changed_when: false

    - name: swap off
      shell: swapoff -a
      when: swap_state.stdout != ''

    - name: swap check (/etc/fstab)
      shell: grep -v "\s*#" /etc/fstab | awk '{print $2}' | grep swap -c
      register: swap_state_in_fstab
      check_mode: false
      changed_when: false
      ignore_errors: true

    - name: disable swap (/etc/fstab)
      replace:
        path: /etc/fstab
        regexp: ([^\s]+\s+swap\s+.*)
        replace: '# \1'
      when: swap_state_in_fstab.stdout != '0'

やっていることは以下の通り

現在のswap設定

swapが有効化かチェック

      shell: swapon -v
      register: swap_state
      check_mode: false
      changed_when: false

swapが現在有効になっているかどうかはswapon -vの結果で判断できます。
有効になっていればどのデバイスがswapに使用されているかが出力されますが、無効の場合は何も出力されません。

swapが有効な場合

[zaki@manager-dev ~]$ swapon -v
NAME      TYPE      SIZE USED PRIO
/dev/dm-1 partition 3.5G   0B   -2
[zaki@manager-dev ~]$ echo $?
0

swapが無効な場合

[zaki@manager-dev ~]$ swapon -v
[zaki@manager-dev ~]$ echo $?
0
[zaki@manager-dev ~]$ 

なのでここでは、swapon -vを実行するだけで、その結果をregisterを使ってswap_stateに保持します。
また、ここは状態をチェックするだけで何も変更を加えないので、changed_when: falseによってchangedとならないようにしています。
加えて、--checkの場合はshellはデフォルトで動作しないため、check_mode: falseで強制的に実行させます。

swapを無効化

      shell: swapoff -a
      when: swap_state.stdout != ''

swapを無効化するにはswapoff -aを実行します。
すでに無効化されてる状態で追加で実行してもまぁ問題はないのですが、せっかくAnsibleを使ってるので「有効だったら無効化する(changed)」「既に無効になっていれば何もしない(ok)」と冪等になるように、前段のswapが有効だった場合のみ実行するようにwhenを使って「swapが有効だった場合(swap_state.stdout != '')」とします。

fstabの編集

上記の処理で現在のswap状態は無効となりますが、/etc/fstabにswapのディスク設定が残っていると、OSリブート後にまた有効になってしまうので、設定を削除します。

ここでもswapoff同様に、設定があれば無効化(なければ何もしない)という処理にしてみます。

fstabにswap設定があるかチェック

      shell: grep -v "\s*#" /etc/fstab | awk '{print $2}' | grep swap -c
      register: swap_state_in_fstab
      check_mode: false
      changed_when: false
      ignore_errors: true

チェック処理自体はLinuxコマンドのgrepawkで原始的に。
後の処理をやりやすいよう、-cオプションを付けてカウント数を取得し、結果をregisterswap_state_in_fstabにセット。

前述のswapon -vと同様に--checkでも動作するようにcheck_mode: falseと、結果がchnagedとならないようにchanged_when: falseを付与。
また、Linuxgrepコマンドは、ヒットしない場合はリターンコードが1となるため、swap設定が無い場合はAnsibleの処理的にはエラーとなってしまうため、ignore_errors: trueによって強制的にエラーを無視するようにしています。

fstabのswap設定をコメントアウト

      replace:
        path: /etc/fstab
        regexp: ([^\s]+\s+swap\s+.*)
        replace: '# \1'
      when: swap_state_in_fstab.stdout != '0'

ここではAnsibleのreplaceモジュールを使って、/etc/fstabファイルのswap設定の行(設定行の2カラム目がswapの行)の先頭に#を入れる、というtaskを記述。
これは正規表現を使ってふつうに。

普通と言いつつ、「ヒットしたswap設定行をキャプチャ、置換先の文字列はキャプチャした文字列の先頭に#を付加する」だと、繰り返し実行するとどんどん#が付加され続けて冪等にならないので、前段の/etc/fstabにswap行がある場合、にwhenを使い条件を絞ってます。

対象行の削除でもいいけどね。


参考

  • check_mode

docs.ansible.com

qiita.com

qiita.com

dev.classmethod.jp

  • ignore_errors

docs.ansible.com

  • changed_when

docs.ansible.com

qiita.com


たぶんもっといい書き方ありそう…
なんだけど、手作業の手順をAnsible化しつつ冪等性を考慮する、という題材にはちょうどよいかも。