概要
本記事はAnsible Advent Calendar 2019の16日目の記事になります。
Ansibleを使うことを意識せずにセットアップされたLinuxマシンに対して、何をすればAnsible Readyになるかについて説明します。
Ansibleを使ったサーバーやネットワーク構築の情報は豊富だし、「この環境を使えばすぐにAnsible動かせます」という環境も割とあると思うのですが、「今あるこの手元(特にオンプレ)の環境でAnsibleを使い始めるにはどうすればよいか」についての情報が少ないと(私が個人的に)感じたので、その内容についてまとめました。
ですので本記事は「Ansibleを勉強し始めるにはどうすればよいか」ではなく「Ansibleを使ったサーバー構築を始めるときは何を準備すればいいか」という内容になっています。
- 「Ansibleを勉強したい!」という方はこちら: 【初心者歓迎】Ansible始めてみたい人はまずはAnsibleもくもく会に参加してみよう!
- すぐに検証できるAnsible環境がとりあえず手元に欲しい方はこちら: Ansible検証環境に特化したVagrantを使ったVM構築 - 複数VM・VM間ssh公開鍵認証設定・共有フォルダ
構成
CentOSを前提としています。
ホスト名 | IPアドレス | 役割 |
---|---|---|
control-node | 192.168.0.140 | コントロールノード |
target-node01 | 192.168.0.141 | ターゲットノード |
target-node02 | 192.168.0.142 | ターゲットノード |
Ansibleのコマンド(ansible
やansible-playbook
など)を実行するホストをコントロールノード、コントロールノードのAnsibleによって処理される対象のホストをターゲットノードと言います。
-
コントロールノードに必要なもの
- Ansible
- Python
-
ターゲットノードに必要なもの
- Python
- SSHサーバー
- sudoによるrootへの昇格
また本記事では、コントロールノード・ターゲットノードそれぞれ、作業用のユーザ名(非root)と認証用パスワードは全て同一である前提です。
インストールと設定
Ansible本体
CentOS7の場合、標準のYumリポジトリだとAnsible 2.4がインストールされますが、ちょっと古すぎます(2019.12時点で最新は2.9)
$ yum info ansible
:
:
利用可能なパッケージ
名前 : ansible
アーキテクチャー : noarch
バージョン : 2.4.2.0
リリース : 2.el7
容量 : 7.6 M
リポジトリー : extras/7/x86_64
要約 : SSH-based configuration management, deployment, and task
:
:
ですので、CentOS7の場合はEPELリポジトリにあるパッケージでインストールすると楽で良いです。
$ sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
$ sudo yum install ansible
これで最新安定板がインストールできるはずです。
バージョンを確認するにはansible --version
を実行します。
[zaki@control-node ~]$ ansible --version
ansible 2.9.1
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/home/zaki/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.5 (default, Aug 7 2019, 00:51:29) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]
[zaki@control-node ~]$
RHELやDebian/Ubuntuなどその他のプラットフォームの場合については、AnsibleのInstallation Guideに載っています。
また、pip
を使ってもインストールできます。
インストールができたら簡単な動作確認として、対象でAnsibleが実行できるかを確認するping
モジュールをlocalhost宛に実行してみます。
$ ansible localhost -m ping
localhost | SUCCESS => {
"changed": false,
"ping": "pong"
}
SUCCESS
と表示されればOKです。
※ ICMPを使ったLinuxのping
コマンドと異なり、疎通というよりはAnsibleが実行可能かどうかを確認します。また、localhost
の場合はSSH接続を要しません
Python
yum
などのパッケージマネージャでインストールできます…が、最近のよく使われるディストリビューションであればPythonは初めから入っているはずです。
また、Ansibleのインストール要件にPythonは必要とされるので、Ansibleがインストール済みであればPythonもインストール済みになっているはずです。
$ python --version
でPythonのバージョンが確認できます。
※ Python version2 は、2020年1月1日でサポートが終了します。
SSHアクセス
SSHサーバーもメジャーなディストリビューションであれば、OSインストール直後の状態で起動しているはずです。
Ansibleを使えるようにするには、コントロールノードからターゲットノードへSSHアクセスできる必要があります。(ターゲットノードにSSHサーバーが動いていること)
認証についてはパスワード認証・公開鍵認証どちらでも実行可能ですが、パスワード認証やパスフレーズ付き公開鍵認証の場合は実行のたびにパスワード/パスフレーズの入力が必要になるので、パスフレーズ無しの秘密鍵を設定すると構築の際は手間が無くて便利です。
$ ssh-keygen -t rsa -f $HOME/.ssh/id_rsa -N ""
これで~/.ssh/id_rsa
にパスフレーズ無しの公開鍵が作成されます。
キーペアを作成したら、各ターゲットノードへ公開鍵を配布します。
$ ssh-copy-id zaki@192.168.0.141 # ターゲットノード1
$ ssh-copy-id zaki@192.168.0.142 # ターゲットノード2
これで認証無しで各ターゲットノードへSSHアクセスできるはずです。
[zaki@control-node ~]$ ssh 192.168.0.141
[zaki@target-node01 ~]$
[zaki@control-node ~]$ ssh 192.168.0.142
[zaki@target-node02 ~]$
ここまで設定できれば、2台のターゲットノードに対してping
モジュールでアクセスできるはずです。
ターゲットノードを定義した以下の内容のインベントリファイルを作成。
[nodes]
192.168.0.141
192.168.0.142
このインベントリファイルを-i
で指定しansible
を実行。この時、ローカルを対象に実行した際にlocalhost
と指定したところを、インベントリの最初の行に書いた[nodes]
というグループ名を指定します。
$ ansible nodes -i inventory.ini -m ping
192.168.0.142 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.0.141 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
これでコントロールノードからターゲットノードに対してAnsibleが実行できることが確認できました。
パスフレーズ無しの公開鍵設定を行わない場合は、以下のようにすることでAnsibleは実行できます。
認証方式 | Ansibleの操作 |
---|---|
パスワード認証 |
-k を付与することでパスワード認証のプロンプトを表示する |
パスフレーズ付き公開鍵認証 | 自動でパスフレーズの入力プロンプトが表示される |
sudo設定
さらににもう1点。
Ansibleを使ってサーバー構築する場合、(yum
によるパッケージインストールなど)大抵の作業はroot権限が必要です。
ターゲットノードにおいてsudo
がそもそも使用不可能である場合は、対象ユーザに対して(wheel
グループに追加するなどの)sudoersの設定を行ってください。
また、sudo
実行時にパスワードが不要な設定にしておけば、Ansible実行時にもパスワード入力が必要なくなるため、手間が無くて便利です。
%wheel ALL=(ALL) NOPASSWD: ALL
※ vi
じゃなくてvisudo
を使いましょう
これは全ターゲットノードで実施します。(コントロールノードに対しても処理を行う場合はコントロールノードにも設定)
設定できたら-b
オプションを追加(デフォルトrootとして動作)してAnsibleを実行します。
$ ansible nodes -i inventory.ini -b -m ping
192.168.0.142 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.0.141 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
エラーにならなければ、ターゲットノード上ではroot権限で処理が実行されます。
といってもping
モジュールだとわかりづらいので、もし全ノードでyum update
してもよいのであれば、以下のコマンドを実行してみましょう。全てのパッケージが更新されます。
$ ansible nodes -i inventory.ini -b -m yum -a "name=* state=latest"
パスワード無しのsudo
設定を行わない場合は、実行時に-K
を付与することでroot権限でAnsibleは実行できます。
パスワード認証用の-k
と併用可能です。
初期構築のAnsibleによる自動化
ここまで手作業でAnsibleのインストールとSSH/sudoの設定について説明しましたが、せっかくAnsibleをインストールするのだから、じゃがいもに怒られないように自動化できるところは自動化しちゃいましょう。
特に全てのターゲットノードに対して、SSH公開鍵を配布とsudo設定は手作業でポチポチやるものじゃないです。
前提
- コントロールノードでのAnsibleのインストール(手動)
- ターゲットノードで作業ユーザが
wheel
グループに所属しておりsudoでroot昇格できること(ただし要パスワード) - 作業ユーザ名とパスワードは全ノード共通
- パスワード認証でSSH接続でき、Pythonがインストール済みである
それ以外の要件であるパスフレーズ無しSSH公開鍵設定とパスワード無しsudo設定をAnsibleでやります。
ansible.cfg
ここまで説明してないので、初回SSH実行時の手間を減らすおまじないだと思ってください。
[defaults]
host_key_checking = False
[ssh_connection]
ssh_args -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
インベントリ
[nodes]
192.168.0.141
192.168.0.142
※ Ansibleを実行するコントロールノード(192.168.0.140)も構築対象にする場合、それも追加してください。
プレイブック
---
- hosts: localhost
tasks:
- name: create directory for ssh keypair
file:
path: "{{ lookup('env','HOME') }}/.ssh/"
state: directory
mode: 0700
- name: create ssh privatekey
openssh_keypair:
path: "{{ lookup('env','HOME') }}/.ssh/id_rsa"
- hosts: all
tasks:
- name: publickey copy to target-nodes
authorized_key:
user: "{{ ansible_env.USER }}"
key: "{{ lookup('file', lookup('env', 'HOME') + '/.ssh/id_rsa.pub' )}}"
- hosts: all
become: True
tasks:
- name: configure non-password sudo
copy:
dest: /etc/sudoers.d/nopass
mode: 0600
content: |
%wheel ALL=(ALL) NOPASSWD: ALL
この3つのファイルを同一ディレクトリに置いて、以下のコマンドを実行。
$ ansible-playbook -i inventory.ini playbook.yml -kK
-k
でパスワード認証、-K
でsudoの昇格用パスワード認証がまだ未設定(このAnsibleで設定する)なので、忘れないように。
lookup
プラグインなどを使って以下のものを外部参照しています。
変数 | 内容 |
---|---|
{{ lookup('env','HOME') }} | 実行ユーザのホームディレクトリのパス |
{{ ansible_env.USER }} | ユーザ名 |
{{ lookup('file', lookup('env', 'HOME') + '/.ssh/id_rsa.pub' )}} |
~/.ssh/id_rsa.pub のファイルの内容 |
以上を踏まえて、このプレイブックの各タスクでは以下の処理が行われます。
(既にパスワード無しでsudo
できるなど、設定済みのものがあれば削ってください)
- create directory for ssh keypair (ローカル実行)
-
~/.ssh
ディレクトリを作成
-
- create ssh privatekey (ローカル実行)
- SSH秘密鍵キーペアを
~/.ssh/id_rsa
に作成
- SSH秘密鍵キーペアを
- publickey copy to target-nodes (リモートアクセス)
- 全ターゲットノードのauthorized_keyに
~/.ssh/id_rsa.pub
をコピー
- 全ターゲットノードのauthorized_keyに
- configure non-password sudo (要root権限)
- 全ターゲットノードのsudoの
NOPASSWD
設定
- 全ターゲットノードのsudoの
ね、簡単でしょう?
(補足)openssh_keypairモジュールについて
ドキュメントにも記載がありますが、このモジュールはversion 2.8から使用可能な新しいモジュールです。それ以前のAnsibleバージョンだと使えません。
それ以前のバージョンを使っている場合は、モジュールでは鍵作成ができないので、shell
モジュールで作成するタスクに置き換えます。
- name: check exists ssh privatekey
shell: test -f $HOME/.ssh/id_rsa
register: exist_key
ignore_errors: True
check_mode: False
changed_when: False
- name: create ssh privatekey
shell: ssh-keygen -t rsa -f $HOME/.ssh/id_rsa -N ""
when: exist_key.rc != 0
ちょっと長いけど「~/.ssh/id_rsa
があるかどうかチェック」して「なければssh-keygen
」という2段階になっています。
初回実行時は~/.ssh/id_rsa
が無いためエラーの表示が出力されますが、ignore_errors: True
によって無視して処理が継続されます。
…ssh-keygen
って強制上書きモードないんかな??
まとめ
ということで、Ansibleを使ったサーバー構築をするための準備について、具体的な作業手順(マニュアル&Ansibleによる自動構築)について説明しました。
台数が2,3台であれば手作業でもミスなく頑張れると思いますが、10台20台になってくると絶対に自動化した方が良いです。
ネットワークの自動化やクラウド環境だとまたちょっと変わってくると思いますが、オンプレでのAnsible使ったサーバー構築の自動化はこれで始めることができると思います。
余談だけど、AnsibleのインストールはAnsibleで自動化できないのだろうか。。
参考
- openssh_keypair – Generate OpenSSH private and public keys — Ansible Documentation ※ version 2.8から
- authorized_key – Adds or removes an SSH authorized key — Ansible Documentation
- OSSはアルミニウムの翼で飛ぶ: ものぐさ playbook
- Ansibleでとりあえず authorized_key を通す - Qiita
- IT とかその他もろもろ: Ansible の authorized_key モジュールで lookup プラグインを使う時にユーザー名を変数で指定