Skip to content

Commit

Permalink
[vtadmin] grpc healthserver + channelz (#10038)
Browse files Browse the repository at this point in the history
* Add `--rbac` to example vtadmin-up

This was introduced and made a required flag (with mutually-exclusive `--no-rbac`)
in #9972.

Signed-off-by: Andrew Mason <andrew@planetscale.com>

* Cleanup `Options.Services`, and inspect the ServiceInfo() directly

Instead of requiring users to know in advance (and put into their startup
scripts), which services will run, we can (correctly) inspect the service
names that have been registered on the underlying grpc.Server and mark
them as SERVING in the health service.

_Alsooooo_, this was never bound to a flag, so users couldn't use it
anyway! Whoops.

Signed-off-by: Andrew Mason <andrew@planetscale.com>

* Provide option to enable channelz service

Signed-off-by: Andrew Mason <andrew@planetscale.com>

* Add flag to enable channelz

Signed-off-by: Andrew Mason <andrew@planetscale.com>

* Tidy up flags; label all sections

Signed-off-by: Andrew Mason <andrew@planetscale.com>

* Add missing flag for AllowTracing

Signed-off-by: Andrew Mason <andrew@planetscale.com>
  • Loading branch information
Andrew Mason committed Apr 5, 2022
1 parent d7cd8cc commit 2d1681a
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 29 deletions.
1 change: 1 addition & 0 deletions examples/local/scripts/vtadmin-up.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ vtadmin \
--http-tracing \
--logtostderr \
--alsologtostderr \
--rbac \
--rbac-config="./vtadmin/rbac.yaml" \
--cluster "id=local,name=local,discovery=staticfile,discovery-staticfile-path=./vtadmin/discovery.json,tablet-fqdn-tmpl={{ .Tablet.Hostname }}:15{{ .Tablet.Alias.Uid }}" \
> "${log_dir}/vtadmin-api.out" 2>&1 &
Expand Down
11 changes: 10 additions & 1 deletion go/cmd/vtadmin/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,20 +141,29 @@ func run(cmd *cobra.Command, args []string) {
}

func main() {
// Common flags
rootCmd.Flags().StringVar(&opts.Addr, "addr", ":15000", "address to serve on")
rootCmd.Flags().DurationVar(&opts.CMuxReadTimeout, "lmux-read-timeout", time.Second, "how long to spend connection muxing")
rootCmd.Flags().DurationVar(&opts.LameDuckDuration, "lame-duck-duration", time.Second*5, "length of lame duck period at shutdown")

// Cluster config flags
rootCmd.Flags().Var(&clusterConfigs, "cluster", "per-cluster configuration. any values here take precedence over those in -cluster-defaults or -cluster-config")
rootCmd.Flags().Var(&clusterFileConfig, "cluster-config", "path to a yaml cluster configuration. see clusters.example.yaml") // (TODO:@amason) provide example config.
rootCmd.Flags().Var(&defaultClusterConfig, "cluster-defaults", "default options for all clusters")

// Tracing flags
rootCmd.Flags().AddGoFlag(flag.Lookup("tracer")) // defined in go/vt/trace
rootCmd.Flags().AddGoFlag(flag.Lookup("tracing-enable-logging")) // defined in go/vt/trace
rootCmd.Flags().AddGoFlag(flag.Lookup("tracing-sampling-type")) // defined in go/vt/trace
rootCmd.Flags().AddGoFlag(flag.Lookup("tracing-sampling-rate")) // defined in go/vt/trace
rootCmd.Flags().BoolVar(&opts.EnableTracing, "grpc-tracing", false, "whether to enable tracing on the gRPC server")
rootCmd.Flags().BoolVar(&httpOpts.EnableTracing, "http-tracing", false, "whether to enable tracing on the HTTP server")

// gRPC server flags
rootCmd.Flags().BoolVar(&opts.AllowReflection, "grpc-allow-reflection", false, "whether to register the gRPC server for reflection; this is required to use tools like `grpc_cli`")
rootCmd.Flags().BoolVar(&opts.EnableChannelz, "grpc-enable-channelz", false, "whether to enable the channelz service on the gRPC server")

// HTTP server flags
rootCmd.Flags().BoolVar(&httpOpts.DisableCompression, "http-no-compress", false, "whether to disable compression of HTTP API responses")
rootCmd.Flags().BoolVar(&httpOpts.DisableDebug, "http-no-debug", false, "whether to disable /debug/pprof/* and /debug/env HTTP endpoints")
rootCmd.Flags().Var(&debug.OmitEnv, "http-debug-omit-env", "name of an environment variable to omit from /debug/env, if http debug endpoints are enabled. specify multiple times to omit multiple env vars")
Expand All @@ -169,7 +178,7 @@ func main() {
)
rootCmd.Flags().BoolVar(&httpOpts.EnableDynamicClusters, "http-enable-dynamic-clusters", false, "whether to enable dynamic clusters that are set by request header cookies")

// rbac flags
// RBAC flags
rootCmd.Flags().StringVar(&rbacConfigPath, "rbac-config", "", "path to an RBAC config file. must be set if passing --rbac")
rootCmd.Flags().BoolVar(&enableRBAC, "rbac", false, "whether to enable RBAC. must be set if not passing --rbac")
rootCmd.Flags().BoolVar(&disableRBAC, "no-rbac", false, "whether to disable RBAC. must be set if not passing --no-rbac")
Expand Down
4 changes: 0 additions & 4 deletions go/vt/vtadmin/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,6 @@ func NewAPI(clusters []*cluster.Cluster, opts Options) *API {
return c1.ID < c2.ID
}).Sort(clusters)

if opts.GRPCOpts.Services == nil {
opts.GRPCOpts.Services = []string{"vtadmin.VTAdminServer"}
}

var (
authn rbac.Authenticator
authz *rbac.Authorizer
Expand Down
34 changes: 10 additions & 24 deletions go/vt/vtadmin/grpcserver/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
"github.com/opentracing/opentracing-go"
"github.com/soheilhy/cmux"
"google.golang.org/grpc"
channelz "google.golang.org/grpc/channelz/service"
"google.golang.org/grpc/health"
"google.golang.org/grpc/reflection"

Expand Down Expand Up @@ -63,26 +64,14 @@ type Options struct {
// EnableTracing specifies whether to install opentracing interceptors on
// the gRPC server.
EnableTracing bool
// Services is a list of service names to declare as SERVING in health
// checks. Names should be fully-qualified (package_name.service_name, e.g.
// vtadmin.VTAdminServer, not VTAdminServer), and must be unique for a
// single Server instance. Users of this package are responsible for
// ensuring they do not pass a list with duplicate service names.
//
// The service name "grpc.health.v1.Health" is reserved by this package in
// order to power the healthcheck service. Attempting to pass this in the
// Services list to a grpcserver will be ignored.
//
// See https://github.com/grpc/grpc/blob/7324556353e831c57d30973db33df489c3ed3576/doc/health-checking.md
// for more details on healthchecking.
Services []string
// EnableChannelz specifies whether to register the channelz service on the
// gRPC server.
EnableChannelz bool

StreamInterceptors []grpc.StreamServerInterceptor
UnaryInterceptors []grpc.UnaryServerInterceptor
}

const healthServiceName = "grpc.health.v1.Health" // reserved health service name

// Server provides a multiplexed gRPC/HTTP server.
type Server struct {
name string
Expand Down Expand Up @@ -137,6 +126,10 @@ func New(name string, opts Options) *Server {
healthServer := health.NewServer()
healthpb.RegisterHealthServer(gserv, healthServer)

if opts.EnableChannelz {
channelz.RegisterChannelzServiceToServer(gserv)
}

return &Server{
name: name,
gRPCServer: gserv,
Expand Down Expand Up @@ -225,15 +218,8 @@ func (s *Server) ListenAndServe() error { // nolint:funlen
shutdown <- err
}()

s.healthServer.SetServingStatus(healthServiceName, healthpb.HealthCheckResponse_SERVING)

for _, name := range s.opts.Services {
if name == healthServiceName {
log.Warningf("Attempted to register a service under the reserved healthcheck service name %s; ignoring", healthServiceName)
continue
}

s.healthServer.SetServingStatus(name, healthpb.HealthCheckResponse_SERVING)
for service := range s.gRPCServer.GetServiceInfo() {
s.healthServer.SetServingStatus(service, healthpb.HealthCheckResponse_SERVING)
}

s.setServing(true)
Expand Down

0 comments on commit 2d1681a

Please sign in to comment.