Skip to content

K8s: Replace Ingress NGINX with Traefik for default ingress controller#3083

Merged
VietND96 merged 1 commit intotrunkfrom
traefik-controller
Feb 21, 2026
Merged

K8s: Replace Ingress NGINX with Traefik for default ingress controller#3083
VietND96 merged 1 commit intotrunkfrom
traefik-controller

Conversation

@VietND96
Copy link
Member

@VietND96 VietND96 commented Feb 20, 2026

User description

Thanks for contributing to the Docker-Selenium project!
A PR well described will help maintainers to quickly review and merge it

Before submitting your PR, please check our contributing guidelines, applied for this repository.
Avoid large PRs, help reviewers by making them as simple and short as possible.

Description

Fixes #3076

Motivation and Context

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist

  • I have read the contributing document.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

PR Type

Enhancement


Description

  • Replace Ingress NGINX with Traefik as default ingress controller

  • Update Helm chart dependencies and configuration values

  • Refactor ingress annotations from NGINX to Traefik format

  • Create Traefik ServersTransport resource for backend connectivity

  • Update test cases and documentation for Traefik integration


Diagram Walkthrough

flowchart LR
  A["Ingress NGINX<br/>Controller"] -->|"Replace with"| B["Traefik<br/>Controller"]
  C["NGINX<br/>Annotations"] -->|"Convert to"| D["Traefik<br/>Annotations"]
  E["Chart<br/>Dependencies"] -->|"Update"| F["Traefik v39+<br/>Dependency"]
  G["Test<br/>Configuration"] -->|"Migrate"| H["Traefik<br/>Test Values"]
  B -->|"Creates"| I["ServersTransport<br/>Resource"]
Loading

File Walkthrough

Relevant files
Configuration changes
11 files
chart_cluster_setup.sh
Update ingress namespace from nginx to traefik                     
+1/-1     
chart_test.sh
Update ingress namespace and helm parameters for traefik 
+6/-7     
values.yaml
Replace nginx config with traefik config in values             
+57/-35 
base-auth-ingress-values.yaml
Update ingress class and traefik configuration                     
+12/-7   
base-subPath-values.yaml
Simplify subpath configuration for traefik                             
+2/-16   
ct.yaml
Update chart repository to traefik helm charts                     
+1/-1     
sample-aws.yaml
Migrate aws sample values to traefik configuration             
+7/-9     
simplex-docker-desktop.yaml
Migrate docker desktop sample to traefik setup                     
+22/-25 
simplex-minikube.yaml
Migrate minikube sample values to traefik                               
+20/-17 
dummy.yaml
Update dummy test values for traefik configuration             
+20/-11 
dummy_solution.yaml
Update solution template values for traefik                           
+20/-11 
Tests
1 files
test.py
Refactor ingress annotation tests for traefik                       
+39/-9   
Documentation
3 files
CONFIGURATION.md
Update documentation for traefik ingress configuration     
+23/-17 
README.md
Update ingress configuration guide for traefik                     
+60/-63 
TESTING.md
Update test documentation for traefik annotations               
+1/-1     
Dependencies
1 files
Chart.yaml
Replace ingress-nginx dependency with traefik                       
+4/-4     
Enhancement
4 files
_helpers.tpl
Replace nginx annotation helpers with traefik helpers       
+50/-44 
_nameHelpers.tpl
Add traefik serverstransport naming helpers                           
+9/-0     
ingress.yaml
Update ingress template for traefik annotations                   
+3/-3     
traefik-servers-transport.yaml
Create new traefik serverstransport resource template       
+36/-0   

@qodo-code-review
Copy link
Contributor

qodo-code-review bot commented Feb 20, 2026

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
TLS verification disabled

Description: ingress.traefik.serversTransport.insecureSkipVerify defaults to true, which can disable
backend TLS certificate verification and enables realistic MITM risk between Traefik and
the Grid backend unless users explicitly set it to false.
values.yaml [232-247]

Referred Code
serversTransport:
  # -- Enable creating a Traefik ServersTransport resource and auto-link it to ingress annotation `traefik.ingress.kubernetes.io/service.serverstransport`
  enabled: true
  # -- Override ServersTransport resource name. Defaults to `<ingress-fullname>-serverstransport`
  nameOverride: ""
  # -- Use an existing ServersTransport reference `<namespace>-<name>@kubernetescrd` when `enabled` is false
  reference: ""
  # -- For backend HTTPS with self-signed certs
  insecureSkipVerify: true
  forwardingTimeouts:
    # -- Maximum duration Traefik waits when establishing a connection to backend servers
    dialTimeout: "120s"
    # -- Maximum duration Traefik waits for backend response headers
    responseHeaderTimeout: "3600s"
    # -- Maximum duration an idle keep-alive backend connection remains open
    idleConnTimeout: "3600s"
Ticket Compliance
🟡
🎫 #3076
🟢 Replace the deprecated ingress-nginx Helm chart dependency with an alternative ingress
controller in the Selenium Grid Helm chart.
Update Helm chart configuration/values and documentation accordingly so consumers can use
the new default ingress controller setup.
Verify in a real Kubernetes cluster that Traefik installs and functions correctly as a
drop-in default (ingress routing, TLS behavior, timeouts) across the documented scenarios.

Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

🔴
Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Insecure TLS default: The new default ingress.traefik.serversTransport.insecureSkipVerify is set to true, which
weakens TLS verification for backend connections by default.

Referred Code
serversTransport:
  # -- Enable creating a Traefik ServersTransport resource and auto-link it to ingress annotation `traefik.ingress.kubernetes.io/service.serverstransport`
  enabled: true
  # -- Override ServersTransport resource name. Defaults to `<ingress-fullname>-serverstransport`
  nameOverride: ""
  # -- Use an existing ServersTransport reference `<namespace>-<name>@kubernetescrd` when `enabled` is false
  reference: ""
  # -- For backend HTTPS with self-signed certs
  insecureSkipVerify: true
  forwardingTimeouts:
    # -- Maximum duration Traefik waits when establishing a connection to backend servers
    dialTimeout: "120s"
    # -- Maximum duration Traefik waits for backend response headers
    responseHeaderTimeout: "3600s"
    # -- Maximum duration an idle keep-alive backend connection remains open
    idleConnTimeout: "3600s"

Learn more about managing compliance generic rules or creating your own custom rules

  • Update
Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-code-review
Copy link
Contributor

qodo-code-review bot commented Feb 20, 2026

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
High-level
Consider the impact of sub-path handling simplification

The PR simplifies sub-path handling by replacing NGINX's regex-based path
rewriting with Traefik's PathPrefix matcher. This is a behavioral change that
should be documented as it may affect users with advanced path configurations.

Examples:

tests/charts/ci/base-subPath-values.yaml [1-20]
hub:
  subPath: "/selenium"

components:
  router:
    subPath: "/selenium"
tests/charts/refValues/sample-aws.yaml [11-24]
ingress:
  enabled: true
  annotations:
    traefik.ingress.kubernetes.io/router.pathmatcher: "PathPrefix"
  className: traefik
  hostname: "aws.ndviet.org" # Replace with your hostname
  paths:
    - path: /selenium
      pathType: Prefix
      backend:

 ... (clipped 4 lines)

Solution Walkthrough:

Before:

# Ingress configuration with NGINX
ingress:
  annotations:
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /$2
  paths:
    - path: /selenium(/|$)(.*)
      pathType: ImplementationSpecific
      ...

# Backend (hub/router) configuration
hub:
  subPath: "/selenium" # Used for URL generation, not for listening path

After:

# Ingress configuration with Traefik
ingress:
  traefik:
    pathMatcher: "PathPrefix"
  paths:
    - path: /selenium
      pathType: Prefix
      ...

# Backend (hub/router) configuration
hub:
  subPath: "/selenium" # Backend now listens on this sub-path
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies a significant behavioral change in ingress path handling, which could impact users with custom configurations, and rightly advises documenting it.

Medium
Possible issue
Avoid hardcoding namespace in test

In the test test_ingress_traefik_servers_transport, avoid hardcoding the
namespace as "default" by dynamically extracting it from the rendered
ServersTransport resource to make the test more robust.

tests/charts/templates/test.py [77-101]

 def test_ingress_traefik_servers_transport(self):
     ingress_name = f'{RELEASE_NAME}selenium-ingress'
     servers_transport_name = f'{ingress_name}-serverstransport'
-    namespace = "default"
+    namespace = None
     ingress_found = False
     servers_transport_found = False
+
+    # First, find the ServersTransport and get its namespace
+    for doc in LIST_OF_DOCUMENTS:
+        if doc['kind'] == 'ServersTransport' and doc['metadata']['name'] == servers_transport_name:
+            namespace = doc['metadata']['namespace']
+            break
+    
+    self.assertIsNotNone(namespace, "Could not determine namespace from ServersTransport resource")
+
     for doc in LIST_OF_DOCUMENTS:
         if doc['kind'] == 'Ingress' and doc['metadata']['name'] == ingress_name:
             logger.info(f"Assert ingress has Traefik ServersTransport reference annotation")
             expected_ref = f'{namespace}-{servers_transport_name}@kubernetescrd'
             self.assertEqual(
                 doc['metadata']['annotations']['traefik.ingress.kubernetes.io/service.serverstransport'],
                 expected_ref,
             )
             ingress_found = True
         if doc['kind'] == 'ServersTransport' and doc['metadata']['name'] == servers_transport_name:
             logger.info(f"Assert Traefik ServersTransport forwarding timeouts are set")
             self.assertFalse(doc['spec']['insecureSkipVerify'])
             forwarding_timeouts = doc['spec']['forwardingTimeouts']
             self.assertEqual(forwarding_timeouts['dialTimeout'], '30s')
             self.assertEqual(forwarding_timeouts['responseHeaderTimeout'], '360s')
             self.assertEqual(forwarding_timeouts['idleConnTimeout'], '360s')
             servers_transport_found = True
     self.assertTrue(ingress_found, "No ingress resource found with ServersTransport annotation")
     self.assertTrue(servers_transport_found, "No Traefik ServersTransport resource found")
  • Apply / Chat
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies a hardcoded namespace in a test, which makes the test brittle. The proposed fix to dynamically determine the namespace makes the test more robust and reliable.

Medium
Apply extra settings for ServersTransport

In traefik-servers-transport.yaml, merge the extraSettings value into the $spec
dictionary to allow users to configure additional ServersTransport options.

charts/selenium-grid/templates/traefik-servers-transport.yaml [9-35]

 {{- $spec := dict -}}
 {{- $timeouts := dict -}}
 {{- with .Values.ingress.traefik.serversTransport }}
   {{- if kindIs "bool" .insecureSkipVerify }}
     {{- $_ := set $spec "insecureSkipVerify" .insecureSkipVerify -}}
   {{- end }}
 {{- end }}
 {{- with .Values.ingress.traefik.serversTransport.forwardingTimeouts }}
   {{- with .dialTimeout }}
     {{- $_ := set $timeouts "dialTimeout" (tpl (. | toString) $) -}}
   {{- end }}
   {{- with .responseHeaderTimeout }}
     {{- $_ := set $timeouts "responseHeaderTimeout" (tpl (. | toString) $) -}}
   {{- end }}
   {{- with .idleConnTimeout }}
     {{- $_ := set $timeouts "idleConnTimeout" (tpl (. | toString) $) -}}
   {{- end }}
 {{- end }}
 {{- if not (empty $timeouts) }}
   {{- $_ := set $spec "forwardingTimeouts" $timeouts -}}
 {{- end }}
+{{- $spec = mergeOverwrite .Values.ingress.traefik.serversTransport.extraSettings $spec -}}
 {{- if empty $spec }}
 spec: {}
 {{- else }}
 spec:
   {{- toYaml $spec | nindent 2 }}
 {{- end }}
  • Apply / Chat
Suggestion importance[1-10]: 6

__

Why: The suggestion correctly identifies that the extraSettings value is not used in the template, and the proposed fix enables greater customization of the ServersTransport resource, improving the chart's flexibility.

Low
Use boolean ingress.enabled check

In traefik-servers-transport.yaml, modify the conditional to check the boolean
.Values.ingress.enabled directly instead of using (eq (include
"seleniumGrid.ingress.enabled" $) "true").

charts/selenium-grid/templates/traefik-servers-transport.yaml [1]

-{{- if and (eq (include "seleniumGrid.ingress.enabled" $) "true") .Values.ingress.traefik.enabled .Values.ingress.traefik.serversTransport.enabled }}
+{{- if and .Values.ingress.enabled .Values.ingress.traefik.enabled .Values.ingress.traefik.serversTransport.enabled }}
  • Apply / Chat
Suggestion importance[1-10]: 5

__

Why: The suggestion correctly points out that checking a boolean value directly is better practice than comparing the string output of a helper template, improving code clarity and robustness.

Low
Learned
best practice
Guard null nested config lookups

Users can set ingress.traefik: null (as documented), so guard access to
.Values.ingress.traefik.* using a with block (or similar) to prevent template
rendering errors.

charts/selenium-grid/templates/traefik-servers-transport.yaml [1-36]

-{{- if and (eq (include "seleniumGrid.ingress.enabled" $) "true") .Values.ingress.traefik.enabled .Values.ingress.traefik.serversTransport.enabled }}
+{{- if eq (include "seleniumGrid.ingress.enabled" $) "true" }}
+{{- with .Values.ingress.traefik }}
+{{- if and .enabled .serversTransport.enabled }}
 apiVersion: traefik.io/v1alpha1
 kind: ServersTransport
 metadata:
-  name: {{ include "seleniumGrid.ingress.traefik.serversTransport.name" . }}
-  namespace: {{ .Release.Namespace }}
+  name: {{ include "seleniumGrid.ingress.traefik.serversTransport.name" $ }}
+  namespace: {{ $.Release.Namespace }}
   labels:
     {{- include "seleniumGrid.commonLabels" $ | nindent 4 }}
 {{- $spec := dict -}}
 {{- $timeouts := dict -}}
-{{- with .Values.ingress.traefik.serversTransport }}
+{{- with .serversTransport }}
   {{- if kindIs "bool" .insecureSkipVerify }}
     {{- $_ := set $spec "insecureSkipVerify" .insecureSkipVerify -}}
   {{- end }}
 {{- end }}
-{{- with .Values.ingress.traefik.serversTransport.forwardingTimeouts }}
+{{- with .serversTransport.forwardingTimeouts }}
   {{- with .dialTimeout }}
     {{- $_ := set $timeouts "dialTimeout" (tpl (. | toString) $) -}}
   {{- end }}
   {{- with .responseHeaderTimeout }}
     {{- $_ := set $timeouts "responseHeaderTimeout" (tpl (. | toString) $) -}}
   {{- end }}
   {{- with .idleConnTimeout }}
     {{- $_ := set $timeouts "idleConnTimeout" (tpl (. | toString) $) -}}
   {{- end }}
 {{- end }}
 {{- if not (empty $timeouts) }}
   {{- $_ := set $spec "forwardingTimeouts" $timeouts -}}
 {{- end }}
 {{- if empty $spec }}
 spec: {}
 {{- else }}
 spec:
   {{- toYaml $spec | nindent 2 }}
 {{- end }}
 {{- end }}
+{{- end }}
+{{- end }}
  • Apply / Chat
Suggestion importance[1-10]: 6

__

Why:
Relevant best practice - Make Helm templates resilient to optional/null values by guarding nested lookups (avoid dereferencing fields on a possibly null map).

Low
  • Update

@VietND96 VietND96 force-pushed the traefik-controller branch 5 times, most recently from 4f88d0f to 5022060 Compare February 21, 2026 12:58
@VietND96 VietND96 merged commit f4132db into trunk Feb 21, 2026
54 of 57 checks passed
@VietND96 VietND96 deleted the traefik-controller branch February 21, 2026 17:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[🚀 Feature]: Replace Ingress NGINX Dependency

1 participant