diff --git a/openapi/generated_openapi/zz_generated.openapi.go b/openapi/generated_openapi/zz_generated.openapi.go index 30f0f48cbaf..5e5a78a4937 100644 --- a/openapi/generated_openapi/zz_generated.openapi.go +++ b/openapi/generated_openapi/zz_generated.openapi.go @@ -46362,6 +46362,12 @@ func schema_openshift_api_operator_v1_IngressControllerTuningOptions(ref common. Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"), }, }, + "connectTimeout": { + SchemaProps: spec.SchemaProps{ + Description: "ConnectTimeout defines the maximum time to wait for a connection attempt to a server/backend to succeed.\n\nThis field expects an unsigned duration string of decimal numbers, each with optional fraction and a unit suffix, e.g. \"300ms\", \"1.5h\" or \"2h45m\". Valid time units are \"ns\", \"us\" (or \"µs\" U+00B5 or \"μs\" U+03BC), \"ms\", \"s\", \"m\", \"h\".\n\nWhen omitted, this means the user has no opinion and the platform is left to choose a reasonable default. This default is subject to change over time. The current default is 5s.", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"), + }, + }, "tlsInspectDelay": { SchemaProps: spec.SchemaProps{ Description: "tlsInspectDelay defines how long the router can hold data to find a matching route.\n\nSetting this too short can cause the router to fall back to the default certificate for edge-terminated or reencrypt routes even when a better matching certificate could be used.\n\nIf unset, the default inspect delay is 5s", diff --git a/openapi/openapi.json b/openapi/openapi.json index 90cfc71baa6..80a038daf84 100644 --- a/openapi/openapi.json +++ b/openapi/openapi.json @@ -27062,6 +27062,10 @@ "description": "clientTimeout defines how long a connection will be held open while waiting for a client response.\n\nIf unset, the default timeout is 30s", "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Duration" }, + "connectTimeout": { + "description": "ConnectTimeout defines the maximum time to wait for a connection attempt to a server/backend to succeed.\n\nThis field expects an unsigned duration string of decimal numbers, each with optional fraction and a unit suffix, e.g. \"300ms\", \"1.5h\" or \"2h45m\". Valid time units are \"ns\", \"us\" (or \"µs\" U+00B5 or \"μs\" U+03BC), \"ms\", \"s\", \"m\", \"h\".\n\nWhen omitted, this means the user has no opinion and the platform is left to choose a reasonable default. This default is subject to change over time. The current default is 5s.", + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Duration" + }, "headerBufferBytes": { "description": "headerBufferBytes describes how much memory should be reserved (in bytes) for IngressController connection sessions. Note that this value must be at least 16384 if HTTP/2 is enabled for the IngressController (https://tools.ietf.org/html/rfc7540). If this field is empty, the IngressController will use a default value of 32768 bytes.\n\nSetting this field is generally not recommended as headerBufferBytes values that are too small may break the IngressController and headerBufferBytes values that are too large could cause the IngressController to use significantly more memory than necessary.", "type": "integer", diff --git a/operator/v1/0000_50_ingress-operator_00-ingresscontroller.crd.yaml b/operator/v1/0000_50_ingress-operator_00-ingresscontroller.crd.yaml index c5188cc0788..f90fba4646d 100644 --- a/operator/v1/0000_50_ingress-operator_00-ingresscontroller.crd.yaml +++ b/operator/v1/0000_50_ingress-operator_00-ingresscontroller.crd.yaml @@ -802,6 +802,10 @@ spec: description: "clientTimeout defines how long a connection will be held open while waiting for a client response. \n If unset, the default timeout is 30s" format: duration type: string + connectTimeout: + description: "ConnectTimeout defines the maximum time to wait for a connection attempt to a server/backend to succeed. \n This field expects an unsigned duration string of decimal numbers, each with optional fraction and a unit suffix, e.g. \"300ms\", \"1.5h\" or \"2h45m\". Valid time units are \"ns\", \"us\" (or \"µs\" U+00B5 or \"μs\" U+03BC), \"ms\", \"s\", \"m\", \"h\". \n When omitted, this means the user has no opinion and the platform is left to choose a reasonable default. This default is subject to change over time. The current default is 5s." + pattern: ^(0|([0-9]+(\.[0-9]+)?(ns|us|µs|μs|ms|s|m|h))+)$ + type: string headerBufferBytes: description: "headerBufferBytes describes how much memory should be reserved (in bytes) for IngressController connection sessions. Note that this value must be at least 16384 if HTTP/2 is enabled for the IngressController (https://tools.ietf.org/html/rfc7540). If this field is empty, the IngressController will use a default value of 32768 bytes. \n Setting this field is generally not recommended as headerBufferBytes values that are too small may break the IngressController and headerBufferBytes values that are too large could cause the IngressController to use significantly more memory than necessary." format: int32 diff --git a/operator/v1/stable.ingresscontroller.testsuite.yaml b/operator/v1/stable.ingresscontroller.testsuite.yaml index 903d8e60c54..b70cd9ecdb4 100644 --- a/operator/v1/stable.ingresscontroller.testsuite.yaml +++ b/operator/v1/stable.ingresscontroller.testsuite.yaml @@ -476,3 +476,85 @@ tests: set: value: DENY expectedError: 'IngressController.operator.openshift.io "default-not-allowed-values" is invalid: [spec.httpHeaders.actions.response[0].action.type: Required value, : Invalid value: "null": some validation rules were not checked because the object was invalid; correct the existing errors to complete validation]' + - name: Should be able to create an IngressController with valid nominal connect timeout + initial: | + apiVersion: operator.openshift.io/v1 + kind: IngressController + metadata: + name: default + namespace: openshift-ingress-operator + spec: + tuningOptions: + connectTimeout: 10s + expected: | + apiVersion: operator.openshift.io/v1 + kind: IngressController + metadata: + name: default + namespace: openshift-ingress-operator + spec: + httpEmptyRequestsPolicy: Respond + tuningOptions: + connectTimeout: 10s + - name: Should be able to create an IngressController with valid composite connect timeout + initial: | + apiVersion: operator.openshift.io/v1 + kind: IngressController + metadata: + name: default + namespace: openshift-ingress-operator + spec: + tuningOptions: + connectTimeout: 100ms300μs + expected: | + apiVersion: operator.openshift.io/v1 + kind: IngressController + metadata: + name: default + namespace: openshift-ingress-operator + spec: + httpEmptyRequestsPolicy: Respond + tuningOptions: + connectTimeout: 100ms300μs + - name: Should be able to create an IngressController with valid fraction connect timeout + initial: | + apiVersion: operator.openshift.io/v1 + kind: IngressController + metadata: + name: default + namespace: openshift-ingress-operator + spec: + tuningOptions: + connectTimeout: 1.5m + expected: | + apiVersion: operator.openshift.io/v1 + kind: IngressController + metadata: + name: default + namespace: openshift-ingress-operator + spec: + httpEmptyRequestsPolicy: Respond + tuningOptions: + connectTimeout: 1.5m + - name: Should not be able to create an IngressController with invalid unit connect timeout + initial: | + apiVersion: operator.openshift.io/v1 + kind: IngressController + metadata: + name: default + namespace: openshift-ingress-operator + spec: + tuningOptions: + connectTimeout: 3d + expectedError: "IngressController.operator.openshift.io \"default\" is invalid: spec.tuningOptions.connectTimeout: Invalid value: \"3d\": spec.tuningOptions.connectTimeout in body should match '^(0|([0-9]+(\\.[0-9]+)?(ns|us|µs|μs|ms|s|m|h))+)$'" + - name: Should not be able to create an IngressController with invalid space connect timeout + initial: | + apiVersion: operator.openshift.io/v1 + kind: IngressController + metadata: + name: default + namespace: openshift-ingress-operator + spec: + tuningOptions: + connectTimeout: "4 s" + expectedError: "IngressController.operator.openshift.io \"default\" is invalid: spec.tuningOptions.connectTimeout: Invalid value: \"4 s\": spec.tuningOptions.connectTimeout in body should match '^(0|([0-9]+(\\.[0-9]+)?(ns|us|µs|μs|ms|s|m|h))+)$'" diff --git a/operator/v1/types_ingress.go b/operator/v1/types_ingress.go index 3d9f512a934..92d862a50d4 100644 --- a/operator/v1/types_ingress.go +++ b/operator/v1/types_ingress.go @@ -1645,6 +1645,23 @@ type IngressControllerTuningOptions struct { // +optional TunnelTimeout *metav1.Duration `json:"tunnelTimeout,omitempty"` + // ConnectTimeout defines the maximum time to wait for + // a connection attempt to a server/backend to succeed. + // + // This field expects an unsigned duration string of decimal numbers, each with optional + // fraction and a unit suffix, e.g. "300ms", "1.5h" or "2h45m". + // Valid time units are "ns", "us" (or "µs" U+00B5 or "μs" U+03BC), "ms", "s", "m", "h". + // + // When omitted, this means the user has no opinion and the platform is left + // to choose a reasonable default. This default is subject to change over time. + // The current default is 5s. + // + // +kubebuilder:validation:Optional + // +kubebuilder:validation:Pattern=^(0|([0-9]+(\.[0-9]+)?(ns|us|µs|μs|ms|s|m|h))+)$ + // +kubebuilder:validation:Type:=string + // +optional + ConnectTimeout *metav1.Duration `json:"connectTimeout,omitempty"` + // tlsInspectDelay defines how long the router can hold data to find a // matching route. // diff --git a/operator/v1/zz_generated.deepcopy.go b/operator/v1/zz_generated.deepcopy.go index 112ff6bcb87..8f070327842 100644 --- a/operator/v1/zz_generated.deepcopy.go +++ b/operator/v1/zz_generated.deepcopy.go @@ -2268,6 +2268,11 @@ func (in *IngressControllerTuningOptions) DeepCopyInto(out *IngressControllerTun *out = new(metav1.Duration) **out = **in } + if in.ConnectTimeout != nil { + in, out := &in.ConnectTimeout, &out.ConnectTimeout + *out = new(metav1.Duration) + **out = **in + } if in.TLSInspectDelay != nil { in, out := &in.TLSInspectDelay, &out.TLSInspectDelay *out = new(metav1.Duration) diff --git a/operator/v1/zz_generated.swagger_doc_generated.go b/operator/v1/zz_generated.swagger_doc_generated.go index a49a7694a55..ea77aab6ea0 100644 --- a/operator/v1/zz_generated.swagger_doc_generated.go +++ b/operator/v1/zz_generated.swagger_doc_generated.go @@ -999,6 +999,7 @@ var map_IngressControllerTuningOptions = map[string]string{ "serverTimeout": "serverTimeout defines how long a connection will be held open while waiting for a server/backend response.\n\nIf unset, the default timeout is 30s", "serverFinTimeout": "serverFinTimeout defines how long a connection will be held open while waiting for the server/backend response to the client closing the connection.\n\nIf unset, the default timeout is 1s", "tunnelTimeout": "tunnelTimeout defines how long a tunnel connection (including websockets) will be held open while the tunnel is idle.\n\nIf unset, the default timeout is 1h", + "connectTimeout": "ConnectTimeout defines the maximum time to wait for a connection attempt to a server/backend to succeed.\n\nThis field expects an unsigned duration string of decimal numbers, each with optional fraction and a unit suffix, e.g. \"300ms\", \"1.5h\" or \"2h45m\". Valid time units are \"ns\", \"us\" (or \"µs\" U+00B5 or \"μs\" U+03BC), \"ms\", \"s\", \"m\", \"h\".\n\nWhen omitted, this means the user has no opinion and the platform is left to choose a reasonable default. This default is subject to change over time. The current default is 5s.", "tlsInspectDelay": "tlsInspectDelay defines how long the router can hold data to find a matching route.\n\nSetting this too short can cause the router to fall back to the default certificate for edge-terminated or reencrypt routes even when a better matching certificate could be used.\n\nIf unset, the default inspect delay is 5s", "healthCheckInterval": "healthCheckInterval defines how long the router waits between two consecutive health checks on its configured backends. This value is applied globally as a default for all routes, but may be overridden per-route by the route annotation \"router.openshift.io/haproxy.health.check.interval\".\n\nExpects an unsigned duration string of decimal numbers, each with optional fraction and a unit suffix, eg \"300ms\", \"1.5h\" or \"2h45m\". Valid time units are \"ns\", \"us\" (or \"µs\" U+00B5 or \"μs\" U+03BC), \"ms\", \"s\", \"m\", \"h\".\n\nSetting this to less than 5s can cause excess traffic due to too frequent TCP health checks and accompanying SYN packet storms. Alternatively, setting this too high can result in increased latency, due to backend servers that are no longer available, but haven't yet been detected as such.\n\nAn empty or zero healthCheckInterval means no opinion and IngressController chooses a default, which is subject to change over time. Currently the default healthCheckInterval value is 5s.\n\nCurrently the minimum allowed value is 1s and the maximum allowed value is 2147483647ms (24.85 days). Both are subject to change over time.", "maxConnections": "maxConnections defines the maximum number of simultaneous connections that can be established per HAProxy process. Increasing this value allows each ingress controller pod to handle more connections but at the cost of additional system resources being consumed.\n\nPermitted values are: empty, 0, -1, and the range 2000-2000000.\n\nIf this field is empty or 0, the IngressController will use the default value of 50000, but the default is subject to change in future releases.\n\nIf the value is -1 then HAProxy will dynamically compute a maximum value based on the available ulimits in the running container. Selecting -1 (i.e., auto) will result in a large value being computed (~520000 on OpenShift >=4.10 clusters) and therefore each HAProxy process will incur significant memory usage compared to the current default of 50000.\n\nSetting a value that is greater than the current operating system limit will prevent the HAProxy process from starting.\n\nIf you choose a discrete value (e.g., 750000) and the router pod is migrated to a new node, there's no guarantee that that new node has identical ulimits configured. In such a scenario the pod would fail to start. If you have nodes with different ulimits configured (e.g., different tuned profiles) and you choose a discrete value then the guidance is to use -1 and let the value be computed dynamically at runtime.\n\nYou can monitor memory usage for router containers with the following metric: 'container_memory_working_set_bytes{container=\"router\",namespace=\"openshift-ingress\"}'.\n\nYou can monitor memory usage of individual HAProxy processes in router containers with the following metric: 'container_memory_working_set_bytes{container=\"router\",namespace=\"openshift-ingress\"}/container_processes{container=\"router\",namespace=\"openshift-ingress\"}'.",