環境変数LEADER_ELECTION関連の設定値ごとの動作検証

## はじめに
高可用性の観点からArgoWorkflowsは、[v3.0からworkflow controllerのpodをホットスタンバイできる](https://argoproj.github.io/argo-workflows/high-availability/)。

[ArgoWorkflowsの環境変数](https://argoproj.github.io/argo-workflows/environment-variables/)を読むと、リーダーの停止時にホットスタンバイするpodへのリーダー権の移行時間は、LEADER_ELECTION_LEASE_DURATION、LEADER_ELECTION_RENEW_DEADLINE、LEADER_ELECTION_RETRY_PERIODで設定できそうな事が分かる。LEADER_ELECTION_LEASE_DURATIONのデフォルトの設定は15秒であるが、この時間を短縮できればリーダーの権限移行にかかる時間を短くできると考えられる。

そこで、LEADER_ELECTION関連の環境変数の設定値を変化させ、リーダーの権限移行速度がどのように変化するか検証した。いくつかの設定値ごとにリーダーのworkflow-controllerのpodをdeleteしたタイミングで新規workflowをcreateし、各設定値ごとにworkflowの実行開始から終了までにかかる時間を計測、この時間がどのように変化するかを検証した。

また、各設定値ごとにworkflowを起動する事なくただworkflow-controllerを動作させた場合の動作安定性についても合わせて確認した。

## 検証方法
検証環境として、Ubuntu20.04、Minikube v1.29.0、ArgoWorkflows v3.4.5を利用する。[namespace-installマニフェスト](https://github.com/argoproj/argo-workflows/releases/tag/v3.4.5)を利用し、レプリカ数を2で設定、workflow-controllerの環境変数として以下4パターンの設定を行い、namespace argoで動作検証する。

|  | LEADER_ELECTION_<br>LEASE_DURATION | LEADER_ELECTION_<br>RENEW_DEADLINE | LEADER_ELECTION_<br>RETRY_PERIOD |
| -- | -- | -- | -- |
|パターン1| Default(15秒) | Default(10秒) | Default(5秒) |
|パターン2| 3秒 | 2秒 | 1秒 |
|パターン3| 6秒 | 4秒 | 2秒 |
|パターン4| 30秒 | 20秒 | 10秒 |


レプリカ数を2で指定した場合、リーダーとホットスタンバイのpodが1個ずつ生成されるが、どちらがリーダーかは```$ kubectl logs```コマンドでpodのログを確認し判別する。```msg="new leader" leader=workflow-controller-<ランダム数字文字列>-<ランダム文字列>```で出力されるpodがリーダーのworkflow-controllerである。

はじめにで述べた通り、検証は①リーダー権限の移行時間の変化に関する観点と②podの動作安定性の2つの観点より行う。

①の観点は、workflow-controllerをdeleteしたタイミングで新たにworkflowを生成し、```$ watch -n 1 kubectl get workflow -n argo```コマンドにより1秒周期でworkflowリソースのステータスを確認、各設定値のパターンごとにworkflowの動作にかかる時間がどのように変化するかを確認する。

下記スクリプトを実行する事で、リーダーのworkflow-controllerをdeleteしたタイミングで[hello-world.yaml](https://github.com/argoproj/argo-workflows/blob/master/examples/hello-world.yaml)をcreateする。
```
#!/bin/sh

kubectl delete pod $1 -n argo
kubectl create -f hello-world.yaml -n argo
```

②の観点は、各パターンごとに何もworkflowを動作させず15分workflow-contorllerのpodを動作させた時のpodのステータスを監視し、```$ watch -n 1 kubectl get pod -n argo```コマンドにより1秒周期でpodを監視する。argoのnamespaceに存在するpodはargo-serverとworkflow-controllerのみである。

## 検証結果
### リーダー権限の移行時間の変化
各パターンごとにcreateしたworkflowの動作変化を以下に示す。多少誤差はあるが、ステータス無しの時間がLEADER_ELECTION_LEASE_DURATIONの設定値とおおよそ一致する事が分かる。

| パターン | 動作 |
| -- | -- |
| パターン1 | 10秒間ステータス無し。11秒後にステータスがRunningとなり、33秒後にステータスがSucceededとなる。|
| パターン2 | 3秒間ステータス無し。4秒後にステータスがRunningとなり、24秒後にステータスがSucceededとなる。|
| パターン3 | 5秒間ステータス無し。6秒後にステータスがRunningとなり、28秒後にステータスがSucceededとなる。|
| パターン4 | 33秒間ステータス無し。34秒後にステータスがRunningとなり、55秒後にステータスがSucceededとなる。 |

検証結果より、LEADER_ELECTION_LEASE_DURATIONで設定する時間がworkflow-controllerのリーダー権がホットスタンバイのpodに移行し正常に動作するまでにかかる時間と考える事ができる。

### podの動作安定性
動作安定性の検証結果を下表に示す。LEADER_ELECTION_LEASE_DURATIONがデフォルトの設定値より小さい場合、CrashLoopBackOffやCompletedとなる時間が生じ、動作が不安定になる事が分かる。また、設定値が小さい程その時間は長くなる傾向にある事が分かる。※ CrashLoopBackOff、Completedと表示される行数からカウントしている。1秒周期で監視するがパスされるケースもあるため正確な数値では無く傾向として見て頂きたい。
| パターン | CrashLoopBackOffとなる時間 | Completedとなる時間 | 
| -- | -- | -- |
| パターン1 | 0秒 | 0秒 |
| パターン2 | 5分程度 | 2分程度 |
| パターン3 | 0秒 | 10秒程度 |
| パターン4 | 0秒 | 0秒 |

検証結果より、LEADER_ELECTION_LEASE_DURATIONで設定する時間がデフォルトの15秒よりも短い場合、workflow-controllerのpodの動作が不安定になる事を確認した。

## まとめ
LEADER_ELECTION_LEASE_DURATIONの設定値を変化させる事で、ホットスタンバイ状態のworkflow-contorllerのリーダー権の受領から起動までにかかる時間を調整できる事を確認した。また、LEADER_ELECTION_LEASE_DURATIONの時間がデフォルト値よりも小さくなる場合、値が小さい程一定時間内におけるCrashLoopBackOffやCompletedとなる確率が増え、workflow-controllerの動作が不安定になる事を確認した。

残念ながら、LEADER_ELECTION_LEASE_DURATIONの設定値をデフォルト値よりも小さく設定する事でホットスタンバイのpodのリーダー権限の移行から起動にかかる時間を短くする事は、動作不安定というリスクが伴うためあまり得策では無さそうな事が分かった。

## 参考文献
[Argo Workflows Webサイト](https://argoproj.github.io/argo-workflows/)