Ansible¶
- 目次
- Ansible
- 主な構成と必要なツール
- playbookを作る
- 逆引き
- タスク
- 被制御側マシン上で特定のユーザーとして処理を実行したい
- 制御側マシンにあるrpmファイルを被制御側に転送してからインストールしたい
- URLで指定したRPMをインストールしたい
- シンボリックリンクを作成したい
- ホスト名を設定したい
- /etc/hostsにホスト名とIPアドレスを設定したい
- サービスの自動起動設定、起動をさせたい
- Linux上にグループを作成したい
- Linux上にユーザーを作成したい
- gitのクローンを作成したい
- カレントディレクトリと環境変数を設定してコマンドを実行したい
- MySQLの設定に初回インストール時と2回目以降で冪等性を持たせたい
- 設定ファイルの一部修正
- 特定のホストグループの場合にモジュールを実行したい
- 複数のRPMパッケージを1つのタスクでまとめてインストールしたい(with_items)
- ハンドラー
- インベントリ
- ワンライナー
- ロール
- 実行環境
- タスク
- トラブルシュート
- 参考情報
LinuxおよびWindowsの環境構築を自動化(スクリプト化)するツールです。複数台の計算機の環境を構築するとか、同じ計算機を繰り返し構築するとかの際に重宝します。類似ツールにはChefとかPuppetがあります。Ansibleの特徴はエージェント不要、すなわち構築対象となる計算機にはAnsibleのソフトウェアを入れなくてもよい点です。
主な構成と必要なツール¶
設定をされる管理ノード(Management Node)と設定をする制御マシン(Control Machine)から構成されます。
制御マシン(Unix) | ーーー> | 管理ノード(Unix) |
SSH | ||
ーーー> | 管理ノード(Windows) | |
WinRM |
バージョン¶
Ansible 2.1¶
2016年5月にリリースされたばーじょんです。
- Windows対応、Microsoft Azure対応およびDocker対応の強化
- ネットワーク機器への対応
Ansible 2.0¶
2016年1月にリリースされたバージョンです。
- 制御マシン(Unix)
Python 2.6または2.7、SSH接続、およびAnsibleソフトウェア(Pythonモジュール)が必要です。
管理ノード(Windows)を制御する場合は、Python winrmモジュールが追加で必要です。
WinRMの接続認証にActive Directoryのドメインユーザーを使う場合は、Kerberos認証ができるOSパッケージおよびPythonモジュールが必要です。 - 管理ノード(Unix)
Python 2.x(2.4以降)とSSH接続が可能であれば構成できるので、現行のLinuxディストリビューションであればOS標準パッケージだけで利用可能です。 - 管理ノード(Windows)
PowerShell 3.0以降
Ansible制御マシン側の設定¶
SSH接続のエラー(Host fingerprint)¶
SSH初回接続では、known_hostsにフィンガープリントが登録されていないのでエラーになります。
$ ansible -i hosts -k -m command -a "date" all
SSH password: **
192.168.1.15 | FAILED => Using a SSH password instead of a key is not possible because
Host Key checking is enabled and sshpass does not support this. Please add this host's
fingerprint to your known_hosts file to manage this host.
一度手動でssh接続をしておくのが常套ですが、そうしたくない場合は次のいずれかの回避策を取ります。
- 環境変数ANSIBLE_SSH_ARGSに
-o StrictHostKeyChecking=no
を追加 - 環境変数ANSIBLE_HOST_KEY_CHECKINGに
False
を設定 - ansible.cfgファイル(/etc/ansible/下に置く)に以下を記述
[defaults] host_key_checking = False
- known_hostsモジュールを実行してknown_hostsファイルから指定のホストのフィンガープリント情報を追加または削除
known_hostsにフィンガープリントが登録されており、そのホストを再構築するなどしてフィンガープリントが変わってしまった場合、host_key_checking = Falseにしていてもダメなようです。
Windowsを管理ノードとするときの制御ホスト側の設定¶
- python pywinrmモジュール(とその依存モジュール群)
- python kerberosモジュール(とその依存モジュール群)
※ kerberosモジュールはActive DirectoryのドメインユーザーをWinRM接続のアカウントに使用する場合に必要
Windowsを制御対象とするときは、通信にSSHではなくWinRM(Windows Remote Management)を使用します。
その際、Pythonライブラリ pywinrm をインストールする必要があります。
~$ pip install pywinrm
CentOS 6でpywinrpmを作成する作業をチケット[#53]で実施しています。
ドメインユーザーで接続する場合¶
ドメインユーザーで接続する場合の接続指定は次のようになります。
[windows:vars] ansible_user=foobar@bravo.local ansible_connection=winrm
- ansible_userに、'@'を含む文字列を指定した場合、Kerberos認証で接続します。
ドメインユーザーをansibleの接続に使用するときは、Kerberos認証となります。Kerberos認証で接続するときは、保有しているデフォルトプリンシパルのチケットを使用します。チケットは、ansibleを実行する前に取得しておく必要があります。取得には、kinitコマンド(引数にドメインユーザー名を指定)を使います。 - -vvvvvオプション(vを5個以上)で詳細メッセージを出すと、次のメッセージでKerberos認証が使われているか確認できます。
<192.168.1.111> WINRM CONNECT: transport=kerberos endpoint=https://192.168.1.111:5986/wsman
transport= kerberos がKerberos認証を使っていることを示します。ここが、transport= ssl だとKerberosではなくパスワード認証になっていることを示します。
現在保有しているチケットの確認には、klistコマンドを使います。
~$ klist klist: Credentials cache file '/tmp/krb5cc_12345' not found
- これは空です。LinuxのKerberosパッケージは、チケットを/tmp/krb5cc_<ユーザーID>に置くようです。
- Java SE Development Kit(JDK)をインストールしていて、JDKのコマンドへパスを通していると、JKDにもklistがあるので要注意です。
チケットの取得(レルム名は大文字で指定します。Kerberosのレルム名は大文字・小文字を区別します。原則大文字)
~$ kinit foobar@BRAVO.LOCAL Password for foobar@BRAVO.LOCAL: ******** ~$ klist Ticket cache: FILE:/tmp/krb5cc_12345 Default principal: foobar@BRAVO.LOCAL Valid starting Expires Service principal 2016-02-07T21:04:55 2016-02-08T07:04:55
Kerberos認証でチケットを保有せずに実行した場合のエラー
TASK [setup] ******************************************************************* fatal: [turner]: FAILED! => {"failed": true, "msg": "ERROR! ssl: 500 WinRMTransport. [Errno 8] Name or service not known"}
ユーザーの指定は、アカウント名@ドメイン名 です。
python 2.7.10以降でWindows管理ノードとWinRM通信するときの自己署名証明書対応設定¶
WinRMは、標準では自己署名証明書を使ったHTTPSプロトコルを使います。
Python 2.7.10以降のバージョンを使う場合、SSLで自己署名証明書は認証エラーとされるようになったため、対応が別途必要になります。(Cygwin 64bit版の場合、python 2.7.10なので該当。CentOS 7.1はpython 2.7.5なので非該当)
CentOS 7.1 Python 2.7.5での接続確認¶
最初、公式サイトのドキュメントを参照してインベントリに次の記述をします。
http://docs.ansible.com/ansible/intro_windows.html
[windows] winhost [windows:vars] ansible_user: winaccount ansible_password: WinAcc0unt ansible_connection: winrm
Windows機を指定してansible 1.9.4を実行したところ、エラーとなりました。
$ ansible winhost -i hosts -m setup winhost | FAILED => 401 Unauthorized.
公式サイトのドキュメントは Ansible 2.0版での設定なので、1.9.4ではインベントリの変数定義を次に変更してみました。
[windows:vars]
- ansible_user: winaccount
- ansible_password: WinAcc0unt
+ ansible_ssh_uesr: winaccount
+ ansible_ssh_pass: WinAcc0unt
ansible_connection: winrm
$ ansible winhost -i hosts -m setup winhost | success >> { "ansible_facts": { "ansible_distribution": "Microsoft Windows NT 6.1.7601 Service Pack 1", :
Cygwin 7.1 Python 2.7.10での接続確認¶
$ ansible winhost -m setup winhost | FAILED => 500 WinRMTransport. [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)
HTTPSプロトコルを使ってWinRM接続をする際、Python 2.7.9以降SSL証明書の検証をちゃんとするようになったらしく、SSLサーバー側(この場合はWindows)が自己証明書の場合エラーになってしまうようです。
Ansible 2.0であれば、接続設定に次を追記します。
ansible_winrm_server_cert_validation=ignore
- 追記場所は、ansible_connection=winrm他を指定している場所がよいかと
それ以外はちょっと設定や細工が必要です。
- 回避策1は、HTTPプロトコルで通信
- 回避策2は、ansibleのwinrmプラグインの書き換え
- 回避策3は、コールバックの作成
- 回避策4は、sitecustomize.py(またはusercustomize.py)に追加コード記載
回避策1¶
HTTPプロトコルを使うには(ConfigureRemotingForAnsible.ps1ではHTTPを許可していない)、次のコマンドをPowerShellで実行します。
PS > winrm set winrm/config/service '@{AllowUnencrypted="true"}'
設定結果は次のコマンドで確認します。
PS > winrm get winrm/config : AllowUnencrypted = true :
インベントリで接続ポートをHTTPで使用する5985を明示的に指定します(デフォルトはHTTPSの5896)。
[windows:vars] ansible_ssh_uesr: winaccount ansible_ssh_pass: WinAcc0unt ansible_ssh_port=5985 ansible_connection=winrm
回避策2¶
Cygwin 2.3.1 64bit版で、python 2.7.10、Ansible 1.9.4 の場合、次のパスにあるファイルを修正します。/usr/lib/python2.7/site-packages/ansible/runner/connection_plugins/winrm.py
--- winrm.py.orig 2015-12-20 22:38:06.000000000 +0900
+++ winrm.py 2015-12-25 00:02:04.139133000 +0900
@@ -74,6 +74,8 @@
'''
Establish a WinRM connection over HTTP/HTTPS.
'''
+ import ssl
+ ssl._create_default_https_context = ssl._create_unverified_context
port = self.port or 5986
vvv("ESTABLISH WINRM CONNECTION FOR USER: %s on PORT %s TO %s" % \
(self.user, port, self.host), host=self.host)
Ansible 2.0ではうまく入れられなかったので他の回避策を取るのがよいかと
回避策3¶
省略
回避策4¶
参考: https://github.com/ansible/ansible/issues/10294
sitecustomize.py もしくはusercustomize.pyに次のコードを追記(ファイルがなければ新規作成)します。
/usr/lib/python-2.7/site-packages/sitecustomize.py
import ssl
try:
_create_unverified_https_context = ssl._create_unverified_context
except AttributeError:
# Legacy Python that doesn't verify HTTPS certificates by default
pass
else:
# Handle target environment that doesn't support HTTPS verification
ssl._create_default_https_context = _create_unverified_https_context
- cygwinのpythonの場合、Windows側から見たディレクトリは、
<cygwinインストールパス>\lib\python-2.7\site-packages\sitecustomize.py
- usercustomize.pyを置く場所は、pythonコードを実行して確認します
>>> import site >>> userdir = site.getusersitepackages() >>> print userdir
で表示されたパスになります。
Ansible管理ノード(制御される側)の設定¶
条件¶
Linux系OSでAnsible制御を受ける条件
- Python 2.6または2.7がインストールされていること
- SSHで制御側からSSHで接続できること
- SSHで接続したユーザーアカウントでsudoができること
→ 初期設定をAnsibleからrootユーザーで接続することも可能 - SELinuxが稼動している(EnforcedまたはPermissive)場合は、libselinux-pythonがインストールされていること
Windows系OSでAnsible制御を受ける条件
- PowerShell 3.0以上がインストールされていること
- Windows Remote Management(WinRM)で制御側から接続できること
- PowerShellスクリプトの実行が許可されていること
Windows OS(全般)¶
Windows OSは、SSHを標準装備していないので、AnsibleではWindow Remote Management(WinRM)を使用します。また、PowerShell 3.0以上を必要とします。これは、Windows 8以降、およびWindows Server 2012以降では標準装備です。Windows 7やServer 2008などは、別途MicrosoftからWindows Management Framework(WinRMとPowerShellを含む)をダウンロードしインストールします。
http://docs.ansible.com/ansible/intro_windows.html
- WMF 3.0はhotfix2842230を当てる必要あり
WinRM 4.0のインストール(Windows 7, 2008)¶
Windows Management Framework 4.0をダウンロードします(次のURL)。これには、PowerShell、WinRMなどが含まれます。
https://www.microsoft.com/ja-jp/download/details.aspx?id=40855
Windows 7 64bit用のファイルは次です。
Windows6.1-KB2819745-x64-MultiPkg.msu
WMF4.0は、.NET Framework 4.5を必要としています。Windows 7、Windows Server 2008は、OSの標準搭載.NET Frameworkが3.5と古いので、他のアプリケーションと一緒に.NET Framework 4.5以上がインストールされていない場合、先にインストールしておく必要があります。次の記事の中にあるリンクからダウンロードできます。
https://msdn.microsoft.com/ja-jp/library/5a4x27ek%28v=vs.110%29.aspx
WMF4.0インストーラを実行すると更新プログラムとしてインストールされます。
インストール後再起動を促されるので、再起動してからPowerShellを起動しバージョンを確認します。
PS > $PSVersionTable Name Value ---- ----- PSVersion 4.0 WSManStackVersion 3.0 SerializationVersion 1.1.0.1 CLRVersion 4.0.30319.34209 BuildVersion 6.3.9600.16406 PSCompatibleVersions {1.0, 2.0, 3.0, 4.0} PSRemotingProtocolVersion 2.2
Windows準備作業¶
WindowsでWinRMを使ってAnsibleの制御を受け入れるために、準備スクリプトをダウンロードし実行します。
https://github.com/ansible/ansible/raw/devel/examples/scripts/ConfigureRemotingForAnsible.ps1
PowerShellスクリプトを管理者権限で実行します。
エラー(デジタル署名されていません。このスクリプトは現在のシステムでは実行できません)¶
設定ではRemoteSignedにしています。
PS > Get-ExecutionPolicy RemoteSigned
PS > .\ConfigureRemotingForAnsible.ps1 .\ConfigureRemotingForAnsible.ps1 : ファイル C:\users\torutk\Documents\ConfigureRemotingForAnsible.ps1 を読み込めません。 ファイル C:\users\torutk\Documents\ConfigureRemotingForAnsible.ps1 はデジタル署名されていません。このスクリプトは現在の システムでは実行できません。スクリプトの実行および実行ポリシーの設定の詳細については、「about_Execution_Policies」 (http://go.microsoft.com/fwlink/?LinkID=135170) を参照してください。 発生場所 行:1 文字:1 + .\ConfigureRemotingForAnsible.ps1 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : セキュリティ エラー: (: ) []、PSSecurityException + FullyQualifiedErrorId : UnauthorizedAccess
これは、ブラウザでダウンロードしたスクリプトファイルを実行したときに発生しました。
ブラウザでダウンロードしたファイルには「ブロック」がかかっていることがあり、その場合、エクスプローラからファイルのプロパティ > 全般 > [ブロックの解除]をする必要があります。
エラー(Windowsファイアウォールサービスとの通信中にエラーが発生)¶
PS > powershell -ExecutionPolicy RemoteSigned .\ConfigureRemotingForAnsible.ps1 WinRM は要求を受信するように更新されました。 WinRM サービスの種類を正しく変更できました。 WinRM はリモート管理用に更新されました。 このコンピューター上のあらゆる IP への WS-Man 要求を受け付けるため、HTTP://* 上に WinRM リスナーを作成しました。 ローカル ユーザーにリモートで管理権限を付与するよう LocalAccountTokenFilterPolicy を構成しました。 wxf : http://schemas.xmlsoap.org/ws/2004/09/transfer a : http://schemas.xmlsoap.org/ws/2004/08/addressing w : http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd lang : ja-JP Address : http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous ReferenceParameters : ReferenceParameters Windows ファイアウォール サービスとの通信中にエラーが発生しました。このサービスが実行されていることを確認して、もう一度 試してください。 PS >
これを実行したPCには、市販のアンチウィルスソフトをインストールしており、Windowsファイアウォールを停止しています(アンチウィルス独自のファイアウォールを使うため)。そのため、このエラーが発生しています。しかし、このままansibleから接続してみたところ、問題なく動作していました。
playbookを作る¶
YAMLの書き方メモ¶
- (1) ファイル名の拡張子.yml
- (2) UTF-8で記述
- (3) 2空白インデント
- (4) 全てのYAMLファイルはリストで開始すること(Ansibleの制約)
- (5) 全てのYAMLファイルは'---'で開始すること(1つのファイルに複数YAMLを記載するときの区切り子)
- インクルードされるYAMLファイルには不要(roles下のmain.yml等)
- (6) 変数は、
{{ varname }}
と2重波括弧と変数名の前後に空白を入れる--- - hosts: clients tasks: - name: myappの更新 yum: name="myapp" state=latest update_cache=yes
- (7)長い行の折り返し(改行)方法はいくつかある
- 普通に改行
- name: long line break manyoptionmodule: firstOption="foo bar bz" secondOption="Thomas Percy James Henry Gordon" thridOption="river lake sea"
- YAML折り返し('>'記号)
- name: long line break manyoptionmodule: > firstOption="foo bar bz" secondOption="Thomas Percy James Henry Gordon" thridOption="river lake sea"
- ディクショナリ形式
- name: long line break manyoptionmodule: firstOption: "foo bar bz" secondOption: "Thomas Percy James Henry Gordon" thridOption: "river lake sea"
- 普通に改行
ファイル分割¶
次の構造をちらほら見かけます。
root +-- roles | +-- foo.yml | +-- bar.yml +-- hosts +-- site.yml
ベストプラクティス構造¶
1つのymlファイルに全てを記述すると、長くなって把握性、再利用性、確認容易性が悪くなるので、分割して、また可変部を変数等に括り出す構造のお勧め構造があります。
root/ +-- group_vars/ # グループ毎に定義する変数設定ファイルを収容 | +-- blues # bluesグループ用の変数設定ファイル | +-- reds # redsグループ用の変数設定ファイル | +-- host_vars/ # ホスト毎に定義する変数設定ファイルを収容 | +-- ultramarine # ultramarine用の変数設定ファイル | +-- pink # pink用の変数設定ファイル | +-- production # 本番環境用inventoryファイル +-- staging # 検証環境用inventoryファイル | +-- site.yml # site全体用 playbookファイル +-- blues.yml # bluesに対するplaybookファイル +-- reds.yml # redsに対するplaybookファイル | +-- roles/ # ロール(タスクを目的毎に束ねた単位)を収容 +-- alfa/ # alfa作業を収容 | +-- tasks/ | | +-- main.yml # alfa作業のタスク群を定義したファイル | +-- files/ | | +-- alfa.conf # alfa作業で使用する(対象ホストに送り込む)ファイル等 | +-- templates/ | | +-- alfa.ini.j2 # alfa作業で使用するテンプレート定義ファイル | +-- handlers/ | | +-- main.yml # ハンドラータスクを定義したファイル | +-- defaults/ # 変数のデフォルト設定用 | | +-- main.yml | +-- meta/ # メタ情報用 | | +-- main.yml | +-- vars/ # 変数用 | +-- main.yml | +-- bravo/ : :
単一ファイル構成¶
作り捨て的な作業などで、ベストプラクティス構造を作るのはちょっとなぁ…というときには、一時作業用の単一ファイルで作って実行してもよいかと思います。一時作業といってもplaybookファイルを作って実行し、それを保管しておくと、後日流用したりするのが楽です。
root +-- shortshorts +-- foo.xml +-- bar.xml : : +-- files/ +-- foo.conf +-- var.sh : :
モジュール¶
commandかshellか¶
Linuxでコマンドを実行するモジュールには、commandとshellがあります。
違いは、commandの場合、shellインタプリタが解釈する機能(環境変数の展開、リダイレクト、パイプ、バックグラウンド実行)が使えません。
GATHERING FACTをスキップして実行時間を短縮¶
デフォルトではplaybookを実行すると最初に対象ホストすべてに情報を問い合わせます。
この各ホストから取得した情報を使うことがなければ、問い合わせ処理をスキップすることでplaybookの実行を短縮できます。その場合は、gather_facts: no
を記述します。
---
- hosts: all
become: yes
gather_facts: no
roles:
逆引き¶
タスク¶
被制御側マシン上で特定のユーザーとして処理を実行したい¶
sudo: yes
は、root権限で処理を実行します。rootではなく特定のユーザーで処理を実行したい場合、かつSSH接続するユーザーとは別の場合は次の記述をします。
Ansible 1.9より古いバージョン¶
sudo: yes
sudo_uesr: apache
Ansible 1.9以降¶
become: yes
become_uesr: apache
制御側マシンにあるrpmファイルを被制御側に転送してからインストールしたい¶
タスクを定義するファイルとRPMファイルを配置します。
some_ansible +-- roles +-- hello +-- tasks | +-- main.yml +-- files +-- hello-0.2.4-6.el7.x86_64.rpm
タスクの定義で、copyしてからローカルファイルシステムのパスを指定してyumを実行します。
- name: RPMを対象へコピー
copy: src=hello-0.2.4-6.el7.x86_64.rpm dest=/tmp/hello-0.2.4-6.el7.x86_64.rpm
- name: RPMをインストール
sudo: yes
yum: name=/tmp/hello-0.2.4-6.el7.x86_64.rpm
URLで指定したRPMをインストールしたい¶
- name: RPMをインストール
sudo: yes
yum: name=http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
state=present
シンボリックリンクを作成したい¶
fileモジュールが提供されています。
- name: シンボリックリンクの作成
file: src=/var/lib/redmine-3.1.1
dest=/var/lib/redmine
force=yes
state=link
ホスト名を設定したい¶
hostnameモジュールが提供されています。
- name: ホスト名を変更する
sudo: yes
hostname: name=oscar01
inventoryファイルで定義したホスト名に設定する場合は、hostname: name={{ inventory_hostname }}
で指定できます。
FQDNでホスト名を設定する場合も、hostname: name={{ inventory_hostname }}.mydomain
で指定できます。
- name: ホスト名を変更する
sudo: yes
hostname: name={{ inventory_hostname }}.example.com
/etc/hostsにホスト名とIPアドレスを設定したい¶
localhostと自ホストだけを定義した/etc/hostsを作成する場合は、自ホスト名とIPアドレスをテンプレートに埋め込む方法が使えます。
- name: /etc/hsotsを設置する
sudo: yes
template: src=templates/hosts.j2 dest=/etc/hosts
templateモジュールでテンプレートとなるhostsファイルを指定します。テンプレートは次のようになります。
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 {{ ansible_default_ipv4.address }} {{ inventory_hostname }}.mydomain {{ inventory_hostname }}
ここで、ansible_default_ipv4.address は、"gather fact(setup)"で収集されるホスト情報に含まれます。
$ ansible oscar01 -i ./hosts -m setup oscar01 | SUCCESS => { "ansible_facts": { :(中略) "ansible_default_ipv4": { "address": "192.168.1.11", "alias": "eth0", "broadcast": "192.168.1.255", "gateway": "192.168.1.254", "interface": "eth0", "macaddress": "52:54:00:ab:cd:ef", "mtu": 1500, "netmask": "255.255.255.0", "network": "192.168.1.0", "type": "ether" }, :(後略)
サービスの自動起動設定、起動をさせたい¶
- name: MariaDB 起動・自動起動設定
sudo: yes
service: name=mariadb state=started enabled=yes
Linux上にグループを作成したい¶
- name: redmineグループの作成
sudo: yes
group: name=redmine gid=1000
Linux上にユーザーを作成したい¶
- name: redmineユーザーの作成
sudo: yes
user: name=redmine uid=1000 group=redmine
password=$6$rounds=656000$g0iZb...(中略)...EFsbxk/KVBZUIM8rXRUpms0
パスワードは、あらかじめSHA-512でハッシュしたものをここに指定しています。作成方法はansibleのドキュメントに記載(次のURL)されています。
http://docs.ansible.com/ansible/faq.html#how-do-i-generate-crypted-passwords-for-the-user-module
ハッシュの生成には、mkpasswdコマンドか、pythonのプログラム(passlibを使う)が使えます。なお、Cygwinにはmkpasswdがありますが、--methodオプションがなく、本目的のものとは違うようです。
そこで、pythonのプログラムで作成します。プログラムといっても、ワンライナーで実行します。pip install passlib
でpasslibモジュールをインストールして、次のハッシュを作成します。
~$ python -c "from passlib.hash import sha512_crypt; import getpass; print sha512_crypt.encrypt('パスワード')"
gitのクローンを作成したい¶
- name: farend_basicテーマのダウンロード
sudo: yes
sudo_user: redmine
git: repo=https://github.com/farend/redmine_theme_farend_basic.git
dest={{ redmine_dir }}/public/themes/farend_basic
カレントディレクトリと環境変数を設定してコマンドを実行したい¶
- name: secret tokenの作成
sudo: yes
sudo_user: redmine
command: bundle exec rake generate_secret_token
chdir={{ redmine_dir }}
environment:
RAILS_ENV: production
MySQLの設定に初回インストール時と2回目以降で冪等性を持たせたい¶
MySQLは初期インストールではrootユーザーがパスワードなしとなっています。mysql_userやmysql_dbなどのモジュールは、接続ユーザー/パスワードの指定(login_user/login_password)がない場合は、my.cnfの認証設定を使用し、それがなければrootユーザーでパスワードなしを使用します。
そのため、rootユーザーにパスワードを設定する次のタスクは、MySQLをインストールした直後の1回目は成功しますが、2回目以降は失敗します。
- name: rootパスワード設定
mysql_user: name=root
password={{ db_passwd_root }}
この記述を持つplaybookを実行すると2回目以降で次のエラーが発生します。
failed: [foohost] => {"failed": true} msg: unable to connect to database, check login_user and login_password are correct or ~/.my.cnf has the credentials
冪等性を持たせるには、次のように記述します。
- name: rootパスワード設定
mysql_user: name=root
password={{ db_passwd_root }}
login_user=root
login_password={{ db_password_root }}
check_implicit_admin=yes
login_userとlogin_passwordは、MySQLへ接続する認証で、1回目はrootにパスワードが設定されていないのでこの認証はエラーになります。
しかし、check_implicit_admin=yesを設定しておくと、認証に先立ちパスワード無しrootでの接続を試みます。そのため、1回目の設定が可能になります。
設定ファイルの一部修正¶
対象ホストの設定ファイルを一部修正する場合、状況によってlineinfileモジュール、replaceモジュール、ini_fileモジュールを使うか、commandあるいはshellモジュールでUNIXコマンドレベルで実施するといった方法があります。
lineinfileモジュールは、1行追加、1行置換のどちらかを行います。with_itemsと組み合わせることで複数行の置換も可能です。
次に、/etc/chrony.conf でNTPサーバー設定行を次のように書き換える例を示します。
- server 0.fedora.pool.ntp.org iburst
- server 1.fedora.pool.ntp.org iburst
- server 2.fedora.pool.ntp.org iburst
- server 3.fedora.pool.ntp.org iburst
+ server ntp.nict.jp
+ server ntp1.jst.mfeed.ad.jp
+ server ntp2.jst.mfeed.ad.jp
+ server ntp3.jst.mfeed.ad.jp
これをlineinfileモジュールで修正する場合の例を次に示します。
- name: chrony設定
lineinfile: backrefs=yes
dest='/etc/chrony.conf'
regexp='{{ item.regexp }}'
line='{{ item.line }}'
with_items:
# nict ntp server
- regexp: '^server 0.centos.*'
line: 'server ntp.nict.jp'
- regexp: '^server 1.centos.*'
line: 'server ntp1.jst.mfeed.ad.jp'
- regexp: '^server 2.centos.*'
line: 'server ntp2.jst.mfeed.ad.jp'
- regexp: '^server 3.centos.*'
line: 'server ntp3.jst.mfeed.ad.jp'
- backrefsを指定すると、正規表現にマッチしない場合は変更なしと判断されます。backrefsを指定しないと、実際には修正をしなくても毎回変更ありとなってしまいます。
- with_itemsでは、マップ形式でregexとlineの組合せを定義します。
- バックアップを残したい場合は、backup=yesを設定します。
正規表現に合致した行を、置換ではなく削除したい場合は、lineinfileモジュールでregexとstate=absentを指定します。
- name: chrony設定(2)
lineinfile: backrefs=yes
dest='/etc/chrony.conf'
regexp='^server [123].centos.*'
state=absent
または、replaceモジュールでregexpを指定し、replaceを省略します。
- name: chrony設定(2)
replace: dest='/etc/chrony.conf'
regexp='^server [123].centos.*'
特定のホストグループの場合にモジュールを実行したい¶
インベントリファイルに'ntpservers'グループで定義したホストの場合にサービスnfsを起動・自動起動設定する場合の例を示します。
- name: NFSサーバーのサービス起動
service: name=nfs state=started enabled=yes
when: "'ntpservers' in group_names"
複数のRPMパッケージを1つのタスクでまとめてインストールしたい(with_items)¶
- name:
yum: name={{ item }} state=latest update_cache=yes
with_items:
- acpid
- openssh-clients
- ntp
ハンドラー¶
あるタスクが実行(changed)されたら実行したい¶
設定ファイルに変更があればサービスを再起動するとします。
tasks:
- name: httpd.confのコピー
copy: src=files/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify: restart httpd
- name: httpdのコピー
copy: src=files/httpd dest=/etc/sysconfig/httpd
notify: restart httpd
handlers:
- name: restart httpd
service: name=httpd state=restarted
各タスクで、notifyに通知先タスク名を記述しておきます。各タスクの実行結果がchangedであれば、notifyで記述した通知先タスクが実行されます。
handlersは、tasksの処理が全て終わったあとに実行されるので、複数のタスクでnotifyが通知されても1回だけ実行します。
インベントリ¶
ホスト名とIPアドレスをインベントリに記述する¶
ホスト名を変数として設定に使用したいが、ホスト名からIPアドレス解決を外部的に持たない場合、インベントリにホスト名とIPアドレスの定義を一緒に記述することができます。
Ansible 2.0未満¶
[tango] tango1 ansible_ssh_host=192.168.1.131
Ansible 2.0以降¶
[tango] tango1 ansible_host=192.168.1.131
ワンライナー¶
パスワード指定で各マシンに接続してコマンドを実行する¶
Ansibleは、インベントリファイルに記述がないホストへは接続しないので、インベントリファイルを用意します。例:inventories
alfa bravo charlie delta echo foxtrot golf
指定したインベントリファイルに記載の対象ホスト(allはすべて)、接続するユーザー名とコマンドを指定し、パスワードを入力して実行します。
~$ ansible all -i inventories -u root -k -m command -a "uname -a" SSH password: ******** alfa | success | rc=0 >> Linux alfa 2.6.32-504.1.3.el6.x86_64 #1 SMP Tue Nov 11 17:57:25 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux bravo | success | rc=0 >> Linux bravo 2.6.32-504.8.1.el6.x86_64 #1 SMP Wed Jan 28 21:11:36 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux charlie | success | rc=0 >> Linux charlie 3.10.0-229.el7.x86_64 #1 SMP Fri Mar 6 11:36:42 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux :(略)
all
インベントリファイルのホスト全てを指定-i inventories
インベントリファイルにinventoriesを指定(省略時は/etc/ansible/hostsを使用)-u root
rootユーザーで接続を指定-k
ユーザー認証はパスワード認証で、ansibleコマンド実行時に対話的に入力する指定-m command
commandモジュールを実行-a "uname -a"
モジュールに渡す引数
指定したインベントリファイルに記載の対象ホスト(allはすべて)と、ansibleを実行しているユーザーで接続し、sudo でコマンドを実行、パスワードを入力して実行します。
~$ ansible all -i inventories -s -K -m command -a "uname -a" SUDO password: ******** :
-s
sudo で特権実行-K
sudo のパスワードをansibleコマンド実行時に対話的に入力する指定
指定したインベントリファイルに記載の対象ホストと、ansibleを実行しているユーザーで接続し、su でコマンドを実行するユーザーを指定、パスワードを入力して実行します。
~$ ansible redmine_servers -i inventories -U redmine -k -m command -a "tail -1 /var/lib/redmine/log/production.log" SUDO password: ******** :
ロール¶
ロールにタグを付け、指定したタグのロールのみ実行あるいはスキップ¶
playbookファイルのロールについてタグを指定します。ロール名と同じ名前でタグを付けるとよいでしょう。
---
- hosts: redmine-servers
become: yes
roles:
- { role: admin, tags: admin }
- role: system
tags: system
ansible-playbookコマンドのオプション-t タグ名
で実行するロールを指定します。--skip-tags=タグ名
でスキップするロールを指定します。
$ ansbile-playbook site.yml -t "unicorn,nginx" redmine-servers
実行環境¶
メッセージの色を見やすいように変更する¶
暗色系の背景でansibleを実行すると、詳細メッセージが青でコントラストが小さく文字が読みにくいことがあります。
/etc/ansible/ansible.cfg で色設定を変更できないか試してみましたが、だめなようです。
デフォルトのカラー設定
部位 | 定義色名 | ANSI設定 | 備考 |
---|---|---|---|
詳細メッセージ(verbose) | blue | 暗色系背景では視認性悪い | |
警告メッセージ(warn) | bright purple | ||
エラーメッセージ(error) | red | ||
デバッグメッセージ(debug) | dark gray | ||
非推奨メッセージ(deprecate) | purple | ||
スキップメッセージ(skip) | cyan | ||
到達できず(unreachable) | red | ||
OK(ok) | green | ||
変更あり(changed) | yellow | ||
差異の追加(diff add) | green | ||
差異の削除(diff remove) | red | ||
差異の行(diff lines) | cyan |
codeCodes = {
'black': u'0;30', 'bright gray': u'0;37',
'blue': u'0;34', 'white': u'1;37',
'green': u'0;32', 'bright blue': u'1;34',
'cyan': u'0;36', 'bright green': u'1;32',
'red': u'0;31', 'bright cyan': u'1;36',
'purple': u'0;35', 'bright red': u'1;31',
'yellow': u'0;33', 'bright purple': u'1;35',
'dark gray': u'1;30', 'bright yellow': u'1;33',
'normal': u'0'
}
そこでメッセージを出力している箇所を直接調べてみると、
- /usr/lib/python2.7/site-packages/ansible/utils/display.py
def verbose(self, msg, host=None, caplevel=2):
# FIXME: this needs to be implemented
#msg = utils.sanitize_output(msg)
if self.verbosity > caplevel:
if host is None:
- self.display(msg, color='blue')
+ self.display(msg, color='bright gray')
else:
- self.display("<%s> %s" % (host, msg), color='blue', screen_only=True)
+ self.display("<%s> %s" % (host, msg), color='bright gray', screen_only=True)
トラブルシュート¶
接続¶
YAML¶
参考情報¶
インターネット公開資料¶
Ansible公式サイト¶
書籍¶
邦訳・和書¶
- 「入門 Ansible」(若山史郎 著、Gumroad販売、2014年11月、電子書籍)
https://gumroad.com/l/TNHSc - 「初めてのAnsible」(Lorin Hochstein著、Sky株式会社 玉川竜司 訳、2016年4月、オライリー刊)
原書 Ansible: Up and Running(2015-12)
http://www.oreilly.co.jp/books/9784873117652/ - 「Ansible完全読本」(廣川英寿 著、アマゾン販売、2016年5月、電子書籍(Kindle))
https://www.amazon.co.jp/dp/B01G3OZG78