deep dive into modules

38
Deep Dive into Modules JULY TECH FESTA 2015 1

Upload: hideki-saito

Post on 14-Aug-2015

1.721 views

Category:

Technology


3 download

TRANSCRIPT

Page 1: Deep Dive into Modules

Deep Dive into ModulesJULY TECH FESTA 2015 1

Page 2: Deep Dive into Modules

whoami齊藤 秀喜(さいとう ひでき) / TwitterID: @saito_hideki

日本OpenStackユーザ会 株式会社インターネットイニシアティブ

著書 OpenStackクラウドインテグレーション ISBN: 9784798141251

2

Page 3: Deep Dive into Modules

Agenda• 本日のテーマ

• Ansibleとは

• モジュールの仕組み

• モジュールを開発する

3

Page 4: Deep Dive into Modules

トピック★対象とするもの • Ansibleの簡単な紹介 • Ansibleの仕組みの中核であるモジュールについての解説 • モジュールの作成・テスト方法

★対象外とするもの • Ansibleそのもの • モジュール以外の構成要素

4

Page 5: Deep Dive into Modules

本日のテーマAnsibleが行うさまざまな仕事を実現しているのがモジュールです。

本セッションでは、このモジュールに焦点をあてて、その構造や開発方法について、少し掘り下げて紹介します。

5

Page 6: Deep Dive into Modules

Ansibleとは

6

Page 7: Deep Dive into Modules

Configuration Management Tool

Ansibleは、シンプルで使い勝手の良いCMTです

オペレーションの自動化 システムの構成管理

7

Page 8: Deep Dive into Modules

Ansibleとは★何をしてくれるのか?

• システムの構成管理を比較的容易に実現できる • システムの設定やテストなどのオペレーションを自動化できる

★利点 • エージェントレス • 操作対象ノードの増減など環境変化にも柔軟に対応可能 • シンプルな構成ゆえに拡張性が高い • デフォルトで多くの操作モジュールが付属している(BATTERIES INCLUDED) • AWSやOpenStackなどのクラウド基盤管理システムとの親和性が高い • ドキュメントが充実している

★欠点 • リリース頻度が高く落ち着かない • Windows対応が弱い • スケールさせるには工夫が必要

8

Page 9: Deep Dive into Modules

6つの構成要素本セッションで関係するのは5つ

1. コマンドラインインターフェイス

2. 設定ファイル

3. インベントリ/ダイナミックインベントリ

4. モジュール

5. プラグイン

6. Playbook9

Page 10: Deep Dive into Modules

BATTERIES INCLUDED

10

Page 11: Deep Dive into Modules

モジュールの定義モジュールは、ansibleコマンドやansible-playbookコマンドから利用されるプログラムで、その役割は、大きく以下の2つです。 Ansibleには標準で数多くのモジュールが付属しています。

1. 対象ノードの情報を収集する(gathering) 他のモジュールから再利用する目的で、操作対象ノードの情報を取得する

2. 対象ノードを操作する(do something) 設定ファイルの配置や、パッケージのインストール、システムの再起動などのさまざまな操作を行う

11

Page 12: Deep Dive into Modules

実行に必要な要素は3つ1. ansibleコマンド

2. インベントリファイル

3. モジュール

[書式] ansible <ホストパターン> -i <インベントリファイル> -m <モジュール>

[実行例] $ ansible web -i ansible_hosts -m setup $ ansible 192.168.0.1 -i ansible_hosts -m hostname -a name=hogehoge -u vagrant -k -s

12

Page 13: Deep Dive into Modules

ansibleコマンドの動き1.インベントリ内で、ホストパターンにマッチするノードをリストアップする => ターゲットノード 2.ターゲットノードに対してモジュールを適用する

[localhost] 127.0.0.1 ansible_connection=local

[test] 192.168.0.1 ansible_connection=ssh 192.168.0.2 ansible_connection=ssh 192.168.0.3 ansible_connection=ssh

[web] web0[0:3] ansible_connection=ssh

インベントリファイル[localhost] 127.0.0.1 ansible_connection=local

[test] 192.168.0.1 ansible_connection=ssh 192.168.0.2 ansible_connection=ssh 192.168.0.3 ansible_connection=ssh

[web] web0[0:3] ansible_connection=ssh

ホストパターン=>”web”

webグループにマッチ

13

Page 14: Deep Dive into Modules

対象ノードの情報を収集する[例] 対象ホストの情報を収集する $ ansible localhost -i ansible_hosts -m setup 127.0.0.1 | success >> { "ansible_facts": { "ansible_all_ipv4_addresses": [ …(中略)… ], "ansible_all_ipv6_addresses": [ …(中略)… ], "ansible_architecture": “x86_64", …(中略)… }, "module_setup": true }, "changed": false }

収集したホストの情報は、ansible_*変数に代入される。 Playbookでは、この変数を他のモジュールから再利用可能。

14

Page 15: Deep Dive into Modules

対象ノードを操作する[例] ホスト名を変更(web00->foo)する $ ansible web00 -i ansible_hosts -m hostname \ -a name=foo -u vagrant -k -s

SSH password: ******** web00 | success >> { "changed": true, "name": "foo" }

ホスト名が変更された場合はtrue 変更されなかった場合はfalse

現在のホスト名は”foo”

どのような実行結果を返すのかは、モジュールの作り方しだい。

15

Page 16: Deep Dive into Modules

モジュールの仕組み

16

Page 17: Deep Dive into Modules

モジュールの実行Ansibleが標準提供するCoreやExtrasモジュールはPythonで記述されています。 これらのモジュールを利用した構成管理の流れは以下の通りです。

モジュール 実行可能 プログラム

実行 掃除変換 転送

コントロールノード ターゲットノード

17

Page 18: Deep Dive into Modules

デモ2台のホストをAnsibleから操作してみます。

1. setupモジュールによる情報収集

$ ansible members -i ansible_hosts -m setup

2. commandモジュールによる任意のコマンド実行

$ ansible members -i ansible_hosts -m command -a ‘uname -a’

3. hostnameモジュールによるホスト名の変更

$ ansible members -i ansible_hosts -m hostname -a ‘name=foo’ -s

18

Page 19: Deep Dive into Modules

本題:モジュールを開発する

19

Page 20: Deep Dive into Modules

モジュールを書いてみるモジュールの働きを理解するために、現在の時刻を取得するtimetestモジュールを書いて実行してみましょう。

#!/usr/bin/env python

import datetime import json

date = str(datetime.datetime.now()) print json.dumps({ "time": date })

20

Page 21: Deep Dive into Modules

モジュールを実行してみる[単体実行] $ python timetest {"time": "2015-07-23 16:39:22.283407”}

[モジュールとして実行] $ ansible localhost -i ansible_hosts --module-path . -m timetest 127.0.0.1 | success >> { "time": "2015-07-23 16:52:29.755416" }

21

Page 22: Deep Dive into Modules

生成される実行プログラムシェル変数ANSIBLE_KEEP_REMOTE_FILESを1にセットしてansibleコマンドを実行すると…

$ export ANSIBLE_KEEP_REMOTE_FILES=1 $ ansible localhost -i ansible_hosts -M . -m timetest

-mで指定したモジュールから生成された実行可能プログラムは、$HOME/.ansible/tmp/に配置されます。

通常、このプログラムは実行後に削除されますが、ANSIBLE_KEEP_REMOTE_FILESに1がセットされている場合は、削除されずに残ります。

22

Page 23: Deep Dive into Modules

timetestモジュールの 実行可能プログラム

自作したtimetestモジュールと、Ansibleが生成した実行可能プログラムを確認してみると、内容に差異がなく、そのまま転送されて実行されているようです。

[モジュール] $ md5 timetest MD5 (timetest) = ca381d31af18e5bce5d6e4e260362062

[実行可能プログラム] $ md5 ~/.ansible/tmp/ansible-tmp-1437633590.03-115993239580867/timetest MD5 (/Users/saitou/.ansible/tmp/ansible-tmp-1437633590.03-115993239580867/timetest) = ca381d31af18e5bce5d6e4e260362062

23

Page 24: Deep Dive into Modules

引数はどうなるの?$ ansible 192.168.0.1 -i ansible_hosts -M . -m timetest2 \ -a time=072411352015.45 -u saitou -k -K -s

SSH password: ******** SUDO password[defaults to SSH password]: ********

192.168.0.1 | success >> { "changed": true, "time": "2015-07-24 11:35:45.001731" }

モジュールの引数は、実行可能プログラムと同じディレクトリにあるargumentsファイルに文字列として格納されます。

$ cd ~/.ansible/tmp/ansible-tmp-1437705347.69-147453231832727 $ ls arguments timetest2 $ cat arguments time=072411352015.45

24

Page 25: Deep Dive into Modules

pingモジュールの 実行可能プログラム

[モジュール] $ wc ansible/lib/ansible/modules/core/system/ping.py 61 235 1702 ansible/lib/ansible/modules/core/system/ping.py

[実行可能プログラム] $ wc ~/.ansible/tmp/ansible-tmp-1437620077.92-75246064236647/ping 1665 6089 63273 ~/.ansible-tmp-1437620077.92-75246064236647/ping

ファイルサイズ激増 何かいろいろとやっていそう

Ansibleの標準モジュールは、ちょっと違います。

25

Page 26: Deep Dive into Modules

この差は何!?

26

Page 27: Deep Dive into Modules

pingモジュールの コードを読んでみる

import exceptions

def main(): module = AnsibleModule( argument_spec = dict( data=dict(required=False, default=None), ), supports_check_mode = True ) result = dict(ping='pong') if module.params['data']: if module.params['data'] == 'crash': raise exceptions.Exception("boom") result['ping'] = module.params['data'] module.exit_json(**result)

from ansible.module_utils.basic import *

main()

このあたりが あきらかに怪しい

27

Page 28: Deep Dive into Modules

lib/ansible/module_utils/basic.py

Ansibleは、モジュールに必要となる基本的な機能をライブラリとして提供しています。 basic.pyには、モジュールの骨子となるAnsibleModuleクラスと、モジュールの振る舞いを決めるために利用できる便利な関数があらかじめ定義されています。

モジュールから生成される実行可能プログラムは、基本的にそれ単体(1ファイル)で動作することが推奨されています。

basic.pyが提供しているコードは、モジュールから生成する実行可能プログラムにインライン展開される仕組みになっており、実行可能プログラムの単独動作を実現しています。

28

Page 29: Deep Dive into Modules

標準モジュールに準拠させる(1/2)

自作モジュールをAnsibleの本家に取り込んでもらうには、最低限、以下の3つの条件を満たしている必要があります。

1. DOCUMENTATION変数に概要説明を定義

2. EXAMPLES変数にモジュールの利用例を定義

3. AnsibleModuleクラスを利用する

注意) ansible.module_utils.basicは*でインポートする

29

Page 30: Deep Dive into Modules

標準モジュールに準拠させる(2/2)#!/usr/bin/python

import datetime

DOCUMENTATION = ''' module: timetest version_added: 1.9.2 short_description: Get date and time description: - Get date and time on target node options: {} author: - "Hideki Saito" '''

EXAMPLES = ''' # Get date and time ansible target -m timetest '''

def main(): module = AnsibleModule(argument_spec={}) date = dict(now=str(datetime.datetime.now())) module.exit_json(**date)

from ansible.module_utils.basic import *

main()

本家にPull Requestするなら このような形式が必須です

30

Page 31: Deep Dive into Modules

ドキュメンテーションモジュールコード中の、DOCUMENTとEXAMPLESに書いた概要や利用例は、ansible-docコマンドで利用されます。

[例] timetestモジュールのドキュメントを読む $ ansible-doc -M . timetest

[実行結果] > TIMETEST

Get date and time on target node

EXAMPLES: # Get date and time ansible target -m timetest

DOCUMENTATION に定義した概要説明

EXAMPLESに定義した利用例

31

Page 32: Deep Dive into Modules

標準モジュールでの 引数の扱い

Ansible ver1.9の場合、モジュールのオプションとして指定されたパラメータは、実行可能プログラムのMODULE_ARGSに文字列として展開されます。

[例] statモジュールで指定したオプションの展開例 $ ansible localhost -i ansible_hosts -m stat \ -a "path=/etc/hosts get_md5=no get_checksum=no”

[展開例] 実行可能プログラム中のMODULE_ARGS #!/usr/bin/python …(中略)… MODULE_ARGS = 'path=/etc/hosts get_md5=no get_checksum=no’ …(以下略)…

32

Page 33: Deep Dive into Modules

モジュールのテスト

33

Page 34: Deep Dive into Modules

常に実弾演習?Ansibleは、モジュールのテストスクリプト(test-module)を提供しています。 モジュールのテストには、test-moduleスクリプトを利用しましょう。 $ git clone [email protected]:ansible/ansible.git --recursive $ source ansible/v1/hacking/env-setup $ ansible/v1/hacking/test-module -m ./timetest

* including generated source, if any, saving to: .ansible_module_generated * this may offset any line numbers in tracebacks/debuggers! *********************************** RAW OUTPUT {"now": "2015-07-24 17:31:38.794721", "changed": false}

*********************************** PARSED OUTPUT { "changed": false, }

34

Page 35: Deep Dive into Modules

まとめ本日お話したことを以下にまとめます。

★ Ansibleのモジュールの働き ★ モジュールが実行される過程と、その確認方法について ★ 自分でモジュールを書く方法 ★ 標準モジュールとして必要な要件 ★ テスト方法

Ansibleは数多くの機能を標準モジュールとして提供していますが、求める機能がその中になければ、自作することも可能です。

35

Page 36: Deep Dive into Modules

あれば使う・なければ作る★さまざまな機能を提供するモジュール群が標準提供されています

★しかし、あなたが必要とする全ての機能をカバーしているわけではありません

★あれば使う・なければ作るの精神で、Ansibleを構成管理フレームワークとして活用しましょう!

36

Page 37: Deep Dive into Modules

参考★Developing Modules

Ansibleの公式モジュール開発ガイド

• [本家] http://docs.ansible.com/ansible/developing_modules.html

• [勝手な和訳] http://tzpst.hatenablog.com/entry/2015/07/21/175159

37

Page 38: Deep Dive into Modules

ご静聴ありがとうございました

JULY TECH FESTA 2015 38