はじめに
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
こっちもなさそう。