Skip to content
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
94 changes: 90 additions & 4 deletions apis/v1alpha1/upstreamsettingspolicy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ type UpstreamSettingsPolicyList struct {
}

// UpstreamSettingsPolicySpec defines the desired state of the UpstreamSettingsPolicy.
// +kubebuilder:validation:XValidation:rule="!(has(self.loadBalancingMethod) && (self.loadBalancingMethod == 'hash' || self.loadBalancingMethod == 'hash consistent')) || has(self.hashMethodKey)",message="hashMethodKey is required when loadBalancingMethod is 'hash' or 'hash consistent'"
//
//nolint:lll
type UpstreamSettingsPolicySpec struct {
// ZoneSize is the size of the shared memory zone used by the upstream. This memory zone is used to share
// the upstream configuration between nginx worker processes. The more servers that an upstream has,
Expand All @@ -58,6 +61,12 @@ type UpstreamSettingsPolicySpec struct {
// +optional
LoadBalancingMethod *LoadBalancingType `json:"loadBalancingMethod,omitempty"`

// HashMethodKey defines the key used for hash-based load balancing methods.
// This field is required when `LoadBalancingMethod` is set to `hash` or `hash consistent`.
//
// +optional
HashMethodKey *HashMethodKey `json:"hashMethodKey,omitempty"`

// TargetRefs identifies API object(s) to apply the policy to.
// Objects must be in the same namespace as the policy.
// Support: Service
Expand Down Expand Up @@ -108,19 +117,96 @@ type UpstreamKeepAlive struct {

// LoadBalancingType defines the supported load balancing methods.
//
// +kubebuilder:validation:Enum=ip_hash;random two least_conn
// +kubebuilder:validation:Enum=round_robin;least_conn;ip_hash;hash;hash consistent;random;random two;random two least_conn;random two least_time=header;random two least_time=last_byte;least_time header;least_time last_byte;least_time header inflight;least_time last_byte inflight
//
//nolint:lll
type LoadBalancingType string

const (
// Combination of NGINX directive
// - https://nginx.org/en/docs/http/ngx_http_upstream_module.html#random
// - https://nginx.org/en/docs/http/ngx_http_upstream_module.html#least_conn
// - https://nginx.org/en/docs/http/ngx_http_upstream_module.html#least_time
// - https://nginx.org/en/docs/http/ngx_http_upstream_module.html#upstream
// - https://nginx.org/en/docs/http/ngx_http_upstream_module.html#ip_hash
// - https://nginx.org/en/docs/http/ngx_http_upstream_module.html#hash

// LoadBalancingMethods supported by NGINX OSS and NGINX Plus.

// LoadBalancingTypeRoundRobin enables round-robin load balancing,
// distributing requests evenly across all upstream servers.
LoadBalancingTypeRoundRobin LoadBalancingType = "round_robin"

// LoadBalancingTypeLeastConnection enables least-connections load balancing,
// routing requests to the upstream server with the fewest active connections.
LoadBalancingTypeLeastConnection LoadBalancingType = "least_conn"

// LoadBalancingTypeIPHash enables IP hash-based load balancing,
// ensuring requests from the same client IP are routed to the same upstream server.
// NGINX directive: https://nginx.org/en/docs/http/ngx_http_upstream_module.html#ip_hash
LoadBalancingTypeIPHash LoadBalancingType = "ip_hash"

// LoadBalancingTypeHash enables generic hash-based load balancing,
// routing requests to upstream servers based on a hash of a specified key
// HashMethodKey field must be set when this method is selected.
// Example configuration: hash $binary_remote_addr;.
LoadBalancingTypeHash LoadBalancingType = "hash"

// LoadBalancingTypeHashConsistent enables consistent hash-based load balancing,
// which minimizes the number of keys remapped when a server is added or removed.
// HashMethodKey field must be set when this method is selected.
// Example configuration: hash $binary_remote_addr consistent;.
LoadBalancingTypeHashConsistent LoadBalancingType = "hash consistent"

// LoadBalancingTypeRandom enables random load balancing,
// routing requests to upstream servers in a random manner.
LoadBalancingTypeRandom LoadBalancingType = "random"

// LoadBalancingTypeRandomTwo enables a variation of random load balancing
// that randomly selects two servers and forwards traffic to one of them.
// The default method is least_conn which passes a request to a server with the least number of active connections.
LoadBalancingTypeRandomTwo LoadBalancingType = "random two"

// LoadBalancingTypeRandomTwoLeastConnection enables a variation of least-connections
// balancing that randomly selects two servers and forwards traffic to the one with
// fewer active connections.
// NGINX directive least_conn: https://nginx.org/en/docs/http/ngx_http_upstream_module.html#least_conn
// NGINX directive random: https://nginx.org/en/docs/http/ngx_http_upstream_module.html#random
LoadBalancingTypeRandomTwoLeastConnection LoadBalancingType = "random two least_conn"

// LoadBalancingMethods supported by NGINX Plus.

// LoadBalancingTypeRandomTwoLeastTimeHeader enables a variation of least-time load balancing
// that randomly selects two servers and forwards traffic to the one with the least
// time to receive the response header.
LoadBalancingTypeRandomTwoLeastTimeHeader LoadBalancingType = "random two least_time=header"

// LoadBalancingTypeRandomTwoLeastTimeLastByte enables a variation of least-time load balancing
// that randomly selects two servers and forwards traffic to the one with the least time
// to receive the full response.
LoadBalancingTypeRandomTwoLeastTimeLastByte LoadBalancingType = "random two least_time=last_byte"

// LoadBalancingTypeLeastTimeHeader enables least-time load balancing,
// routing requests to the upstream server with the least time to receive the response header.
LoadBalancingTypeLeastTimeHeader LoadBalancingType = "least_time header"

// LoadBalancingTypeLeastTimeLastByte enables least-time load balancing,
// routing requests to the upstream server with the least time to receive the full response.
LoadBalancingTypeLeastTimeLastByte LoadBalancingType = "least_time last_byte"

// LoadBalancingTypeLeastTimeHeaderInflight enables least-time load balancing,
// routing requests to the upstream server with the least time to receive the response header,
// considering the incomplete requests.
LoadBalancingTypeLeastTimeHeaderInflight LoadBalancingType = "least_time header inflight"

// LoadBalancingTypeLeastTimeLastByteInflight enables least-time load balancing,
// routing requests to the upstream server with the least time to receive the full response,
// considering the incomplete requests.
LoadBalancingTypeLeastTimeLastByteInflight LoadBalancingType = "least_time last_byte inflight"
)

// HashMethodKey defines the key used for hash-based load balancing methods.
// The key must be a valid NGINX variable name starting with '$' followed by lowercase
// letters and underscores only.
// For a full list of NGINX variables,
// refer to: https://nginx.org/en/docs/http/ngx_http_upstream_module.html#variables
//
// +kubebuilder:validation:Pattern=`^\$[a-z_]+$`
type HashMethodKey string
5 changes: 5 additions & 0 deletions apis/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ spec:
spec:
description: Spec defines the desired state of the UpstreamSettingsPolicy.
properties:
hashMethodKey:
description: |-
HashMethodKey defines the key used for hash-based load balancing methods.
This field is required when `LoadBalancingMethod` is set to `hash` or `hash consistent`.
pattern: ^\$[a-z_]+$
type: string
keepAlive:
description: KeepAlive defines the keep-alive settings.
properties:
Expand Down Expand Up @@ -91,8 +97,20 @@ spec:
If not specified, NGINX Gateway Fabric defaults to `random two least_conn`,
which differs from the standard NGINX default `round-robin`.
enum:
- round_robin
- least_conn
- ip_hash
- hash
- hash consistent
- random
- random two
- random two least_conn
- random two least_time=header
- random two least_time=last_byte
- least_time header
- least_time last_byte
- least_time header inflight
- least_time last_byte inflight
type: string
targetRefs:
description: |-
Expand Down Expand Up @@ -152,6 +170,12 @@ spec:
required:
- targetRefs
type: object
x-kubernetes-validations:
- message: hashMethodKey is required when loadBalancingMethod is 'hash'
or 'hash consistent'
rule: '!(has(self.loadBalancingMethod) && (self.loadBalancingMethod
== ''hash'' || self.loadBalancingMethod == ''hash consistent'')) ||
has(self.hashMethodKey)'
status:
description: Status defines the state of the UpstreamSettingsPolicy.
properties:
Expand Down
24 changes: 24 additions & 0 deletions deploy/crds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9578,6 +9578,12 @@ spec:
spec:
description: Spec defines the desired state of the UpstreamSettingsPolicy.
properties:
hashMethodKey:
description: |-
HashMethodKey defines the key used for hash-based load balancing methods.
This field is required when `LoadBalancingMethod` is set to `hash` or `hash consistent`.
pattern: ^\$[a-z_]+$
type: string
keepAlive:
description: KeepAlive defines the keep-alive settings.
properties:
Expand Down Expand Up @@ -9618,8 +9624,20 @@ spec:
If not specified, NGINX Gateway Fabric defaults to `random two least_conn`,
which differs from the standard NGINX default `round-robin`.
enum:
- round_robin
- least_conn
- ip_hash
- hash
- hash consistent
- random
- random two
- random two least_conn
- random two least_time=header
- random two least_time=last_byte
- least_time header
- least_time last_byte
- least_time header inflight
- least_time last_byte inflight
type: string
targetRefs:
description: |-
Expand Down Expand Up @@ -9679,6 +9697,12 @@ spec:
required:
- targetRefs
type: object
x-kubernetes-validations:
- message: hashMethodKey is required when loadBalancingMethod is 'hash'
or 'hash consistent'
rule: '!(has(self.loadBalancingMethod) && (self.loadBalancingMethod
== ''hash'' || self.loadBalancingMethod == ''hash consistent'')) ||
has(self.hashMethodKey)'
status:
description: Status defines the state of the UpstreamSettingsPolicy.
properties:
Expand Down
5 changes: 3 additions & 2 deletions internal/controller/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ func StartManager(cfg config.Config) error {
mustExtractGVK := kinds.NewMustExtractGKV(scheme)

genericValidator := ngxvalidation.GenericValidator{}
policyManager := createPolicyManager(mustExtractGVK, genericValidator)
policyManager := createPolicyManager(mustExtractGVK, genericValidator, cfg.Plus)

plusSecrets, err := createPlusSecretMetadata(cfg, mgr.GetAPIReader())
if err != nil {
Expand Down Expand Up @@ -323,6 +323,7 @@ func StartManager(cfg config.Config) error {
func createPolicyManager(
mustExtractGVK kinds.MustExtractGVK,
validator validation.GenericValidator,
plusEnabled bool,
) *policies.CompositeValidator {
cfgs := []policies.ManagerConfig{
{
Expand All @@ -335,7 +336,7 @@ func createPolicyManager(
},
{
GVK: mustExtractGVK(&ngfAPIv1alpha1.UpstreamSettingsPolicy{}),
Validator: upstreamsettings.NewValidator(validator),
Validator: upstreamsettings.NewValidator(validator, plusEnabled),
},
}

Expand Down
32 changes: 32 additions & 0 deletions internal/controller/nginx/config/http/config.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package http

import (
ngfAPI "github.com/nginx/nginx-gateway-fabric/v2/apis/v1alpha1"
"github.com/nginx/nginx-gateway-fabric/v2/internal/controller/nginx/config/shared"
)

Expand Down Expand Up @@ -123,6 +124,7 @@ type Upstream struct {
ZoneSize string // format: 512k, 1m
StateFile string
LoadBalancingMethod string
HashMethodKey string
KeepAlive UpstreamKeepAlive
Servers []UpstreamServer
}
Expand Down Expand Up @@ -167,3 +169,33 @@ type ServerConfig struct {
Plus bool
DisableSNIHostValidation bool
}

var (
OSSAllowedLBMethods = map[ngfAPI.LoadBalancingType]struct{}{
ngfAPI.LoadBalancingTypeRoundRobin: {},
ngfAPI.LoadBalancingTypeLeastConnection: {},
ngfAPI.LoadBalancingTypeIPHash: {},
ngfAPI.LoadBalancingTypeRandom: {},
ngfAPI.LoadBalancingTypeHash: {},
ngfAPI.LoadBalancingTypeHashConsistent: {},
ngfAPI.LoadBalancingTypeRandomTwo: {},
ngfAPI.LoadBalancingTypeRandomTwoLeastConnection: {},
}

PlusAllowedLBMethods = map[ngfAPI.LoadBalancingType]struct{}{
ngfAPI.LoadBalancingTypeRoundRobin: {},
ngfAPI.LoadBalancingTypeLeastConnection: {},
ngfAPI.LoadBalancingTypeIPHash: {},
ngfAPI.LoadBalancingTypeRandom: {},
ngfAPI.LoadBalancingTypeHash: {},
ngfAPI.LoadBalancingTypeHashConsistent: {},
ngfAPI.LoadBalancingTypeRandomTwo: {},
ngfAPI.LoadBalancingTypeRandomTwoLeastConnection: {},
ngfAPI.LoadBalancingTypeLeastTimeHeader: {},
ngfAPI.LoadBalancingTypeLeastTimeLastByte: {},
ngfAPI.LoadBalancingTypeLeastTimeHeaderInflight: {},
ngfAPI.LoadBalancingTypeLeastTimeLastByteInflight: {},
ngfAPI.LoadBalancingTypeRandomTwoLeastTimeHeader: {},
ngfAPI.LoadBalancingTypeRandomTwoLeastTimeLastByte: {},
}
)
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ type UpstreamSettings struct {
ZoneSize string
// LoadBalancingMethod is the load balancing method setting.
LoadBalancingMethod string
// HashMethodKey is the key to be used for hash-based load balancing methods.
HashMethodKey string
// KeepAlive contains the keepalive settings.
KeepAlive http.UpstreamKeepAlive
}
Expand Down Expand Up @@ -67,6 +69,10 @@ func processPolicies(pols []policies.Policy) UpstreamSettings {
if usp.Spec.LoadBalancingMethod != nil {
upstreamSettings.LoadBalancingMethod = string(*usp.Spec.LoadBalancingMethod)
}

if usp.Spec.HashMethodKey != nil {
upstreamSettings.HashMethodKey = string(*usp.Spec.HashMethodKey)
}
}

return upstreamSettings
Expand Down
Loading
Loading