LoginSignup
12
15

More than 5 years have passed since last update.

AnsibleでIPアドレスを変更した後も処理を継続する

Posted at

一見これで良さそうだが

Ansibleで対象ホストのIPアドレスを変更して、さらに処理が継続されるようなplaybookを考えてみる。
Ansible v2で操作対象がCentOS 7だと以下のような感じになる。

- hosts: all
  tasks:
  - (前処理)
  - command: nmcli connection modify {{ nic }} ipv4.method manual ipv4.addresses {{ new_addr }}/{{ prefix }} ipv4.gateway {{ gateway }} ipv4.dns {{ dns }}
  - shell: sleep 1; ifdown {{ nic }} && ifup {{ nic }}
    async: -1
    poll: 0
  - block:
    - lineinfile: dest=/etc/hosts backrefs=yes regexp='^\S+( .*{{ inventory_hostname | regex_escape }}.*)$' line='{{ new_addr }}\1'
    - wait_for: host={{ new_addr }} port=22 delay=1 timeout=50
    delegate_to: localhost
  - (後続処理)

ここではAnsible実行側の/etc/hostsを使っている。処理対象のIPアドレス変更後に/etc/hostsも変更して、継続して処理ができるようしたわけだ。
.ssh/configなどを使っても同様のことができるだろう。

実際には

しかし一見上手く行きそうなこの方法だが、実際には大抵の環境で上手く行かない。

それは何故か。
AnsibleはSSH接続を行う時、標準設定だとControlMasterを使用している。ControlPersist=60sなので1分の間は接続先を覚えている。
従って如何に/etc/hostsなどを変更したとしても接続しに行く先はなお変更前のまま、というわけだ。

それではどうすれば良いか。
一例として接続元の残っているSSHプロセスをkillしてやるのが良い。
Ansibleの使っているControlPathは$HOME/.ansible/cp/ansible-ssh-%h-%p-%r(%h,%p,%rはそれぞれ対象ホスト、対象ポート、対象ユーザ)なので以下のようにすれば良いだろう。
このやり方だとAnsible実行側で同じユーザが2つ以上Ansibleを実行していると良くないことが起こりそうだが、それはないこととしておく。

- hosts: all
  tasks:
  - (前処理)
  - command: nmcli connection modify {{ nic }} ipv4.method manual ipv4.addresses {{ new_addr }}/{{ prefix }} ipv4.gateway {{ gateway }} ipv4.dns {{ dns }}
  - shell: sleep 1; ifdown {{ nic }} && ifup {{ nic }}
    async: -1
    poll: 0
  - block:
    - command: pkill -f {{ lookup('pipe', 'echo $HOME') }}/.ansible/cp/ansible-ssh-
      ignore_errors: yes
      run_once: yes
    - lineinfile: dest=/etc/hosts backrefs=yes regexp='^\S+( .*{{ inventory_hostname | regex_escape }}.*)$' line='{{ new_addr }}\1'
    - wait_for: host={{ new_addr }} port=22 delay=1 timeout=50
    delegate_to: localhost
  - (後続処理)

なお、pkillのところは実害はあまりないがshellモジュールではエラーになったのでcommandモジュールを使っている。(理由を調べてはいない)

おまけ:nmcliモジュールなどここまで辿り着くまでの色々

この文章を書くのにnmcliモジュールを使おうとしたらipv4.methodを変更する方法がなくdhcpからautoにできなかったので没。

nmcliモジュールが使えるようになるまでも一苦労だったし。試行錯誤の結果、操作される側でyumで(インストールされていなければ)NetworkManager-glib, dbus-python, pygobject2をインストールし、pipでpython-nmcliをインストールするのが一番楽っぽい。

最初Fedora 23でやろうとしたらPython 3が標準になったせいでdnfモジュールすら動かないし。python2-dnfをインストールする必要があるのだが、dnfモジュールが使えないのでrawモジュールを使わなければならない。
なお、Fedora 23だと上記のnmcliモジュールに必要なpygobject2はpython-gobjectという名前に変わっている。

12
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
15