K8s client-goのLeader Electionを読む
はじめに
sample-controllerのコードリーディングではリーダ選出には触れていませんでした。
client-goにはリーダ選出の仕組みが備わっているため、サンプルコードを読みつつ理解してみようというのが趣旨になります。
コードリーディング
細かく読み込む前に、client-goのリーダ選出がどのように実装されているのかをコメントからみてみます。
Lease
Resourceを使ったリーダ選出
コメントにあるように、リーダ選出にはKubernetesのLease
Resourceを利用します。
このLease
Resourceですが、Nodeの死活監視やkube-controller-manager
やkube-scheduler
のリーダ選出でも使われているResourceです。
中身は下記のようになっています。
apiVersion: coordination.k8s.io/v1
kind: Lease
metadata:
creationTimestamp: "2023-07-02T13:16:48Z"
labels:
apiserver.kubernetes.io/identity: kube-apiserver
kubernetes.io/hostname: master-1
name: apiserver-07a5ea9b9b072c4a5f3d1c3702
namespace: kube-system
resourceVersion: "334899"
uid: 90870ab5-1ba9-4523-b215-e4d4e662acb1
spec:
holderIdentity: apiserver-07a5ea9b9b072c4a5f3d1c3702_0c8914f7-0f35-440e-8676-7844977d3a05
leaseDurationSeconds: 3600
renewTime: "2023-07-04T21:58:48.065888Z"
ざっくりとですが「誰がいつからLease
Resourceを所有しているか」という情報が含まれています。
公式ドキュメントのWorkloadsにもあるように、このLease
Resourceを使ったリーダ選出がclient-goで実装されています。
それでは読んでいきましょう。
リーダとして実行する処理
モックです。実際はこの部分にリーダとして実行したい処理を書く必要があります。
シグナル時の安全な停止
シグナル発生時の処理が記載されています。sample-controller
の時にも似たような処理がありました。
Lease
Resourceの設定
ここでリーダ選出に利用するLease
Resourceの設定がされています。
特定のNamespaceにLease
Resourceを作成するので、実行環境のアイデンティティにはRole/RoleBinding
が必要になります。
リーダ選出を含む処理の開始
実際の処理がこのRunOrDie
で行われています。各引数を見ていきましょう。
項目 | 内容 | 実装例 |
---|---|---|
Lock rl.Interface |
ロック用のLease Resource。(ConfigMap Resource等も利用可) |
|
LeaseDuration time.Duration |
リーダ以外がLease を強制取得開始する時間 |
|
RenewDeadline time.Duration |
リーダがLease を更新するまでのタイムリミット |
|
RetryPeriod time.Duration |
各インスタンスがリーダ選出を試す間隔 | |
Callbacks LeaderCallbacks |
後述 | |
WatchDog *HealthzAdaptor |
ヘルスチェック用の機能 | |
ReleaseOnCancel bool |
contextの終了時にLease を手放すかどうかのフラグ。true にする場合はcontextの終了前にリーダ処理を正しく終了させること |
|
Name string |
デバッグ用の名前。ログに表示される | |
Coordinated bool |
Coordinated Leader Electionを利用するかどうかのフラグ。通常のLeader Electionと何が違うの?という件についてはこのQiita記事を参照 |
Callbacks LeaderCallbacks
は下記になります。
項目 | 内容 |
---|---|
OnStartleading |
自身がリーダとなったときに呼び出される。リーダとして実行したい処理を実装する。 |
OnStoppedLeading |
リーダではなくなった場合や、一度もリーダにならずに終了した場合に呼び出される |
OnNewLeader |
自身を含むいずれかのインスタンスが新しいリーダとして選出されたときに呼び出される。 |
今回の設定だと、
- 前回の
Lease
更新から15秒
以内にリーダがLease
を更新できなければ、リーダから降りてLease
を開放する - 前回の
Lease
更新から60秒
経過していたら、リーダではないインスタンスによって強制的にリーダ選出がされる -
5秒
毎にリーダ選出の処理が行われる(LeaseDuration
以内であればリーダの強制選出はされない)
となります。
おわりに
今回はclient-goに実装されているリーダ選出の機能をみていきました。
分散システムであるKubernetesでは、Lease
Resourceのような仕組みがもともと含まれており、それが使いやすい形にライブラリ化されているのは良いですね。
宿題
-
WatchDog *HealthzAdaptor
のサンプル作成と疎通 -
sample-controller
へのリーダ選出機能の追加
おまけ
kubernetes/ingress-nginxのLeader Election
HealthzAdaptor
の設定あるかなと思って調べてみましたがなさそうです。
oracle/oci-native-ingress-controllerのLeader Election
こっちもなさそう。
Discussion