Skip to content

Commit e085964

Browse files
committed
Update JEPSEN_TODO.md with checklist progress
1 parent a27267c commit e085964

File tree

7 files changed

+134
-68
lines changed

7 files changed

+134
-68
lines changed

JEPSEN_TODO.md

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,49 +3,59 @@
33
本家 Jepsen Redis テストに近いレベルで Elastickv/Redis プロトコルを検証するために必要な構成要素と TODO です。
44

55
## 1. クラスタ構成
6-
- 最低 5 台のノードを用意する:
6+
- [x] 最低 5 台のノードを用意する:
77
- 1 台: コントロールノード(Jepsen runner)
88
- 4〜5 台: DB ノード(Elastickv を起動)
9-
- 全ノードで SSH 鍵認証(root または sudo 無パス)をセットアップ。
10-
- `/etc/hosts` 等でノード名解決をそろえる。
9+
- [x] 全ノードで SSH 鍵認証(root または sudo 無パス)をセットアップ。
10+
- [x] `/etc/hosts` 等でノード名解決をそろえる。
1111

1212
## 2. DB ドライバの拡張
13-
- `jepsen/src/elastickv/redis_workload.clj` を拡張し、`jepsen.os.debian` などを使って以下を実装:
14-
- 各ノードへのバイナリ配布(ビルド or 配布)。
15-
- 起動/停止/リスタートを `Remote` 経由で管理。
16-
- データ/ログディレクトリをノードごとに初期化・掃除。
17-
- ポート割り当て (Redis/GRPC/Raft) をノードごとに設定。
13+
- [x] `jepsen/src/elastickv/redis_workload.clj` を拡張し、`jepsen.os.debian` などを使って以下を実装:
14+
- [x] 各ノードへのバイナリ配布(ビルド or 配布)。
15+
- [x] 起動/停止/リスタートを `Remote` 経由で管理。
16+
- [x] データ/ログディレクトリをノードごとに初期化・掃除。
17+
- [x] ポート割り当て (Redis/GRPC/Raft) をノードごとに設定。
18+
- [x] 起動時のサービス待機(gRPCポート待機など)の実装。
1819

1920
## 3. 故障注入 (Nemesis)
20-
- 本家に近いセットを有効化する:
21-
- ネットワーク分断(partition-random-halves, majorities-ring 等)
22-
- プロセス kill / 再起動
23-
- ノード停止/再起動(必要なら再デプロイ)
24-
- 時刻ずれ(clock-skew)
25-
- `jepsen.nemesis` を使い、複数 nemesis の組み合わせをテスト。
21+
- [x] 本家に近いセットを有効化する:
22+
- [x] ネットワーク分断(partition-random-halves, majorities-ring 等)
23+
- [x] プロセス kill / 再起動 (server 側の bootstrap エラー無視対応済み)
24+
- [x] ノード停止/再起動(必要なら再デプロイ)
25+
- [x] 時刻ずれ(clock-skew)
26+
- [x] `jepsen.nemesis` を使い、複数 nemesis の組み合わせをテスト。
2627

2728
## 4. ワークロード
28-
- 既存 append ワークロードに加え、以下を追加検討:
29-
- 混合 read/write、トランザクション長バリエーション
30-
- キー数増加、コンカレンシ/レート可変
31-
- テスト時間 5〜10 分 / 試行、複数試行
29+
- [x] 既存 append ワークロード (基本動作確認済み)
30+
- [ ] 以下を追加検討:
31+
- [ ] 混合 read/write、トランザクション長バリエーション
32+
- [ ] キー数増加、コンカレンシ/レート可変
33+
- [ ] テスト時間 5〜10 分 / 試行、複数試行 (現在は 60秒程度で検証中)
3234

3335
## 5. バイナリ配布/ビルド
34-
- DB ノード上で Elastickv をビルドするか、事前ビルド済みバイナリを `scp` 配布。
35-
- systemd/supervisor か Jepsen 管理スクリプトでプロセスを起動・監視。
36+
- [x] DB ノード上で Elastickv をビルドするか、事前ビルド済みバイナリを `scp` 配布。
37+
- [x] systemd/supervisor か Jepsen 管理スクリプトでプロセスを起動・監視。
3638

3739
## 6. 計測と証跡
38-
- Raft/Redis/アプリログをノード別に収集。
39-
- Jepsen history/analysis の保管。
40-
- 可能なら tcpdump やメトリクス(Prometheus/Grafana)も併設。
40+
- [x] Raft/Redis/アプリログをノード別に収集。
41+
- [x] Jepsen history/analysis の保管。
42+
- [ ] 可能なら tcpdump やメトリクス(Prometheus/Grafana)も併設。
4143

4244
## 7. CI への統合
43-
- GitHub Actions 単体では不足するため、外部の VM/ベアメタルクラスタを用意し、Actions から SSH で制御するワークフローを作成。
44-
- サブモジュール(`jepsen/redis`)取得を忘れず `submodules: recursive` を設定。
45+
- [x] GitHub Actions 単体では不足するため、外部の VM/ベアメタルクラスタを用意し、Actions から SSH で制御するワークフローを作成。
46+
- [x] サブモジュール(`jepsen/redis`)取得を忘れず `submodules: recursive` を設定。
4547

4648
## 8. 作業ステップ案
47-
1. ワークロードドライバを `db` / `os` / `nemesis` 付きに書き換える。
48-
2. デプロイ・起動スクリプトを用意(ビルド or 配布を選択)。
49-
3. 小規模 (2~3 ノード) でローカル VM を用いた疎通テスト。
50-
4. 故障注入を広げ、本家標準セットに近づける。
51-
5. 外部クラスタで長時間テストを回し、結果を保存。
49+
1. [x] ワークロードドライバを `db` / `os` / `nemesis` 付きに書き換える。
50+
2. [x] デプロイ・起動スクリプトを用意(ビルド or 配布を選択)。
51+
3. [x] 小規模 (2~3 ノード) でローカル VM を用いた疎通テスト。
52+
4. [x] 故障注入を広げ、本家標準セットに近づける (Partition, Kill, Clock 対応)。
53+
5. [ ] 外部クラスタで長時間テストを回し、結果を保存。
54+
55+
## 9. 実装済みの足回り (最新ステータス)
56+
- **Vagrant Cluster**: `jepsen/Vagrantfile``jepsen/VM.md` でコントロール + 5 ノードの VM クラスタ構築済み。
57+
- **DB Adapter**: `jepsen/src/elastickv/db.clj` 実装済み。Go バイナリのビルド/配布、起動・停止、Raft 参加、再起動時の待機処理を管理。
58+
- **Fault Tolerance**: `elastickv` サーバー側で `raft.ErrCantBootstrap` を無視する修正を適用し、Kill Nemesis 耐性を獲得。
59+
- **Workload**: `jepsen/src/elastickv/redis_workload.clj` は Debian/SSH/combined nemesis(partition, kill, clock)対応済み。
60+
- **CI**: `.github/workflows/jepsen.yml` で self-hosted ランナー向けワークフローを用意。
61+
- **Result**: `partition`, `kill`, `clock` 障害下での `append` ワークロードテストをパス (`{:valid? true}`)。

cmd/server/demo.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,4 +193,4 @@ func run(eg *errgroup.Group) error {
193193
})
194194

195195
return nil
196-
}
196+
}

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ require (
6565
github.com/hashicorp/go-msgpack/v2 v2.1.2 // indirect
6666
github.com/hashicorp/go-multierror v1.1.1 // indirect
6767
github.com/hashicorp/golang-lru v1.0.2 // indirect
68+
github.com/iancoleman/strcase v0.3.0 // indirect
6869
github.com/klauspost/compress v1.16.0 // indirect
6970
github.com/kr/pretty v0.3.1 // indirect
7071
github.com/kr/text v0.2.0 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@ github.com/hashicorp/raft-boltdb v0.0.0-20230125174641-2a8082862702 h1:RLKEcCuKc
203203
github.com/hashicorp/raft-boltdb v0.0.0-20230125174641-2a8082862702/go.mod h1:nTakvJ4XYq45UXtn0DbwR4aU9ZdjlnIenpbs6Cd+FM0=
204204
github.com/hashicorp/raft-boltdb/v2 v2.3.1 h1:ackhdCNPKblmOhjEU9+4lHSJYFkJd6Jqyvj6eW9pwkc=
205205
github.com/hashicorp/raft-boltdb/v2 v2.3.1/go.mod h1:n4S+g43dXF1tqDT+yzcXHhXM6y7MrlUd3TTwGRcUvQE=
206+
github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI=
207+
github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
206208
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
207209
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
208210
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=

jepsen/VM.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Local Jepsen VM Cluster
2+
3+
This brings up a 5-node Jepsen lab (control + 5 DB nodes) using Vagrant and VirtualBox.
4+
5+
## Requirements
6+
- VirtualBox (tested with 7.x)
7+
- Vagrant 2.3+
8+
9+
## Boot and Login
10+
```bash
11+
cd jepsen
12+
vagrant up # spins up ctrl, n1..n5 (first run takes a few minutes)
13+
vagrant ssh ctrl # control node
14+
```
15+
16+
The repository is rsynced into `~/elastickv` on the control node. SSH between nodes uses the bundled Vagrant insecure key.
17+
18+
## Run Jepsen workload
19+
On the control node:
20+
```bash
21+
cd ~/elastickv/jepsen
22+
HOME=$(pwd)/tmp-home LEIN_HOME=$(pwd)/.lein LEIN_JVM_OPTS="-Duser.home=$(pwd)/tmp-home" \
23+
lein run -m elastickv.redis-workload \
24+
--nodes n1,n2,n3,n4,n5 \
25+
--time-limit 60 --rate 10 --concurrency 10 \
26+
--faults partition,kill,clock
27+
```
28+
29+
The test will:
30+
- build Linux/amd64 elastickv + raftadmin binaries on the control node,
31+
- deploy them to each VM under `/opt/elastickv/bin`,
32+
- start the cluster (bootstrap on `n1`, join others),
33+
- run the Redis append workload with the Jepsen combined nemesis (partitions + process kills by default).
34+
35+
## Tear down
36+
```bash
37+
cd jepsen
38+
vagrant destroy -f
39+
```
40+
41+
## Notes
42+
- Ports: Redis 6379, gRPC/Raft 50051 on each node.
43+
- SSH defaults: user `vagrant`, key `~/.ssh/id_rsa` inside `ctrl`.
44+
- Adjust fault mix via `--faults partition,kill,clock` (aliases: `reboot` maps to `kill`).

jepsen/Vagrantfile

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
NODES = {
2+
ctrl: "192.168.56.10",
3+
n1: "192.168.56.11",
4+
n2: "192.168.56.12",
5+
n3: "192.168.56.13",
6+
n4: "192.168.56.14",
7+
n5: "192.168.56.15"
8+
}.freeze
9+
10+
Vagrant.configure("2") do |config|
11+
config.ssh.insert_key = false
12+
#config.vm.box = "debian/bookworm64"
13+
config.vm.box = "bento/debian-12"
14+
15+
NODES.each do |name, ip|
16+
config.vm.define name do |node|
17+
node.vm.hostname = name.to_s
18+
node.vm.network "private_network", ip: ip
19+
20+
# VirtualBox (Intel) defaults
21+
node.vm.provider "virtualbox" do |vb|
22+
vb.memory = name == :ctrl ? 4096 : 2048
23+
vb.cpus = 2
24+
end
25+
26+
# UTM (Apple Silicon) defaults
27+
node.vm.provider "utm" do |utm|
28+
utm.memory = name == :ctrl ? 4096 : 2048
29+
utm.cpus = 2
30+
end
31+
32+
if name == :ctrl
33+
node.vm.synced_folder "..", "/home/vagrant/elastickv",
34+
type: "rsync",
35+
rsync__exclude: [".git", "target", "build", ".cache", "tmp-home", "jepsen/target", "jepsen/tmp-home"]
36+
else
37+
node.vm.synced_folder ".", "/vagrant", disabled: true
38+
end
39+
40+
node.vm.provision "shell", path: "provision/base.sh", args: name.to_s
41+
end
42+
end
43+
end

jepsen/src/elastickv/jepsen_test.clj

Lines changed: 3 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,10 @@
11
(ns elastickv.jepsen-test
22
(:gen-class)
3-
(:require [jepsen
4-
[core :as jepsen]
5-
[cli :as cli]
6-
[db :as db]
7-
[client :as client]
8-
[checker :as checker]]
9-
[jepsen.checker.timeline :as timeline]
10-
[jepsen.tests.linearizable-register :as register]
11-
[jepsen.nemesis :as nemesis])
12-
(:import (redis.clients.jedis Jedis)))
13-
14-
(defrecord RedisClient [port]
15-
client/Client
16-
(open! [this test node]
17-
(assoc this :conn (Jedis. (name node) port)))
18-
(close! [this test]
19-
(.close (:conn this))
20-
this)
21-
(setup! [this test])
22-
(teardown! [this test])
23-
(invoke! [this test op]
24-
(let [conn (:conn this)
25-
value (:value op)]
26-
(case (:f op)
27-
:write (do (.set conn "k" (pr-str value))
28-
(assoc op :type :ok))
29-
:read (let [v (.get conn "k")]
30-
(assoc op :type :ok
31-
:value (when v (read-string v))))
32-
(assoc op :type :fail :error :unknown-op)))))
3+
(:require [elastickv.redis-workload :as redis-workload]
4+
[jepsen.cli :as cli]))
335

346
(defn elastickv-test []
35-
(register/test
36-
{:name "elastickv-register"
37-
:nodes ["n1" "n2" "n3"]
38-
:db db/noop
39-
:client (->RedisClient 63791)
40-
:concurrency 5
41-
:nemesis (nemesis/partition-random-halves)}))
7+
(redis-workload/elastickv-redis-test {}))
428

439
(defn -main
4410
[& args]

0 commit comments

Comments
 (0)