こんにちは、キクです。
最近になって少しずつAnsibleを利用することにも慣れてきました。
先日、大量のサーバを対象にDNS設定を変更する案件がありました。
そこで「Ansibleで自動化できないか?」と思い立ち、「これはいい練習になりそう!」と思ったのでチャレンジしました。
本記事では、Ansibleで大量のサーバにDNS設定変更処理を実施した方法をご紹介します。
と言っても非常にシンプルなのでサクッと行きましょう!
それでは、よろしくお願いします。
背景
まず、今回の作業の概要と背景について簡単に触れておきます。
現在利用しているDNSサーバの稼働環境が丸ごとなくなるというのがそもそもの背景でした。
そのため、新しい環境にDNSサーバを構築し、旧DNSサーバを利用する設定になっているサーバ群に対して「新DNSサーバを使いなさい」という設定を行う必要がありました。
台数にして60台以上のサーバが対象となるため「手動ではやってられん!」と思い、Ansibleでの自動化に踏み切りました。
なお、今回の作業対象は本番稼働中のサーバではあるものの、万が一名前解決ができなくなったとしてもクリティカルな影響が出るサーバではありませんでした。
そのため、比較的ラフに作業を実施しましたが、名前解決がシビアなシステムにおいてはもう少し丁寧に作業をしてもいいかもしれないといった内容になっています。
作業1. インベントリファイルの作成
対象ホストへの接続で利用するインベントリファイルを作成していきます。
各サーバはいくつかのグループに分類されるため、それを考慮してインベントリファイルを記載していきます。
$ vi inventory/hosts
[groupA]
192.168.1.1
192.168.1.2
・・・
192.168.1.20
[groupB]
192.168.1.21
192.168.1.22
・・・
192.168.1.40
[groupC]
192.168.1.41
192.168.1.42
・・・
192.168.1.60
作業2. Playbookの作成
続いて、本体となるPlaybookを作成していきます。
今回は複雑な作業も特にないので、ひとつのplaybookに直書きしちゃいます。
構成としては以下3ステップになります。
- 既存resolv.confのバックアップ
- resolv.confの修正
- 名前解決テスト
$ vi playbook.yml
- name: Manage resolv.conf
hosts: all
become: true
tasks:
- name: Create a custom backup of resolv.conf
command: cp /etc/resolv.conf /etc/resolv.conf.ansible_bak
- name: Replace nameserver in resolv.conf
lineinfile:
path: /etc/resolv.conf
regexp: '^.*\\bnameserver\\b.*192\\.168\\.2\\.53.*$'
line: 'nameserver 192.168.3.53'
state: present
backup: no
- name: Verify DNS resolution with ping
shell: ping -c 3 www.test.co.jp
register: ping_result
failed_when: ping_result.rc != 0
ignore_errors: true
changed_when: false
ポイント①
新しい設定を記載したresolv.confを作成して既存ファイルと差し替えるという案もありましたが、全サーバで既存ファイルが同じ内容か不明でした。
もし一部サーバで特殊な設定が含まれていた場合、共通で差し替えてしまうと厄介なことになりそうだと考えました。
そのため、テキストファイルを行単位で編集できる「lineinfileモジュール」なるものを利用して対応しました。
ポイント②
処理の最後には「名前解決テスト」を実施するようにしました。
Ansibleのフローで「Replace nameserver in resolv.conf」のステータスがOKであれば変更自体はできているものと思いますが、「本当に名前解決できるよね?」の確認を込めて追加しています。
ちなみに、作業対象サーバにdigコマンドが入っていなかったのでpingでの確認としました。
備忘
ignore_errors: true
名前解決が失敗した場合でも後続処理は流したかった
changed_when: false
shellモジュールを使用すると、コマンドの実行そのものを「変更(changed)」として扱ってしまうようで、それだとpingがどうだったのか判断がしづらかったです。
そのため、本設定を入れることで「OK」または「FAILED」の表示になるようにしました。
作業3. Playbookの実行
各グループ毎にPlaybookを実行してDNS設定を変更していきます。
$ ansible-playbook -u testuser playbook.yml -i inventory/hosts -l groupA -K -k --diff
$ ansible-playbook -u testuser playbook.yml -i inventory/hosts -l groupB -K -k --diff
$ ansible-playbook -u testuser playbook.yml -i inventory/hosts -l groupC -K -k --diff
以下は実行例になります。
$ ansible-playbook -u testuser playbook.yml -i inventory/hosts -l groupA -K -k --diff
SSH password:
BECOME password[defaults to SSH password]:
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details
PLAY [Manage resolv.conf] **********************************************************************
TASK [Gathering Facts] *************************************************************************
ok: [192.168.1.1]
ok: [192.168.1.2]
~中略~
ok: [192.168.1.20]
TASK [Create a custom backup of resolv.conf] ***************************************************
changed: [192.168.1.1]
changed: [192.168.1.2]
~中略~
changed: [192.168.1.20]
TASK [Replace nameserver in resolv.conf] *******************************************************
+++ after: /etc/resolv.conf (content)
@@ -1,2 +1,2 @@
# Generated by NetworkManager
-nameserver 192.168.2.53
+nameserver 192.168.3.53
changed: [192.168.1.1]
--- before: /etc/resolv.conf (content)
+++ after: /etc/resolv.conf (content)
@@ -1,2 +1,2 @@
# Generated by NetworkManager
-nameserver 192.168.2.53
+nameserver 192.168.3.53
changed: [192.168.1.2]
~中略~
--- before: /etc/resolv.conf (content)
+++ after: /etc/resolv.conf (content)
@@ -1,2 +1,2 @@
# Generated by NetworkManager
-nameserver 192.168.2.53
+nameserver 192.168.3.53
changed: [192.168.1.20]
TASK [Verify DNS resolution with ping] *********************************************************
ok: [192.168.1.1]
ok: [192.168.1.2]
~中略~
ok: [192.168.1.20]
PLAY RECAP *******************************************************************************************************
192.168.1.1 : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.1.2 : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
~中略~
192.168.1.20 : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
内容の確認
TASK [Create a custom backup of resolv.conf] ***************************************************
changed: [192.168.1.1]
changed: [192.168.1.2]
~中略~
changed: [192.168.1.20]
作業前のバックアップ取得が正常に行われました。
TASK [Replace nameserver in resolv.conf] *******************************************************
--- before: /etc/resolv.conf (content)
+++ after: /etc/resolv.conf (content)
@@ -1,2 +1,2 @@
# Generated by NetworkManager
-nameserver 192.168.2.53
+nameserver 192.168.3.53
changed: [192.168.1.1]
--- before: /etc/resolv.conf (content)
+++ after: /etc/resolv.conf (content)
@@ -1,2 +1,2 @@
# Generated by NetworkManager
-nameserver 192.168.2.53
+nameserver 192.168.3.53
changed: [192.168.1.2]
~中略~
--- before: /etc/resolv.conf (content)
+++ after: /etc/resolv.conf (content)
@@ -1,2 +1,2 @@
# Generated by NetworkManager
-nameserver 192.168.2.53
+nameserver 192.168.3.53
changed: [192.168.1.20]
正規表現にマッチした既存の「nameserver 192.168.2.53」から新たに「nameserver 192.168.3.53」に差し替えているのが分かります。
TASK [Verify DNS resolution with ping] *********************************************************
ok: [192.168.1.1]
ok: [192.168.1.2]
~中略~
ok: [192.168.1.20]
作業後のpingによるドメイン指定での疎通確認も全台「ok」となっており、問題なく名前解決ができていることが確認できました。
すべての処理が想定通りに動いていたので、今回の作業は無事完了しました。
まとめ
今回はDNSサーバの切り替えに伴うresolv.confファイルの修正をAnsibleで大量のサーバに一気にやってしまおうという内容でした。
改めて、今回は以下の内容を実施しました。
まだまだAnsible初心者ではありますが、今後も少しずつ活用の幅を広げて知見を深めていきと思います!
本記事を最後まで読んでいただき、ありがとうございました。
ではでは!