zaki work log

作業ログやら生活ログやらなんやら

[Ansible] untilを使って非同期処理が完了するまで次のtaskを待つ

例えばK8s環境でpodをデプロイするマニフェストapplyしてRunningになるまで待つとか。

手作業のときにkubectl get podRunningになるまで何度も再実行して(もしくは-wつけて)、Runningになったのを目視確認したら次のコマンドを打つ、みたいな作業をAnsibleで実現します。

docs.ansible.com

上記のユーザーガイドのサンプルを見るのが早いけどuntilを使えばOK

基本的な流れ

  • (shellなどで)状態をチェックする処理を発行
  • ↑の結果をregisterで保持
  • 保持した値から結果(標準出力やリターンコードなど)を取り出しuntilの条件式で評価
    • 評価結果が条件を満たさなければ再実行
    • 評価結果が条件を満たせば成功として次のtaskへ

言い換えると、「状態をチェックする処理」に対して、プログラミング言語for制御構文みたいな作用がuntilによって付加されます。

CNIをデプロイしてnodeがReadyになるまで待つ例

(podの例を出しながらnodeですみません)

kubeadmを使ってKubernetesクラスタをデプロイする際は、CNIをインストールするなどしてノードを跨いだpod間のネットワークを有効にするまでノードはReadyになりません。
そこで、ノードがReadyになるまで処理を待つtaskを作成しました。
(ちなみに以下のplaybookは、nodeが1つの場合前提の処理です)

- hosts: master[0]
  gather_facts: false
  tasks:
    - name: install flannel
      shell: kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/2140ac876ef134e0ed5af15c65e414cf26827915/Documentation/kube-flannel.yml

    - name: wait for Node-Ready
      shell: kubectl get node --no-headers | awk '{print $2}'
      register: node_state
      until: node_state.stdout == "Ready"
      retries: 10
      delay: 5

こんな感じ。

1つ目のinstall flannelはCNIをインストールする処理なので今回は割愛。
2つ目のwait for Node-Readyが、ノードがReadyになるまで待つtask

チェックに使用しているコマンドはkubectl get nodeで、普通に実行するとこんな感じ。

$ kubectl get node
NAME                        STATUS   ROLES    AGE   VERSION
k8s-master01.esxi.jp-z.jp   Ready    master   32h   v1.18.0

これに--no-headersを付けてNAME ...とかのヘッダ行を非表示にして、awkに突っ込んでステータスの部分のみ取り出し、次のregisterを使ってnode_stateという変数に保持してます。
そして、untilで、node_stateの標準出力(stdout)がReadyになっているかを評価します。

上の例では5秒おきに10回までリトライ(最大11回実行)

実際に実行するとこんな感じ。
(上記に加えて成功時にchangedにならないようにchanged_whenを使ってます)

PLAY [master[0]] ***************************************************************************************

TASK [install flannel] *********************************************************************************
changed: [master01]

TASK [wait for Node-Ready] *****************************************************************************
FAILED - RETRYING: wait for Node-Ready (10 retries left).
FAILED - RETRYING: wait for Node-Ready (9 retries left).
FAILED - RETRYING: wait for Node-Ready (8 retries left).
FAILED - RETRYING: wait for Node-Ready (7 retries left).
ok: [master01]

PLAY RECAP *********************************************************************************************
master01                   : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

使ったplaybookはこちら

github.com


おおまかな処理時間を見積もってsleepとかしないよーに


kubectl applyk8sモジュール使えるのでは?(セルフツッコミ)
https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#pod-network
https://docs.ansible.com/ansible/latest/modules/k8s_module.html