mirror of
https://github.com/siderolabs/discovery-service.git
synced 2025-03-14 09:55:08 +00:00
feat: implement landing page for the discovery service
Landing page is served on a different port for easier ingress configuration. Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
This commit is contained in:
@ -32,6 +32,7 @@ import (
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/talos-systems/discovery-service/api/v1alpha1/server/pb"
|
||||
"github.com/talos-systems/discovery-service/internal/landing"
|
||||
_ "github.com/talos-systems/discovery-service/internal/proto"
|
||||
"github.com/talos-systems/discovery-service/internal/state"
|
||||
"github.com/talos-systems/discovery-service/pkg/server"
|
||||
@ -39,6 +40,7 @@ import (
|
||||
|
||||
var (
|
||||
listenAddr = ":3000"
|
||||
landingAddr = ":3001"
|
||||
metricsAddr = ":2122"
|
||||
debugAddr = ":2123"
|
||||
devMode = false
|
||||
@ -47,6 +49,7 @@ var (
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&listenAddr, "addr", listenAddr, "addr on which to listen")
|
||||
flag.StringVar(&landingAddr, "landing-addr", landingAddr, "addr on which to listen for landing page")
|
||||
flag.StringVar(&metricsAddr, "metrics-addr", metricsAddr, "prometheus metrics listen addr")
|
||||
flag.BoolVar(&devMode, "debug", devMode, "enable debug mode")
|
||||
flag.DurationVar(&gcInterval, "gc-interval", gcInterval, "garbage collection interval")
|
||||
@ -143,6 +146,11 @@ func run(ctx context.Context, logger *zap.Logger) error {
|
||||
return fmt.Errorf("failed to listen: %w", err)
|
||||
}
|
||||
|
||||
landingLis, err := net.Listen("tcp", landingAddr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to listen: %w", err)
|
||||
}
|
||||
|
||||
s := grpc.NewServer(serverOptions...)
|
||||
pb.RegisterClusterServer(s, srv)
|
||||
|
||||
@ -160,6 +168,10 @@ func run(ctx context.Context, logger *zap.Logger) error {
|
||||
Handler: &metricsMux,
|
||||
}
|
||||
|
||||
landingServer := http.Server{
|
||||
Handler: landing.Handler(),
|
||||
}
|
||||
|
||||
eg, ctx := errgroup.WithContext(ctx)
|
||||
|
||||
eg.Go(func() error {
|
||||
@ -172,6 +184,16 @@ func run(ctx context.Context, logger *zap.Logger) error {
|
||||
return nil
|
||||
})
|
||||
|
||||
eg.Go(func() error {
|
||||
logger.Info("landing server starting", zap.Stringer("address", landingLis.Addr()))
|
||||
|
||||
if err := landingServer.Serve(landingLis); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||
return fmt.Errorf("failed to serve: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
eg.Go(func() error {
|
||||
logger.Info("metrics starting", zap.String("address", metricsServer.Addr))
|
||||
|
||||
@ -189,6 +211,7 @@ func run(ctx context.Context, logger *zap.Logger) error {
|
||||
defer shutdownCancel()
|
||||
|
||||
s.GracefulStop()
|
||||
landingServer.Shutdown(ctx) //nolint:errcheck
|
||||
metricsServer.Shutdown(shutdownCtx) //nolint:errcheck
|
||||
|
||||
return nil
|
||||
|
47
internal/landing/html/index.html
Normal file
47
internal/landing/html/index.html
Normal file
@ -0,0 +1,47 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Discovery Service</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>What is this IP address?</h1>
|
||||
|
||||
<p>This is the Kubernetes cluster Member Discovery Service run by <a href="https://www.siderolabs.com/kubespan/">Sidero Labs</a>.</p>
|
||||
|
||||
<p>
|
||||
If you see traffic to this IP address, it is from Kubernetes nodes in your organization that are using KubeSpan to coordinate secure, encrypted membership of a Kubernetes cluster.
|
||||
This service provides back information needed to establish the secure communication channels.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
All information to and from this service is encrypted, and the service cannot decrypt the data - only the nodes that are part of the same Kubernetes cluster can decrypt it.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For more information, see <a href="https://www.siderolabs.com/kubespan/">https://www.siderolabs.com/kubespan/</a>.
|
||||
</p>
|
||||
|
||||
<h2>Details</h2>
|
||||
|
||||
<p>
|
||||
Before sending data to the discovery service, Talos will encrypt the affiliate data with AES-GCM encryption and
|
||||
separately encrypt endpoints with AES in ECB mode so that endpoints coming from different sources can be deduplicated server-side.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Each node submits it's data encrypted plus it submits the endpoints it sees from other peers to the discovery service.
|
||||
The discovery service aggregates the data, deduplicates the endpoints, and sends updates to each connected peer.
|
||||
Each peer receives information back about other affiliates from the discovery service, decrypts it and uses it to drive KubeSpan and cluster discovery.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Moreover, the discovery service has no peristence.
|
||||
Data is stored in memory only with a TTL set by the clients (i.e. Talos).
|
||||
The cluster ID is used as a key to select the affiliates (so that different clusters see different affiliates).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To summarize, the discovery service knows the client version, cluster ID, the number of affiliates, some encrypted data for each affiliate, and a list of encrypted endpoints.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
28
internal/landing/landing.go
Normal file
28
internal/landing/landing.go
Normal file
@ -0,0 +1,28 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// Package landing provides the HTML landing page.
|
||||
package landing
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
//go:embed "html/index.html"
|
||||
var static embed.FS
|
||||
|
||||
// Handler returns static landing page handler.
|
||||
func Handler() http.Handler {
|
||||
subfs, err := fs.Sub(static, "html")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle("/", http.FileServer(http.FS(subfs)))
|
||||
|
||||
return mux
|
||||
}
|
Reference in New Issue
Block a user