Skip to content
Published on

etcd WatchとLeaseメカニズム分析

Authors

etcd WatchとLeaseメカニズム分析

etcdのWatchとLeaseは分散システムで核心的な機能を提供します。Watchはキー変更のリアルタイム監視を、Leaseはキーの自動期限切れを可能にします。


1. Watch内部構造

1.1 Watchable Storeアーキテクチャ

type watchableStore struct {
    *store
    synced   watcherGroup   // 現在のrevisionに同期済みwatcher
    unsynced watcherGroup   // まだ追いついていないwatcher
    victims  []watcherBatch // 送信失敗イベントキュー
}

1.2 Watcherライフサイクル

  1. クライアントがWatchリクエスト送信
  2. Watcher生成、開始revision決定
  3. 開始revisionが古ければunsyncedグループに配置
  4. ヒストリーからイベントを再生して追いつき
  5. 現在のrevisionまで追いつくとsyncedグループに移動
  6. 以降新しいイベントをリアルタイム受信

2. イベント生成と配信

2.1 イベント生成過程

MVCCストアに書き込みが発生するとトランザクションコミット時にイベントが生成され、マッチするwatcherに配信されgRPCストリームでクライアントに送信されます。

2.2 イベント順序保証

etcd Watchはイベントの順序を保証します:

  • 同じキーに対するイベントはrevision順で配信
  • Watch IDごとにイベントが順番に配信

3. gRPC Watchストリーミング

3.1 Compacted Revision処理

Watchの開始revisionが既にコンパクションされている場合:

  1. サーバーがErrCompactedエラーとcompactRevisionを返す
  2. クライアントは現在のデータを再ロード
  3. 返されたrevisionから新しいWatchを開始
wch := client.Watch(ctx, "key", clientv3.WithRev(oldRev))
for resp := range wch {
    if resp.CompactRevision > 0 {
        reloadData()
        wch = client.Watch(ctx, "key", clientv3.WithRev(resp.CompactRevision))
    }
}

4. Leaseメカニズム

4.1 Lease概要

LeaseはキーにTTLを付与して自動期限切れを可能にします:

  • Leaseを作成すると固有IDとTTLが割り当て
  • キーをLeaseに接続するとLease期限切れ時にキーも削除
  • 1つのLeaseに複数キーを接続可能

4.2 Lease GrantとKeepAlive

# Lease作成(TTL 300秒)
etcdctl lease grant 300

# キーにLease接続
etcdctl put --lease=694d71ddafb1e01a mykey myvalue
resp, _ := client.Grant(ctx, 30)
_, _ = client.Put(ctx, "key", "value", clientv3.WithLease(resp.ID))
ch, _ := client.KeepAlive(ctx, resp.ID)
for ka := range ch {
    fmt.Println("TTL renewed:", ka.TTL)
}

4.3 TTL実装と期限切れ処理

  1. Lessorが定期的に期限切れLeaseを確認(500ms間隔)
  2. 期限切れLease発見時RevokeリクエストをRaftに提案
  3. Raft合意後Leaseに接続されたすべてのキーを削除
  4. Lease自体も除去

5. LeaseとKubernetes

5.1 リーダー選出

Kubernetesのリーダー選出はetcd Leaseを活用:

  1. 候補が特定キーに自分のIDをLeaseと共に記録
  2. 成功すればリーダーに
  3. リーダーはKeepAliveでLeaseを維持
  4. リーダー障害時KeepAliveが中断しLease期限切れ
  5. 期限切れ後他の候補が新リーダーに選出

5.2 ノードハートビート

kubeletはkube-node-leaseネームスペースのLeaseオブジェクトを使用してノード状態を報告します。定期的なLease更新でノード活性状態を表示し、更新失敗時ノードがNotReady状態に転換します。


6. WatchとLease結合パターン

6.1 分散設定管理

  1. 設定値をetcdに保存
  2. クライアントが設定キーをWatch
  3. 変更時イベント受信して即座に反映
  4. Leaseで一時設定の自動クリーンアップ

6.2 サービス登録/発見

  1. サービスインスタンスがLeaseと共に自身を登録
  2. 他サービスが登録キーをWatchして変化検知
  3. インスタンス障害時Lease期限切れで自動登録解除
  4. Watchを通じて他サービスが即座に認知

7. まとめ

etcdのWatchとLeaseは分散システムのコアプリミティブを提供します。Watchはリアルタイム変更検知を、LeaseはTTLベースの自動期限切れを可能にし、この2つの組み合わせでリーダー選出、サービスディスカバリなど様々な分散パターンを実装できます。