[lxc-devel] [lxd/master] lxd/cluster: Add time skew detection
stgraber on Github
lxc-bot at linuxcontainers.org
Thu May 21 16:23:54 UTC 2020
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 370 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200521/db819849/attachment.bin>
-------------- next part --------------
From 029e18d71d9b498bb6522fb779130634fdbe3c4b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 21 May 2020 12:11:28 -0400
Subject: [PATCH] lxd/cluster: Add time skew detection
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Closes #7321
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/cluster/gateway.go | 19 +++++++++++++++++++
lxd/cluster/heartbeat.go | 5 +++--
2 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/lxd/cluster/gateway.go b/lxd/cluster/gateway.go
index 2195ca6d9f..14cad5378d 100644
--- a/lxd/cluster/gateway.go
+++ b/lxd/cluster/gateway.go
@@ -117,6 +117,9 @@ type Gateway struct {
// Abstract unix socket that the local dqlite task is listening to.
bindAddress string
+
+ // Keep track of skews
+ timeSkew bool
}
// Current dqlite protocol version.
@@ -183,6 +186,22 @@ func (g *Gateway) HandlerFuncs(nodeRefreshTask func(*APIHeartbeat)) map[string]h
return
}
+ // Look for time skews
+ if heartbeatData.Time.Add(5 * time.Second).Before(time.Now().UTC()) {
+ if !g.timeSkew {
+ logger.Warnf("Time skew detected between local member and leader (%s vs %s)", heartbeatData.Time, time.Now().UTC())
+ }
+ g.timeSkew = true
+ } else if heartbeatData.Time.Add(-5 * time.Second).After(time.Now().UTC()) {
+ if !g.timeSkew {
+ logger.Warnf("Time skew detected between local member and leader (%s vs %s)", heartbeatData.Time, time.Now().UTC())
+ }
+ g.timeSkew = true
+ } else {
+ logger.Warnf("Time skew resolved")
+ g.timeSkew = false
+ }
+
raftNodes := make([]db.RaftNode, 0)
for _, node := range heartbeatData.Members {
if node.RaftID > 0 {
diff --git a/lxd/cluster/heartbeat.go b/lxd/cluster/heartbeat.go
index 6db52b4ed9..b43be4d9b1 100644
--- a/lxd/cluster/heartbeat.go
+++ b/lxd/cluster/heartbeat.go
@@ -52,7 +52,6 @@ type APIHeartbeat struct {
// If allNodes provided is an empty set then this is considered a non-full state list.
func (hbState *APIHeartbeat) Update(fullStateList bool, raftNodes []db.RaftNode, allNodes []db.NodeInfo, offlineThreshold time.Duration) {
var maxSchemaVersion, maxAPIExtensionsVersion int
- hbState.Time = time.Now()
if hbState.Members == nil {
hbState.Members = make(map[int64]APIHeartbeatMember)
@@ -121,8 +120,10 @@ func (hbState *APIHeartbeat) Send(ctx context.Context, cert *shared.CertInfo, lo
}
logger.Debugf("Sending heartbeat to %s", address)
- err := HeartbeatNode(ctx, address, cert, heartbeatData)
+ // Update timestamp to current, used for time skew detection
+ heartbeatData.Time = time.Now().UTC()
+ err := HeartbeatNode(ctx, address, cert, heartbeatData)
if err == nil {
hbState.Lock()
// Ensure only update nodes that exist in Members already.
More information about the lxc-devel
mailing list