mirror of
https://github.com/pomerium/pomerium.git
synced 2025-08-06 10:21:05 +02:00
authorize: grpc health check (#2200)
This commit is contained in:
parent
7d5754ec36
commit
c71f7dca5b
3 changed files with 91 additions and 1 deletions
|
@ -7,15 +7,18 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
envoy_config_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3"
|
envoy_config_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3"
|
||||||
envoy_config_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
|
envoy_config_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
|
||||||
envoy_config_endpoint_v3 "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3"
|
envoy_config_endpoint_v3 "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3"
|
||||||
envoy_extensions_transport_sockets_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
|
envoy_extensions_transport_sockets_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
|
||||||
envoy_type_matcher_v3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3"
|
envoy_type_matcher_v3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3"
|
||||||
"github.com/golang/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
"google.golang.org/protobuf/types/known/anypb"
|
"google.golang.org/protobuf/types/known/anypb"
|
||||||
|
"google.golang.org/protobuf/types/known/durationpb"
|
||||||
"google.golang.org/protobuf/types/known/structpb"
|
"google.golang.org/protobuf/types/known/structpb"
|
||||||
|
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||||
|
|
||||||
"github.com/pomerium/pomerium/config"
|
"github.com/pomerium/pomerium/config"
|
||||||
"github.com/pomerium/pomerium/internal/log"
|
"github.com/pomerium/pomerium/internal/log"
|
||||||
|
@ -50,6 +53,11 @@ func (b *Builder) BuildClusters(ctx context.Context, cfg *config.Config) ([]*env
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(authzURLs) > 1 {
|
||||||
|
authZ.HealthChecks = grpcHealthChecks("pomerium-authorize")
|
||||||
|
authZ.OutlierDetection = grpcAuthorizeOutlierDetection()
|
||||||
|
}
|
||||||
|
|
||||||
clusters := []*envoy_config_cluster_v3.Cluster{
|
clusters := []*envoy_config_cluster_v3.Cluster{
|
||||||
controlGRPC,
|
controlGRPC,
|
||||||
controlHTTP,
|
controlHTTP,
|
||||||
|
@ -99,6 +107,7 @@ func (b *Builder) buildInternalCluster(
|
||||||
if err := b.buildCluster(cluster, name, endpoints, forceHTTP2); err != nil {
|
if err := b.buildCluster(cluster, name, endpoints, forceHTTP2); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return cluster, nil
|
return cluster, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,6 +354,49 @@ func (b *Builder) buildCluster(
|
||||||
return cluster.Validate()
|
return cluster.Validate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// grpcAuthorizeOutlierDetection defines slightly more aggressive malfunction detection for authorize endpoints
|
||||||
|
func grpcAuthorizeOutlierDetection() *envoy_config_cluster_v3.OutlierDetection {
|
||||||
|
return &envoy_config_cluster_v3.OutlierDetection{
|
||||||
|
Consecutive_5Xx: wrapperspb.UInt32(5),
|
||||||
|
Interval: durationpb.New(time.Second * 10),
|
||||||
|
BaseEjectionTime: durationpb.New(time.Second * 30),
|
||||||
|
MaxEjectionPercent: wrapperspb.UInt32(100),
|
||||||
|
EnforcingConsecutive_5Xx: wrapperspb.UInt32(100),
|
||||||
|
EnforcingSuccessRate: wrapperspb.UInt32(100),
|
||||||
|
SuccessRateMinimumHosts: wrapperspb.UInt32(2),
|
||||||
|
SuccessRateRequestVolume: wrapperspb.UInt32(10),
|
||||||
|
SuccessRateStdevFactor: wrapperspb.UInt32(1900),
|
||||||
|
ConsecutiveGatewayFailure: wrapperspb.UInt32(5),
|
||||||
|
EnforcingConsecutiveGatewayFailure: wrapperspb.UInt32(0),
|
||||||
|
SplitExternalLocalOriginErrors: false,
|
||||||
|
FailurePercentageThreshold: wrapperspb.UInt32(85),
|
||||||
|
EnforcingFailurePercentage: wrapperspb.UInt32(100),
|
||||||
|
EnforcingFailurePercentageLocalOrigin: wrapperspb.UInt32(100),
|
||||||
|
FailurePercentageMinimumHosts: wrapperspb.UInt32(2),
|
||||||
|
FailurePercentageRequestVolume: wrapperspb.UInt32(10),
|
||||||
|
MaxEjectionTime: durationpb.New(time.Minute * 5),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func grpcHealthChecks(name string) []*envoy_config_core_v3.HealthCheck {
|
||||||
|
return []*envoy_config_core_v3.HealthCheck{{
|
||||||
|
Timeout: durationpb.New(time.Second * 10),
|
||||||
|
Interval: durationpb.New(time.Second * 10),
|
||||||
|
InitialJitter: durationpb.New(time.Millisecond * 100),
|
||||||
|
IntervalJitter: durationpb.New(time.Millisecond * 100),
|
||||||
|
IntervalJitterPercent: 10,
|
||||||
|
UnhealthyThreshold: wrapperspb.UInt32(1),
|
||||||
|
HealthyThreshold: wrapperspb.UInt32(1),
|
||||||
|
ReuseConnection: wrapperspb.Bool(true),
|
||||||
|
NoTrafficInterval: durationpb.New(time.Minute),
|
||||||
|
HealthChecker: &envoy_config_core_v3.HealthCheck_GrpcHealthCheck_{
|
||||||
|
GrpcHealthCheck: &envoy_config_core_v3.HealthCheck_GrpcHealthCheck{
|
||||||
|
ServiceName: name,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
func (b *Builder) buildLbEndpoints(endpoints []Endpoint) ([]*envoy_config_endpoint_v3.LbEndpoint, error) {
|
func (b *Builder) buildLbEndpoints(endpoints []Endpoint) ([]*envoy_config_endpoint_v3.LbEndpoint, error) {
|
||||||
var lbes []*envoy_config_endpoint_v3.LbEndpoint
|
var lbes []*envoy_config_endpoint_v3.LbEndpoint
|
||||||
for _, e := range endpoints {
|
for _, e := range endpoints {
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/health/grpc_health_v1"
|
||||||
"google.golang.org/grpc/metadata"
|
"google.golang.org/grpc/metadata"
|
||||||
"google.golang.org/grpc/reflection"
|
"google.golang.org/grpc/reflection"
|
||||||
|
|
||||||
|
@ -24,6 +25,7 @@ import (
|
||||||
"github.com/pomerium/pomerium/internal/telemetry"
|
"github.com/pomerium/pomerium/internal/telemetry"
|
||||||
"github.com/pomerium/pomerium/internal/telemetry/requestid"
|
"github.com/pomerium/pomerium/internal/telemetry/requestid"
|
||||||
"github.com/pomerium/pomerium/internal/version"
|
"github.com/pomerium/pomerium/internal/version"
|
||||||
|
pom_grpc "github.com/pomerium/pomerium/pkg/grpc"
|
||||||
"github.com/pomerium/pomerium/pkg/grpc/events"
|
"github.com/pomerium/pomerium/pkg/grpc/events"
|
||||||
"github.com/pomerium/pomerium/pkg/grpcutil"
|
"github.com/pomerium/pomerium/pkg/grpcutil"
|
||||||
)
|
)
|
||||||
|
@ -93,6 +95,8 @@ func NewServer(name string, metricsMgr *config.MetricsManager) (*Server, error)
|
||||||
reflection.Register(srv.GRPCServer)
|
reflection.Register(srv.GRPCServer)
|
||||||
srv.registerAccessLogHandlers()
|
srv.registerAccessLogHandlers()
|
||||||
|
|
||||||
|
grpc_health_v1.RegisterHealthServer(srv.GRPCServer, pom_grpc.NewHealthCheckServer())
|
||||||
|
|
||||||
// setup HTTP
|
// setup HTTP
|
||||||
srv.HTTPListener, err = net.Listen("tcp4", "127.0.0.1:0")
|
srv.HTTPListener, err = net.Listen("tcp4", "127.0.0.1:0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
34
pkg/grpc/health.go
Normal file
34
pkg/grpc/health.go
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
package grpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
grpc_health "google.golang.org/grpc/health/grpc_health_v1"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
|
||||||
|
"github.com/pomerium/pomerium/internal/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type healthCheckSrv struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewHealthCheckServer returns a basic health checker
|
||||||
|
func NewHealthCheckServer() grpc_health.HealthServer {
|
||||||
|
return &healthCheckSrv{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check confirms service is reachable, and assumes any service is operational
|
||||||
|
// an outlier detection should be used to detect runtime malfunction based on consequitive 5xx
|
||||||
|
func (h *healthCheckSrv) Check(ctx context.Context, req *grpc_health.HealthCheckRequest) (*grpc_health.HealthCheckResponse, error) {
|
||||||
|
log.Debug(ctx).Str("service", req.Service).Msg("health check")
|
||||||
|
return &grpc_health.HealthCheckResponse{
|
||||||
|
Status: grpc_health.HealthCheckResponse_SERVING,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Watch is not implemented as is not used by Envoy
|
||||||
|
func (h *healthCheckSrv) Watch(req *grpc_health.HealthCheckRequest, _ grpc_health.Health_WatchServer) error {
|
||||||
|
log.Error(context.Background()).Str("service", req.Service).Msg("health check watch")
|
||||||
|
return status.Errorf(codes.Unimplemented, "method Watch not implemented")
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue