Skip to content

feat(healthz-server): add option to customize port #5151

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions api/v1alpha1/envoygateway_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,14 @@ type EnvoyGatewayProvider struct {
//
// +optional
Custom *EnvoyGatewayCustomProvider `json:"custom,omitempty"`

// HealthzServerPort defines the port for the healthz probe server.
// By default, when this field is unset or empty, Envoy Gateway will use the port 8081 for the healthz server.
// +optional
// +kubebuilder:default=8081
// +kubebuilder:validation:Minimum=0
// +kubebuilder:validation:Maximum=65535
HealthzServerPort int `json:"healthzServerPort,omitempty"`
}

// EnvoyGatewayKubernetesProvider defines configuration for the Kubernetes provider.
Expand Down
21 changes: 21 additions & 0 deletions api/v1alpha1/validation/envoygateway_validate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,27 @@ func TestValidateEnvoyGateway(t *testing.T) {
},
expect: false,
},
{
name: "custom provider with file provider and k8s infra with custom healthz probe port",
eg: &egv1a1.EnvoyGateway{
EnvoyGatewaySpec: egv1a1.EnvoyGatewaySpec{
Gateway: egv1a1.DefaultGateway(),
Provider: &egv1a1.EnvoyGatewayProvider{
Type: egv1a1.ProviderTypeCustom,
Custom: &egv1a1.EnvoyGatewayCustomProvider{
Resource: egv1a1.EnvoyGatewayResourceProvider{
Type: egv1a1.ResourceProviderTypeFile,
File: &egv1a1.EnvoyGatewayFileResourceProvider{
Paths: []string{"foo", "bar"},
},
},
},
HealthzServerPort: 1234,
},
},
},
expect: true,
},
{
name: "custom provider with file resource provider and host infra provider",
eg: &egv1a1.EnvoyGateway{
Expand Down
26 changes: 14 additions & 12 deletions internal/provider/file/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,27 +28,29 @@ import (
)

type Provider struct {
paths []string
logger logr.Logger
watcher filewatcher.FileWatcher
resourcesStore *resourcesStore
paths []string
logger logr.Logger
watcher filewatcher.FileWatcher
resourcesStore *resourcesStore
healthzServerPort int

// ready indicates whether the provider can start watching filesystem events.
ready atomic.Bool
}

func New(svr *config.Server, resources *message.ProviderResources) (*Provider, error) {
func New(svr *config.Server, resources *message.ProviderResources, healthzServerPort int) (*Provider, error) {
logger := svr.Logger.Logger
paths := sets.New[string]()
if svr.EnvoyGateway.Provider.Custom.Resource.File != nil {
paths.Insert(svr.EnvoyGateway.Provider.Custom.Resource.File.Paths...)
}

return &Provider{
paths: paths.UnsortedList(),
logger: logger,
watcher: filewatcher.NewWatcher(),
resourcesStore: newResourcesStore(svr.EnvoyGateway.Gateway.ControllerName, resources, logger),
paths: paths.UnsortedList(),
logger: logger,
watcher: filewatcher.NewWatcher(),
resourcesStore: newResourcesStore(svr.EnvoyGateway.Gateway.ControllerName, resources, logger),
healthzServerPort: healthzServerPort,
}, nil
}

Expand All @@ -68,7 +70,7 @@ func (p *Provider) Start(ctx context.Context) error {
}
return nil
}
go p.startHealthProbeServer(ctx, readyzChecker)
go p.startHealthProbeServer(ctx, readyzChecker, p.healthzServerPort)

initDirs, initFiles := path.ListDirsAndFiles(p.paths)
// Initially load resources from paths on host.
Expand Down Expand Up @@ -160,15 +162,15 @@ func (p *Provider) Start(ctx context.Context) error {
}
}

func (p *Provider) startHealthProbeServer(ctx context.Context, readyzChecker healthz.Checker) {
func (p *Provider) startHealthProbeServer(ctx context.Context, readyzChecker healthz.Checker, port int) {
const (
readyzEndpoint = "/readyz"
healthzEndpoint = "/healthz"
)

mux := http.NewServeMux()
srv := &http.Server{
Addr: ":8081",
Addr: fmt.Sprintf(":%d", port),
Handler: mux,
MaxHeaderBytes: 1 << 20,
IdleTimeout: 90 * time.Second, // matches http.DefaultTransport keep-alive timeout
Expand Down
6 changes: 4 additions & 2 deletions internal/provider/file/file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package file

import (
"context"
"fmt"
"html/template"
"io"
"net/http"
Expand All @@ -29,6 +30,7 @@ import (
const (
resourcesUpdateTimeout = 1 * time.Minute
resourcesUpdateTick = 1 * time.Second
healthzServerPort = 8081
)

type resourcesParam struct {
Expand Down Expand Up @@ -81,7 +83,7 @@ func TestFileProvider(t *testing.T) {
cfg, err := newFileProviderConfig([]string{watchFilePath, watchDirPath})
require.NoError(t, err)
pResources := new(message.ProviderResources)
fp, err := New(cfg, pResources)
fp, err := New(cfg, pResources, healthzServerPort)
require.NoError(t, err)
// Start file provider.
go func() {
Expand Down Expand Up @@ -195,7 +197,7 @@ func writeResourcesFile(t *testing.T, tmpl, dst string, params *resourcesParam)

func waitFileProviderReady(t *testing.T) {
require.Eventually(t, func() bool {
resp, err := http.Get("http://localhost:8081/readyz")
resp, err := http.Get(fmt.Sprintf("http://localhost:%d/readyz", healthzServerPort))
if err != nil {
t.Logf("failed to get from heathlz server")
return false
Expand Down
4 changes: 2 additions & 2 deletions internal/provider/kubernetes/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ type Provider struct {
}

// New creates a new Provider from the provided EnvoyGateway.
func New(ctx context.Context, restCfg *rest.Config, svrCfg *ec.Server, resources *message.ProviderResources) (*Provider, error) {
func New(ctx context.Context, restCfg *rest.Config, svrCfg *ec.Server, resources *message.ProviderResources, healthzServerPort int) (*Provider, error) {
// TODO: Decide which mgr opts should be exposed through envoygateway.provider.kubernetes API.

mgrOpts := manager.Options{
Scheme: envoygateway.GetScheme(),
Logger: svrCfg.Logger.Logger,
HealthProbeBindAddress: ":8081",
HealthProbeBindAddress: fmt.Sprintf(":%d", healthzServerPort),
LeaderElectionID: "5b9825d2.gateway.envoyproxy.io",
LeaderElectionNamespace: svrCfg.Namespace,
}
Expand Down
11 changes: 6 additions & 5 deletions internal/provider/kubernetes/kubernetes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ import (
)

const (
defaultWait = time.Second * 60
defaultTick = time.Millisecond * 20
defaultWait = time.Second * 60
defaultTick = time.Millisecond * 20
healthzServerPort = 8082
)

func TestMain(m *testing.M) {
Expand All @@ -63,7 +64,7 @@ func TestProvider(t *testing.T) {
svr, err := config.New()
require.NoError(t, err)
resources := new(message.ProviderResources)
provider, err := New(context.Background(), cliCfg, svr, resources)
provider, err := New(context.Background(), cliCfg, svr, resources, healthzServerPort)
require.NoError(t, err)
ctx, cancel := context.WithCancel(ctrl.SetupSignalHandler())
go func() {
Expand Down Expand Up @@ -1274,7 +1275,7 @@ func TestNamespacedProvider(t *testing.T) {
LeaderElection: egv1a1.DefaultLeaderElection(),
}
resources := new(message.ProviderResources)
provider, err := New(context.Background(), cliCfg, svr, resources)
provider, err := New(context.Background(), cliCfg, svr, resources, healthzServerPort)
require.NoError(t, err)
ctx, cancel := context.WithCancel(context.Background())
go func() {
Expand Down Expand Up @@ -1334,7 +1335,7 @@ func TestNamespaceSelectorProvider(t *testing.T) {
LeaderElection: egv1a1.DefaultLeaderElection(),
}
resources := new(message.ProviderResources)
provider, err := New(context.Background(), cliCfg, svr, resources)
provider, err := New(context.Background(), cliCfg, svr, resources, healthzServerPort)
require.NoError(t, err)
ctx, cancel := context.WithCancel(context.Background())
go func() {
Expand Down
4 changes: 2 additions & 2 deletions internal/provider/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func (r *Runner) createKubernetesProvider(ctx context.Context) (*kubernetes.Prov
return nil, fmt.Errorf("failed to get kubeconfig: %w", err)
}

p, err := kubernetes.New(ctx, cfg, &r.Config.Server, r.ProviderResources)
p, err := kubernetes.New(ctx, cfg, &r.Config.Server, r.ProviderResources, r.EnvoyGateway.Provider.HealthzServerPort)
if err != nil {
return nil, fmt.Errorf("failed to create provider %s: %w", egv1a1.ProviderTypeKubernetes, err)
}
Expand All @@ -86,7 +86,7 @@ func (r *Runner) createKubernetesProvider(ctx context.Context) (*kubernetes.Prov
func (r *Runner) createCustomResourceProvider() (p provider.Provider, err error) {
switch r.EnvoyGateway.Provider.Custom.Resource.Type {
case egv1a1.ResourceProviderTypeFile:
p, err = file.New(&r.Config.Server, r.ProviderResources)
p, err = file.New(&r.Config.Server, r.ProviderResources, r.EnvoyGateway.Provider.HealthzServerPort)
if err != nil {
return nil, fmt.Errorf("failed to create provider %s: %w", egv1a1.ProviderTypeCustom, err)
}
Expand Down
1 change: 1 addition & 0 deletions release-notes/current.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ security updates: |

# New features or capabilities added in this release.
new features: |
Added support to configure custom port for healthz server for EnvoyGatewayProvider.

bug fixes: |

Expand Down
1 change: 1 addition & 0 deletions site/content/en/latest/api/extension_types.md
Original file line number Diff line number Diff line change
Expand Up @@ -1291,6 +1291,7 @@ _Appears in:_
| `type` | _[ProviderType](#providertype)_ | true | | Type is the type of provider to use. Supported types are "Kubernetes", "Custom". |
| `kubernetes` | _[EnvoyGatewayKubernetesProvider](#envoygatewaykubernetesprovider)_ | false | | Kubernetes defines the configuration of the Kubernetes provider. Kubernetes<br />provides runtime configuration via the Kubernetes API. |
| `custom` | _[EnvoyGatewayCustomProvider](#envoygatewaycustomprovider)_ | false | | Custom defines the configuration for the Custom provider. This provider<br />allows you to define a specific resource provider and an infrastructure<br />provider. |
| `healthzServerPort` | _integer_ | false | 8081 | HealthzServerPort defines the port for the healthz probe server.<br />By default, when this field is unset or empty, Envoy Gateway will use the port 8081 for the healthz server. |


#### EnvoyGatewayResourceProvider
Expand Down
1 change: 1 addition & 0 deletions site/content/zh/latest/api/extension_types.md
Original file line number Diff line number Diff line change
Expand Up @@ -1291,6 +1291,7 @@ _Appears in:_
| `type` | _[ProviderType](#providertype)_ | true | | Type is the type of provider to use. Supported types are "Kubernetes", "Custom". |
| `kubernetes` | _[EnvoyGatewayKubernetesProvider](#envoygatewaykubernetesprovider)_ | false | | Kubernetes defines the configuration of the Kubernetes provider. Kubernetes<br />provides runtime configuration via the Kubernetes API. |
| `custom` | _[EnvoyGatewayCustomProvider](#envoygatewaycustomprovider)_ | false | | Custom defines the configuration for the Custom provider. This provider<br />allows you to define a specific resource provider and an infrastructure<br />provider. |
| `healthzServerPort` | _integer_ | false | 8081 | HealthzServerPort defines the port for the healthz probe server.<br />By default, when this field is unset or empty, Envoy Gateway will use the port 8081 for the healthz server. |


#### EnvoyGatewayResourceProvider
Expand Down