|  | 
|  | 1 | +--- | 
|  | 2 | +title: microshift-router-configuration-errors-logging | 
|  | 3 | +authors: | 
|  | 4 | +  - "@pacevedom" | 
|  | 5 | +reviewers: | 
|  | 6 | +  - "@eslutsky" | 
|  | 7 | +  - "@copejon" | 
|  | 8 | +  - "@ggiguash" | 
|  | 9 | +  - "@pmtk" | 
|  | 10 | +  - "@pliurh" | 
|  | 11 | +  - "@Miciah" | 
|  | 12 | +approvers: | 
|  | 13 | +  - "@jerpeter1" | 
|  | 14 | +api-approvers: | 
|  | 15 | +  - None | 
|  | 16 | +creation-date: 2025-04-24 | 
|  | 17 | +last-updated: 2025-05-09 | 
|  | 18 | +tracking-link: | 
|  | 19 | +  - https://issues.redhat.com/browse/USHIFT-4092 | 
|  | 20 | +--- | 
|  | 21 | + | 
|  | 22 | +# MicroShift router errors and logging configuration options | 
|  | 23 | + | 
|  | 24 | +## Summary | 
|  | 25 | +MicroShift's default router is created as part of the platform, but does not | 
|  | 26 | +allow configuring some of its specific parameters. For example, you cannot | 
|  | 27 | +configure custom behavior with error pages, or whether headers and cookies are | 
|  | 28 | +captured in the access logs. | 
|  | 29 | + | 
|  | 30 | +In order to allow these operations and more, a set of configuration options is | 
|  | 31 | +proposed. | 
|  | 32 | + | 
|  | 33 | +## Motivation | 
|  | 34 | +Microshift Customers need a way to override the default Ingress Controller | 
|  | 35 | +logging configuration similar as OpenShift does. | 
|  | 36 | + | 
|  | 37 | +### User Stories | 
|  | 38 | +* As a MicroShift admin, I want to configure custom error code pages in the | 
|  | 39 | +  router. | 
|  | 40 | +* As a MicroShift admin, I want to enable/disable access logging in the | 
|  | 41 | +  router. | 
|  | 42 | +* As a MicroShift admin, I want to configure which HTTP headers are captured | 
|  | 43 | +  in the access logs. | 
|  | 44 | +* As a MicroShift admin, I want to configure which HTTP cookies are captured | 
|  | 45 | +  in the access logs. | 
|  | 46 | + | 
|  | 47 | +### Goals | 
|  | 48 | +Allow users to configure the additional Router customization parameters. | 
|  | 49 | + | 
|  | 50 | +### Non-Goals | 
|  | 51 | +N/A | 
|  | 52 | + | 
|  | 53 | +## Proposal | 
|  | 54 | +Microshift doesn't use [ingress operator](https://github.com/openshift/cluster-ingress-operator), | 
|  | 55 | +which means all the customization is performed through the configuration file. | 
|  | 56 | +The configuration will propagate to the router deployment [manifest](https://github.com/openshift/microshift/blob/aea40ae1ee66dc697996c309268be1939b018f56/assets/components/openshift-router/deployment.yaml) through environment variables, just like what the ingress operator does. | 
|  | 57 | + | 
|  | 58 | +See the API Extensions section to check the details. | 
|  | 59 | + | 
|  | 60 | +See full [OpenShift Router](https://docs.openshift.com/container-platform/4.18/networking/ingress-operator.html) | 
|  | 61 | +configuration reference for more information. | 
|  | 62 | + | 
|  | 63 | +### Workflow Description | 
|  | 64 | +***configuring errors and logging options*** | 
|  | 65 | +1. The cluster admin adds specific configuration for the router prior to | 
|  | 66 | +   MicroShift's start. | 
|  | 67 | +2. After MicroShift starts, the system will read the configuration and setup | 
|  | 68 | +   the router according to it. | 
|  | 69 | + | 
|  | 70 | +### API Extensions | 
|  | 71 | +As mentioned in the proposal, there is an entire new section in the configuration: | 
|  | 72 | +```yaml | 
|  | 73 | +ingress: | 
|  | 74 | +  httpErrorCodePages: | 
|  | 75 | +    name: <string> | 
|  | 76 | +  accessLogging: | 
|  | 77 | +    status: <Enabled|Disabled> | 
|  | 78 | +    format: <string> | 
|  | 79 | +    destination: | 
|  | 80 | +      type: <Container|Syslog> | 
|  | 81 | +      container: | 
|  | 82 | +        maxLength: <int> | 
|  | 83 | +      syslog: | 
|  | 84 | +        address: <ip address> | 
|  | 85 | +        facility: <string> | 
|  | 86 | +        maxLength: <int> | 
|  | 87 | +        port: <int> | 
|  | 88 | +    httpCaptureHeaders: | 
|  | 89 | +      request: | 
|  | 90 | +      - maxLength: <integer> | 
|  | 91 | +        name: <string> | 
|  | 92 | +      response: | 
|  | 93 | +      - maxLength: <integer> | 
|  | 94 | +        name: <string> | 
|  | 95 | +    httpCaptureCookies: | 
|  | 96 | +      - matchType: <Exact|Prefix> | 
|  | 97 | +        maxLength: <integer> | 
|  | 98 | +        name: <string> | 
|  | 99 | +        namePrefix: <string> | 
|  | 100 | +``` | 
|  | 101 | +
 | 
|  | 102 | +For more information check each individual section. | 
|  | 103 | +
 | 
|  | 104 | +#### Hypershift / Hosted Control Planes | 
|  | 105 | +N/A | 
|  | 106 | +### Topology Considerations | 
|  | 107 | +N/A | 
|  | 108 | +
 | 
|  | 109 | +#### Standalone Clusters | 
|  | 110 | +N/A | 
|  | 111 | +
 | 
|  | 112 | +#### Single-node Deployments or MicroShift | 
|  | 113 | +Enhancement is solely intended for MicroShift. | 
|  | 114 | +
 | 
|  | 115 | +### Implementation Details/Notes/Constraints | 
|  | 116 | +The default router is composed of a bunch of assets that are embedded as part | 
|  | 117 | +of the MicroShift binary. These assets come from the rebase, copied from the | 
|  | 118 | +original router in [cluster-ingress-operator](https://github.com/openshift/cluster-ingress-operator). | 
|  | 119 | +
 | 
|  | 120 | +Based on the configuration parameters, the manifest for the router pod will | 
|  | 121 | +mutate to translate all the new options. | 
|  | 122 | +
 | 
|  | 123 | +#### Enabling access logging | 
|  | 124 | +TODO reword this. | 
|  | 125 | +HAProxy allows configuration for access logging. This happens through rsyslog, | 
|  | 126 | +which needs to be running in an endpoints. Options for this are discussed below. | 
|  | 127 | +
 | 
|  | 128 | +The second container (named `access-log`) will print through stdout all the | 
|  | 129 | +logs from the router. | 
|  | 130 | + | 
|  | 131 | +This approach does not require configuring rsyslogd in the host and is self | 
|  | 132 | +contained, not dedicating any resources in case it is not enabled. | 
|  | 133 | + | 
|  | 134 | +Configuring either of `ingress.accessLogging.httpCaptureHeaders` or | 
|  | 135 | +`ingress.accessLogging.httpCaptureCookies` will also enable `ingress.accessLogging.status`. | 
|  | 136 | + | 
|  | 137 | +`ingress.accessLogging.status` defaults to `Disabled`. | 
|  | 138 | + | 
|  | 139 | +##### Access logging destination | 
|  | 140 | +There are two supported ways of configuring the destination: container or | 
|  | 141 | +remote. | 
|  | 142 | + | 
|  | 143 | +These are configured by means of `ingress.accessLogging.destination.type`, | 
|  | 144 | +which is an enum accepting either `Container` or `Syslog`. | 
|  | 145 | +If `ingress.accessLogging.status` is `Enabled` it defaults to `Container`. | 
|  | 146 | + | 
|  | 147 | +`Container` destination type configuration: | 
|  | 148 | +* `maxLength`: maximum length of the log message. Range between 480 and 8192. | 
|  | 149 | +  Defaults to 1024. Optional. | 
|  | 150 | + | 
|  | 151 | +`Syslog` destination type configuration: | 
|  | 152 | +* `address`: IP address of the syslog endpoint that receives log messages. | 
|  | 153 | +  Required. | 
|  | 154 | +* `port`: UDP port number of the syslog endpoint that receives log messages. | 
|  | 155 | +  Required. | 
|  | 156 | +* `facility`: Syslog facility of log messages. If empty it will default to | 
|  | 157 | +  `local1`. Allowed values: `kern;user;mail;daemon;auth;syslog;lpr;news;uucp;cron;auth2;ftp;ntp;audit;alert;cron2;local0;local1;local2;local3;local4;local5;local6;local7`. | 
|  | 158 | +  Optional. | 
|  | 159 | +* `maxLength`: maximum length of the log message. Range between 480 and 8192. | 
|  | 160 | +  Defaults to 1024. Optional. | 
|  | 161 | + | 
|  | 162 | +#### Configuring access log format | 
|  | 163 | +`ingress.accessLogging.format` specifies the format of the log message for an | 
|  | 164 | +HTTP request. If this field is empty, log messages use the implementation's | 
|  | 165 | +default HTTP log format, which is described [here](http://cbonte.github.io/haproxy-dconv/2.0/configuration.html#8.2.3). | 
|  | 166 | + | 
|  | 167 | +Note that this format only applies to cleartext and encryption terminated | 
|  | 168 | +requests. | 
|  | 169 | + | 
|  | 170 | +#### Configuring custom error code pages | 
|  | 171 | +To configure custom error code pages the user needs to specify a configmap name | 
|  | 172 | +in `ingress.httpErrorCodePages.name`. This configmap must be in the | 
|  | 173 | +`openshift-config` namespace and should have keys in the format of | 
|  | 174 | +`error-page-<error code>.http` where `<error code>` is an HTTP status code. | 
|  | 175 | + | 
|  | 176 | +Each value in the configmap should be the full response, including HTTP | 
|  | 177 | +headers. | 
|  | 178 | + | 
|  | 179 | +As of today, only errors for 503 and 404 can be customized. | 
|  | 180 | + | 
|  | 181 | +`ingress.httpErrorCodePages.name` defaults to empty. | 
|  | 182 | + | 
|  | 183 | +#### Capturing headers | 
|  | 184 | +To configure specific HTTP header capture so they are included in the access | 
|  | 185 | +logs the user needs to create entries in `ingress.accessLogging.httpCaptureHeaders`. | 
|  | 186 | +This field is a list and allows capturing request and response headers | 
|  | 187 | +independently. Each of the entries in the list has different parameters that | 
|  | 188 | +follow. If the list is empty (which is the default value) no headers will be | 
|  | 189 | +captured. | 
|  | 190 | + | 
|  | 191 | +This option only applies to cleartext HTTP or reencrypt connections. Headers | 
|  | 192 | +can not be captured for TLS passthrough connections. | 
|  | 193 | + | 
|  | 194 | +Each element of the list includes: | 
|  | 195 | +* `request`. Specifies which HTTP request headers to capture. If this field is | 
|  | 196 | +  empty, no request headers are captured. | 
|  | 197 | +* `response`. Specifies which HTTP response headers to capture. If this field | 
|  | 198 | +  is empty, no request headers are captured. | 
|  | 199 | + | 
|  | 200 | +Both elements have the same fields: | 
|  | 201 | +* `maxLength`. Specifies a maximum length for the header value. If a header | 
|  | 202 | +  value exceeds this length, the value will be truncated in the log message. Minimum value 1. | 
|  | 203 | +* `name`. Specifies a header name.  Its value must be a valid HTTP header name | 
|  | 204 | +  as defined in RFC 2616 section 4.2. String regex ```^[-!#$%&'*+.0-9A-Z^_`a-z|~]+$```. | 
|  | 205 | + | 
|  | 206 | +If configured, it is mandatory to include at least `maxLength` and `name`. | 
|  | 207 | + | 
|  | 208 | +`ingress.accessLogging.httpCaptureHeaders` defaults to an empty list. | 
|  | 209 | + | 
|  | 210 | +#### Capturing cookies | 
|  | 211 | +To configure specific HTTP cookie capture so they are included in the access | 
|  | 212 | +logs the user needs to create an entry in `ingress.accessLogging.httpCaptureCookies`. | 
|  | 213 | +This field is a list (limited to 1 element) which includes information on which | 
|  | 214 | +cookie to capture. If the list is empty (which is the default value) no cookies | 
|  | 215 | +will be captured. | 
|  | 216 | + | 
|  | 217 | +In each element of the list we find: | 
|  | 218 | +* `matchType`. Specifies the type of match to perform against the cookie name. | 
|  | 219 | +  Allowed values are `Exact` and `Prefix`. | 
|  | 220 | +* `maxLength`. Specifies a maximum length of the string that will be logged, | 
|  | 221 | +  which includes the cookie name, cookie value, and one-character delimiter. | 
|  | 222 | +  If the log entry exceeds this length, the value will be truncated in the log | 
|  | 223 | +  message. Minimum value 1, maximum value 1024. | 
|  | 224 | +* `name`. Specifies a cookie name. It must be a valid HTTP cookie name as | 
|  | 225 | +  defined in RFC 6265 section 4.1. String regex ```^[-!#$%&'*+.0-9A-Z^_`a-z|~]*$```. | 
|  | 226 | +  Minimum length 0, maximum length 1024. | 
|  | 227 | +* `namePrefix`. Specifies a cookie name prefix. It must be a valid HTTP cookie | 
|  | 228 | +  name as defined in RFC 6265 section 4.1. String regex ```^[-!#$%&'*+.0-9A-Z^_`a-z|~]*$```. | 
|  | 229 | +  Minimum length 0, maximum length 1024. | 
|  | 230 | + | 
|  | 231 | +If configured, it is mandatory to include at least `matchType` and `maxLength`. | 
|  | 232 | + | 
|  | 233 | +`ingress.accessLogging.httpCaptureCookies` defaults to an empty list. | 
|  | 234 | + | 
|  | 235 | +#### How config options change manifests | 
|  | 236 | +Each of the configuration options described above has a direct effect on the | 
|  | 237 | +manifests that MicroShift will apply after starting.   | 
|  | 238 | +See the full Implementation details in the [router-configuration](microshift-router-configuration.md) | 
|  | 239 | +enhancement. | 
|  | 240 | + | 
|  | 241 | +### Risks and Mitigations | 
|  | 242 | +* Not configuring custom error pages will return the default ones, which are | 
|  | 243 | +  usually empty and only return the http status code. | 
|  | 244 | +* Not configuring capture of http headers and/or cookies will not include them | 
|  | 245 | +  in the access logs of the router. | 
|  | 246 | + | 
|  | 247 | +### Drawbacks | 
|  | 248 | +N/A | 
|  | 249 | + | 
|  | 250 | +## Open Questions | 
|  | 251 | +N/A | 
|  | 252 | + | 
|  | 253 | +## Test Plan | 
|  | 254 | +All configuration changes will be included in already existing e2e router | 
|  | 255 | +tests. Testing router functionality is out of scope of this enhancement. | 
|  | 256 | + | 
|  | 257 | + | 
|  | 258 | +## Graduation Criteria | 
|  | 259 | +Not applicable | 
|  | 260 | + | 
|  | 261 | +### Dev Preview -> Tech Preview | 
|  | 262 | +- Ability to utilize the enhancement end to end | 
|  | 263 | +- End user documentation, relative API stability | 
|  | 264 | +- Sufficient test coverage | 
|  | 265 | + | 
|  | 266 | +### Tech Preview -> GA | 
|  | 267 | +- More testing (upgrade, downgrade) | 
|  | 268 | +- Sufficient time for feedback | 
|  | 269 | +- Available by default | 
|  | 270 | +- User facing documentation created in [openshift-docs](https://github.com/openshift/openshift-docs/) | 
|  | 271 | + | 
|  | 272 | +### Removing a deprecated feature | 
|  | 273 | +N/A | 
|  | 274 | + | 
|  | 275 | +## Upgrade / Downgrade Strategy | 
|  | 276 | +When upgrading from 4.19 or earlier the new configuration fields will remain | 
|  | 277 | +unset, causing the existing defaults to be used. | 
|  | 278 | + | 
|  | 279 | +When downgrading from 4.20 to earlier versions the new parameters will be | 
|  | 280 | +ignored. | 
|  | 281 | + | 
|  | 282 | +## Version Skew Strategy | 
|  | 283 | +N/A | 
|  | 284 | + | 
|  | 285 | +## Operational Aspects of API Extensions | 
|  | 286 | + | 
|  | 287 | +### Failure Modes | 
|  | 288 | +N/A | 
|  | 289 | + | 
|  | 290 | +## Support Procedures | 
|  | 291 | +Access logging, if enabled, will be part of the logs of the openshift-router | 
|  | 292 | +logs. Logs from this pod are captured in the already existing sos report | 
|  | 293 | +procedure available for MicroShift. | 
|  | 294 | + | 
|  | 295 | +## Implementation History | 
|  | 296 | +Implementation [PR](https://github.com/openshift/microshift/pull/4474/) for Micorshift | 
|  | 297 | +## Alternatives (Not Implemented) | 
|  | 298 | +N/A | 
0 commit comments