みなさん、こんにちは!
私はホテル予約サービスの DevOps エンジニアとして働いています。
Ostrovok.ru では、構成マネージャーとして ansible を使用しています。 最近、ロールをテストする必要があるようになりましたが、結局のところ、これを行うためのツールはあまり多くありません。おそらく最も人気のあるのは Molecule フレームワークなので、それを使用することにしました。 しかし、彼の文書には多くの落とし穴について記載されていないことが判明しました。 ロシア語で十分に詳細なガイドが見つからなかったので、この記事を書くことにしました。
分子
簡単な説明: Molecule は、指定したプラットフォーム (クラウド、仮想マシン、コンテナー) 上にインスタンスを作成します。詳細については、セクションを参照してください。
今もっと。
いくつかの説
分子の XNUMX つの主要なエンティティ、シナリオとドライバーについて考えてみましょう。
<span class="notranslate">シナリオ</span>
スクリプトには、何を、どこで、どのように、どのような順序で実行するかについての説明が含まれています。 XNUMX つのロールに複数のスクリプトを含めることができ、それぞれがパス上のディレクトリになります。 <role>/molecule/<scenario>
、テストに必要なアクションの説明が含まれています。 スクリプトを含める必要があります default
これは、Molecule を使用してロールを初期化すると自動的に作成されます。 次のスクリプトの名前は任意です。
スクリプト内の一連のテスト アクションは次のように呼ばれます。 マトリックス、デフォルトでは次のようになります。
(マークされたステップ ?
、ユーザーが指定しない場合、デフォルトでスキップされます)
lint
- リンターの実行。 デフォルトではyamllint
иflake8
,destroy
— Molecule の前回の起動からインスタンスを削除します (残っている場合)。dependency
? — テストされたロールの ansible 依存関係のインストール、syntax
- を使用してロール構文をチェックするansible-playbook --syntax-check
,create
- インスタンスの作成、prepare
? — インスタンスを準備する。 たとえば、python2の確認/インストールconverge
— テスト済みのプレイブックを起動する、idempotence
— 冪等性テストのプレイブックを再実行します。side_effect
? — 役割には直接関係しないが、テストには必要なアクション、verify
— を使用して、結果の構成のテストを実行します。testinfra
(デフォルト) /goss
/inspec
,cleanup
? - (新しいバージョンでは) - 大まかに言うと、Molecule の影響を受ける外部インフラストラクチャを「クリーニング」します。destroy
— インスタンスの削除。
この順序はほとんどのケースをカバーしますが、必要に応じて変更できます。
上記の各ステップは、次を使用して個別に実行できます。 molecule <command>
。 ただし、そのような cli コマンドごとに独自のアクションのシーケンスが存在する可能性があることを理解しておく必要があります。これは、次のコマンドを実行して確認できます。 molecule matrix <command>
。 たとえば、コマンドを実行すると、 converge
(テストされたプレイブックを実行すると) 次のアクションが実行されます。
$ molecule matrix converge
...
└── default # название сценария
├── dependency # установка зависимостей
├── create # создание инстанса
├── prepare # преднастройка инстанса
└── converge # прогон плейбука
これらのアクションのシーケンスは編集できます。 リスト内の何かがすでに完了している場合、それはスキップされます。 現在の状態とインスタンス構成は、Molecule ディレクトリに保存されます。 $TMPDIR/molecule/<role>/<scenario>
.
ステップを追加する ?
Ansible Playbook 形式で必要なアクションを記述し、次の手順に従ってファイル名を付けることができます。 prepare.yml
/side_effect.yml
。 これらの Molecule ファイルはスクリプト フォルダー内にあると考えられます。
ドライバ
ドライバーは、テスト用のインスタンスが作成されるエンティティです。
Molecule が既製のテンプレートを備えている標準ドライバーのリストは、Azure、Docker、EC2、GCE、LXC、LXD、OpenStack、Vagrant、Delegated です。
ほとんどの場合、テンプレートはファイルです create.yml
и destroy.yml
スクリプト フォルダー内に、インスタンスの作成と削除がそれぞれ記述されています。
Docker と Vagrant は例外です。これらのモジュールとの対話は、上記のファイルがなくても発生する可能性があるためです。
Delegated ドライバーを使用する場合、インスタンスの作成ファイルと削除ファイルにはインスタンス構成に関する作業のみが記述され、残りの部分はエンジニアが記述する必要があるため、Delegated ドライバーを強調する価値があります。
デフォルトのドライバーは Docker です。
それでは、練習に移り、さらなる機能を検討してみましょう。
はじめに
「Hello world」として、単純な nginx インストール ロールをテストしてみましょう。 ドライバーとして docker を選択しましょう。ほとんどの人はそれをインストールしていると思います (docker がデフォルトのドライバーであることを覚えておいてください)。
準備をしましょう virtualenv
そしてそこにインストールします molecule
:
> pip install virtualenv
> virtualenv -p `which python2` venv
> source venv/bin/activate
> pip install molecule docker # molecule установит ansible как зависимость; docker для драйвера
次のステップは、新しいロールを初期化することです。
新しいロールと新しいスクリプトの初期化は、次のコマンドを使用して実行されます。 molecule init <params>
:
> molecule init role -r nginx
--> Initializing new role nginx...
Initialized role in <path>/nginx successfully.
> cd nginx
> tree -L 1
.
├── README.md
├── defaults
├── handlers
├── meta
├── molecule
├── tasks
└── vars
6 directories, 1 file
結果は典型的な ansible ロールになります。 さらに、Molecules CLI とのすべての対話は、ロール ルートから行われます。
役割ディレクトリの内容を見てみましょう。
> tree molecule/default/
molecule/default/
├── Dockerfile.j2 # Jinja-шаблон для Dockerfile
├── INSTALL.rst. # Немного информации об установке зависимостей сценария
├── molecule.yml # Файл конфигурации
├── playbook.yml # Плейбук запуска роли
└── tests # Директория с тестами стадии verify
└── test_default.py
1 directory, 6 files
構成を見てみましょう molecule/default/molecule.yml
(Docker イメージのみを置き換えます):
---
dependency:
name: galaxy
driver:
name: docker
lint:
name: yamllint
platforms:
- name: instance
image: centos:7
provisioner:
name: ansible
lint:
name: ansible-lint
scenario:
name: default
verifier:
name: testinfra
lint:
name: flake8
依存関係
このセクションでは、依存関係のソースについて説明します。
Shell は、Galaxy と Gilt ではニーズが満たされない場合に使用するコマンド シェルです。
私はここに長く滞在しません、それはで十分に説明されています
ドライバー
ドライバー名。 私たちにとって、これは docker です。
糸くず
Yamllint はリンターとして使用されます。
構成のこの部分の便利なオプションには、yamllint の構成ファイルを指定する機能、環境変数を転送する機能、またはリンターを無効にする機能があります。
lint:
name: yamllint
options:
config-file: foo/bar
env:
FOO: bar
enabled: False
プラットフォーム
インスタンスの構成について説明します。
ドライバーとして docker を使用する場合、Molecule はこのセクションを反復処理し、リストの各要素は以下で使用できます。 Dockerfile.j2
変数として item
.
ドライバーの場合、 create.yml
и destroy.yml
、セクションは次のように利用できます。 molecule_yml.platforms
、およびそれに対する反復は、これらのファイルにすでに記述されています。
Molecule は Ansible モジュールにインスタンス管理を提供するため、そこで可能な設定のリストを探す必要があります。 たとえば、Docker の場合、モジュールが使用されます。
各種ドライバーの使用例もご覧いただけます
ここで交換しましょう セントス:7 на Ubuntuの.
プロビジョナー
「プロバイダ」とは、インスタンスを管理する主体です。 Molecule の場合、これは Ansible ですが、他のサポートは計画されていないため、このセクションは、留保付きで拡張 Ansible 構成と呼ぶことができます。
ここで指摘できることはたくさんありますが、私の意見では、主要な点を強調します。
- プレイブック: 特定の段階でどの Playbook を使用するかを指定できます。
provisioner:
name: ansible
playbooks:
create: create.yml
destroy: ../default/destroy.yml
converge: playbook.yml
side_effect: side_effect.yml
cleanup: cleanup.yml
- 構成オプション:
アンシブル設定
provisioner:
name: ansible
config_options:
defaults:
fact_caching: jsonfile
ssh_connection:
scp_if_ssh: True
- 接続オプション: オプション
接続性
provisioner:
name: ansible
connection_options:
ansible_ssh_common_args: "-o 'UserKnownHostsFile=/dev/null' -o 'ForwardAgent=yes'"
- オプション: Ansible パラメーターと環境変数
provisioner:
name: ansible
options:
vvv: true
diff: true
env:
FOO: BAR
シナリオ
スクリプト シーケンスの名前と説明。
キーを追加すると、コマンドのデフォルトのアクション マトリックスを変更できます。 <command>_sequence
必要なステップのリストを定義することで、その値として使用します。
Playbook run コマンドを実行するときのアクションのシーケンスを変更したいとします。 molecule converge
# изначально:
# - dependency
# - create
# - prepare
# - converge
scenario:
name: default
converge_sequence:
- create
- converge
検証者
テスト用のフレームワークとそのリンターをセットアップします。 デフォルトではリンターが使用されます testinfra
и flake8
。 可能なオプションは上記と同じです。
verifier:
name: testinfra
additional_files_or_dirs:
- ../path/to/test_1.py
- ../path/to/test_2.py
- ../path/to/directory/*
options:
n: 1
enabled: False
env:
FOO: bar
lint:
name: flake8
options:
benchmark: True
enabled: False
env:
FOO: bar
私たちの役割に戻りましょう。 ファイルを編集しましょう tasks/main.yml
この見た目に:
---
- name: Install nginx
apt:
name: nginx
state: present
- name: Start nginx
service:
name: nginx
state: started
そしてテストを追加します molecule/default/tests/test_default.py
def test_nginx_is_installed(host):
nginx = host.package("nginx")
assert nginx.is_installed
def test_nginx_running_and_enabled(host):
nginx = host.service("nginx")
assert nginx.is_running
assert nginx.is_enabled
def test_nginx_config(host):
host.run("nginx -t")
完了したら、あとは実行するだけです (ロールのルートから実行します)。
> molecule test
スポイラー下のロングエキゾースト:
--> Validating schema <path>/nginx/molecule/default/molecule.yml.
Validation completed successfully.
--> Test matrix
└── default
├── lint
├── destroy
├── dependency
├── syntax
├── create
├── prepare
├── converge
├── idempotence
├── side_effect
├── verify
└── destroy
--> Scenario: 'default'
--> Action: 'lint'
--> Executing Yamllint on files found in <path>/nginx/...
Lint completed successfully.
--> Executing Flake8 on files found in <path>/nginx/molecule/default/tests/...
Lint completed successfully.
--> Executing Ansible Lint on <path>/nginx/molecule/default/playbook.yml...
Lint completed successfully.
--> Scenario: 'default'
--> Action: 'destroy'
PLAY [Destroy] *****************************************************************
TASK [Destroy molecule instance(s)] ********************************************
changed: [localhost] => (item=None)
changed: [localhost]
TASK [Wait for instance(s) deletion to complete] *******************************
ok: [localhost] => (item=None)
ok: [localhost]
TASK [Delete docker network(s)] ************************************************
PLAY RECAP *********************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0
--> Scenario: 'default'
--> Action: 'dependency'
Skipping, missing the requirements file.
--> Scenario: 'default'
--> Action: 'syntax'
playbook: <path>/nginx/molecule/default/playbook.yml
--> Scenario: 'default'
--> Action: 'create'
PLAY [Create] ******************************************************************
TASK [Log into a Docker registry] **********************************************
skipping: [localhost] => (item=None)
TASK [Create Dockerfiles from image names] *************************************
changed: [localhost] => (item=None)
changed: [localhost]
TASK [Discover local Docker images] ********************************************
ok: [localhost] => (item=None)
ok: [localhost]
TASK [Build an Ansible compatible image] ***************************************
changed: [localhost] => (item=None)
changed: [localhost]
TASK [Create docker network(s)] ************************************************
TASK [Create molecule instance(s)] *********************************************
changed: [localhost] => (item=None)
changed: [localhost]
TASK [Wait for instance(s) creation to complete] *******************************
changed: [localhost] => (item=None)
changed: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=5 changed=4 unreachable=0 failed=0
--> Scenario: 'default'
--> Action: 'prepare'
Skipping, prepare playbook not configured.
--> Scenario: 'default'
--> Action: 'converge'
PLAY [Converge] ****************************************************************
TASK [Gathering Facts] *********************************************************
ok: [instance]
TASK [nginx : Install nginx] ***************************************************
changed: [instance]
TASK [nginx : Start nginx] *****************************************************
changed: [instance]
PLAY RECAP *********************************************************************
instance : ok=3 changed=2 unreachable=0 failed=0
--> Scenario: 'default'
--> Action: 'idempotence'
Idempotence completed successfully.
--> Scenario: 'default'
--> Action: 'side_effect'
Skipping, side effect playbook not configured.
--> Scenario: 'default'
--> Action: 'verify'
--> Executing Testinfra tests found in <path>/nginx/molecule/default/tests/...
============================= test session starts ==============================
platform darwin -- Python 2.7.15, pytest-4.3.0, py-1.8.0, pluggy-0.9.0
rootdir: <path>/nginx/molecule/default, inifile:
plugins: testinfra-1.16.0
collected 4 items
tests/test_default.py .... [100%]
========================== 4 passed in 27.23 seconds ===========================
Verifier completed successfully.
--> Scenario: 'default'
--> Action: 'destroy'
PLAY [Destroy] *****************************************************************
TASK [Destroy molecule instance(s)] ********************************************
changed: [localhost] => (item=None)
changed: [localhost]
TASK [Wait for instance(s) deletion to complete] *******************************
changed: [localhost] => (item=None)
changed: [localhost]
TASK [Delete docker network(s)] ************************************************
PLAY RECAP *********************************************************************
localhost : ok=2 changed=2 unreachable=0 failed=0
私たちの単純な役割は問題なくテストされました。
操作中に問題が発生した場合は、次のことを覚えておく価値があります。 molecule test
、標準シーケンスを変更しなかった場合、Molecule はインスタンスを削除します。
次のコマンドはデバッグに役立ちます。
> molecule --debug <command> # debug info. При обычном запуске Молекула скрывает логи.
> molecule converge # Оставляет инстанс после прогона тестируемой роли.
> molecule login # Зайти в созданный инстанс.
> molecule --help # Полный список команд.
既存の役割
既存のロールに新しいスクリプトを追加するには、 役割ディレクトリから 次のコマンドを使用します。
# полный список доступных параметров
> molecule init scenarion --help
# создание нового сценария
> molecule init scenario -r <role_name> -s <scenario_name>
これがロール内の最初のスクリプトの場合、パラメータ -s
スクリプトが作成されるため省略可能 default
.
まとめ
ご覧のとおり、Molecule はそれほど複雑ではありません。独自のテンプレートを使用すると、新しいスクリプトのデプロイを、インスタンスの作成と削除のための Playbook 内の変数の編集に減らすことができます。 この分子は CI システムとシームレスに統合されているため、Playbook の手動テストの時間が短縮され、開発速度が向上します。
ご清聴ありがとうございました。 Ansible のロールをテストした経験があり、それが Molecule に関係ない場合は、コメントでそれについて教えてください。
出所: habr.com