Skip to content

Commit 495d54f

Browse files
grpc: Enable client-side health_v1 health checking
1 parent 61d2558 commit 495d54f

File tree

3 files changed

+32
-21
lines changed

3 files changed

+32
-21
lines changed

grpc/client.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@ import (
1414
"github.com/letsencrypt/boulder/cmd"
1515
bcreds "github.com/letsencrypt/boulder/grpc/creds"
1616

17-
// 'grpc/health' is imported for its init function, which causes clients to
18-
// rely on the Health Service for load-balancing.
1917
// 'grpc/internal/resolver/dns' is imported for its init function, which
2018
// registers the SRV resolver.
2119
"google.golang.org/grpc/balancer/roundrobin"
20+
21+
// 'grpc/health' is imported for its init function, which causes clients to
22+
// rely on the Health Service for load-balancing as long as a
23+
// "healthCheckConfig" is specified in the gRPC service config.
2224
_ "google.golang.org/grpc/health"
2325

2426
_ "github.com/letsencrypt/boulder/grpc/internal/resolver/dns"
@@ -61,7 +63,21 @@ func ClientSetup(c *cmd.GRPCClientConfig, tlsConfig *tls.Config, statsRegistry p
6163
creds := bcreds.NewClientCredentials(tlsConfig.RootCAs, tlsConfig.Certificates, hostOverride)
6264
return grpc.NewClient(
6365
target,
64-
grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"loadBalancingConfig": [{"%s":{}}]}`, roundrobin.Name)),
66+
grpc.WithDefaultServiceConfig(
67+
fmt.Sprintf(
68+
// By setting the service name to an empty string in
69+
// healthCheckConfig, we're instructing the gRPC client to query
70+
// the overall health status of each server. The grpc-go health
71+
// server, as constructed by health.NewServer(), unconditionally
72+
// sets the overall service (e.g. "") status to SERVING. If a
73+
// specific service name were set, the server would need to
74+
// explicitly transition that service to SERVING; otherwise,
75+
// clients would receive a NOT_FOUND status and the connection
76+
// would be marked as unhealthy (TRANSIENT_FAILURE).
77+
`{"healthCheckConfig": {"serviceName": ""},"loadBalancingConfig": [{"%s":{}}]}`,
78+
roundrobin.Name,
79+
),
80+
),
6581
grpc.WithTransportCredentials(creds),
6682
grpc.WithChainUnaryInterceptor(unaryInterceptors...),
6783
grpc.WithChainStreamInterceptor(streamInterceptors...),

grpc/server.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,15 @@ func (sb *serverBuilder) Build(tlsConfig *tls.Config, statsRegistry prometheus.R
129129
}
130130
}
131131

132+
// Ensure that the health service has the same ClientNames as the other
133+
// services, so that health checks can be performed by clients which are
134+
// allowed to connect to the server.
135+
healthService := sb.cfg.Services[healthpb.Health_ServiceDesc.ServiceName]
136+
for as := range acceptedSANs {
137+
healthService.ClientNames = append(healthService.ClientNames, as)
138+
}
139+
sb.cfg.Services[healthpb.Health_ServiceDesc.ServiceName] = healthService
140+
132141
creds, err := bcreds.NewServerCredentials(tlsConfig, acceptedSANs)
133142
if err != nil {
134143
return nil, err
@@ -224,6 +233,9 @@ func (sb *serverBuilder) Build(tlsConfig *tls.Config, statsRegistry prometheus.R
224233

225234
// initLongRunningCheck initializes a goroutine which will periodically check
226235
// the health of the provided service and update the health server accordingly.
236+
//
237+
// TODO(): Remove the service parameter and instead rely on transitioning the
238+
// overall health of the server (e.g. "") instead of individual services.
227239
func (sb *serverBuilder) initLongRunningCheck(shutdownCtx context.Context, service string, checkImpl func(context.Context) error) {
228240
// Set the initial health status for the service.
229241
sb.healthSrv.SetServingStatus(service, healthpb.HealthCheckResponse_NOT_SERVING)
@@ -253,6 +265,7 @@ func (sb *serverBuilder) initLongRunningCheck(shutdownCtx context.Context, servi
253265
} else {
254266
sb.logger.Infof("transitioning health of %q from %q to %q", service, last, next)
255267
}
268+
sb.healthSrv.SetServingStatus("", next)
256269
sb.healthSrv.SetServingStatus(service, next)
257270
return next
258271
}

test/consul/config.hcl

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -240,24 +240,6 @@ services {
240240
tls_server_name = "sa.boulder"
241241
tls_skip_verify = false
242242
interval = "2s"
243-
},
244-
{
245-
id = "sa-a-grpc-sa"
246-
name = "sa-a-grpc-sa"
247-
grpc = "10.77.77.77:9395/sa.StorageAuthority"
248-
grpc_use_tls = true
249-
tls_server_name = "sa.boulder"
250-
tls_skip_verify = false
251-
interval = "2s"
252-
},
253-
{
254-
id = "sa-a-grpc-saro"
255-
name = "sa-a-grpc-saro"
256-
grpc = "10.77.77.77:9395/sa.StorageAuthorityReadOnly"
257-
grpc_use_tls = true
258-
tls_server_name = "sa.boulder"
259-
tls_skip_verify = false
260-
interval = "2s"
261243
}
262244
]
263245
}

0 commit comments

Comments
 (0)