Skip to content

Commit f35423c

Browse files
authored
fix: update conn derpmap every 5s in single tailnet (#9176)
1 parent 53de47d commit f35423c

File tree

9 files changed

+113
-16
lines changed

9 files changed

+113
-16
lines changed

coderd/apidoc/docs.go

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/coderd.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ func New(options *Options) *API {
404404
api.agentProvider, err = NewServerTailnet(api.ctx,
405405
options.Logger,
406406
options.DERPServer,
407-
options.BaseDERPMap,
407+
api.DERPMap,
408408
func(context.Context) (tailnet.MultiAgentConn, error) {
409409
return (*api.TailnetCoordinator.Load()).ServeMultiAgent(uuid.New()), nil
410410
},

coderd/tailnet.go

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,25 +44,49 @@ func NewServerTailnet(
4444
ctx context.Context,
4545
logger slog.Logger,
4646
derpServer *derp.Server,
47-
derpMap *tailcfg.DERPMap,
47+
derpMapFn func() *tailcfg.DERPMap,
4848
getMultiAgent func(context.Context) (tailnet.MultiAgentConn, error),
4949
cache *wsconncache.Cache,
5050
traceProvider trace.TracerProvider,
5151
) (*ServerTailnet, error) {
5252
logger = logger.Named("servertailnet")
53+
originalDerpMap := derpMapFn()
5354
conn, err := tailnet.NewConn(&tailnet.Options{
5455
Addresses: []netip.Prefix{netip.PrefixFrom(tailnet.IP(), 128)},
55-
DERPMap: derpMap,
56+
DERPMap: originalDerpMap,
5657
Logger: logger,
5758
})
5859
if err != nil {
5960
return nil, xerrors.Errorf("create tailnet conn: %w", err)
6061
}
6162

6263
serverCtx, cancel := context.WithCancel(ctx)
64+
derpMapUpdaterClosed := make(chan struct{})
65+
go func() {
66+
defer close(derpMapUpdaterClosed)
67+
68+
ticker := time.NewTicker(5 * time.Second)
69+
defer ticker.Stop()
70+
71+
for {
72+
select {
73+
case <-serverCtx.Done():
74+
return
75+
case <-ticker.C:
76+
}
77+
78+
newDerpMap := derpMapFn()
79+
if !tailnet.CompareDERPMaps(originalDerpMap, newDerpMap) {
80+
conn.SetDERPMap(newDerpMap)
81+
originalDerpMap = newDerpMap
82+
}
83+
}
84+
}()
85+
6386
tn := &ServerTailnet{
6487
ctx: serverCtx,
6588
cancel: cancel,
89+
derpMapUpdaterClosed: derpMapUpdaterClosed,
6690
logger: logger,
6791
tracer: traceProvider.Tracer(tracing.TracerName),
6892
conn: conn,
@@ -237,8 +261,9 @@ func (s *ServerTailnet) reinitCoordinator() {
237261
}
238262

239263
type ServerTailnet struct {
240-
ctx context.Context
241-
cancel func()
264+
ctx context.Context
265+
cancel func()
266+
derpMapUpdaterClosed chan struct{}
242267

243268
logger slog.Logger
244269
tracer trace.Tracer
@@ -403,5 +428,6 @@ func (s *ServerTailnet) Close() error {
403428
_ = s.cache.Close()
404429
_ = s.conn.Close()
405430
s.transport.CloseIdleConnections()
431+
<-s.derpMapUpdaterClosed
406432
return nil
407433
}

coderd/tailnet_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/stretchr/testify/assert"
1616
"github.com/stretchr/testify/require"
1717
"go.opentelemetry.io/otel/trace"
18+
"tailscale.com/tailcfg"
1819

1920
"cdr.dev/slog"
2021
"cdr.dev/slog/sloggers/slogtest"
@@ -230,7 +231,7 @@ func setupAgent(t *testing.T, agentAddresses []netip.Prefix) (uuid.UUID, agent.A
230231
context.Background(),
231232
logger,
232233
derpServer,
233-
manifest.DERPMap,
234+
func() *tailcfg.DERPMap { return manifest.DERPMap },
234235
func(context.Context) (tailnet.MultiAgentConn, error) { return coord.ServeMultiAgent(uuid.New()), nil },
235236
cache,
236237
trace.NewNoopTracerProvider(),

docs/api/schemas.md

Lines changed: 60 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

enterprise/coderd/workspaceproxy.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,7 @@ func (api *API) workspaceProxyRegister(rw http.ResponseWriter, r *http.Request)
720720
AppSecurityKey: api.AppSecurityKey.String(),
721721
DERPMeshKey: api.DERPServer.MeshKey(),
722722
DERPRegionID: regionID,
723+
DERPMap: api.AGPL.DERPMap(),
723724
SiblingReplicas: siblingsRes,
724725
})
725726

enterprise/wsproxy/wsproxy.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"golang.org/x/xerrors"
2222
"tailscale.com/derp"
2323
"tailscale.com/derp/derphttp"
24+
"tailscale.com/tailcfg"
2425
"tailscale.com/types/key"
2526

2627
"cdr.dev/slog"
@@ -119,7 +120,8 @@ type Server struct {
119120
SDKClient *wsproxysdk.Client
120121

121122
// DERP
122-
derpMesh *derpmesh.Mesh
123+
derpMesh *derpmesh.Mesh
124+
latestDERPMap *tailcfg.DERPMap
123125

124126
// Used for graceful shutdown. Required for the dialer.
125127
ctx context.Context
@@ -239,17 +241,14 @@ func New(ctx context.Context, opts *Options) (*Server, error) {
239241
return nil, xerrors.Errorf("parse app security key: %w", err)
240242
}
241243

242-
connInfo, err := client.SDKClient.WorkspaceAgentConnectionInfoGeneric(ctx)
243-
if err != nil {
244-
return nil, xerrors.Errorf("get derpmap: %w", err)
245-
}
246-
247244
var agentProvider workspaceapps.AgentProvider
248245
if opts.Experiments.Enabled(codersdk.ExperimentSingleTailnet) {
249246
stn, err := coderd.NewServerTailnet(ctx,
250247
s.Logger,
251248
nil,
252-
connInfo.DERPMap,
249+
func() *tailcfg.DERPMap {
250+
return s.latestDERPMap
251+
},
253252
s.DialCoordinator,
254253
wsconncache.New(s.DialWorkspaceAgent, 0),
255254
s.TracerProvider,
@@ -456,6 +455,8 @@ func (s *Server) handleRegister(_ context.Context, res wsproxysdk.RegisterWorksp
456455
}
457456
s.derpMesh.SetAddresses(addresses, false)
458457

458+
s.latestDERPMap = res.DERPMap
459+
459460
return nil
460461
}
461462

enterprise/wsproxy/wsproxysdk/wsproxysdk.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/google/uuid"
1515
"golang.org/x/xerrors"
1616
"nhooyr.io/websocket"
17+
"tailscale.com/tailcfg"
1718
"tailscale.com/util/singleflight"
1819

1920
"cdr.dev/slog"
@@ -206,9 +207,10 @@ type RegisterWorkspaceProxyRequest struct {
206207
}
207208

208209
type RegisterWorkspaceProxyResponse struct {
209-
AppSecurityKey string `json:"app_security_key"`
210-
DERPMeshKey string `json:"derp_mesh_key"`
211-
DERPRegionID int32 `json:"derp_region_id"`
210+
AppSecurityKey string `json:"app_security_key"`
211+
DERPMeshKey string `json:"derp_mesh_key"`
212+
DERPRegionID int32 `json:"derp_region_id"`
213+
DERPMap *tailcfg.DERPMap `json:"derp_map"`
212214
// SiblingReplicas is a list of all other replicas of the proxy that have
213215
// not timed out.
214216
SiblingReplicas []codersdk.Replica `json:"sibling_replicas"`

0 commit comments

Comments
 (0)