複数のリモートコンピュータでパラメータを使用してスクリプトを実行および停止する方法

複数のリモートコンピュータでパラメータを使用してスクリプトを実行および停止する方法

10年前、こんな質問がありました。多くのサーバーでSSHを介したコマンド実行の自動化

デフォルトでは、同じ操作がありますが(おそらく異なる場合があります)、パラメーターを使用してコマンド/スクリプトを実行し、長期実行操作を停止する必要があります。また、どのスクリプトが実行されているか完了していて、結果が何であるかを監視できるように、最新のモニター(少なくともWeb UIやElastic出力など)を好みます。最終的に並べるか、時間を制限することをお勧めします。また、すべてのコンピュータに自分の公開鍵を追加することはできませんが、そこにいくつかのソフトウェアをインストールさせることもできます。

これは主にAIトレーニングプロセスに使用されますが、フレームワークをアップグレードし、最終的に新しいスクリプトとデータを転送(ダウンロード)するためにも使用されます。

上記のリンクでは、誰もがAnsibleの使用を提案しましたが、私は自動化方式が現代的な方法だと思いますが、他の方法はありませんか?

友達もCI / CD(gitlab作業)を提案しましたが、それは少し過度だと思われ、コードテストのような他の目的に使用しました。 AutoMLに関するヒントも得られましたが、これは完全なAIフレームワークであり、さまざまなパラメータを使用して複数のコマンド/スクリプトを実行する必要があるため必要ありません。

答え1

パラメータを辞書に入れます。

  • たとえば、デフォルトから始めましょう。
shell> cat group_vars/all/scripts.yml
scripts:
  default:
    script: /root/bin/default.sh
    params: p1 p2 p3
    timeout: 30
    retries: 10
    delay: 3
    log: /tmp/ansible_script.log

特定のコントローラのスクリプト

shell> tree files
files
├── default.sh
├── script_A.sh
├── script_B.sh
└── script_C.sh
shell> cat files/default.sh 
#!/bin/sh
echo $1 $2 $3
echo finished > /tmp/ansible_script.log
exit 0

以下のスクリプト

shell> cat pb.yml
- hosts: all

  vars:
    my_script: "{{ scripts[inventory_hostname]|d(scripts['default']) }}"
    _script: "{{ my_script.script|d(scripts.default.script) }}"
    _params: "{{ my_script.params|d(scripts.default.params) }}"
    _timeout: "{{ my_script.timeout|d(scripts.default.timeout) }}"
    _retries: "{{ my_script.retries|d(scripts.default.retries) }}"
    _delay: "{{ my_script.delay|d(scripts.default.delay) }}"
    _log: "{{ my_script.log|d(scripts.default.log) }}"

  tasks:
    - debug:
        msg: |-
          _script: {{ _script }}
          _params: {{ _params }}
          _timeout: {{ _timeout }}
          _retries: {{ _retries }}
          _delay: {{ _delay }}
          _log: {{ _log }}
      when: debug|d(false)|bool

    - name: Copy script
      block:
        - file:
            state: directory
            path: "{{ _script|dirname }}"
            mode: 0750
        - copy:
            src: "{{ _script|basename }}"
            dest: "{{ _script }}"
            mode: 0550
      when: copy_script|d(false)|bool

    - name: Run script
      block:
        - command:
            cmd: "{{ _script }} {{ _params }}"
          async: "{{ _timeout }}"
          poll: 0
          register: cmd_async
        - debug:
            var: cmd_async.ansible_job_id
          when: debug|d(false)|bool

    - name: Read log until finished
      block:
        - command:
            cmd: "cat {{ _log }}"
          register: cmd_log
          until: cmd_log.stdout == 'finished'
          retries: "{{ _retries }}"
          delay:  "{{ _delay }}"
        - debug:
            var: cmd_log.stdout
          when: debug|d(false)|bool
      when: read_log_fin|d(false)|bool

    - name: Check async script
      block:
        - async_status:
            jid: "{{ cmd_async.ansible_job_id }}"
          register: job_result
          until: job_result.finished
          retries: "{{ _retries }}"
          delay: "{{ _delay }}"
        - debug:
            msg: >-
              {{ job_result.start }}
              {{ job_result.end }}
              rc: {{ job_result.rc}}
          when: debug|d(false)|bool

与えられた

shell> ansible-playbook pb.yml -e debug=true -e copy_script=true -e read_log_fin=true

PLAY [all] ***********************************************************************************

TASK [debug] *********************************************************************************
ok: [test_11] => 
  msg: |-
    _script: /root/bin/default.sh
    _params: p1 p2 p3
    _timeout: 30
    _retries: 10
    _delay: 3
    _log: /tmp/ansible_script.log
ok: [test_12] => 
  msg: |-
    _script: /root/bin/default.sh
    _params: p1 p2 p3
    _timeout: 30
    _retries: 10
    _delay: 3
    _log: /tmp/ansible_script.log
ok: [test_13] => 
  msg: |-
    _script: /root/bin/default.sh
    _params: p1 p2 p3
    _timeout: 30
    _retries: 10
    _delay: 3
    _log: /tmp/ansible_script.log

TASK [file] **********************************************************************************
ok: [test_13]
ok: [test_12]
ok: [test_11]

TASK [copy] **********************************************************************************
ok: [test_12]
ok: [test_11]
ok: [test_13]

TASK [command] *******************************************************************************
changed: [test_12]
changed: [test_11]
changed: [test_13]

TASK [debug] *********************************************************************************
ok: [test_11] => 
  cmd_async.ansible_job_id: '754707567219.90860'
ok: [test_12] => 
  cmd_async.ansible_job_id: '148176661548.90862'
ok: [test_13] => 
  cmd_async.ansible_job_id: '688240445475.90861'

TASK [command] *******************************************************************************
changed: [test_13]
changed: [test_11]
changed: [test_12]

TASK [debug] *********************************************************************************
ok: [test_11] => 
  cmd_log.stdout: finished
ok: [test_12] => 
  cmd_log.stdout: finished
ok: [test_13] => 
  cmd_log.stdout: finished

TASK [async_status] **************************************************************************
changed: [test_12]
changed: [test_13]
changed: [test_11]

TASK [debug] *********************************************************************************
ok: [test_11] => 
  msg: '2022-08-01 16:02:50.287027 2022-08-01 16:02:50.320177 rc: 0'
ok: [test_12] => 
  msg: '2022-08-01 16:02:49.770331 2022-08-01 16:02:49.801347 rc: 0'
ok: [test_13] => 
  msg: '2022-08-01 16:02:50.189800 2022-08-01 16:02:50.343773 rc: 0'

PLAY RECAP ***********************************************************************************
test_11: ok=9    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
test_12: ok=9    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
test_13: ok=9    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

  • 繰り返し中は中間ログを表示できません。コールバックプラグインは、反復後にすべての結果をまとめて表示します。中間ログを観察するには、Ansibleから出る必要があります。たとえば、ログファイルをインポートします。
    - name: Fetch log until finished
      fetch:
        dest: /tmp/ansible/
        src: "{{ _log }}"
      until: lookup('file', my_logfile) == 'finished'
      retries: "{{ _retries }}"
      delay:  "{{ _delay }}"
      vars:
        my_logfile: "/tmp/ansible/{{ inventory_hostname}}/tmp/ansible_script.log"
      when: fetch_log_fin|d(false)|bool

これにより、コントローラに定期的に更新されるファイルが生成されます。

shell> tree /tmp/ansible/
/tmp/ansible/
├── test_11
│   └── tmp
│       └── ansible_script.log
├── test_12
│   └── tmp
│       └── ansible_script.log
└── test_13
    └── tmp
        └── ansible_script.log

コントローラにファイルを表示します。例えばより

shell> watch cat /tmp/ansible/test_11/tmp/ansible_script.log

これをテストするために、次のスクリプトは$ 2間隔でログに$ 1回書き込みます。

shell> cat files/script_A.sh
#!/bin/sh
for i in $(seq 1 $1); do
    echo step $i  > /tmp/ansible_script.log
    sleep $2
done
echo finished > /tmp/ansible_script.log
exit 0

ポスターを見るために辞書を更新してください。テスト_11スクリプトの実行

shell> cat group_vars/all/scripts.yml
scripts:
  default:
    script: /root/bin/default.sh
    params: p1 p2 p3
    timeout: 30
    retries: 10
    delay: 3
    log: /tmp/ansible_script.log
  test_11:
    script: /root/bin/script_A.sh
    params: 7 3

スクリプトには要約が含まれています。 (プレイブックを再実行する前にインポートしたファイルを削除してください。そうしないと、最後のファイルからジョブをスキップします。)

shell> ansible-playbook pb.yml -e debug=true -e fetch_log_fin=true
...
TASK [Fetch log until finished] **************************************************************
ok: [test_12]
FAILED - RETRYING: [test_11]: Fetch log until finished (10 retries left).
ok: [test_13]
FAILED - RETRYING: [test_11]: Fetch log until finished (9 retries left).
FAILED - RETRYING: [test_11]: Fetch log until finished (8 retries left).
FAILED - RETRYING: [test_11]: Fetch log until finished (7 retries left).
FAILED - RETRYING: [test_11]: Fetch log until finished (6 retries left).
changed: [test_11]

TASK [async_status] **************************************************************************
changed: [test_13]
changed: [test_12]
changed: [test_11]

TASK [debug] *********************************************************************************
ok: [test_11] => 
  msg: '2022-08-01 18:00:13.304133 2022-08-01 18:00:34.768385 rc: 0'
ok: [test_12] => 
  msg: '2022-08-01 18:00:13.413492 2022-08-01 18:00:13.480142 rc: 0'
ok: [test_13] => 
  msg: '2022-08-01 18:00:13.537767 2022-08-01 18:00:13.731926 rc: 0'

PLAY RECAP ***********************************************************************************
test_11: ok=6    changed=3    unreachable=0    failed=0    skipped=4    rescued=0    ignored=0   
test_12: ok=6    changed=2    unreachable=0    failed=0    skipped=4    rescued=0    ignored=0   
test_13: ok=6    changed=2    unreachable=0    failed=0    skipped=4    rescued=0    ignored=0

ログを読むと、出力はほぼ同じです。

shell> ansible-playbook pb.yml -e debug=true -e read_log_fin=true
...
TASK [Read log until finished] ***************************************************************
FAILED - RETRYING: [test_11]: Read log until finished (10 retries left).
changed: [test_12]
changed: [test_13]
FAILED - RETRYING: [test_11]: Read log until finished (9 retries left).
FAILED - RETRYING: [test_11]: Read log until finished (8 retries left).
FAILED - RETRYING: [test_11]: Read log until finished (7 retries left).
FAILED - RETRYING: [test_11]: Read log until finished (6 retries left).
changed: [test_11]

TASK [debug] *********************************************************************************
ok: [test_11] => 
  cmd_log.stdout: finished
ok: [test_12] => 
  cmd_log.stdout: finished
ok: [test_13] => 
  cmd_log.stdout: finished

フルスクリプトpb.ymlへのリンク

答え2

あなたの質問は2つの部分で構成されているようです。

  1. (大規模)サーバーリストで実行されているスクリプト/プロセスを停止/開始/管理する方法は?
  2. 同じサーバーのリストから長期実行スクリプト/プロセスの状態をどのように追跡または監視できますか?

Ansibleおよびその他の構成管理ソフトウェア(Puppet、Chef、Saltstackなど)は、質問1の良い候補かもしれませんが、進行状況グラフまたは警告スクリプトを想定している場合は、開始/停止するプロセスの追跡/監視を提供しません。問題が発生しました。 (IMO)監視システムは、これらの状態監視および報告機能をよりよく提供します。

質問1に戻ると、Ansibleは、事前設定されたサーバーであるか、コマンドラインからすぐに入力する「一時的な」コマンド/スクリプトであるかにかかわらず、複数のサーバーでコマンド/スクリプトを実行する機能としてよく知られています。 Saltstackは同様の機能を持っていますが、Ansibleと同じくらい複雑な一時コマンドを処理できない可能性があります。他の構成管理パックは、ターゲットサーバーでコマンドを実行する直接的な方法が少なく、ここで説明されている問題を解決するために簡単に構成できない場合があります。

質問#2では、サーバーベース(CPU、メモリ、ディスク)のモニタリングシステムがすでに存在しているかどうか、スクリプト/プロセス追跡のためにどれだけ簡単に拡張できるかなど、モニタリングシステムを選択する際に考慮すべき要因がたくさんあります。また、これらのサーバーがスクリプト/プロセスの実行専用であるか、他のタスクも実行している場合です。これは、監視する項目、ステータスを確認する方法、および必要な通知の種類に関する詳細を含む独自の質問を受け取るのに十分な大きなトピックです。

答え3

人形ボルト比較的簡単に説明するタスクを実行します。私は私が説明した複雑なワークフローにそれを使用し、短時間でterraform(設定)やserviceNow(CR検証)などの他のツールに接続しました。お客様のユースケースでは統合が不要な場合があります。ただし、これらの要件がどのように変更されるかを知っておくことをお勧めします。

OPはターゲットノードに公開鍵を入れないと言いました...完全に理解したかどうかはわかりませんが、額面のまま受け入れれば、ユーザー名とパスワードを使用してBoltで認証することが可能です。

同僚が提案したようなCIツールは、Webを介してすべてを見るためのエレガントな方法です。

関連情報