手順:実務の前に、ansibleロールをテストし、問題について学ぶ方法

みなさんこんにちは!


私はホテル予約サービスOstrovok.ruでDevOpsエンジニアとして働いています。 この記事では、ansibleロールをテストした経験についてお話したいと思います。


Ostrovok.ruでは、ansibleを構成マネージャーとして使用しています。 最近、ロールテストが必要になりましたが、判明したように、このためのツールはあまりありません。Moleculeフレームワークがおそらく最も人気があるので、使用することにしました。 しかし、彼のドキュメンテーションは多くの落とし穴について沈黙していることが判明しました。 ロシア語で十分に詳細なガイドを見つけることができなかったため、この記事を書くことにしました。



分子


Moleculeは、ansibleロールのテストに役立つフレームワークです。


簡略化された説明:分子は、指定したプラットフォーム(クラウド、仮想マシン、コンテナー。詳細については、 ドライバーのセクションを参照)でインスタンスを作成し、その上でロールを実行し、テストを実行してインスタンスを削除します。 ステップの1つで障害が発生した場合、分子はこれを通知します。


より詳細に。


理論のビット


分子の2つの重要なエンティティ、シナリオとドライバーを検討してください。


シナリオ


このスクリプトには、何を、どこで、どのように、どの順序で実行するかの説明が含まれています。 1つのロールには複数のスクリプトを含めることができ、各スクリプトはパス<role>/molecule/<scenario>に沿ったディレクトリであり、テストに必要なアクションの説明が含まれています。 defaultスクリプトが存在する必要があります。これは、Moleculeを使用してロールを初期化すると自動的に作成されます。 以下のシナリオの名前は、お客様の裁量で選択されます。


スクリプトのテストフローはmatrixと呼ばれ、デフォルトでは次のとおりです。


?マークされたステップは、ユーザーが説明しない場合、デフォルトでスキップされます)



このシーケンスはほとんどの場合に対応しますが、必要に応じて変更できます。


上記の各ステップは、 molecule <command>を使用して個別に起動できます。 ただし、このような各cliコマンドには、 molecule matrix <command>実行することで認識できる独自のアクションシーケンスが存在する可能性があることを理解する価値があります。 たとえば、 convergeコマンドを実行する(テスト済みのプレイブックを実行する)と、次のアクションが実行されます。


 $ molecule matrix converge ... └── default #   ├── dependency #   ├── create #   ├── prepare #   └── converge #   

これらのアクションのシーケンスは編集できます。 リストから何かがすでに完了している場合は、スキップされます。 インスタンスの構成と同様に、現在の状態は$TMPDIR/molecule/<role>/<scenario>ディレクトリに保存されます。


?ステップを追加し? 目的のアクションをansibleプレイブックの形式で記述し、ステップ: prepare.yml / side_effect.ymlに従ってファイル名を作成できます。 分子は、スクリプトフォルダー内のこれらのファイルを待ちます。


運転手


ドライバーは、テストインスタンスが作成されるエンティティです。
Moleculeにテンプレートが用意されている標準ドライバーのリストは、Azure、Docker、EC2、GCE、LXC、LXD、OpenStack、Vagrant、Delegatedです。


ほとんどの場合、テンプレートは、スクリプトフォルダー内のdestroy.ymldestroy.ymlであり、それぞれインスタンスの作成と削除を記述しています。
例外はDockerおよびVagrantです。これらのモジュールとのやり取りは上記のファイルなしで発生する可能性があるためです。


インスタンスを作成および削除するためにファイルで使用される場合、インスタンスの構成での作業のみが説明されているため、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 <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の役割でした。 さらに、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 configを分析しましょう(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 

依存関係


このセクションでは、依存関係のソースについて説明します。


可能なオプション: galaxygilt 、shell。


シェルは、銀河と金箔がニーズを満たしていない場合に使用される単なるコマンドシェルです。


私はここで長い間停止しません、それはドキュメントで十分に説明されています


運転手


ドライバーの名前。 このドッカーがあります。


糸くず


リンターとして、yamllintが使用されます。


構成のこの部分で役立つオプションは、yamllintの構成ファイルを指定する機能、環境変数を転送する機能、またはリンターを無効にする機能です。


 lint: name: yamllint options: config-file: foo/bar env: FOO: bar enabled: False 

プラットフォーム


インスタンスの構成について説明します。
ドライバーとしてのdockerの場合、MoleculeはこのセクションでDockerfile.j2れ、各リスト項目はDockerfile.j2item変数として使用できます。


create.ymldestroy.ymlドライバーの場合、セクションはそれらでmolecule_yml.platformsとして利用可能であり、その繰り返しはこれらのファイルに既に記述されています。


Moleculeはansibleモジュールのインスタンス制御を提供するため、可能な設定のリストをそこに探す必要があります。 たとえば、 dockerの場合、 docker_container_moduleモジュールが使用されます。 他のドライバーで使用されているモジュールは、 ドキュメントに記載されています


また、さまざまなドライバの使用例は、分子自体のテストで見つけることができます。


ここUbuntuの centos:7を置き換えます


プロビジョナー


「プロバイダ」は、インスタンスを制御するエンティティです。 Moleculeの場合、これはansibleであり、他のサポートは計画されていません。したがって、このセクションは、ansibleの拡張構成を予約して呼び出すことができます。
ここでは多くのことを指定できますが、私の意見では、主要な瞬間を強調します:



 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'" 


 provisioner: name: ansible options: vvv: true diff: true env: FOO: BAR 

シナリオ


スクリプトシーケンスの名前と説明。
<command>_sequenceを追加し、その値として必要なステップのリストを決定<command>_sequenceことにより、 <command>_sequenceデフォルトのアクションマトリックスを変更できます。
playbook runコマンドを実行するときにアクションのシーケンスを変更するとします。 molecule converge


 # : # - dependency # - create # - prepare # - converge scenario: name: default converge_sequence: - create - converge 

検証者


テスト用のフレームワークとそれにリンターを設定します。 デフォルトでは、 testinfraflake8flake8として使用さtestinfraます。 可能なオプションは上記と同様です。


 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を次のように編集し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> 

これが役割の最初のスクリプトである場合、 defaultスクリプトが作成されるため、 -sパラメーターは省略できます。


おわりに


ご覧のとおり、Moleculeはそれほど複雑ではなく、独自のテンプレートを使用する場合、新しいスクリプトの展開を減らして、インスタンスを作成および削除するためのプレイブックの変数を編集できます。 この分子はCIシステムとシームレスに統合されるため、プレイブックを手動でテストする時間を短縮することで開発速度を向上させることができます。


ご清聴ありがとうございました。 ansibleロールのテストの経験があり、Moleculeとは関係がない場合は、コメントで教えてください!



Source: https://habr.com/ru/post/J448136/


All Articles