4

現在、私は人形からAnsibleに切り替えていますが、いくつかの概念、または少なくとも ansible の仕組みについて少し混乱しています。

セットアップに関する情報:

私はAnsible Best Practicesの例を使用しており、プロジェクトをいくつかのロール (プレイブック) などと同様に構成しています。

プロビジョニングに Vagrant を使用しており、ボックスは Saucy64 VBox です。

混乱の原因:

プロビジョニングして ansible を実行すると、タスクの実行が開始され、次に通知のスタックが開始されます。

例:

最後のタスク:

TASK: [mysql | delete anonymous MySQL server user for localhost] ************** 
<127.0.0.1> REMOTE_MODULE mysql_user user='' state=absent 
changed: [default] => {"changed": true, "item": "", "user": ""}

それから最初の通知:

NOTIFIED: [timezone | update tzdata] ****************************************** 
<127.0.0.1> REMOTE_MODULE command /usr/sbin/dpkg-reconfigure --frontend noninteractive tzdata
changed: [default] => {"changed": true, "cmd": ["/usr/sbin/dpkg-reconfigure", "--frontend", "noninteractive", "tzdata"], "delta": "0:00:00.224081", "end": "2014-02-03 22:34:48.508961", "item": "", "rc": 0, "start": "2014-02-03 22:34:48.284880", "stderr": "\nCurrent default time zone: 'Europe/Amsterdam'\nLocal time is now:      Mon Feb  3 22:34:48 CET 2014.\nUniversal Time is now:  Mon Feb  3 21:34:48 UTC 2014.", "stdout": ""}

これで問題ありません。役割が増えるにつれて、ますます多くの通知が行き詰まります。

ここで問題が発生します。

通知が失敗すると、プロビジョニングは通常どおり停止します。しかし、通知スタックは空です! これは、障害のある通知以降のすべての通知が実行されないことを意味します。

その場合、apache の vhosts 設定を変更し、apache サービスをリロードするように通知した場合、これは失われます。

例を挙げましょう(疑似言語):

- name: Install Apache Modules
  notify: Restart Apache

- name: Enable Vhosts
  notify: Reload Apache

- name: Install PHP
  command: GGGGGG # throws an error

上記が実行されると:

  1. Apache モジュールがインストールされている
  2. 仮想ホストは有効です
  3. PHP がインストールを試みて失敗する
  4. スクリプトの終了
  5. (通知はどこにありますか?)

この時点で、すべてが論理的に見えますが、Ansible は巧妙に (いいえ!*) スタック通知を試行するため、apache をリロードして再起動すると、プロビジョニングの最後に実行される apache が 1 回再起動されます。つまり、すべての通知が失敗します!!!

ここまでは、人によってはこれでもいいです。彼らは、プロビジョニングを再実行するだけで通知が起動すると言うでしょう。したがって、Apache が最終的にリロードされ、サイトが再び起動します。これはそうではありません。

PHP をインストールするためのコードが修正された後のスクリプトの 2 回目の実行では、設計により通知が実行されません。なんで?

これが理由です: Ansible は、正常に実行されたタスクを「完了/グリーン」としてマークし、これらのタスクの通知を登録しません。プロビジョニングが成功し、通知をトリガーして apache を再起動するには、次のいずれかを実行できます。

  1. ansible または ssh を介してサーバーに直接コマンドを実行します。
  2. スクリプトを編集してタスクをトリガーする
  3. そのための別のタスクを追加します
  4. ボックスのインスタンスを破棄して再プロビジョニングする

ボックスの完全なクリーンアップが必要なため、これは非常にイライラしますか、それとも Ansible で何かを正しく理解していないのでしょうか?

通知を「回収」/再生/強制的に実行する別の方法はありますか?

  • 賢明なのは、タスクを未完了としてマークしてから通知を再開するか、通知を独自のタスクとして別のキューに保持することです.*
4

2 に答える 2

3

ええ、それは Puppet と比較して言うべき Ansible の欠点の 1 つです。Puppet は宣言型であり、Ansible (または Chef) のようにエラーが発生しません。長所と短所があります。たとえば、Puppet はカタログをコンパイルする必要があるため、実行を開始するまでに少し時間がかかります。

したがって、Ansible スクリプトでエラーが発生した場合、通知の更新は行われません。これを回避する唯一の方法は、条件ステートメントを使用することです。プレイブックでは、次のようなことができます。

- name: My cool playbook
  hosts: all

  vars:
      force_tasks: 0

  tasks:
    - name: Apache install
      action: apt pkg=$item state=latest
      with_items:
       - apache2
       - apache2-mpm-prefork

    - name: Restart apache
      action: service name=apache2 state=restart
      when: force_tasks

次に、プレイブックを実行するときに、force_tasks を環境変数として渡すことができます。

ansible-playbook -i my_inventory -e "force_tasks=True" my_ansible_playbook.yml

これは、タグを使用して同様の方法で実現できます。

于 2014-02-07T22:42:53.210 に答える