---
name: openshift-ts-ingress-debug-roks4
title: Debugging Ingress
description: Start by checking for errors in your app deployment and the Ingress resource deployment. Error messages in your deployments can help you find the root causes for failures and further debug your Ingress setup in the next sections.
last-updated: 2026-08-12
---

> ## Documentation Index
> The table of contents for this documentation set is at https://cloud.ibm.com/docs/openshift?format=markdown
> The index for all IBM Cloud docs is at: https://cloud.ibm.com/docs/llms.txt
> Use these files to discover more information as needed.

# Debugging Ingress
{: #ingress-debug-roks4}
{: troubleshoot}
{: support}

[Virtual Private Cloud]{: tag-vpc} [Classic infrastructure]{: tag-classic-inf}


You exposed your app by creating an Ingress resource for your app in your cluster. However, when you try to connect to your app through the Ingress subdomain or the IP address of the Ingress controller, the connection fails or times out.
{: tsSymptoms}


The steps in the following sections can help you debug your Ingress setup.
{: tsResolve}

Before you begin, ensure you have the following [IBM Cloud IAM access policies](https://cloud.ibm.com/docs/openshift?topic=openshift-iam-platform-access-roles&format=markdown) for IBM Cloud Kubernetes Service:
    - **Editor** or **Administrator** platform access role for the cluster
    - **Writer** or **Manager** service access role

Seeing an **Application is not available** page when you try to access your app's subdomain? [Check your app deployment, Ingress and Route resources configuration](#app-debug-ingress-43). Seeing a **Connection timeout** page? [Check the health of the Ingress controller pods](#errors-43).
{: tip}

## Step 1: Check your app deployment, Ingress and Route resources configuration
{: #app-debug-ingress-43}

Start by checking for errors in your app deployment and the Ingress resource deployment. Error messages in your deployments can help you find the root causes for failures and further debug your Ingress setup in the next sections.
{: shortdesc}

1. Before you debug Ingress, first check out [Debugging app deployments](https://cloud.ibm.com/docs/openshift?topic=openshift-debug_apps&format=markdown). Ingress issues are often caused by underlying issues in your app deployment or in the `ClusterIP` service that exposes your app. For example, your app label and service selector might not match, or your app and service target ports might not match.

2. Check your Ingress resource deployment and look for warnings or error messages.
    ```sh
    oc describe ingress <ingress_resource_name>
    ```
    {: pre}

    In the **Events** section of the output, you might see warning messages about invalid values in your Ingress resource or in certain annotations that you used. For annotations, note that the IBM Cloud Kubernetes Service annotations (`ingress.bluemix.net/<annotation>`) and Ingress-NGINX annotations (`nginx.ingress.kubernetes.io/<annotation>`) are not supported for the Ingress controller or the Ingress resource in Red Hat OpenShift version 4. If you want to customize routing rules for apps in a cluster that runs Red Hat OpenShift version 4, you can use [route-specific HAProxy annotations](https://docs.redhat.com/en/documentation/openshift_container_platform/4.21/html/ingress_and_load_balancing/routes){: external}, which are in the format `haproxy.router.openshift.io/<annotation>` or `router.openshift.io/<annotation>`.

    ```sh
    NAME:             myingress
    Namespace:        default
    Address:          169.xx.xxx.xxx,169.xx.xxx.xxx
    Default backend:  default-http-backend:80 (<none>)
    Rules:
        Host                                             Path  Backends
        ----                                             ----  --------
        mycluster-<hash>-0000.us-south.containers.appdomain.cloud
        /tea      myservice1:80 (<none>)
        /coffee   myservice2:80 (<none>)
    Annotations:  <none>
    Events:       <none>
    ```
    {: screen}

3. Check your Route resource deployment and look for warnings or error messages.
    ```sh
    oc describe route <myroute>
    ```
    {: pre}

    In the **Status** and **Events** sections of the output, you might see warning messages about invalid values in your Route resource or in certain annotations that you used.

    ```sh
    Name:         myroute
    Namespace:    default
    Labels:       <none>
    Annotations:  <none>
    API Version:  route.openshift.io/v1
    Kind:         Route
    Metadata:
      Creation Timestamp:  2026-07-01T10:18:43Z
      Generation:          1
      Owner References:
        API Version:     networking.k8s.io/v1
        Controller:      true
        Kind:            Ingress
        Name:            coffee-ingress
        UID:             e7a18dd4-402d-461c-a41f-c4750b6d2032
      Resource Version:  178601
      UID:               17c623e6-e9ef-4179-a3ad-af8ea311f2e5
    Spec:
      Host:  mycluster-<hash>-0000.us-south.containers.appdomain.cloud
      Path:  /
      Port:
        Target Port:  http
      Tls:
        Certificate:  ...
        Insecure Edge Termination Policy:  Redirect
        Key: ...
        Termination:  edge
      To:
        Kind:           Service
        Name:           myservice1
        Weight:         100
      Wildcard Policy:  None
    Status:
      Ingress:
        Conditions:
          Last Transition Time:     2026-07-01T10:18:43Z
          Status:                   True
          Type:                     Admitted
        Host:                       mycluster-<hash>-0000.us-south.containers.appdomain.cloud
        Router Canonical Hostname:  router-default.mycluster-<hash>-0000.us-south.containers.appdomain.cloud
        Router Name:                default
        Wildcard Policy:            None
    Events:  <none>
    ```
    {: screen}

4. Check the cluster level events for warnings or error messages.
    ```sh
    oc get events
    ```
    {: pre}

    In some cases warning or error events related to Ingress resources are emitted on the cluster level. Keep in mind that Events are scoped to namespace.
    ```sh
    LAST SEEN   TYPE      REASON                          OBJECT             MESSAGE
    2m40s       Warning   IncompleteIngressToRouteRules   ingress/myingress  Incomplete ingress to route rules detected: Invalid or missing TLS secret for rule host "mycluster-<hash>-0000.us-south.containers.appdomain.cloud" at index 0, path index 0
    ```
    {: screen}

5. Check the Ingress or Route resource configuration file.
    ```sh
    oc get ingress -o yaml
    ```
    {: pre}

    1. Ensure that you define a host in only one Ingress resource. If one host is defined in multiple Ingress resources, the Ingress controller might not forward traffic properly and you might experience errors.

    2. Check that the subdomain and TLS certificate are correct. To find the IBM provided Ingress subdomain and TLS certificate, run `ibmcloud oc cluster get --cluster <cluster_name_or_ID>`.

    3. Make sure that your app listens on the same path that is configured in the **path** section of your Ingress.

    4. Edit your resource configuration YAML as needed. When you close the editor, your changes are saved and automatically applied.
        ```sh
        oc edit ingress <myingressresource>
        ```
        {: pre}
        
6. Check to see if you reached the maximum number of VPC load balancers permitted per account. Check the [VPC quotas documentation](https://cloud.ibm.com/docs/vpc?topic=vpc-quotas&format=markdown) for VPC resource quotas across all your VPC clusters in your VPC.

## Step 2: Check the health of the Ingress controller
{: #errors-43}

Verify that the Ingress operator and the Ingress controller are healthy. Ingress controllers are managed by the Ingress operator. The Ingress controller forwards requests to the pods for that app only according to the rules defined in the Ingress resource and implemented by the Ingress controller.
{: shortdesc}

1. Check the status of your Ingress operator by inspecting the `IngressController` custom resource. In Red Hat OpenShift on IBM Cloud, the Ingress operator is managed by the platform and its pods are not directly accessible. Instead, check the health of the operator through the `IngressController` resource status.
    1. Describe the default `IngressController` and review the **Conditions** section for any `False` or `Unknown` status entries and their messages.
        ```sh
        oc describe ingresscontroller/default -n openshift-ingress-operator
        ```
        {: pre}

    2. List all `IngressController` resources to verify that none are in a degraded state.
        ```sh
        oc get ingresscontrollers -n openshift-ingress-operator
        ```
        {: pre}

2. Check the status and logs of your Ingress controller pods.
    1. Get the Ingress controller pods that are running in your cluster.
        ```sh
        oc get pods -n openshift-ingress
        ```
        {: pre}

    2. Make sure that all `router-default` pods and pods for Ingress controllers in any other zone are running by checking the **STATUS** column. If you have a multizone cluster, note that the Ingress controller service in the first zone where you have workers nodes is always named `router-default`, and Ingress controller services in the zones that you subsequently add to your cluster have names such as `router-dal12`.

    3. If a pod does not have a `Running` status, you can delete the pod to restart it.
        ```sh
        oc delete pod <pod> -n openshift-ingress
        ```
        {: pre}

    4. Get the logs for each pod and look for error messages in the logs.
        ```sh
        oc logs <pod> -n openshift-ingress
        ```
        {: pre}

3. Check for events and errors on each Ingress controller service.
    1. List the services in the `openshift-ingress` namespace.
        ```sh
        oc get svc -n openshift-ingress
        ```
        {: pre}

        Example output for a multizone cluster with worker nodes in `dal10` and `dal13`:
        ```sh
        NAME                                         TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)                      AGE
        router-dal13                                 LoadBalancer   172.21.47.119   169.XX.XX.XX   80:32318/TCP,443:30915/TCP   26d
        router-default                               LoadBalancer   172.21.47.119   169.XX.XX.XX   80:32637/TCP,443:31719/TCP   26d
        router-internal-default                      ClusterIP      172.21.51.30    <none>         80/TCP,443/TCP,1936/TCP      26d
        ```
        {: screen}

    2. Describe each Ingress controller service and check for messages in the `Events` section of the output.
        ```sh
        oc describe svc router-default -n openshift-ingress
        ```
        {: pre}

        For example, in VPC clusters, you might see an error message such as `The VPC load balancer that routes requests to this Kubernetes LoadBalancer service is offline`. For more information, see [VPC clusters: Why can't my app connect via load balancer?](https://cloud.ibm.com/docs/openshift?topic=openshift-vpc_ts_lb&format=markdown).

## Step 3: Ping the Ingress subdomain and Ingress controller public IP address
{: #ping-43}

Check the availability of the public IP addresses of the Ingress controller and verify your subdomain mappings. Additionally, ensure that the Red Hat OpenShift control plane can access your Ingress controllers to health check them.
{: shortdesc}

1. Verify that your Ingress controller services are reachable by the Ingress controller health check.

    * **Classic**: If you use Calico pre-DNAT network policies or another custom firewall to block incoming traffic to your cluster, you must allow inbound access on port 80 or 443 from the Red Hat OpenShift control plane and IBM NS1's IPv4 IP addresses to the IP addresses of your Ingress controller services so that the Red Hat OpenShift control plane can check the health of your Ingress controllers. For example, if you use Calico policies, [create a Calico pre-DNAT policy](https://cloud.ibm.com/docs/openshift?topic=openshift-policy_tutorial&format=markdown#lesson3) to allow inbound access to your Ingress controllers from [IBM NS1's source IP addresses](https://cloud.ibm.com/docs/containers?topic=containers-firewall&format=markdown#firewall-ingress-domain-monitor) that are used to check the health of your Ingress controllers on port 80 and the [control plane subnets for the region where your cluster is located](https://github.com/IBM-Cloud/kube-samples/tree/master/control-plane-ips){: external}. Continue to the next step to get the Ingress controller service IP addresses.

    * **VPC**: If you have a custom security group on the VPC LBaaS (LoadBalancer-as-a-Service) instances for the cluster ingress, ensure that the security group rules allow the necessary health-check traffic from the Kubernetes [control plane IP addresses](https://github.com/IBM-Cloud/kube-samples/tree/master/control-plane-ips){: external} to port 443.

2. Get the external IP addresses that the Ingress controller services are listening on. If you have a multizone cluster, note that the Ingress controller service in the first zone where you have workers nodes is always named `router-default`, and Ingress controller services in the zones that you subsequently add to your cluster have names such as `router-dal12`. In VPC clusters, the external IP addresses are behind a hostname that is assigned by the VPC load balancer, such as `aabb1122-us-south.lb.appdomain.cloud`.
    ```sh
    oc get svc -n openshift-ingress
    ```
    {: pre}

    Example output for a classic multizone cluster with worker nodes in `dal10` and `dal13`:
    ```sh
    NAME                                         TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)                      AGE
    router-dal13                                 LoadBalancer   172.21.47.119   169.XX.XX.XX   80:32318/TCP,443:30915/TCP   26d
    router-default                               LoadBalancer   172.21.47.119   169.XX.XX.XX   80:32637/TCP,443:31719/TCP   26d
    router-internal-default                      ClusterIP      172.21.51.30    <none>         80/TCP,443/TCP,1936/TCP      26d
    ```
    {: screen}

    If a Ingress controller has no external IP address (classic) or hostname (VPC), see [Version 4: Why doesn't the Ingress controller deploy in a zone?](https://cloud.ibm.com/docs/openshift?topic=openshift-cs_subnet_limit_43&format=markdown).
    {: note}

3. Check the health of your Ingress controller pods (classic) or hostname (VPC).
    - Classic clusters: [Check the status of your Ingress controller pods](#errors-43).
    - VPC clusters: Router services in multizone clusters are created with a `/healthz` path so that you can check the health of each service IP address. The following HTTP cURL command uses the `/healthz` path, which returns the `ok` status for a healthy IP.

    ```sh
    curl -X GET http://<router_svc_IP_or_hostname>/healthz -H "Host:router-default.<ingress_subdomain>"
    ```
    {: pre}

    If one or more of the IP addresses does not return `ok`, [check the status of your Ingress controller pods](#errors-43).

4. Get the IBM-provided Ingress subdomain.
    ```sh
    ibmcloud oc cluster get --cluster <cluster_name_or_ID> | grep Ingress
    ```
    {: pre}

    Example output

    ```sh
    Ingress Subdomain:      mycluster-<hash>-0000.us-south.containers.appdomain.cloud
    Ingress Secret:         mycluster-<hash>-0000
    ```
    {: screen}

5. Ensure that the Ingress controller IP address is registered with your cluster's IBM-provided Ingress subdomain. For example, in a multizone cluster, the public Ingress controller IP in each zone where you have worker nodes must be registered under the same subdomain.
    ```sh
    host <ingress_subdomain>
    ```
    {: pre}

    Example output

    ```sh
    mycluster-<hash>-0000.us-south.containers.appdomain.cloud has address 169.XX.XX.XXX
    mycluster-<hash>-0000.us-south.containers.appdomain.cloud has address 169.XX.XXX.XX
    ```
    {: screen}

6. If you use a custom domain, verify that you used your DNS provider to map the custom domain to the IBM-provided subdomain or the Ingress controller's public IP address.
    * **IBM-provided subdomain CNAME**: Check that your custom domain is mapped to the cluster's IBM-provided subdomain in the Canonical Name record (CNAME).
        ```sh
        host www.my-domain.com
        ```
        {: pre}

        Example output
        ```sh
        www.my-domain.com is an alias for mycluster-<hash>-0000.us-south.containers.appdomain.cloud
        mycluster-<hash>-0000.us-south.containers.appdomain.cloud has address 169.XX.XX.XXX
        mycluster-<hash>-0000.us-south.containers.appdomain.cloud has address 169.XX.XX.XXX
        ```
        {: screen}

    * **Public IP address A record**: Check that your custom domain is mapped to the Ingress controller's portable public IP address in the A record.
        ```sh
        host www.my-domain.com
        ```
        {: pre}

        Example output
        ```sh
        www.my-domain.com has address 169.XX.XX.XXX
        www.my-domain.com has address 169.XX.XX.XXX
        ```
        {: screen}