Skip to content

Commit

Permalink
refactor: avoid recreating grpc clients in service health checks
Browse files Browse the repository at this point in the history
Creating a new GRPC client for containerd and CRI every time we do a health check creates a lot of garbage. With this PR, we create them once and reuse them instead.

Signed-off-by: Utku Ozdemir <[email protected]>
  • Loading branch information
utkuozdemir committed Jun 28, 2022
1 parent a68a00f commit 57b625e
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 8 deletions.
29 changes: 25 additions & 4 deletions internal/app/machined/pkg/system/services/containerd.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,26 @@ import (

// Containerd implements the Service interface. It serves as the concrete type with
// the required methods.
type Containerd struct{}
type Containerd struct {
// client is a lazy-initialized containerd client. It should be accessed using the Client() method.
client *containerd.Client
}

// Client lazy-initializes the containerd client if needed and returns it.
func (c *Containerd) Client() (*containerd.Client, error) {
if c.client != nil {
return c.client, nil
}

client, err := containerd.New(constants.SystemContainerdAddress)
if err != nil {
return nil, err
}

c.client = client

return c.client, err
}

// ID implements the Service interface.
func (c *Containerd) ID(r runtime.Runtime) string {
Expand All @@ -38,6 +57,10 @@ func (c *Containerd) PreFunc(ctx context.Context, r runtime.Runtime) error {

// PostFunc implements the Service interface.
func (c *Containerd) PostFunc(r runtime.Runtime, state events.ServiceState) (err error) {
if c.client != nil {
return c.client.Close()
}

return nil
}

Expand Down Expand Up @@ -87,12 +110,10 @@ func (c *Containerd) Runner(r runtime.Runtime) (runner.Runner, error) {
// HealthFunc implements the HealthcheckedService interface.
func (c *Containerd) HealthFunc(runtime.Runtime) health.Check {
return func(ctx context.Context) error {
client, err := containerd.New(constants.SystemContainerdAddress)
client, err := c.Client()
if err != nil {
return err
}
//nolint:errcheck
defer client.Close()

resp, err := client.HealthService().Check(ctx, &grpc_health_v1.HealthCheckRequest{})
if err != nil {
Expand Down
29 changes: 25 additions & 4 deletions internal/app/machined/pkg/system/services/cri.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,26 @@ import (

// CRI implements the Service interface. It serves as the concrete type with
// the required methods.
type CRI struct{}
type CRI struct {
// client is a lazy-initialized containerd client. It should be accessed using the Client() method.
client *containerd.Client
}

// Client lazy-initializes the containerd client if needed and returns it.
func (c *CRI) Client() (*containerd.Client, error) {
if c.client != nil {
return c.client, nil
}

client, err := containerd.New(constants.CRIContainerdAddress)
if err != nil {
return nil, err
}

c.client = client

return c.client, err
}

// ID implements the Service interface.
func (c *CRI) ID(r runtime.Runtime) string {
Expand All @@ -40,6 +59,10 @@ func (c *CRI) PreFunc(ctx context.Context, r runtime.Runtime) error {

// PostFunc implements the Service interface.
func (c *CRI) PostFunc(r runtime.Runtime, state events.ServiceState) (err error) {
if c.client != nil {
return c.client.Close()
}

return nil
}

Expand Down Expand Up @@ -87,12 +110,10 @@ func (c *CRI) Runner(r runtime.Runtime) (runner.Runner, error) {
// HealthFunc implements the HealthcheckedService interface.
func (c *CRI) HealthFunc(runtime.Runtime) health.Check {
return func(ctx context.Context) error {
client, err := containerd.New(constants.CRIContainerdAddress)
client, err := c.Client()
if err != nil {
return err
}
//nolint:errcheck
defer client.Close()

resp, err := client.HealthService().Check(ctx, &grpc_health_v1.HealthCheckRequest{})
if err != nil {
Expand Down

0 comments on commit 57b625e

Please sign in to comment.