etcdとは
etcdは、CoreOSチームにより2013年にリリースされた分散型キーバリューデータベースです。Go言語で実装されており、RAFTコンセンサスアルゴリズムを採用することで、複数のノード間でのデータ整合性を保証しています。
名前について:UNIXの「/etc」ディレクトリ(設定ファイルの保存場所)と分散システムの「D」を組み合わせた造語で、分散環境における設定情報存储サービスを意図しています。
Kubernetesとetcdの関係
2014年に公開されたKubernetesは、当初からGo言語で実装され、etcdの高可用性とWatch機構を必要としていました。Kubernetesの最初のバージョン(0.4)では、etcd v2が採用されていました。
Kubernetesにおけるetcdの活用例:
- 宣言的APIの実現:KubernetesのコントローラはetcdのWatch機構を使用してリソース変更をリアルタイムで監視し、期待状態と現実状態の整合性を維持します
- 原子性の保証:CAS(Compare-And-Swap)機構により、同時更新時のデータ整合性を確保
- イベント管理:TTL(Time-To-Live)機能により、古いイベントデータを自動削除し、ストレージ効率を維持
CoreOSがKubernetesエコシステムのコアメンバーであったことも、技術選定に影響を与えました。
バージョン履歴
| 時期 | 出来事 |
|---|---|
| 2013年 | etcdプロジェクト開始 |
| 2014年 | Kubernetes最初のバージョン公開 |
| 2016年 | etcd 3.0リリース |
| 2017年 | Kubernetes 1.6公開、etcd v3がデフォルトに |
Kubernetesのスケール拡大に伴い、v2の性能限界が顕著になったため、v3への移行が進められました。v3は5000ノードクラスタの構築をサポートし、云原生時代の標準メタデータストレージとして定着しました。
アーキテクチャ
etcdは以下のレイヤー構成で構築されています:
- クライアント層:v2/v3 APIクライアントライブラリを提供。負荷分散やフェイルオーバーを組み込みでサポートし、开发工数を削減します
- APIネットワーク層:v2はHTTP/1.x、v3はgRPCを使用。grpc-gatewayによりHTTP対応も可能。ノード間通信にはRAFTアルゴリズム用のHTTPプロトコルを採用
- RAFTアルゴリズム層: Leader選出、木log複製、ReadIndexなどの 핵심機能を実装し、データ整合性を保证
- 機能論理層:KVServer、MVCC、Auth、Lease、Compactorなどのモジュールで構成。MVCCはtreeIndexとboltdbから成る
- ストレージ層:WAL(予書きログ)、Snapshot、boltdbを配置。WALはクラッシュ耐性を、boltdbは永続化を担当
基本用語集
- RAFT:分散システムの整合性を保证するコンセンサスアルゴリズム
- Node:RAFT状態機械の实例
- Member:etcdインスタンス。Nodeを管理しサービスを提供
- Cluster:複数のMemberで構成される协作動作するクラスタ
- Peer:同一クラスタ内の他のMemberへの称呼
- WAL:永続化用の予書きログ
- Snapshot:WALファイル過多防止のためのデータスナップショット
- Leader:RAFT選出されたデータ提交負責ノード
- Follower:選出に失敗した从属ノード
- Candidate:Heartbeat未受信により立候補状態となったノード
- Term:Leader选出から下次选出までの期間
- Index:データ项目の連番
etcdctlコマンドラインツール
接続設定
ETCD_CA_CERT="/opt/etcd/ssl/ca.crt"
ETCD_CERT="/opt/etcd/ssl/server.crt"
ETCD_KEY="/opt/etcd/ssl/server.key"
ENDPOINT="https://192.168.1.100:2379"
使用例:
ETCDCTL_API=3 etcdctl --cacert="${ETCD_CA_CERT}" --cert="${ETCD_CERT}" --key="${ETCD_KEY}" \
--endpoints="${ENDPOINT}" endpoint status --write-out=table
主要操作コマンド
# キー操作
put mykey myvalue # 作成・更新
get mykey # 取得
get --prefix "/config" # プレフィックス検索
get --prefix "" --keys-only # 全キーリスト
del mykey # 削除
txn <<<'mod("key1") > "0"
put key1 "overwrite-value"
put key1 "new-value"
'
compaction 1234 # 圧縮
watch mykey # 監視
# クラスタ管理
member list # メンバー一覧
endpoint health # 健全性確認
endpoint status # 状態確認
alarm list # アラート一覧
alarm disarm # アラート解除
defrag # デフラグ
snapshot save backup.db # バックアップ
snapshot restore backup.db # リストア
snapshot status backup.db # ステータス確認
モニタリング
重要指標カテゴリ
| カテゴリ | 指標 | 説明 |
|---|---|---|
| 健全性 | ノード状態 | クラスタメンバーのオンライン/オフライン状況 |
| 健全性 | Leader切替頻度 | 频繁なLeader変更はネットワーク問題や負荷過多を示唆 |
| 健全性 | Heartbeat | ノード間通信の正常性を反映 |
| RED | QPS | 每秒リクエスト処理数 |
| RED | 错误率 | опера成功率の指標 |
| RED | 応答遅延 | API処理時間の分布 |
| RED | ディスク同期時間 | WAL/DB fsyncの遅延。10ms以上は大容量I/Oの問題を示唆 |
| RED | 复制遅延 | LeaderとFollower間のデータ同期状況 |
| RED | 提案失败数 | Leader选出失敗やクォーラム喪失を示唆 |
| RED | Watcher数 | 接続クライアント数 |
| USE | CPU使用率 | プロセッサ負荷 |
| USE | メモリ使用量 | RAM消費状況 |
| USE | オープンファイル数 | ファイルディスククリプタ使用状況 |
| USE | ストレージ使用率 | ディスク容量の占有率 |
Prometheusによる監視設定
HTTPモード(推奨):
# etcd起動パラメータに追加
--listen-metrics-urls=http://127.0.0.1:2381,http://0.0.0.0:2381
# Helmデプロイ
helm install prometheus -n monitoring \
--set kubeEtcd.service.port=2381 \
--set kubeEtcd.service.targetPort=2381 \
./prometheus
HTTPSモード:
# 証明書の作成
kubectl create secret generic etcd-certs -n monitoring \
--from-file=ca.crt=/etc/kubernetes/pki/etcd/ca.crt \
--from-file=client.crt=/etc/kubernetes/pki/etcd/healthcheck-client.crt \
--from-file=client.key=/etc/kubernetes/pki/etcd/healthcheck-client.key
# Helmデプロイ
helm install prometheus -n monitoring \
--set kubeEtcd.serviceMonitor.scheme=https \
--set kubeEtcd.serviceMonitor.caFile=/etc/prometheus/secrets/etcd-certs/ca.crt \
--set kubeEtcd.serviceMonitor.certFile=/etc/prometheus/secrets/etcd-certs/client.crt \
--set kubeEtcd.serviceMonitor.keyFile=/etc/prometheus/secrets/etcd-certs/client.key \
--set prometheus.prometheusSpec.secrets={etcd-certs} \
./prometheus
ベンチマークテスト
SLI/SLO定義
SLI(Service Level Indicator)は安定性を測定する指標、SLO(Service Level Objective)は目標値です。
| SLI | SLO |
|---|---|
| 処理能力 | 每秒40,000讀取・20,000写入リクエスト |
| 応答時間 | 99%の操作が100ms以内に完了 |
benchmarkツールの 설치と実行
# Go環境構築
wget https://golang.google.cn/dl/go1.20.5.linux-amd64.tar.gz
tar -C /usr/local -xzf go1.20.5.linux-amd64.tar.gz
# 環境変数の設定
export PATH=$PATH:/usr/local/go/bin
export GOPROXY=https://goproxy.cn
# バージョ确认
go version
# benchmarkツールの 설치
git clone https://github.com/etcd-io/etcd.git --depth 1
cd etcd/
go install -v ./tools/benchmark
# バイナリ配置確認
go list -f "{{.Target}}" ./tools/benchmark
# テスト用エンドポイント設定
ETCD_CA_CERT="/opt/etcd/ssl/ca.crt"
ETCD_CERT="/opt/etcd/ssl/server.crt"
ETCD_KEY="/opt/etcd/ssl/server.key"
LEADER_NODE="https://192.168.1.101:2379"
ALL_NODES="https://192.168.1.101:2379,https://192.168.1.102:2379,https://192.168.1.103:2379"
# テストキーの作成
TEST_KEY="benchmark-test"
ETCDCTL_API=3 /usr/local/bin/etcdctl --endpoints=${LEADER_NODE} \
--cacert="${ETCD_CA_CERT}" --cert="${ETCD_CERT}" --key="${ETCD_KEY}" \
put $TEST_KEY "test-value"
写入テスト
# Leaderへの写入(单一接続)
./benchmark --endpoints=${LEADER_NODE} \
--cacert="${ETCD_CA_CERT}" --cert="${ETCD_CERT}" --key="${ETCD_KEY}" \
--target-leader --conns=1 --clients=1 \
put --key-size=8 --sequential-keys --total=10000 --val-size=256
# Leaderへの写入(高并发)
./benchmark --endpoints=${LEADER_NODE} \
--cacert="${ETCD_CA_CERT}" --cert="${ETCD_CERT}" --key="${ETCD_KEY}" \
--target-leader --conns=100 --clients=1000 \
put --key-size=8 --sequential-keys --total=100000 --val-size=256
# 全ノードへの写入
./benchmark --endpoints=${ALL_NODES} \
--cacert="${ETCD_CA_CERT}" --cert="${ETCD_CERT}" --key="${ETCD_KEY}" \
--conns=100 --clients=1000 \
put --key-size=8 --sequential-keys --total=100000 --val-size=256
读取テスト
# 単一接続での読み取り(linearizable)
./benchmark --endpoints=${ALL_NODES} \
--cacert="${ETCD_CA_CERT}" --cert="${ETCD_CERT}" --key="${ETCD_KEY}" \
--conns=1 --clients=1 \
range $TEST_KEY --consistency=l --total=10000
# 単一接続での読み取り(serializable)
./benchmark --endpoints=${ALL_NODES} \
--cacert="${ETCD_CA_CERT}" --cert="${ETCD_CERT}" --key="${ETCD_KEY}" \
--conns=1 --clients=1 \
range $TEST_KEY --consistency=s --total=10000
# 高并发読み取り
./benchmark --endpoints=${ALL_NODES} \
--cacert="${ETCD_CA_CERT}" --cert="${ETCD_CERT}" --key="${ETCD_KEY}" \
--conns=100 --clients=1000 \
range $TEST_KEY --consistency=l --total=100000
ディスク性能検証
etcdの性能はネットワーク遅延とディスクI/Oに大きく依存します。同一データセンター内での配置を推奨します。
評価方法:
- 実行中のクラスタでは
etcd_disk_wal_fsync_duration_seconds指標で確認。99%値が10ms未満ならOK - fioコマンドで实际の使用パターンを再現
mkdir -p /tmp/etcd-test
fio --rw=write --ioengine=sync --fdatasync=1 \
--directory=/tmp/etcd-test --size=22m --bs=2300 --name=storage-test
パフォーマンス-tuning
ディスク最適化
SSDの使用を推奨。I/O優先度の高いプロセスとして実行:
sudo ionice -c2 -n0 -p $(pgrep etcd)
CPU最適化
CPUGovernorをperformanceモードに設定:
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
設定パラメータの最適化
- 自動圧縮の有効化
- RAFTメッセージサイズの調整
- ストレージ容量制限の設定
参考リソース
- etcd公式ドキュメント:https://etcd.io/docs/v3.5/
- etcdctlリファレンス:https://github.com/etcd-io/etcd/blob/main/etcdctl/README.md
- Datadog監視ガイド:https://docs.datadoghq.com/integrations/etcd/
- パフォーマンス tuning指南:https://etcd.io/docs/v3.5/tuning/
- Hardware要件:https://etcd.io/docs/v3.5/op-guide/hardware/