パブリッククラウド全盛の現代ですが、OSレイヤーの構築自動化や構成管理用途でAnsible使われてる方は結構いるんじゃないでしょうか。
私もちゃんと勉強したことなかったので、Kindle Unlimitedでこの本を読みつつ、手元のAWS環境でハンズオンもしてみました。
Ansibleとは
- Python製のIT自動化ツール
- OSSだが、Red Hat社が「Red Hat Ansible Automation Platform」としてサポートを提供している
- 自動化対象のノードにエージェントのインストールが不要。SSH接続できてPythonが利用できればOK
基本概念
- 自動化したい内容を「プレイブック」としてYAMLで定義する
- 自動化可能な処理は「モジュール」として提供されている。モジュールは日々追加開発されている
私はもともと、AnsibleってシェルスクリプトのようにOSコマンドを羅列して自動化定義するものかとイメージしていたので、実際のプレイブックのサンプルを見て少し驚きました。
配布形態
リリースサイクル短縮のため、本体と追加機能が別パッケージになっている。
- ansible-core:本体+基本モジュール
- コレクション:その他のモジュールやプラグイン
- Ansible Community Packageを利用すれば、本体+推奨コレクションをまとめてインストールできる
構成
- コントロールノード:Ansibleをインストールするノード
- Python 2.7以上 or 3.5以上が入っていること
- マネージドノード:自動化対象のノード
- Python 2.6以上 or 3.5以上が入っていること
- SSH接続ができること
- SFTP or SCPでファイル転送ができること
Ansibleのコンポーネントは以下。
- モジュール
- 特定の処理が作り込まれた機能の単位のこと
- パラメータを指定することで詳細を定義する
- 冪等性が考慮されているため、現在の状態を確認して分岐…などの考慮は不要
- インベントリ
- 自動化対象ノードの一覧。INI or YAMLで記述する
- ホストをまとめるグループも定義できる
- ホストやグループ内で共用できる「インベントリ変数」を定義できる
- プレイブック
- マネージドノードへの処理をYAMLで記述する
- いくつかのセクションに分かれている
- hosts:対象ホストやグループを指定する
- vars:プレイ内で利用する変数を定義する
- tasks:処理内容をモジュール+パラメータで指定する
- ファイル内で上から順にタスク処理される。繰り返しや条件制御も可能
-
ansible-playbook
コマンドで実行できる
- プラグイン
- 補完機能。いくつかの種別がある
- コネクションプラグイン:マネージドノードへの接続に関するプラグイン群
- コールバックプラグイン:プレイブック実行結果の出力に関するプラグイン群
- 補完機能。いくつかの種別がある
- 設定ファイル(ansible.cfg)
- INIで記述する。いくつかのセクションに分かれる
- 配置可能な場所がいくつかある。どこにも無ければデフォルト設定で動作する
-
ansible-config
コマンドで設定状況を確認できる
- コレクション
- ansible-core に含まれないモジュール、プラグイン、プレイブックの管理単位
- FQCNという名前空間で指定する
- Ansible Galaxyというサイトで配布されている
-
ansible-galaxy
コマンドでコレクション確認やインストールができる -
requirements.yml
を記述して一括インストールも可能
実際に触ってみた
AWSでサーバーを立てて、Ansibleを使ってみることにします。
サーバーワークスさんのこちらの記事を参考にさせていただきました。
環境準備
- VPCを作成
- マルチAZ(利用するのは片方のAZのみ)
- パブリックサブネットにEC2を作成
- ansible-controller:コントロールノード
- プライベートサブネットにEC2を作成
- ansible-managed:マネージドノード
コントロールノードにAnsibleをインストール
※Amazon Linux 2ではExtrasで有効化するとyumから利用できる(参考記事)
$ sudo amazon-linux-extras enable ansible2
$ sudo yum install -y ansible
インストールされたことを確認
$ ansible --version
ansible 2.9.23
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/home/ec2-user/.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.18 (default, May 25 2022, 14:30:51) [GCC 7.3.1 20180712 (Red Hat 7.3.1-15)]
etc/ansible
配下にインベントリおよび設定ファイルがあるようです。
$ ls /etc/ansible
ansible.cfg hosts roles
nanoエディターでhostsを開き、インベントリーにマネージドノードのIPアドレスを追加してみます。
$ sudo nano /etc/ansible/hosts
プレイブック作成&SSH接続
Apacheを起動するだけの簡単なプレイブックを作成してみます。
$ nano playbook.yml
ファイル内には以下を記述。Tabを使うとエラーになるため注意!
---
- hosts: 10.0.141.23
tasks:
- name: start httpd
ansible.builtin.systemd:
name: httpd
state: started
試しに一度、このプレイブックを実行してみます。
$ ansible-playbook playbook.yml
PLAY [10.0.141.23] *************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************
The authenticity of host '10.0.141.23 (10.0.141.23)' can't be established.
ECDSA key fingerprint is SHA256:Ul7RSyNiC5QWSEF0ov88qucD1OQMs303BY7oeCLjBQI.
ECDSA key fingerprint is MD5:28:57:5b:9b:89:32:3e:d6:fc:92:ed:42:94:e9:12:9e.
Are you sure you want to continue connecting (yes/no)? yes
fatal: [10.0.141.23]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: Warning: Permanently added '10.0.141.23' (ECDSA) to the list of known hosts.\r\nPermission denied (publickey,gssapi-keyex,gssapi-with-mic).", "unreachable": true}
PLAY RECAP *********************************************************************************************************
10.0.141.23 : ok=0 changed=0 unreachable=1 failed=0 skipped=0 rescued=0 ignored=0
エラーになりました。
Ansibleコントローラー → マネージドノードへのSSH接続で認証失敗しているようですね。
それでは、マネージドノードのSSH秘密鍵をAnsibleコントローラーへ配置します。
まずSCPで作業用MacからコントローラーEC2のホームディレクトリーへ秘密鍵をアップロードします。
scp -i "onda-ansible.pem" "onda-ansible.pem" ec2-user@ec2-***-***-***-***.ap-east-1.compute.amazonaws.com:/home/ec2-user
一度、AnsibleコントローラーからマネージドノードへSSH接続を試しておきます。
また、Playbookの実行前にApacheの起動状態も確認しておきます。
$ ssh -i "onda-ansible.pem" ec2-user@10.0.141.23
$ systemctl status httpd
Unit httpd.service could not be found.
そもそもApacheがインストールされていなさそうなことが確認できました。
プレイブック実行&トラブルシューティング
それでは、先ほどの秘密鍵を指定して再度Playbookを実行します。
ユーザーは指定していませんが、SSH接続元のコントローラーEC2で利用している ec2-user
が利用されるため結果的に問題ありません。
$ ansible-playbook playbook.yml --private-key onda-ansible.pem
PLAY [10.0.141.23] *************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************
[WARNING]: Platform linux on host 10.0.141.23 is using the discovered Python interpreter at /usr/bin/python, but
future installation of another Python interpreter could change this. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information.
ok: [10.0.141.23]
TASK [start httpd] *************************************************************************************************
fatal: [10.0.141.23]: FAILED! => {"changed": false, "msg": "Could not find the requested service httpd: host"}
PLAY RECAP *********************************************************************************************************
10.0.141.23 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
今度は実行成功しました!
しかしApacheがインストールされていないので、 failed
で終了してしまいました。流石にインストールまではやってくれないですよね。
それでは再度マネージドノードにSSHログインし、Apacheをインストールします。
$ sudo yum install httpd
$ systemctl status httpd #起動状態の確認
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
Active: inactive (dead)
Docs: man:httpd.service(8)
httpdがインストールされ、起動していないことまで確認できました。
それでは再度Ansibleコントローラーへ戻り、先ほどのプレイブックを実行します。
$ ansible-playbook playbook.yml --private-key onda-ansible.pem
PLAY [10.0.141.23] *************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************
[WARNING]: Platform linux on host 10.0.141.23 is using the discovered Python interpreter at /usr/bin/python, but
future installation of another Python interpreter could change this. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information.
ok: [10.0.141.23]
TASK [start httpd] *************************************************************************************************
fatal: [10.0.141.23]: FAILED! => {"changed": false, "msg": "Unable to start service httpd: Failed to start httpd.service: The name org.freedesktop.PolicyKit1 was not provided by any .service files\nSee system logs and 'systemctl status httpd.service' for details.\n"}
PLAY RECAP *********************************************************************************************************
10.0.141.23 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
今度は別のエラーでApache起動失敗です。
ググるとPythonインタープリターの指定で改善しそうなので、 -e
オプションを追加してみます。
$ sudo ansible-playbook playbook.yml --private-key onda-ansible.pem -e ansible_python_interpreter=/usr/bin/python3
PLAY [10.0.141.23] *************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************
[WARNING]: sftp transfer mechanism failed on [10.0.141.23]. Use ANSIBLE_DEBUG=1 to see detailed information
[WARNING]: scp transfer mechanism failed on [10.0.141.23]. Use ANSIBLE_DEBUG=1 to see detailed information
fatal: [10.0.141.23]: FAILED! => {"ansible_facts": {}, "changed": false, "failed_modules": {"setup": {"failed": true, "module_stderr": "Shared connection to 10.0.141.23 closed.\r\n", "module_stdout": "Please login as the user \"ec2-user\" rather than the user \"root\".\r\n\r\n", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 0}}, "msg": "The following modules failed to execute: setup\n"}
PLAY RECAP *********************************************************************************************************
10.0.141.23 : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
メッセージを見ると「rootではなくec2-userで実行せよ」的なことが書いてありますね。
それでは sudo
を外して実行してみます。
$ ansible-playbook playbook.yml --private-key onda-ansible.pem -e ansible_python_interpreter=/usr/bin/python3
PLAY [10.0.141.23] *************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************
ok: [10.0.141.23]
TASK [start httpd] *************************************************************************************************
fatal: [10.0.141.23]: FAILED! => {"changed": false, "msg": "Unable to start service httpd: Failed to start httpd.service: The name org.freedesktop.PolicyKit1 was not provided by any .service files\nSee system logs and 'systemctl status httpd.service' for details.\n"}
PLAY RECAP *********************************************************************************************************
10.0.141.23 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
また権限エラーらしき状態に戻りました。
そろそろホリデーエンジニアの週末カフェタイムが終わってしまうので、残念ですがトラシューはここまでとします。
まとめ
綺麗にエラー解消できなかったのが残念ですが、Ansibleの概念や実装方法がかなりイメージ湧きました。
やっぱり実際に触ってみるのが大事ですね!