Skip to content

Support configurable hostPort in helm chart #3321

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 18 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
19 changes: 19 additions & 0 deletions apis/v1alpha2/nginxproxy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,11 @@ type ContainerSpec struct {
// +optional
Lifecycle *corev1.Lifecycle `json:"lifecycle,omitempty"`

// HostPort configuration
//
// +optional
HostPort *HostPort `json:"hostPort,omitempty"`

// VolumeMounts describe the mounting of Volumes within a container.
//
// +optional
Expand Down Expand Up @@ -608,3 +613,17 @@ type NodePort struct {
// kubebuilder:validation:Maximum=65535
ListenerPort int32 `json:"listenerPort"`
}

// HostPort to expose on the host.
type HostPort struct {
// Whether to enable hostPort feature
// If not specified, or set to false, hostPort will not be enabled.
//
// +optional
Enable bool `json:"enable"`

// Number of port to expose on the host.
// kubebuilder:validation:Minimum=1
// kubebuilder:validation:Maximum=65535
Port int32 `json:"port"`
}
7 changes: 5 additions & 2 deletions charts/nginx-gateway-fabric/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -264,9 +264,12 @@ The following table lists the configurable parameters of the NGINX Gateway Fabri
| `certGenerator.ttlSecondsAfterFinished` | How long to wait after the cert generator job has finished before it is removed by the job controller. | int | `30` |
| `clusterDomain` | The DNS cluster domain of your Kubernetes cluster. | string | `"cluster.local"` |
| `gateways` | A list of Gateway objects. View https://gateway-api.sigs.k8s.io/reference/spec/#gateway for full Gateway reference. | list | `[]` |
| `nginx` | The nginx section contains the configuration for all NGINX data plane deployments installed by the NGINX Gateway Fabric control plane. | object | `{"config":{},"container":{},"debug":false,"image":{"pullPolicy":"Always","repository":"ghcr.io/nginx/nginx-gateway-fabric/nginx","tag":"edge"},"imagePullSecret":"","imagePullSecrets":[],"kind":"deployment","plus":false,"pod":{},"replicas":1,"service":{"externalTrafficPolicy":"Local","loadBalancerClass":"","loadBalancerIP":"","loadBalancerSourceRanges":[],"nodePorts":[],"type":"LoadBalancer"},"usage":{"caSecretName":"","clientSSLSecretName":"","endpoint":"","resolver":"","secretName":"nplus-license","skipVerify":false}}` |
| `nginx` | The nginx section contains the configuration for all NGINX data plane deployments installed by the NGINX Gateway Fabric control plane. | object | `{"config":{},"container":{"hostPort":{"enable":false,"port":443}},"debug":false,"image":{"pullPolicy":"Always","repository":"ghcr.io/nginx/nginx-gateway-fabric/nginx","tag":"edge"},"imagePullSecret":"","imagePullSecrets":[],"kind":"deployment","plus":false,"pod":{},"replicas":1,"service":{"externalTrafficPolicy":"Local","loadBalancerClass":"","loadBalancerIP":"","loadBalancerSourceRanges":[],"nodePorts":[],"type":"LoadBalancer"},"usage":{"caSecretName":"","clientSSLSecretName":"","endpoint":"","resolver":"","secretName":"nplus-license","skipVerify":false}}` |
| `nginx.config` | The configuration for the data plane that is contained in the NginxProxy resource. This is applied globally to all Gateways managed by this instance of NGINX Gateway Fabric. | object | `{}` |
| `nginx.container` | The container configuration for the NGINX container. This is applied globally to all Gateways managed by this instance of NGINX Gateway Fabric. | object | `{}` |
| `nginx.container` | The container configuration for the NGINX container. This is applied globally to all Gateways managed by this instance of NGINX Gateway Fabric. | object | `{"hostPort":{"enable":false,"port":443}}` |
| `nginx.container.hostPort` | The hostPort configuration | object | `{"enable":false,"port":443}` |
| `nginx.container.hostPort.enable` | Enables hostPort. | bool | `false` |
| `nginx.container.hostPort.port` | The port | int | `443` |
| `nginx.debug` | Enable debugging for NGINX. Uses the nginx-debug binary. The NGINX error log level should be set to debug in the NginxProxy resource. | bool | `false` |
| `nginx.image.repository` | The NGINX image to use. | string | `"ghcr.io/nginx/nginx-gateway-fabric/nginx"` |
| `nginx.imagePullSecret` | The name of the secret containing docker registry credentials. Secret must exist in the same namespace as the helm release. The control plane will copy this secret into any namespace where NGINX is deployed. | string | `""` |
Expand Down
26 changes: 26 additions & 0 deletions charts/nginx-gateway-fabric/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,32 @@
},
"container": {
"description": "The container configuration for the NGINX container. This is applied globally to all Gateways managed by this\ninstance of NGINX Gateway Fabric.",
"properties": {
"hostPort": {
"description": "The hostPort configuration",
"properties": {
"enable": {
"default": false,
"description": "Enables hostPort.",
"required": [],
"title": "enable",
"type": "boolean"
},
"port": {
"default": 443,
"description": "The port",
"maximum": 65535,
"minimum": 1,
"required": [],
"title": "port",
"type": "integer"
}
},
"required": [],
"title": "hostPort",
"type": "object"
}
},
"required": [],
"title": "container",
"type": "object"
Expand Down
16 changes: 15 additions & 1 deletion charts/nginx-gateway-fabric/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,21 @@ nginx:

# -- The container configuration for the NGINX container. This is applied globally to all Gateways managed by this
# instance of NGINX Gateway Fabric.
container: {}
container:

# -- The hostPort configuration
hostPort:
# -- Enables hostPort.
enable: false

# @schema
# type: integer
# minimum: 1
# maximum: 65535
# @schema
# -- The port
port: 443

# -- The resource requirements of the NGINX container.
# resources: {}

Expand Down
13 changes: 13 additions & 0 deletions config/crd/bases/gateway.nginx.org_nginxproxies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,19 @@ spec:
StopSignal can only be set for Pods with a non-empty .spec.os.name
type: string
type: object
hostPort:
description: |-
Number of port to expose on the host.
If specified, this must be a valid port number, 0 < x < 65536.
properties:
enable:
description: |-
Whether to enable hostPort
type: boolean
port:
description: |-
Port number
type: integer
resources:
description: Resources describes the compute resource
requirements.
Expand Down
13 changes: 13 additions & 0 deletions deploy/crds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -922,6 +922,19 @@ spec:
StopSignal can only be set for Pods with a non-empty .spec.os.name
type: string
type: object
hostPort:
description: |-
Number of port to expose on the host.
If specified, this must be a valid port number, 0 < x < 65536.
properties:
enable:
description: |-
Whether to enable hostPort
type: boolean
port:
description: |-
Port number
type: integer
resources:
description: Resources describes the compute resource
requirements.
Expand Down
5 changes: 5 additions & 0 deletions internal/controller/provisioner/objects.go
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,11 @@ func (p *NginxProvisioner) buildNginxPodTemplateSpec(
container.Command = append(container.Command, "/agent/entrypoint.sh")
container.Args = append(container.Args, "debug")
}

if containerSpec.HostPort != nil && containerSpec.HostPort.Enable && len(container.Ports) > 0 {
container.Ports[0].HostPort = containerSpec.HostPort.Port
}
Comment on lines +784 to +786
Copy link
Collaborator

@sjberman sjberman Jun 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue with this approach is that the nginx container is going to be exposed on N number of ports, which are directly correlated to the listener ports in the Gateway object.

You've only exposed a single hostPort, and are binding it to whatever the first container port is. When in reality, each container port should have its own hostPort. If you take a look at how we added NodePorts in the values.yaml file and then how we use that to set Service ports; it should be a similar structure, where each port maps to a Gateway listener port.


spec.Spec.Containers[0] = container
}
}
Expand Down
2 changes: 2 additions & 0 deletions internal/controller/provisioner/objects_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ func TestBuildNginxResourceObjects_NginxProxyConfig(t *testing.T) {
corev1.ResourceCPU: resource.Quantity{Format: "100m"},
},
},
HostPort: &ngfAPIv1alpha2.HostPort{Enable: true, Port: int32(8443)},
},
},
},
Expand Down Expand Up @@ -338,6 +339,7 @@ func TestBuildNginxResourceObjects_NginxProxyConfig(t *testing.T) {
g.Expect(container.Ports).To(ContainElement(corev1.ContainerPort{
ContainerPort: 8080,
Name: "metrics",
HostPort: int32(8443),
}))

g.Expect(container.Image).To(Equal("nginx-repo:1.1.1"))
Expand Down