Skip to main content

3 posts tagged with "ansible"

View All Tags

· 6 min read
Shunsuke Suzuki

ansible 専用の testing ツール molecule を紹介します。 molecule の公式ドキュメント以外の情報は少ないので、参考になれば幸いです。

以前 Docker を使って ansible のテストをする方法を紹介しました。

https://suzuki-shunsuke.github.io/test-ansible-on-docker/

この際は Docker Compose と簡単なシェルスクリプトを使って実現しました。 これはこれでブラックボックスな部分がなく、学習コストも低くて悪くないので興味のある方はそちらもご参照ください。

molecule は ansible 専用の testing ツールです。 基本的に playbook というより role 用のツールですが、playbookのテストも工夫すれば出来ます。

  • 情報が少ない
  • 公式ドキュメントも分かりづらい部分がある
  • コマンドがエラー吐いて失敗した際に、ググっても情報が出てこないので辛い

という風に辛い部分もありますが、

という風に良い面もあります。

それでは使っていきましょう。

インストール

https://molecule.readthedocs.io/en/latest/installation.html

$ pip install molecule

Docker を使う場合 docker-py も必要です。

$ pip install docker-py

role のテスト

playbookに比べて role のテストは簡単です。

role のディレクトリ(tasksやfilesなどがあるディレクトリ)に移動してコマンドを実行します。

$ molecule init scenario -r <role name>

こうすると molecule ディレクトリが生成されます。

molecule/default/molecule.yml を修正します。

https://molecule.readthedocs.io/en/latest/configuration.html

---
dependency:
name: galaxy
# 依存する role がある場合
options:
role-file: roles.yml
driver:
name: docker
lint:
name: yamllint
# https://molecule.readthedocs.io/en/latest/configuration.html#platforms
platforms:
- name: server # コンテナの名前になる
# 必要に応じて image を変更
# 今回は ansibleのremote user を非rootにするために自作の Docker Image を指定
# https://hub.docker.com/r/suzukishunsuke/ansible-test-centos/
image: suzukishunsuke/ansible-test-centos:0.1.0
# systemd を使ったりする場合
# https://molecule.readthedocs.io/en/latest/examples.html#systemd-container
privileged: true
command: /sbin/init # systemd を使う場合必要
env:
USER: foo # DockerだとUSER環境変数が空になってしまうようなので明示的に設定
provisioner:
# https://molecule.readthedocs.io/en/latest/configuration.html#id12
name: ansible
lint:
name: ansible-lint
options:
user: foo # 非rootユーザーで実行
inventory:
group_vars:
# variables を指定
all:
nginx_server_name: localhost
mysql_host: localhost
mysql_port: 3306
mysql_database: grafana
mysql_user: root
mysql_password: password
scenario:
name: default
verifier:
name: testinfra
lint:
name: flake8

test の前にまずは lint します。

$ molecule lint [-s <senario name>]

すると yamllint の設定ファイル .yamllint が作られていると思うので、必要に応じて修正します。

https://yamllint.readthedocs.io/en/stable/configuration.html

ansible-lint で引っかかった人はこちらを参照してください。

https://github.com/ansible/ansible-lint

そして test コマンドを実行します。

$ molecule test [-s <senario name>]

test コマンドではコンテナが削除されるため、デバッグが難しかったりします。

その場合、 converge コマンドを実行すればコンテナは消えません。

$ molecule converge [-s <senario name>]

消したくなったら destroy コマンドで消しましょう。

$ molecule destroy [-s <senario name>]

playbook のテスト

次に playbook のテストです。割とこれが本題だったりします。 molecule は基本的に playbook というより role 用のツールなので若干工夫が必要です。

自分はよく ansible playbook のディレクトリ構成を以下のようにします。

hello-molecule/  # ルートディレクトリ
agent.yml # agent グループ用の playbook
group_vars/
all.yml # 共通のvariables
agent.yml # agent グループ用の variables
roles/ # role
inventories/
prod.yml # production用のinventory
roles.yml # 依存する role のリスト
ansible.cfg

このときに playbook agent.yml のテストがしたいとします。 molecule のためにこの構成を弄ったりは極力したくありません。

playbook のディレクトリで molecule init を実行します。 default シナリオは必須のようです。

$ molecule init scenario -r hello-molecule
$ molecule init scenario -s agent -r hello-molecule

するとこうなります。

hello-molecule/
agent.yml
group_vars/
all.yml
agent.yml
roles/
inventories/
prod.yml
roles.yml
ansible.cfg
molecule/
default/
agent/
molecule.yml
playbook.yml # これは使わない。消す

ここから molecule.yml を修正していきます。 一部抜粋します。

---
dependency:
name: galaxy
options:
role-file: roles.yml # ルートディレクトリからの相対パス
platforms:
- name: server # group名
image: centos:7
provisioner:
name: ansible
playbooks:
converge: ../../server.yml # ルートディレクトリにある playbookを指定
env:
ANSIBLE_ROLES_PATH: ../../roles:../../_roles # roleのパスを修正
scenario:
name: server

このように playbookや role のパスを修正すればあとは role のテストと同じ要領でいけると思います。

以上、簡単ですが molecule の使い方を紹介しました。

· 6 min read
Shunsuke Suzuki

自作のOSS akoi の紹介をします。

  • なぜこんなものを作ったのか
  • akoi と ansible を使ってサーバにバイナリをインストールする方法

について主に説明します。

まとめ

  • akoi はバイナリファイルのインストーラ
  • 設定ファイルで管理できる
  • 冪等であり、効率よくインストールできる
    • 並列インストール
    • Accept-Ranges による分散ダウンロード
  • ansibleでサーバにバイナリをインストールするのを補助してくれる
    • ansible で真面目にバージョンコントロールして効率よくインストールするのは難しい(ほとんどの ansible role は出来ていない)

akoi とは

akoi はバイナリファイルのインストーラです。 設定ファイルにインストールするファイルのダウンロードURLとインストール先を記述して管理します。 インストールするバイナリのバージョン管理が可能であり、既にインストールしてあるバージョンへの切り替えはシンボリックを作り直すだけなので一瞬で終わります。無駄にダウンロードをしたりはしません。 複数のバイナリを並列でインストールしたり、Accept-Ranges ヘッダによる分散ダウンロードをサポートしています。

分散ダウンロードについては

https://qiita.com/codehex/items/d0a500ac387d39a34401

が参考になります。

Goで書かれています。

https://github.com/suzuki-shunsuke/akoi/releases からバイナリをダウンロードしてインストールできます。

詳細はREADMEを読んでください。

なぜ作ったのか

サーバにバイナリをインストールする ansible role を書くのが辛かったからです。 最近は色々なソフトウェアがGoで書かれ、バイナリで配布されています。 そういったバイナリをサーバへインストールするのは ansible で行っているという方も少なくないのではないでしょうか? 有名なソフトウェアをインストールする ansible role は大抵Ansible Galaxy で公開されています。

しかし、ほとんどの role は「真面目に」バージョン管理していません。 ここでいう「真面目に」とは

  1. バージョンを指定できる
  2. バージョンを変更できる
  3. 指定したバージョンが既にインストールされている場合は無駄にダウンロードしたりしない

といったことです。

これらを ansible でやろうとすると結構面倒なんです。

既存のroleでよくあるのが

  1. バージョンにかかわらず既にインストールされていたらインストールしない(バージョン変更できない)
  2. 1の問題を解決するため、強制的に再インストールするフラグがある(同じバージョンのものがインストールされていても無駄に再インストールする)

だと思います。

真面目にやろうとするとこんな感じになる気がします。

https://github.com/suzuki-shunsuke/ansible_role_akoi/blob/master/tasks/install_binary.yml

これらのロジックはソフトウェアに関わらずほとんど共通です。 それをソフトウェアごとに実装してテストしてなんてのは面倒です。

そこで akoi を作る前に汎用的な ansible role として開発してみたのが

https://github.com/suzuki-shunsuke/ansible-role-general-installer

です。

しかしこれは ansible のバグでうまく動きませんでした。

https://github.com/ansible/ansible/issues/34736

そこで作られたのが akoi です。 結果的に ansible でやるより高速かつ汎用的なので作って良かったと思います。

akoi と ansible を使ってサーバにバイナリをインストール

akoi を使うにしても ansible が不要になるという話ではなく、ansible でakoiのコマンドを実行する感じになります。 README にも書きましたが、 akoiを ansible の shell モジュールから呼び出して標準出力をパースすることで task の changed を判定することができます。

tasks:
- name: install consul
shell: "/usr/local/bin/akoi install -f ansible 2>&1"
register: result
changed_when: (result.stdout|from_json)["changed"]

akoi を使ってソフトウェアをインストールために、そもそもどうやってサーバに akoi をインストールするかですが(各サーバに akoi をインストールする必要があります)、 akoi をインストールする ansible role を提供しています。

https://github.com/suzuki-shunsuke/ansible_role_akoi

これで akoi を使ってバイナリをインストールできますが、ソフトウェアのセットアップはバイナリをインストールすれば終わりということではなく、ユーザーやグループを作成したり、設定ファイルを作成したり、systemd のサービスを起動したりと色々あります。

自分はそれらの処理は別の ansible role として開発しています。

バイナリのインストールは akoi でやり、それ以外の部分は別途 ansible role を開発するというスタイルです。 それらの role ではいちいちバイナリをインストールする処理を書かなくて良いのでだいぶ開発が楽になりました。

· 3 min read
Shunsuke Suzuki

ansible playbookを(VMの代わりに)Dockerコンテナに対して実行すると、効率よく動作確認できるというお話です。 ansible playbookの動作確認のためにvagrantでVMを起動したりしていると動作確認に時間がかかるし、容量も喰います。 Dockerコンテナを使って動作確認できればこれらの問題を解決できます。

ただし、Dockerコンテナの場合、一部のansible のtaskが失敗することがあるので ansible playbookによってはDockerコンテナではテストにならない場合もあるかと思います。

サンプル

https://github.com/suzuki-shunsuke/example/tree/master/ansible/test-on-docker

簡単なサンプルを用意しました。

ansible playbookに加え、

  • docker-compose.yml
  • test_docker.sh: 簡単なシェルスクリプト

を作成してあります。

$ bash test_docker.sh

とすることで動作確認できます。

説明

スクリプトでやっていることは

  1. Docker Compose でコンテナを起動
  2. コンテナのIDを取得し、inventory ファイルを作成
  3. Docker Connection Pluginを使ってコンテナにplaybookを実行

です。

Docker Connection Plugin を使うとDockerコンテナに対してansible playbookを実行できます。

また、Docker Hubで公開されている多くのDockerイメージのUSERは root ですが、 ansible playbookの動作確認としては都合が悪かったりします。

そこで自分は非rootユーザーを作成したDocker Imageを使っています。

https://hub.docker.com/r/suzukishunsuke/ansible-test-centos/

関係ありそうなツール

今回は簡単なスクリプトとdocker-compose.ymlを用意しましたが、 もっとイケてるやり方がありそうなものです。

Vagrant Docker Provider

https://www.vagrantup.com/docs/docker/

なんかあまり使えなさそうです。 Linux以外だと結局VMが必要で、既に非推奨な boot2docker をデフォルトでは使うらしくだめそうだなって思いました。 あまり調べてません。

https://www.vagrantup.com/docs/docker/basics.html#host-vm

By default, the host VM Vagrant spins up is backed by boot2docker, because it launches quickly and uses little resources.

Ansible Container

https://docs.ansible.com/ansible-container/

よく知りません。動作確認したいだけだとオーバースペックな印象は受けます。

Packer

記事を書き終わってからそういえば Packer があったなと思い出しました。