Repository: traefik/traefik (language: go)

Issue:
Health-Checks for KubernetesCRD ExternalNamedServices
### Welcome!

- [X] Yes, I've searched similar issues on [GitHub](https://github.com/traefik/traefik/issues) and didn't find any.
- [X] Yes, I've searched similar issues on the [Traefik community forum](https://community.containo.us) and didn't find any.

### What did you expect to see?

Health-Checks for KubernetesCRD ExternalNamedServices

#### RATIONALE: Use-Case for Hybrid Kuberenetes/Other Orchestrator Mixes

While many industry-leaders have taken the journey toward using kubernetes to deploy all things Traefik, many of us still have the need to use kubernetes as a control-plane, but not a service deployer. More specifically, there is an interesting use-case for using the KubernetesCRD provider to deploy applications to a non-kubernetes environment.

##### What is possible now

Anyone can use "ExternalName" serviceType with the latest version of traefik as of this writing and deploy services in a non-kubernetes environment.

##### What is not possible now

To add Traefik health-checks into the "ExternalName" serviceType with the latest version of Traefik. 

Sources:
1. https://github.com/traefik/traefik/issues/6128
2. https://community.traefik.io/t/why-the-traefik-health-check-is-not-available-for-kubernetescrd-and-kubernetesingress-providers/10069

##### What I'd like to propose building

In the KubernetesCRD Provider, we have the simple flag "allowExternalNameServices", which allows for the aformentioned section, but the implementation of that exists within the kubernetes-native Service CRD, as it should!

Now that we've ruled that possibility out, let's make this service-crd-agnostic and have an additional healthcheck specifically within the ingressroute configuration:
```yml
routes:
  - match: Host(`example.com`) && Path(`/health`,`/v1/version`)
    kind: Rule
    services:
    - name: external-svc-with-http
      port: 9000
      healthcheck: 
        - path: /health
        interval: 5s
        timeout: 3s
```

This option will only work if the service is of type "externalName".

##### Why this is useful to the community

Two Major Reasons:
1. Not every project has the luxury, budget, or technical feasibility (think voip services, ect) for the whole project to exist within a robust virtualized orchestrator such as kubernetes, but many projects want to use kubernetes to manage dynamic configuration for key pieces of infrastructure such as traefik. 

2. Having a solution to this issue would make it possible to use kubernetes as a provider for many different traefik loadbalancers in different locations, many of which may not always exist in native-kubernetes-land, but also need healthchecks in order to take advantage of traefik's endpoint-removal functionality in the event of an outage.

### TLDR
Love the kuberenetesCRD functionality, and especially externalName. There are specific reasons to add a healthcheck that I've mentioned along with their value to the OS Community. Please consider my proposal/ideas and let me know if it's just a terrible idea as well :)


Discussion / hints:
@rtribotte I think I will take the initiative to build a solution and submit a PR for this issue. Because amending the design might be a bit painful as far as testing, please leave feedback if you have any as I am developing within these issue comments.
@StephanSalas just so you know, this issue is labelled as a proposal which means that we might not accept your pull request as we need to refine the proposal and discuss more this topic.
@kevinpollet hello thank you for the notice on the review process. I have read the contributer guidelines and will be patient as well with the project maintenance team. 

Meantime, I will take a few stabs at coding within the traefik code base to gain more understanding for myself so that when we agree on a solution I can more easily get things rolling. 

One consideration I missed in my original proposal was that there are actually 2 ways services are specified from an ingressroute:

1. Directly from the IngressRouteCR
2. Indirectly from the IngressRouteCR within a Traefik Service CR.

Not sure if we would want to support health checks on both from a CRD perspective, but just something I thought to start the conversation (assuming project maintainers think this is a good idea at all). 


I'm working through the solution to this currently. It seems the difficult part is the translation of objects between the provider and traefik conf[] interfaces, as well as making this backward compatible. Still requesting feedback...
Hello, I was wondering if this functionality is still being considered?

We have recently started developing our LB and distribution, and would like to use Traefik for this. The issue is we have some services off-k8s. Setting up externalnames and ingress/ingressroutes have not been a problem. However during testing it became quickly apparent that Traefik has no awareness when the service goes down. 

We have tried some workarounds, but have nothing so far.

We were thinking we might be able to use https://doc.traefik.io/traefik/reference/dynamic-configuration/rancher/, and place labels on the service so that Traefik would do some basic health check. However, kubectl is not happy with the length of some of these labels. EDIT: Looking at https://doc.traefik.io/traefik/providers/rancher/ it seems like anything labeled 'Rancher' actually refers to old 1.x rancher, so nevermind that.

Right now the only possible workaround we have devised is to setup file provider with either a configmap or a RWX PV, less than ideal. 

Has anyone else with this issue have a sufficient workaround?
Hello @jonathon2nd,

Thanks for your interest in Traefik !

As stated [here](https://github.com/traefik/traefik/issues/8541#issuecomment-957884813):

> this issue is labelled as a proposal which means that we might not accept your pull request as we need to refine the proposal and discuss more this topic.
Hey y'all, so we don't really have a workaround, and a fix is not on the roadmap yet, but we would like to work with you on how to address this.  

We would really love to hear your design ideas on how you would approach this. 
We have a workaround in place that we are evaluating. We have setup an internal http workload which serves the config on a url which Traefik then gets. This way we can update the config without redeploying traefik if we use a standard configmap mounted to the workload, or a rwx pv. Not ideal but should be sufficient.
Hi - @jonathon2nd @tfny I do have a PR that I never got to finish due to lack of time out there - https://github.com/traefik/traefik/pull/8663

Feel free to further contribute to this idea if you have more time than me.

Fix patch:
diff --git a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml
index 93f14adcfa..17f1a57e9a 100644
--- a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml
+++ b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml
@@ -98,6 +98,47 @@ spec:
                         description: Service defines an upstream HTTP service to proxy
                           traffic to.
                         properties:
+                          healthCheck:
+                            description: Healthcheck defines health checks for the
+                              service.
+                            properties:
+                              followRedirects:
+                                type: boolean
+                              headers:
+                                additionalProperties:
+                                  type: string
+                                type: object
+                              hostname:
+                                type: string
+                              interval:
+                                description: |-
+                                  Duration is a custom type suitable for parsing duration values.
+                                  It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                                  the latter case, seconds are assumed.
+                                format: int64
+                                type: integer
+                              method:
+                                type: string
+                              mode:
+                                type: string
+                              path:
+                                type: string
+                              port:
+                                type: integer
+                              scheme:
+                                type: string
+                              status:
+                                type: integer
+                              timeout:
+                                description: |-
+                                  Duration is a custom type suitable for parsing duration values.
+                                  It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                                  the latter case, seconds are assumed.
+                                format: int64
+                                type: integer
+                            required:
+                            - followRedirects
+                            type: object
                           kind:
                             description: Kind defines the kind of the Service.
                             enum:
@@ -919,6 +960,46 @@ spec:
                       Service defines the reference to a Kubernetes Service that will serve the error page.
                       More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/errorpages/#service
                     properties:
+                      healthCheck:
+                        description: Healthcheck defines health checks for the service.
+                        properties:
+                          followRedirects:
+                            type: boolean
+                          headers:
+                            additionalProperties:
+                              type: string
+                            type: object
+                          hostname:
+                            type: string
+                          interval:
+                            description: |-
+                              Duration is a custom type suitable for parsing duration values.
+                              It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                              the latter case, seconds are assumed.
+                            format: int64
+                            type: integer
+                          method:
+                            type: string
+                          mode:
+                            type: string
+                          path:
+                            type: string
+                          port:
+                            type: integer
+                          scheme:
+                            type: string
+                          status:
+                            type: integer
+                          timeout:
+                            description: |-
+                              Duration is a custom type suitable for parsing duration values.
+                              It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                              the latter case, seconds are assumed.
+                            format: int64
+                            type: integer
+                        required:
+                        - followRedirects
+                        type: object
                       kind:
                         description: Kind defines the kind of the Service.
                         enum:
@@ -2295,6 +2376,46 @@ spec:
               mirroring:
                 description: Mirroring defines the Mirroring service configuration.
                 properties:
+                  healthCheck:
+                    description: Healthcheck defines health checks for the service.
+                    properties:
+                      followRedirects:
+                        type: boolean
+                      headers:
+                        additionalProperties:
+                          type: string
+                        type: object
+                      hostname:
+                        type: string
+                      interval:
+                        description: |-
+                          Duration is a custom type suitable for parsing duration values.
+                          It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                          the latter case, seconds are assumed.
+                        format: int64
+                        type: integer
+                      method:
+                        type: string
+                      mode:
+                        type: string
+                      path:
+                        type: string
+                      port:
+                        type: integer
+                      scheme:
+                        type: string
+                      status:
+                        type: integer
+                      timeout:
+                        description: |-
+                          Duration is a custom type suitable for parsing duration values.
+                          It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                          the latter case, seconds are assumed.
+                        format: int64
+                        type: integer
+                    required:
+                    - followRedirects
+                    type: object
                   kind:
                     description: Kind defines the kind of the Service.
                     enum:
@@ -2314,6 +2435,46 @@ spec:
                     items:
                       description: MirrorService holds the mirror configuration.
                       properties:
+                        healthCheck:
+                          description: Healthcheck defines health checks for the service.
+                          properties:
+                            followRedirects:
+                              type: boolean
+                            headers:
+                              additionalProperties:
+                                type: string
+                              type: object
+                            hostname:
+                              type: string
+                            interval:
+                              description: |-
+                                Duration is a custom type suitable for parsing duration values.
+                                It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                                the latter case, seconds are assumed.
+                              format: int64
+                              type: integer
+                            method:
+                              type: string
+                            mode:
+                              type: string
+                            path:
+                              type: string
+                            port:
+                              type: integer
+                            scheme:
+                              type: string
+                            status:
+                              type: integer
+                            timeout:
+                              description: |-
+                                Duration is a custom type suitable for parsing duration values.
+                                It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                                the latter case, seconds are assumed.
+                              format: int64
+                              type: integer
+                          required:
+                          - followRedirects
+                          type: object
                         kind:
                           description: Kind defines the kind of the Service.
                           enum:
@@ -2548,6 +2709,46 @@ spec:
                       description: Service defines an upstream HTTP service to proxy
                         traffic to.
                       properties:
+                        healthCheck:
+                          description: Healthcheck defines health checks for the service.
+                          properties:
+                            followRedirects:
+                              type: boolean
+                            headers:
+                              additionalProperties:
+                                type: string
+                              type: object
+                            hostname:
+                              type: string
+                            interval:
+                              description: |-
+                                Duration is a custom type suitable for parsing duration values.
+                                It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                                the latter case, seconds are assumed.
+                              format: int64
+                              type: integer
+                            method:
+                              type: string
+                            mode:
+                              type: string
+                            path:
+                              type: string
+                            port:
+                              type: integer
+                            scheme:
+                              type: string
+                            status:
+                              type: integer
+                            timeout:
+                              description: |-
+                                Duration is a custom type suitable for parsing duration values.
+                                It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                                the latter case, seconds are assumed.
+                              format: int64
+                              type: integer
+                          required:
+                          - followRedirects
+                          type: object
                         kind:
                           description: Kind defines the kind of the Service.
                           enum:
diff --git a/docs/content/reference/dynamic-configuration/traefik.io_ingressroutes.yaml b/docs/content/reference/dynamic-configuration/traefik.io_ingressroutes.yaml
index 71d4374919..984503f044 100644
--- a/docs/content/reference/dynamic-configuration/traefik.io_ingressroutes.yaml
+++ b/docs/content/reference/dynamic-configuration/traefik.io_ingressroutes.yaml
@@ -98,6 +98,47 @@ spec:
                         description: Service defines an upstream HTTP service to proxy
                           traffic to.
                         properties:
+                          healthCheck:
+                            description: Healthcheck defines health checks for the
+                              service.
+                            properties:
+                              followRedirects:
+                                type: boolean
+                              headers:
+                                additionalProperties:
+                                  type: string
+                                type: object
+                              hostname:
+                                type: string
+                              interval:
+                                description: |-
+                                  Duration is a custom type suitable for parsing duration values.
+                                  It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                                  the latter case, seconds are assumed.
+                                format: int64
+                                type: integer
+                              method:
+                                type: string
+                              mode:
+                                type: string
+                              path:
+                                type: string
+                              port:
+                                type: integer
+                              scheme:
+                                type: string
+                              status:
+                                type: integer
+                              timeout:
+                                description: |-
+                                  Duration is a custom type suitable for parsing duration values.
+                                  It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                                  the latter case, seconds are assumed.
+                                format: int64
+                                type: integer
+                            required:
+                            - followRedirects
+                            type: object
                           kind:
                             description: Kind defines the kind of the Service.
                             enum:
diff --git a/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml b/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml
index 0a1891ea88..7d695362c0 100644
--- a/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml
+++ b/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml
@@ -256,6 +256,46 @@ spec:
                       Service defines the reference to a Kubernetes Service that will serve the error page.
                       More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/errorpages/#service
                     properties:
+                      healthCheck:
+                        description: Healthcheck defines health checks for the service.
+                        properties:
+                          followRedirects:
+                            type: boolean
+                          headers:
+                            additionalProperties:
+                              type: string
+                            type: object
+                          hostname:
+                            type: string
+                          interval:
+                            description: |-
+                              Duration is a custom type suitable for parsing duration values.
+                              It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                              the latter case, seconds are assumed.
+                            format: int64
+                            type: integer
+                          method:
+                            type: string
+                          mode:
+                            type: string
+                          path:
+                            type: string
+                          port:
+                            type: integer
+                          scheme:
+                            type: string
+                          status:
+                            type: integer
+                          timeout:
+                            description: |-
+                              Duration is a custom type suitable for parsing duration values.
+                              It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                              the latter case, seconds are assumed.
+                            format: int64
+                            type: integer
+                        required:
+                        - followRedirects
+                        type: object
                       kind:
                         description: Kind defines the kind of the Service.
                         enum:
diff --git a/docs/content/reference/dynamic-configuration/traefik.io_traefikservices.yaml b/docs/content/reference/dynamic-configuration/traefik.io_traefikservices.yaml
index ee99b7b19e..8a6454858e 100644
--- a/docs/content/reference/dynamic-configuration/traefik.io_traefikservices.yaml
+++ b/docs/content/reference/dynamic-configuration/traefik.io_traefikservices.yaml
@@ -47,6 +47,46 @@ spec:
               mirroring:
                 description: Mirroring defines the Mirroring service configuration.
                 properties:
+                  healthCheck:
+                    description: Healthcheck defines health checks for the service.
+                    properties:
+                      followRedirects:
+                        type: boolean
+                      headers:
+                        additionalProperties:
+                          type: string
+                        type: object
+                      hostname:
+                        type: string
+                      interval:
+                        description: |-
+                          Duration is a custom type suitable for parsing duration values.
+                          It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                          the latter case, seconds are assumed.
+                        format: int64
+                        type: integer
+                      method:
+                        type: string
+                      mode:
+                        type: string
+                      path:
+                        type: string
+                      port:
+                        type: integer
+                      scheme:
+                        type: string
+                      status:
+                        type: integer
+                      timeout:
+                        description: |-
+                          Duration is a custom type suitable for parsing duration values.
+                          It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                          the latter case, seconds are assumed.
+                        format: int64
+                        type: integer
+                    required:
+                    - followRedirects
+                    type: object
                   kind:
                     description: Kind defines the kind of the Service.
                     enum:
@@ -66,6 +106,46 @@ spec:
                     items:
                       description: MirrorService holds the mirror configuration.
                       properties:
+                        healthCheck:
+                          description: Healthcheck defines health checks for the service.
+                          properties:
+                            followRedirects:
+                              type: boolean
+                            headers:
+                              additionalProperties:
+                                type: string
+                              type: object
+                            hostname:
+                              type: string
+                            interval:
+                              description: |-
+                                Duration is a custom type suitable for parsing duration values.
+                                It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                                the latter case, seconds are assumed.
+                              format: int64
+                              type: integer
+                            method:
+                              type: string
+                            mode:
+                              type: string
+                            path:
+                              type: string
+                            port:
+                              type: integer
+                            scheme:
+                              type: string
+                            status:
+                              type: integer
+                            timeout:
+                              description: |-
+                                Duration is a custom type suitable for parsing duration values.
+                                It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                                the latter case, seconds are assumed.
+                              format: int64
+                              type: integer
+                          required:
+                          - followRedirects
+                          type: object
                         kind:
                           description: Kind defines the kind of the Service.
                           enum:
@@ -300,6 +380,46 @@ spec:
                       description: Service defines an upstream HTTP service to proxy
                         traffic to.
                       properties:
+                        healthCheck:
+                          description: Healthcheck defines health checks for the service.
+                          properties:
+                            followRedirects:
+                              type: boolean
+                            headers:
+                              additionalProperties:
+                                type: string
+                              type: object
+                            hostname:
+                              type: string
+                            interval:
+                              description: |-
+                                Duration is a custom type suitable for parsing duration values.
+                                It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                                the latter case, seconds are assumed.
+                              format: int64
+                              type: integer
+                            method:
+                              type: string
+                            mode:
+                              type: string
+                            path:
+                              type: string
+                            port:
+                              type: integer
+                            scheme:
+                              type: string
+                            status:
+                              type: integer
+                            timeout:
+                              description: |-
+                                Duration is a custom type suitable for parsing duration values.
+                                It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                                the latter case, seconds are assumed.
+                              format: int64
+                              type: integer
+                          required:
+                          - followRedirects
+                          type: object
                         kind:
                           description: Kind defines the kind of the Service.
                           enum:
diff --git a/docs/content/routing/providers/kubernetes-crd.md b/docs/content/routing/providers/kubernetes-crd.md
index 2d325d2044..950053a14a 100644
--- a/docs/content/routing/providers/kubernetes-crd.md
+++ b/docs/content/routing/providers/kubernetes-crd.md
@@ -342,6 +342,9 @@ Register the `IngressRoute` [kind](../../reference/dynamic-configuration/kuberne
             flushInterval: 1ms
           scheme: https
           serversTransport: transport   # [10]
+          healthCheck:                  # [11]
+            path: /health
+            interval: 15s
           sticky:
             cookie:
               httpOnly: true
@@ -351,17 +354,17 @@ Register the `IngressRoute` [kind](../../reference/dynamic-configuration/kuberne
               maxAge: 42  
           strategy: RoundRobin
           weight: 10
-          nativeLB: true                # [11]
-          nodePortLB: true              # [12]
-      tls:                              # [13]
-        secretName: supersecret         # [14]
-        options:                        # [15]
-          name: opt                     # [16]
-          namespace: default            # [17]
-        certResolver: foo               # [18]
-        domains:                        # [19]
-        - main: example.net             # [20]
-          sans:                         # [21]
+          nativeLB: true                # [12]
+          nodePortLB: true              # [13]
+      tls:                              # [14]
+        secretName: supersecret         # [15]
+        options:                        # [16]
+          name: opt                     # [17]
+          namespace: default            # [18]
+        certResolver: foo               # [19]
+        domains:                        # [20]
+        - main: example.net             # [21]
+          sans:                         # [22]
           - a.example.net
           - b.example.net
     ```
@@ -378,17 +381,18 @@ Register the `IngressRoute` [kind](../../reference/dynamic-configuration/kuberne
 | [8]  | `routes[n].services`           | List of any combination of [TraefikService](#kind-traefikservice) and reference to a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) (See below for `ExternalName Service` setup)                                                                     |
 | [9]  | `services[n].port`             | Defines the port of a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/). This can be a reference to a named port.                                                                                                                                       |
 | [10] | `services[n].serversTransport` | Defines the reference to a [ServersTransport](#kind-serverstransport). The ServersTransport namespace is assumed to be the [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) namespace (see [ServersTransport reference](#serverstransport-reference)). |
-| [11] | `services[n].nativeLB`         | Controls, when creating the load-balancer, whether the LB's children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP.                                                                                                                                     |
-| [12] | `services[n].nodePortLB`       | Controls, when creating the load-balancer, whether the LB's children are directly the nodes internal IPs using the nodePort when the service type is NodePort.                                                                                                                               |
-| [13] | `tls`                          | Defines [TLS](../routers/index.md#tls) certificate configuration                                                                                                                                                                                                                             |
-| [14] | `tls.secretName`               | Defines the [secret](https://kubernetes.io/docs/concepts/configuration/secret/) name used to store the certificate (in the `IngressRoute` namespace)                                                                                                                                         |
-| [15] | `tls.options`                  | Defines the reference to a [TLSOption](#kind-tlsoption)                                                                                                                                                                                                                                      |
-| [16] | `options.name`                 | Defines the [TLSOption](#kind-tlsoption) name                                                                                                                                                                                                                                                |
-| [17] | `options.namespace`            | Defines the [TLSOption](#kind-tlsoption) namespace                                                                                                                                                                                                                                           |
-| [18] | `tls.certResolver`             | Defines the reference to a [CertResolver](../routers/index.md#certresolver)                                                                                                                                                                                                                  |
-| [19] | `tls.domains`                  | List of [domains](../routers/index.md#domains)                                                                                                                                                                                                                                               |
-| [20] | `domains[n].main`              | Defines the main domain name                                                                                                                                                                                                                                                                 |
-| [21] | `domains[n].sans`              | List of SANs (alternative domains)                                                                                                                                                                                                                                                           |
+| [11] | `services[n].healthCheck`      | Defines the HealthCheck when service references a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) of type ExternalName.                                                                                                                                |
+| [12] | `services[n].nativeLB`         | Controls, when creating the load-balancer, whether the LB's children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP.                                                                                                                                     |
+| [13] | `services[n].nodePortLB`       | Controls, when creating the load-balancer, whether the LB's children are directly the nodes internal IPs using the nodePort when the service type is NodePort.                                                                                                                               |
+| [14] | `tls`                          | Defines [TLS](../routers/index.md#tls) certificate configuration                                                                                                                                                                                                                             |
+| [15] | `tls.secretName`               | Defines the [secret](https://kubernetes.io/docs/concepts/configuration/secret/) name used to store the certificate (in the `IngressRoute` namespace)                                                                                                                                         |
+| [16] | `tls.options`                  | Defines the reference to a [TLSOption](#kind-tlsoption)                                                                                                                                                                                                                                      |
+| [17] | `options.name`                 | Defines the [TLSOption](#kind-tlsoption) name                                                                                                                                                                                                                                                |
+| [18] | `options.namespace`            | Defines the [TLSOption](#kind-tlsoption) namespace                                                                                                                                                                                                                                           |
+| [19] | `tls.certResolver`             | Defines the reference to a [CertResolver](../routers/index.md#certresolver)                                                                                                                                                                                                                  |
+| [20] | `tls.domains`                  | List of [domains](../routers/index.md#domains)                                                                                                                                                                                                                                               |
+| [21] | `domains[n].main`              | Defines the main domain name                                                                                                                                                                                                                                                                 |
+| [22] | `domains[n].sans`              | List of SANs (alternative domains)                                                                                                                                                                                                                                                           |
 
 ??? example "Declaring an IngressRoute"
 
diff --git a/integration/fixtures/k8s/01-traefik-crd.yml b/integration/fixtures/k8s/01-traefik-crd.yml
index 93f14adcfa..17f1a57e9a 100644
--- a/integration/fixtures/k8s/01-traefik-crd.yml
+++ b/integration/fixtures/k8s/01-traefik-crd.yml
@@ -98,6 +98,47 @@ spec:
                         description: Service defines an upstream HTTP service to proxy
                           traffic to.
                         properties:
+                          healthCheck:
+                            description: Healthcheck defines health checks for the
+                              service.
+                            properties:
+                              followRedirects:
+                                type: boolean
+                              headers:
+                                additionalProperties:
+                                  type: string
+                                type: object
+                              hostname:
+                                type: string
+                              interval:
+                                description: |-
+                                  Duration is a custom type suitable for parsing duration values.
+                                  It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                                  the latter case, seconds are assumed.
+                                format: int64
+                                type: integer
+                              method:
+                                type: string
+                              mode:
+                                type: string
+                              path:
+                                type: string
+                              port:
+                                type: integer
+                              scheme:
+                                type: string
+                              status:
+                                type: integer
+                              timeout:
+                                description: |-
+                                  Duration is a custom type suitable for parsing duration values.
+                                  It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                                  the latter case, seconds are assumed.
+                                format: int64
+                                type: integer
+                            required:
+                            - followRedirects
+                            type: object
                           kind:
                             description: Kind defines the kind of the Service.
                             enum:
@@ -919,6 +960,46 @@ spec:
                       Service defines the reference to a Kubernetes Service that will serve the error page.
                       More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/errorpages/#service
                     properties:
+                      healthCheck:
+                        description: Healthcheck defines health checks for the service.
+                        properties:
+                          followRedirects:
+                            type: boolean
+                          headers:
+                            additionalProperties:
+                              type: string
+                            type: object
+                          hostname:
+                            type: string
+                          interval:
+                            description: |-
+                              Duration is a custom type suitable for parsing duration values.
+                              It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                              the latter case, seconds are assumed.
+                            format: int64
+                            type: integer
+                          method:
+                            type: string
+                          mode:
+                            type: string
+                          path:
+                            type: string
+                          port:
+                            type: integer
+                          scheme:
+                            type: string
+                          status:
+                            type: integer
+                          timeout:
+                            description: |-
+                              Duration is a custom type suitable for parsing duration values.
+                              It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                              the latter case, seconds are assumed.
+                            format: int64
+                            type: integer
+                        required:
+                        - followRedirects
+                        type: object
                       kind:
                         description: Kind defines the kind of the Service.
                         enum:
@@ -2295,6 +2376,46 @@ spec:
               mirroring:
                 description: Mirroring defines the Mirroring service configuration.
                 properties:
+                  healthCheck:
+                    description: Healthcheck defines health checks for the service.
+                    properties:
+                      followRedirects:
+                        type: boolean
+                      headers:
+                        additionalProperties:
+                          type: string
+                        type: object
+                      hostname:
+                        type: string
+                      interval:
+                        description: |-
+                          Duration is a custom type suitable for parsing duration values.
+                          It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                          the latter case, seconds are assumed.
+                        format: int64
+                        type: integer
+                      method:
+                        type: string
+                      mode:
+                        type: string
+                      path:
+                        type: string
+                      port:
+                        type: integer
+                      scheme:
+                        type: string
+                      status:
+                        type: integer
+                      timeout:
+                        description: |-
+                          Duration is a custom type suitable for parsing duration values.
+                          It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                          the latter case, seconds are assumed.
+                        format: int64
+                        type: integer
+                    required:
+                    - followRedirects
+                    type: object
                   kind:
                     description: Kind defines the kind of the Service.
                     enum:
@@ -2314,6 +2435,46 @@ spec:
                     items:
                       description: MirrorService holds the mirror configuration.
                       properties:
+                        healthCheck:
+                          description: Healthcheck defines health checks for the service.
+                          properties:
+                            followRedirects:
+                              type: boolean
+                            headers:
+                              additionalProperties:
+                                type: string
+                              type: object
+                            hostname:
+                              type: string
+                            interval:
+                              description: |-
+                                Duration is a custom type suitable for parsing duration values.
+                                It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                                the latter case, seconds are assumed.
+                              format: int64
+                              type: integer
+                            method:
+                              type: string
+                            mode:
+                              type: string
+                            path:
+                              type: string
+                            port:
+                              type: integer
+                            scheme:
+                              type: string
+                            status:
+                              type: integer
+                            timeout:
+                              description: |-
+                                Duration is a custom type suitable for parsing duration values.
+                                It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                                the latter case, seconds are assumed.
+                              format: int64
+                              type: integer
+                          required:
+                          - followRedirects
+                          type: object
                         kind:
                           description: Kind defines the kind of the Service.
                           enum:
@@ -2548,6 +2709,46 @@ spec:
                       description: Service defines an upstream HTTP service to proxy
                         traffic to.
                       properties:
+                        healthCheck:
+                          description: Healthcheck defines health checks for the service.
+                          properties:
+                            followRedirects:
+                              type: boolean
+                            headers:
+                              additionalProperties:
+                                type: string
+                              type: object
+                            hostname:
+                              type: string
+                            interval:
+                              description: |-
+                                Duration is a custom type suitable for parsing duration values.
+                                It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                                the latter case, seconds are assumed.
+                              format: int64
+                              type: integer
+                            method:
+                              type: string
+                            mode:
+                              type: string
+                            path:
+                              type: string
+                            port:
+                              type: integer
+                            scheme:
+                              type: string
+                            status:
+                              type: integer
+                            timeout:
+                              description: |-
+                                Duration is a custom type suitable for parsing duration values.
+                                It supports `time.ParseDuration`-compatible values and suffix-less digits; in
+                                the latter case, seconds are assumed.
+                              format: int64
+                              type: integer
+                          required:
+                          - followRedirects
+                          type: object
                         kind:
                           description: Kind defines the kind of the Service.
                           enum:
diff --git a/pkg/provider/kubernetes/crd/fixtures/with_one_external_service_and_health_check.yml b/pkg/provider/kubernetes/crd/fixtures/with_one_external_service_and_health_check.yml
new file mode 100644
index 0000000000..b0a56d1d18
--- /dev/null
+++ b/pkg/provider/kubernetes/crd/fixtures/with_one_external_service_and_health_check.yml
@@ -0,0 +1,22 @@
+---
+apiVersion: traefik.io/v1alpha1
+kind: IngressRoute
+metadata:
+  name: test.route
+  namespace: default
+
+spec:
+  entryPoints:
+    - foo
+
+  routes:
+  - match: Host(`foo.com`) && PathPrefix(`/foo`)
+    kind: Rule
+    priority: 12
+
+    services:
+    - name: external-svc
+      port: 443
+      healthCheck:
+        path: /health
+        interval: 15s
\ No newline at end of file
diff --git a/pkg/provider/kubernetes/crd/fixtures/with_one_external_svc_and_regular_svc_health_check.yml b/pkg/provider/kubernetes/crd/fixtures/with_one_external_svc_and_regular_svc_health_check.yml
new file mode 100644
index 0000000000..194d04c399
--- /dev/null
+++ b/pkg/provider/kubernetes/crd/fixtures/with_one_external_svc_and_regular_svc_health_check.yml
@@ -0,0 +1,27 @@
+---
+apiVersion: traefik.io/v1alpha1
+kind: IngressRoute
+metadata:
+  name: test.route
+  namespace: default
+
+spec:
+  entryPoints:
+    - foo
+
+  routes:
+  - match: Host(`foo.com`) && PathPrefix(`/foo`)
+    kind: Rule
+    priority: 12
+
+    services:
+    - name: external-svc
+      port: 443
+      healthCheck:
+        path: /health1
+        interval: 15s
+    - name: whoami2
+      port: 443
+      healthCheck:
+        path: /health3
+        interval: 30s
\ No newline at end of file
diff --git a/pkg/provider/kubernetes/crd/fixtures/with_two_external_services_and_health_check.yml b/pkg/provider/kubernetes/crd/fixtures/with_two_external_services_and_health_check.yml
new file mode 100644
index 0000000000..10bdf4ee03
--- /dev/null
+++ b/pkg/provider/kubernetes/crd/fixtures/with_two_external_services_and_health_check.yml
@@ -0,0 +1,27 @@
+---
+apiVersion: traefik.io/v1alpha1
+kind: IngressRoute
+metadata:
+  name: test.route
+  namespace: default
+
+spec:
+  entryPoints:
+    - foo
+
+  routes:
+  - match: Host(`foo.com`) && PathPrefix(`/foo`)
+    kind: Rule
+    priority: 12
+
+    services:
+    - name: external-svc
+      port: 443
+      healthCheck:
+        path: /health1
+        interval: 15s
+    - name: external-svc-with-https
+      port: 443
+      healthCheck:
+        path: /health2
+        interval: 20s
\ No newline at end of file
diff --git a/pkg/provider/kubernetes/crd/kubernetes_http.go b/pkg/provider/kubernetes/crd/kubernetes_http.go
index 760efb1a89..45018f9480 100644
--- a/pkg/provider/kubernetes/crd/kubernetes_http.go
+++ b/pkg/provider/kubernetes/crd/kubernetes_http.go
@@ -305,6 +305,7 @@ func (c configBuilder) buildServersLB(namespace string, svc traefikv1alpha1.Load
 	lb := &dynamic.ServersLoadBalancer{}
 	lb.SetDefaults()
 	lb.Servers = servers
+	lb.HealthCheck = svc.HealthCheck
 
 	conf := svc
 	lb.PassHostHeader = conf.PassHostHeader
@@ -380,6 +381,10 @@ func (c configBuilder) loadServers(parentNamespace string, svc traefikv1alpha1.L
 	}
 
 	var servers []dynamic.Server
+	if service.Spec.Type != corev1.ServiceTypeExternalName && svc.HealthCheck != nil {
+		return nil, fmt.Errorf("HealthCheck allowed only for ExternalName services: %s/%s", namespace, sanitizedName)
+	}
+
 	if service.Spec.Type == corev1.ServiceTypeExternalName {
 		if !c.allowExternalNameServices {
 			return nil, fmt.Errorf("externalName services not allowed: %s/%s", namespace, sanitizedName)
diff --git a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/ingressroute.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/ingressroute.go
index 33fc9c6879..89189e6113 100644
--- a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/ingressroute.go
+++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/ingressroute.go
@@ -131,6 +131,8 @@ type LoadBalancerSpec struct {
 	// It allows services to be reachable when Traefik runs externally from the Kubernetes cluster but within the same network of the nodes.
 	// By default, NodePortLB is false.
 	NodePortLB bool `json:"nodePortLB,omitempty"`
+	// Healthcheck defines health checks for the service.
+	HealthCheck *dynamic.ServerHealthCheck `json:"healthCheck,omitempty"`
 }
 
 type ResponseForwarding struct {
diff --git a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/zz_generated.deepcopy.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/zz_generated.deepcopy.go
index a17ff54840..a4d9c90744 100644
--- a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/zz_generated.deepcopy.go
@@ -582,6 +582,11 @@ func (in *LoadBalancerSpec) DeepCopyInto(out *LoadBalancerSpec) {
 		*out = new(bool)
 		**out = **in
 	}
+	if in.HealthCheck != nil {
+		in, out := &in.HealthCheck, &out.HealthCheck
+		*out = new(dynamic.ServerHealthCheck)
+		(*in).DeepCopyInto(*out)
+	}
 	return
 }
 


Test patch:
diff --git a/pkg/provider/kubernetes/crd/kubernetes_test.go b/pkg/provider/kubernetes/crd/kubernetes_test.go
index ce7cc9cb45..c224b0c3ef 100644
--- a/pkg/provider/kubernetes/crd/kubernetes_test.go
+++ b/pkg/provider/kubernetes/crd/kubernetes_test.go
@@ -2432,6 +2432,174 @@ func TestLoadIngressRoutes(t *testing.T) {
 				},
 			},
 		},
+		{
+			desc:  "with one external service and health check",
+			paths: []string{"services.yml", "with_one_external_service_and_health_check.yml"},
+			expected: &dynamic.Configuration{
+				UDP: &dynamic.UDPConfiguration{
+					Routers:  map[string]*dynamic.UDPRouter{},
+					Services: map[string]*dynamic.UDPService{},
+				},
+				TCP: &dynamic.TCPConfiguration{
+					Routers:           map[string]*dynamic.TCPRouter{},
+					Middlewares:       map[string]*dynamic.TCPMiddleware{},
+					Services:          map[string]*dynamic.TCPService{},
+					ServersTransports: map[string]*dynamic.TCPServersTransport{},
+				},
+				HTTP: &dynamic.HTTPConfiguration{
+					Routers: map[string]*dynamic.Router{
+						"default-test-route-77c62dfe9517144aeeaa": {
+							EntryPoints: []string{"foo"},
+							Service:     "default-test-route-77c62dfe9517144aeeaa",
+							Rule:        "Host(`foo.com`) && PathPrefix(`/foo`)",
+							Priority:    12,
+						},
+					},
+					Middlewares: map[string]*dynamic.Middleware{},
+					Services: map[string]*dynamic.Service{
+						"default-test-route-77c62dfe9517144aeeaa": {
+							LoadBalancer: &dynamic.ServersLoadBalancer{
+								Servers: []dynamic.Server{
+									{
+										URL: "https://external.domain:443",
+									},
+								},
+								PassHostHeader: Bool(true),
+								ResponseForwarding: &dynamic.ResponseForwarding{
+									FlushInterval: ptypes.Duration(100 * time.Millisecond),
+								},
+								HealthCheck: &dynamic.ServerHealthCheck{
+									Path:     "/health",
+									Interval: 15000000000,
+								},
+							},
+						},
+					},
+					ServersTransports: map[string]*dynamic.ServersTransport{},
+				},
+				TLS: &dynamic.TLSConfiguration{},
+			},
+		},
+		{
+			desc:  "with two external services and health check",
+			paths: []string{"services.yml", "with_two_external_services_and_health_check.yml"},
+			expected: &dynamic.Configuration{
+				UDP: &dynamic.UDPConfiguration{
+					Routers:  map[string]*dynamic.UDPRouter{},
+					Services: map[string]*dynamic.UDPService{},
+				},
+				TCP: &dynamic.TCPConfiguration{
+					Routers:           map[string]*dynamic.TCPRouter{},
+					Middlewares:       map[string]*dynamic.TCPMiddleware{},
+					Services:          map[string]*dynamic.TCPService{},
+					ServersTransports: map[string]*dynamic.TCPServersTransport{},
+				},
+				HTTP: &dynamic.HTTPConfiguration{
+					Routers: map[string]*dynamic.Router{
+						"default-test-route-77c62dfe9517144aeeaa": {
+							EntryPoints: []string{"foo"},
+							Service:     "default-test-route-77c62dfe9517144aeeaa",
+							Rule:        "Host(`foo.com`) && PathPrefix(`/foo`)",
+							Priority:    12,
+						},
+					},
+					Middlewares: map[string]*dynamic.Middleware{},
+					Services: map[string]*dynamic.Service{
+						"default-test-route-77c62dfe9517144aeeaa": {
+							Weighted: &dynamic.WeightedRoundRobin{
+								Services: []dynamic.WRRService{
+									{
+										Name:   "default-external-svc-443",
+										Weight: func(i int) *int { return &i }(1),
+									},
+									{
+										Name:   "default-external-svc-with-https-443",
+										Weight: func(i int) *int { return &i }(1),
+									},
+								},
+							},
+						},
+						"default-external-svc-443": {
+							LoadBalancer: &dynamic.ServersLoadBalancer{
+								Servers: []dynamic.Server{
+									{
+										URL: "https://external.domain:443",
+									},
+								},
+								PassHostHeader: Bool(true),
+								ResponseForwarding: &dynamic.ResponseForwarding{
+									FlushInterval: ptypes.Duration(100 * time.Millisecond),
+								},
+								HealthCheck: &dynamic.ServerHealthCheck{
+									Path:     "/health1",
+									Interval: 15000000000,
+								},
+							},
+						},
+						"default-external-svc-with-https-443": {
+							LoadBalancer: &dynamic.ServersLoadBalancer{
+								Servers: []dynamic.Server{
+									{
+										URL: "https://external.domain:443",
+									},
+								},
+								PassHostHeader: Bool(true),
+								ResponseForwarding: &dynamic.ResponseForwarding{
+									FlushInterval: ptypes.Duration(100 * time.Millisecond),
+								},
+								HealthCheck: &dynamic.ServerHealthCheck{
+									Path:     "/health2",
+									Interval: 20000000000,
+								},
+							},
+						},
+					},
+					ServersTransports: map[string]*dynamic.ServersTransport{},
+				},
+				TLS: &dynamic.TLSConfiguration{},
+			},
+		},
+		{
+			desc:  "with one external service and one regular service and health check",
+			paths: []string{"services.yml", "with_one_external_svc_and_regular_svc_health_check.yml"},
+			expected: &dynamic.Configuration{
+				UDP: &dynamic.UDPConfiguration{
+					Routers:  map[string]*dynamic.UDPRouter{},
+					Services: map[string]*dynamic.UDPService{},
+				},
+				TCP: &dynamic.TCPConfiguration{
+					Routers:           map[string]*dynamic.TCPRouter{},
+					Middlewares:       map[string]*dynamic.TCPMiddleware{},
+					Services:          map[string]*dynamic.TCPService{},
+					ServersTransports: map[string]*dynamic.TCPServersTransport{},
+				},
+				HTTP: &dynamic.HTTPConfiguration{
+					Routers:     map[string]*dynamic.Router{},
+					Middlewares: map[string]*dynamic.Middleware{},
+					Services: map[string]*dynamic.Service{
+						"default-external-svc-443": {
+							LoadBalancer: &dynamic.ServersLoadBalancer{
+								Servers: []dynamic.Server{
+									{
+										URL: "https://external.domain:443",
+									},
+								},
+								PassHostHeader: Bool(true),
+								ResponseForwarding: &dynamic.ResponseForwarding{
+									FlushInterval: ptypes.Duration(100 * time.Millisecond),
+								},
+								HealthCheck: &dynamic.ServerHealthCheck{
+									Path:     "/health1",
+									Interval: 15000000000,
+								},
+							},
+						},
+					},
+					ServersTransports: map[string]*dynamic.ServersTransport{},
+				},
+				TLS: &dynamic.TLSConfiguration{},
+			},
+		},
 		{
 			desc:                "services lb, servers lb, and mirror service, all in a wrr with different namespaces",
 			allowCrossNamespace: true,