From e8aceda402f39aaca3c2b2b0c2bf0520b092f8c5 Mon Sep 17 00:00:00 2001 From: Joao Gilberto Magalhaes Date: Mon, 15 Dec 2025 19:58:08 -0500 Subject: [PATCH] Replace deprecated `kubernetes.io/ingress.class` annotation with `spec.ingressClassName` in Kubernetes examples and processor logic for compatibility with Kubernetes v1.22+. Updated documentation and examples to reflect the change while maintaining backward compatibility. --- docs/kubernetes.md | 42 ++++++++++++++---------- examples/kubernetes/cloudflare.yml | 5 +-- examples/kubernetes/ip-whitelist.yml | 5 +-- examples/kubernetes/jwt-validator.yml | 5 +-- examples/kubernetes/plugins-combined.yml | 12 +++++-- examples/kubernetes/service.yml | 5 +-- examples/kubernetes/service_tls.yml | 5 +-- src/processor/__init__.py | 15 +++++++-- 8 files changed, 61 insertions(+), 33 deletions(-) diff --git a/docs/kubernetes.md b/docs/kubernetes.md index cd54dff..3194e29 100644 --- a/docs/kubernetes.md +++ b/docs/kubernetes.md @@ -7,9 +7,10 @@ sidebar_position: 1 ## Setup Kubernetes EasyHAProxy :::info How it works -EasyHAProxy for Kubernetes operates by querying all ingress definitions with the annotation -`kubernetes.io/ingress.class: easyhaproxy-ingress`. Upon finding this annotation, -EasyHAProxy immediately sets up HAProxy and begins serving traffic. +EasyHAProxy for Kubernetes operates by querying all ingress definitions with either the +`spec.ingressClassName: easyhaproxy-ingress` field (recommended) or the deprecated annotation +`kubernetes.io/ingress.class: easyhaproxy-ingress` (for backward compatibility). Upon finding +a matching ingress class, EasyHAProxy immediately sets up HAProxy and begins serving traffic. ::: For Kubernetes installations, there are three available installation modes: @@ -54,18 +55,18 @@ If necessary, you can configure environment variables. To get a list of the vari ## Running containers -Your container only requires creating an ingress with the annotation `kubernetes.io/ingress.class: easyhaproxy-ingress` pointing to your service. +Your container only requires creating an ingress with the `spec.ingressClassName: easyhaproxy-ingress` field pointing to your service. e.g. ```yaml kind: Ingress metadata: - annotations: - kubernetes.io/ingress.class: easyhaproxy-ingress name: example-ingress namespace: example spec: + # Use ingressClassName (recommended) + ingressClassName: easyhaproxy-ingress rules: - host: example.org http: @@ -78,6 +79,10 @@ spec: pathType: ImplementationSpecific ``` +:::note Backward Compatibility +The deprecated annotation `kubernetes.io/ingress.class: easyhaproxy-ingress` is still supported for backward compatibility, but `spec.ingressClassName` is the recommended approach for new deployments. +::: + Once the container is running, EasyHAProxy will detect automatically and start to redirect all traffic from `example.org:80` to your container at port 8080. You don't need to expose any port in your container. @@ -92,7 +97,7 @@ You don't need to expose any port in your container. | annotation | Description | Default | Example | |-------------------------------------|-------------------------------------------------------------------------------------|--------------|----------------------------| -| kubernetes.io/ingress.class | (required) Activate EasyHAProxy. | **required** | easyhaproxy-ingress | +| kubernetes.io/ingress.class | (deprecated) Activate EasyHAProxy. Use `spec.ingressClassName` instead. | *optional* | easyhaproxy-ingress | | easyhaproxy.redirect_ssl | (optional) Boolean. Force redirect all endpoints to HTTPS. | false | true or false | | easyhaproxy.certbot | (optional) Boolean. It will request certbot certificates for the ingresses domains. | false | true or false | | easyhaproxy.redirect | (optional) JSON. Key pair with a domain and its destination. | *empty* | \{"domain":"redirect_url"} | @@ -116,11 +121,11 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: - kubernetes.io/ingress.class: easyhaproxy-ingress easyhaproxy.plugins: "cloudflare,deny_pages" name: example-ingress namespace: example spec: + ingressClassName: easyhaproxy-ingress rules: - host: example.org http: @@ -142,13 +147,13 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: - kubernetes.io/ingress.class: easyhaproxy-ingress easyhaproxy.plugins: "deny_pages" easyhaproxy.plugin.deny_pages.paths: "/admin,/private,/config" easyhaproxy.plugin.deny_pages.status_code: "403" name: secure-app-ingress namespace: production spec: + ingressClassName: easyhaproxy-ingress rules: - host: myapp.example.com http: @@ -168,12 +173,13 @@ spec: ```yaml metadata: annotations: - kubernetes.io/ingress.class: easyhaproxy-ingress easyhaproxy.plugins: "jwt_validator" easyhaproxy.plugin.jwt_validator.algorithm: "RS256" easyhaproxy.plugin.jwt_validator.issuer: "https://auth.example.com/" easyhaproxy.plugin.jwt_validator.audience: "https://api.example.com" easyhaproxy.plugin.jwt_validator.pubkey_path: "/etc/haproxy/jwt_keys/api_pubkey.pem" +spec: + ingressClassName: easyhaproxy-ingress ``` **Note:** For JWT validation, you'll need to mount the public key file into the EasyHAProxy pod. See [Using Plugins](plugins.md#protect-api-with-jwt-authentication) for details. @@ -183,10 +189,11 @@ metadata: ```yaml metadata: annotations: - kubernetes.io/ingress.class: easyhaproxy-ingress easyhaproxy.plugins: "ip_whitelist" easyhaproxy.plugin.ip_whitelist.allowed_ips: "192.168.1.0/24,10.0.0.5" easyhaproxy.plugin.ip_whitelist.status_code: "403" +spec: + ingressClassName: easyhaproxy-ingress ``` **Restore Cloudflare visitor IPs:** @@ -194,8 +201,9 @@ metadata: ```yaml metadata: annotations: - kubernetes.io/ingress.class: easyhaproxy-ingress easyhaproxy.plugins: "cloudflare" +spec: + ingressClassName: easyhaproxy-ingress ``` **Multiple plugins together:** @@ -203,10 +211,11 @@ metadata: ```yaml metadata: annotations: - kubernetes.io/ingress.class: easyhaproxy-ingress easyhaproxy.plugins: "cloudflare,deny_pages" easyhaproxy.plugin.deny_pages.paths: "/wp-admin,/wp-login.php" easyhaproxy.plugin.deny_pages.status_code: "404" +spec: + ingressClassName: easyhaproxy-ingress ``` ### Global Plugin Configuration @@ -238,17 +247,17 @@ For more information on plugin types and available plugins, see the [Using Plugi ## Certbot / ACME / Letsencrypt -It is necessary add the annotation `easyhaproxy.certbot` to the ingress configuration: +It is necessary to add the annotation `easyhaproxy.certbot` to the ingress configuration: ```yaml kind: Ingress metadata: annotations: - kubernetes.io/ingress.class: easyhaproxy-ingress easyhaproxy.certbot: 'true' name: example-ingress namespace: example spec: + ingressClassName: easyhaproxy-ingress .... ``` @@ -276,11 +285,10 @@ type: kubernetes.io/tls apiVersion: networking.k8s.io/v1 kind: Ingress metadata: - annotations: - kubernetes.io/ingress.class: easyhaproxy-ingress name: tls-example namespace: default spec: + ingressClassName: easyhaproxy-ingress tls: - hosts: - host2.local diff --git a/examples/kubernetes/cloudflare.yml b/examples/kubernetes/cloudflare.yml index 43e5ac7..8ca4353 100644 --- a/examples/kubernetes/cloudflare.yml +++ b/examples/kubernetes/cloudflare.yml @@ -112,8 +112,6 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: - kubernetes.io/ingress.class: easyhaproxy-ingress - # Enable Cloudflare plugin easyhaproxy.plugins: "cloudflare" @@ -122,6 +120,9 @@ metadata: name: webapp-ingress-cloudflare namespace: default spec: + # Use ingressClassName instead of the deprecated annotation + # For backward compatibility, annotation kubernetes.io/ingress.class is still supported + ingressClassName: easyhaproxy-ingress rules: - host: myapp.example.local http: diff --git a/examples/kubernetes/ip-whitelist.yml b/examples/kubernetes/ip-whitelist.yml index 8f6e1f3..4020859 100644 --- a/examples/kubernetes/ip-whitelist.yml +++ b/examples/kubernetes/ip-whitelist.yml @@ -95,8 +95,6 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: - kubernetes.io/ingress.class: easyhaproxy-ingress - # Enable IP whitelist plugin easyhaproxy.plugins: "ip_whitelist" @@ -109,6 +107,9 @@ metadata: name: admin-ingress-whitelist namespace: default spec: + # Use ingressClassName instead of the deprecated annotation + # For backward compatibility, annotation kubernetes.io/ingress.class is still supported + ingressClassName: easyhaproxy-ingress rules: - host: admin.example.local http: diff --git a/examples/kubernetes/jwt-validator.yml b/examples/kubernetes/jwt-validator.yml index 2d5ee0e..eee68d5 100644 --- a/examples/kubernetes/jwt-validator.yml +++ b/examples/kubernetes/jwt-validator.yml @@ -116,8 +116,6 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: - kubernetes.io/ingress.class: easyhaproxy-ingress - # Enable JWT validator plugin easyhaproxy.plugins: "jwt_validator" @@ -129,6 +127,9 @@ metadata: name: api-ingress-jwt namespace: default spec: + # Use ingressClassName instead of the deprecated annotation + # For backward compatibility, annotation kubernetes.io/ingress.class is still supported + ingressClassName: easyhaproxy-ingress rules: - host: api.example.local http: diff --git a/examples/kubernetes/plugins-combined.yml b/examples/kubernetes/plugins-combined.yml index 274922f..36f0631 100644 --- a/examples/kubernetes/plugins-combined.yml +++ b/examples/kubernetes/plugins-combined.yml @@ -113,7 +113,6 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: - kubernetes.io/ingress.class: easyhaproxy-ingress # Cloudflare IP restoration + deny pages easyhaproxy.plugins: "cloudflare,deny_pages" easyhaproxy.plugin.deny_pages.paths: "/admin,/wp-admin,/wp-login.php,/.env,/config" @@ -121,6 +120,9 @@ metadata: name: website-ingress namespace: default spec: + # Use ingressClassName instead of the deprecated annotation + # For backward compatibility, annotation kubernetes.io/ingress.class is still supported + ingressClassName: easyhaproxy-ingress rules: - host: website.example.local http: @@ -179,7 +181,6 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: - kubernetes.io/ingress.class: easyhaproxy-ingress # JWT validation + block internal endpoints easyhaproxy.plugins: "jwt_validator,deny_pages" # JWT config @@ -193,6 +194,9 @@ metadata: name: api-ingress namespace: default spec: + # Use ingressClassName instead of the deprecated annotation + # For backward compatibility, annotation kubernetes.io/ingress.class is still supported + ingressClassName: easyhaproxy-ingress rules: - host: api.example.local http: @@ -251,7 +255,6 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: - kubernetes.io/ingress.class: easyhaproxy-ingress # IP whitelist only (strictest security) easyhaproxy.plugins: "ip_whitelist" # UPDATE with your office/VPN IPs! @@ -260,6 +263,9 @@ metadata: name: admin-ingress namespace: default spec: + # Use ingressClassName instead of the deprecated annotation + # For backward compatibility, annotation kubernetes.io/ingress.class is still supported + ingressClassName: easyhaproxy-ingress rules: - host: admin.example.local http: diff --git a/examples/kubernetes/service.yml b/examples/kubernetes/service.yml index b328846..71ae9ed 100644 --- a/examples/kubernetes/service.yml +++ b/examples/kubernetes/service.yml @@ -56,11 +56,12 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: - annotations: - kubernetes.io/ingress.class: easyhaproxy-ingress name: container-example namespace: default spec: + # Use ingressClassName instead of the deprecated annotation + # For backward compatibility, annotation kubernetes.io/ingress.class is still supported + ingressClassName: easyhaproxy-ingress rules: - host: example.org http: diff --git a/examples/kubernetes/service_tls.yml b/examples/kubernetes/service_tls.yml index 076f9a9..fd08594 100644 --- a/examples/kubernetes/service_tls.yml +++ b/examples/kubernetes/service_tls.yml @@ -57,11 +57,12 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: - annotations: - kubernetes.io/ingress.class: easyhaproxy-ingress name: tls-example namespace: default spec: + # Use ingressClassName instead of the deprecated annotation + # For backward compatibility, annotation kubernetes.io/ingress.class is still supported + ingressClassName: easyhaproxy-ingress tls: - hosts: - host2.local diff --git a/src/processor/__init__.py b/src/processor/__init__.py index 0695a46..0fb29fb 100644 --- a/src/processor/__init__.py +++ b/src/processor/__init__.py @@ -239,9 +239,18 @@ class Kubernetes(ProcessorInterface): self.parsed_object = {} for ingress in ret.items: - if 'kubernetes.io/ingress.class' not in ingress.metadata.annotations: - continue - if ingress.metadata.annotations['kubernetes.io/ingress.class'] != "easyhaproxy-ingress": + # Support both new spec.ingressClassName and deprecated annotation for backward compatibility + ingress_class = None + + # Check new spec.ingressClassName first (preferred) + if hasattr(ingress.spec, 'ingress_class_name') and ingress.spec.ingress_class_name is not None: + ingress_class = ingress.spec.ingress_class_name + # Fall back to deprecated annotation + elif ingress.metadata.annotations and 'kubernetes.io/ingress.class' in ingress.metadata.annotations: + ingress_class = ingress.metadata.annotations['kubernetes.io/ingress.class'] + + # Skip if no ingress class is defined or it doesn't match + if ingress_class != "easyhaproxy-ingress": continue ssl_hosts = []