etcd分布式キーバリューストアの基礎知識と運用ガイド

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ノード間通信の正常性を反映
REDQPS每秒リクエスト処理数
RED错误率 опера成功率の指標
RED応答遅延API処理時間の分布
REDディスク同期時間WAL/DB fsyncの遅延。10ms以上は大容量I/Oの問題を示唆
RED复制遅延LeaderとFollower間のデータ同期状況
RED提案失败数Leader选出失敗やクォーラム喪失を示唆
REDWatcher数接続クライアント数
USECPU使用率プロセッサ負荷
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)は目標値です。

SLISLO
処理能力每秒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に大きく依存します。同一データセンター内での配置を推奨します。

評価方法:

  1. 実行中のクラスタではetcd_disk_wal_fsync_duration_seconds指標で確認。99%値が10ms未満ならOK
  2. 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/

タグ: etcd Kubernetes raft distributed-systems key-value-store

6月15日 23:50 投稿