[Yandex Cloud documentation](../../index.md) > [Tutorials](../index.md) > [Container infrastructure](index.md) > Managed Service for Kubernetes > Using Cloud Marketplace products > Health checking your applications in a Managed Service for Kubernetes cluster with an Application Load Balancer ingress controller

# Health checking applications in a Yandex Managed Service for Kubernetes cluster via a Yandex Application Load Balancer

You can use an [Application Load Balancer](../../application-load-balancer/tools/k8s-ingress-controller/index.md) ingress controller to automatically health check your applications deployed in a Managed Service for Kubernetes cluster.

{% note tip %}

We recommend using the new [Yandex Cloud Gwin](../../application-load-balancer/tools/gwin/index.md) controller instead of an ALB Ingress controller and Gateway API.

{% endnote %}

An ingress controller installed in a cluster deploys an [L7 load balancer](../../application-load-balancer/concepts/application-load-balancer.md) with all the required Application Load Balancer resources based on the configuration of the [Ingress](../../managed-kubernetes/alb-ref/ingress.md) and [HttpBackendGroup](../../managed-kubernetes/alb-ref/http-backend-group.md) resources you created.

The L7 load balancer automatically health checks the application in this cluster. Depending on the results, the L7 load balancer allows or denies external traffic to the backend (the [Service](../../managed-kubernetes/alb-ref/service-for-ingress.md) resource). For more information, see [Health checks](../../application-load-balancer/concepts/backend-group.md#health-checks).

By default, the Application Load Balancer ingress controller listens for application health check requests from the L7 load balancer on TCP port `10501` and checks the health of [kube-proxy](https://kubernetes.io/docs/reference/command-line-tools-reference/kube-proxy/) pods on each cluster node. Given that kube-proxy is healthy, the process is as follows: if an application does not respond in a particular pod, Kubernetes redirects traffic to a different pod or node.

In this tutorial, you will configure your own application health checks using the [HttpBackendGroup](../../managed-kubernetes/alb-ref/http-backend-group.md) resource parameters and open a dedicated port on cluster nodes for these checks in the `NodePort` type [Service](../../managed-kubernetes/alb-ref/service-for-ingress.md) resource parameters.

You can view health check results in the [management console](https://console.yandex.cloud).

{% note info %}

You can also configure application health checks using the [ingress.alb.yc.io/health-checks](../../application-load-balancer/k8s-ref/service-for-ingress.md#annot-health-checks) annotation of the [Service](../../application-load-balancer/k8s-ref/service-for-ingress.md) resource.

{% endnote %}

To deploy an application in a Managed Service for Kubernetes cluster, configure access to it, and set up its health checks via an Application Load Balancer:

1. [Get your cloud ready](#before-begin).
1. [Create a Docker image](#docker-image).
1. [Deploy a test application](#test-app).
1. [Set up an address for the L7 load balancer](#prepare-address).
1. [Create the Ingress and HttpBackendGroup resources](#create-ingress).
1. [Check the result](#check-result).

If you no longer need the resources you created, [delete them](#clear-out).


## Required paid resources {#paid-resources}

The support cost for this solution includes:

* Fee for a DNS zone and DNS requests (see [Cloud DNS pricing](../../dns/pricing.md)).
* Fee for using the master and outgoing traffic in a Managed Service for Kubernetes cluster (see [Managed Service for Kubernetes pricing](../../managed-kubernetes/pricing.md)).
* Fee for using computing resources, OS, and storage in cluster nodes (VMs) (see [Compute Cloud pricing](../../compute/pricing.md)).
* Fee for using L7 load balancer's computing resources (see [Application Load Balancer pricing](../../application-load-balancer/pricing.md)).
* Fee for public IP addresses for cluster nodes and L7 load balancer (see [Virtual Private Cloud pricing](../../vpc/pricing.md#prices-public-ip)).
* Fee for Container Registry [storage](../../container-registry/pricing.md).


## Get your cloud ready {#before-begin}

### Set up the infrastructure {#infra}

{% list tabs group=instructions %}

- Manually {#manual}

   1. [Create security groups](../../managed-kubernetes/operations/connect/security-groups.md) for the Managed Service for Kubernetes cluster and its node groups.

      [Configure](../../application-load-balancer/tools/k8s-ingress-controller/security-groups.md) the security groups required for Application Load Balancer as well.

      The application will be available on the Managed Service for Kubernetes cluster nodes on port `30080`. Application health checks will be available on port `30081`. Make sure these ports are open for the L7 load balancer in the node group's security group. You can also [make these ports accessible from the internet](../../managed-kubernetes/operations/connect/security-groups.md#rules-nodes).

      {% note warning %}
      
      The configuration of security groups determines performance and availability of the cluster and the services and applications running in it.
      
      {% endnote %}

   1. [Create a Managed Service for Kubernetes cluster](../../managed-kubernetes/operations/kubernetes-cluster/kubernetes-cluster-create.md). When creating a cluster, specify the preconfigured security groups.
      
      For Yandex Cloud internal network usage, your cluster does not need a public IP address. To enable internet access to your cluster, assign it a public IP address.
   1. [Create a node group](../../managed-kubernetes/operations/node-group/node-group-create.md). To enable internet access for your node group (e.g., for Docker image pulls), assign it a public IP address. Specify the preconfigured security groups.
   1. [Create a registry](../../container-registry/operations/registry/registry-create.md) in Yandex Container Registry.

- Terraform {#tf}

   1. If you do not have Terraform yet, [install it](../infrastructure-management/terraform-quickstart.md#install-terraform).
   1. [Get the authentication credentials](../infrastructure-management/terraform-quickstart.md#get-credentials). You can add them to environment variables or specify them later in the provider configuration file.
   1. [Configure and initialize a provider](../infrastructure-management/terraform-quickstart.md#configure-provider). There is no need to create a provider configuration file manually, you can [download it](https://github.com/yandex-cloud-examples/yc-terraform-provider-settings/blob/main/provider.tf).
   1. Place the configuration file in a separate working directory and [specify the parameter values](../infrastructure-management/terraform-quickstart.md#configure-provider). If you did not add the authentication credentials to environment variables, specify them in the configuration file.
   1. Download the [k8s-custom-health-checks.tf](https://github.com/yandex-cloud-examples/yc-mk8s-alb-ingress-health-checks/blob/main/terraform-manifests/k8s-custom-health-checks.tf) configuration file to the same working directory.

      This file describes:

      * [Network](../../vpc/concepts/network.md#network).
      * [Subnet](../../vpc/concepts/network.md#subnet).
      * [Security groups](../../vpc/concepts/security-groups.md) for the Managed Service for Kubernetes cluster, node group, and the Application Load Balancer.
      * Service account for the Kubernetes cluster.
      * Kubernetes cluster.
      * Kubernetes node group.
      * Yandex Container Registry.

   1. In `k8s-custom-health-checks.tf`, specify the following:

      * `folder_id`: Cloud folder ID as specified in the provider settings.
      * `k8s_version`: Kubernetes version. Available versions are listed in [Release channels](../../managed-kubernetes/concepts/release-channels-and-updates.md).

   1. Make sure the Terraform configuration files are correct using this command:

      ```bash
      terraform validate
      ```

      Terraform will display any configuration errors detected in your files.

   1. Create the required infrastructure:

      1. Run this command to view the planned changes:
      
         ```bash
         terraform plan
         ```
      
         If you described the configuration correctly, the terminal will display a list of the resources to update and their parameters. This is a verification step that does not apply changes to your resources.
      
      1. If everything looks correct, apply the changes:
         1. Run this command:
      
            ```bash
            terraform apply
            ```
      
         1. Confirm updating the resources.
         1. Wait for the operation to complete.

      All the required resources will be created in the specified folder. You can check resource availability and their settings in the [management console](https://console.yandex.cloud).

{% endlist %}

{% note warning %}

Do not change or delete Virtual Private Cloud resources used by the Managed Service for Kubernetes cluster. This may cause cluster errors or make it impossible to delete later.

{% endnote %}

### Install the Application Load Balancer ingress controller {#install-alb-ingress-controller}

Use [this guide](../../managed-kubernetes/operations/applications/alb-ingress-controller.md) to install the [ALB ingress controller](https://yandex.cloud/en/marketplace/products/yc/alb-ingress-controller) in a separate `yc-alb` namespace. Later on, all the required Kubernetes resources will be created in this namespace.

### Install additional dependencies {#prepare}

1. If you do not have the Yandex Cloud CLI yet, [install and initialize it](../../cli/quickstart.md#install).

   The folder used by default is the one specified when [creating](../../cli/operations/profile/profile-create.md) the CLI profile. To change the default folder, use the `yc config set folder-id <folder_ID>` command. You can also specify a different folder for any command using `--folder-name` or `--folder-id`. If you access a resource by its name, the search will be limited to the default folder. If you access a resource by its ID, the search will be global, i.e., through all folders based on access permissions.

1. [Install kubect](https://kubernetes.io/docs/tasks/tools/install-kubectl) and [configure it to work with the new cluster](../../managed-kubernetes/operations/connect/index.md#kubectl-connect).

   If your cluster has no public IP address assigned and `kubectl` is configured via the cluster's private IP address, run `kubectl` commands on a Yandex Cloud VM residing in the same network as the cluster.

1. [Install Docker](https://docs.docker.com/get-docker/).
1. [Authenticate in Yandex Container Registry](../../container-registry/operations/authentication.md#cred-helper) using a Docker credential helper.

## Create a Docker image {#docker-image}

The source files for a Docker image reside in the [yc-mk8s-alb-ingress-health-checks](https://github.com/yandex-cloud-examples/yc-mk8s-alb-ingress-health-checks) repository.

The Docker image will be created from `app/Dockerfile` and will contain the test application code from the `app/healthchecktest.go` file. You will use this Docker image to [deploy the application in your Managed Service for Kubernetes cluster](#test-app).

The application will respond to HTTP requests as follows depending on the pod port:
* `80`: Return request path parameters in the response body, e.g., `/test-path`. This is the main application functionality that will be available via the L7 load balancer.
* `8080`: Return `OK` in the response body. This functionality will be used for application health checks.

Successful requests will return the `200 OK` HTTP code.

To create a Docker image:
1. Clone the `yc-mk8s-alb-ingress-health-checks` repository:

   ```bash
   git clone git@github.com:yandex-cloud-examples/yc-mk8s-alb-ingress-health-checks.git
   ```

1. In the terminal, go to the root of the repository directory.
1. Get the Container Registry ID. You can [get it with the list of registries](../../container-registry/operations/registry/registry-list.md#registry-list) in the folder.
1. Add the name of the Docker image to create to the environment variable:

   ```bash
   export TEST_IMG=cr.yandex/<registry_ID>/example-app1:latest
   ```

1. Build the Docker image:

   ```bash
   docker build -t ${TEST_IMG} -f ./app/Dockerfile .
   ```

   The command specifies the path for the repository root directory.

1. Push the Docker image to the registry:

   ```bash
   docker push ${TEST_IMG}
   ```

   If you fail to push the image, follow these steps:

   * Make sure you are [authenticated in Container Registry](../../container-registry/operations/authentication.md#cred-helper) using a Docker credential helper.
   * [Configure registry access](../../container-registry/operations/registry/registry-access.md): Allow your computer's IP address to push Docker images by granting the PUSH permission.

## Deploy a test application {#test-app}

Build a test application from the created Docker image and the [app/testapp.yaml](https://github.com/yandex-cloud-examples/yc-mk8s-alb-ingress-health-checks/blob/main/app/testapp.yaml) configuration file.

The file contains the description of Kubernetes resources: `Deployment` and `Service` of the `NodePort` type.

The `Service` resource contains the description of ports used to access the application on your cluster nodes:
* `spec.ports.name: http`: Port to access the main functionality of the application, `80` on the pod and `30080` on the node.
* `spec.ports.name: health`: Port for application health checks, `8080` on the pod and `30081` on the node.

To build a test application:

1. Specify the value of the `TEST_IMG` environment variable in the `spec.template.spec.containers.image` field in the `app/testapp.yaml` file. To get this value, run:

   ```bash
   printenv TEST_IMG
   ```

1. Create the application from `app/testapp.yaml`:

   ```bash
   kubectl apply -f ./app/testapp.yaml --namespace=yc-alb
   ```

   The command specifies the path for the repository root directory.

1. Make sure the pods with the application are running:

   ```bash
   kubectl get po --namespace=yc-alb
   ```

   Result:

   ```text
   NAME                               READY   STATUS    RESTARTS   AGE
   alb-demo-1-54b95979b4-***          1/1     Running   0          71s
   alb-demo-1-54b95979b4-***          1/1     Running   0          71s
   yc-alb-ingress-controller-***      1/1     Running   0          11m
   yc-alb-ingress-controller-hc-***   1/1     Running   0          11m
   ```

1. Test the application by specifying the IP address of the Managed Service for Kubernetes cluster node in the request. You can find out the IP address of the node in the [management console](https://console.yandex.cloud).

   * Main functionality:

     ```bash
     curl --include http://<node_IP_address>:30080/test-path
     ```

     Result:

     ```bash
     HTTP/1.1 200 OK
     Date: Thu, 18 Jul 2024 11:55:52 GMT
     Content-Length: 10
     Content-Type: text/plain; charset=utf-8

     /test-path%
     ```

   * Application health check:

     ```bash
     curl --include http://<node_IP_address>:30081
     ```

     Result:

     ```bash
     HTTP/1.1 200 OK
     Date: Thu, 18 Jul 2024 12:00:57 GMT
     Content-Length: 2
     Content-Type: text/plain; charset=utf-8

     OK%
     ```

## Set up an address for the L7 load balancer {#prepare-address}

This address will be used to access the application from the internet.

To set up an address for the load balancer:

{% list tabs group=instructions %}

- Manually {#manual}

   1. [Reserve a static public IP address](../../vpc/operations/get-static-ip.md) for your Application Load Balancer.

   1. [Register a public domain zone and delegate your domain](../../dns/operations/zone-create-public.md).
   
   1. To map the address to the domain, [create an A record](../../dns/operations/resource-record-create.md) for the delegated domain. Specify the reserved IP address as the record value.
   1. Make sure the A record is added:

      ```bash
      host <domain>
      ```

      Result:

      ```text
      <domain> has address <IP_address>
      ```

- Terraform {#tf}

   1. Place the [address-for-k8s-health-checks.tf](https://github.com/yandex-cloud-examples/yc-mk8s-alb-ingress-health-checks/blob/main/terraform-manifests/address-for-k8s-health-checks.tf) configuration file in the same working directory as the `k8s-custom-health-checks.tf` file.

      `address-for-k8s-health-checks.tf` describes:

      
      * [Static public IP address](../../vpc/concepts/address.md#public-addresses).
      * [Public DNS zone](../../dns/concepts/dns-zone.md#public-zones).
      * [Type A record](../../dns/concepts/resource-record.md#a) for this zone to map the reserved IP address to the delegated domain.


   1. Make sure the Terraform configuration files are correct using this command:

      ```bash
      terraform validate
      ```

      Terraform will display any configuration errors detected in your files.

   1. Create the required infrastructure:

      1. Run this command to view the planned changes:
      
         ```bash
         terraform plan
         ```
      
         If you described the configuration correctly, the terminal will display a list of the resources to update and their parameters. This is a verification step that does not apply changes to your resources.
      
      1. If everything looks correct, apply the changes:
         1. Run this command:
      
            ```bash
            terraform apply
            ```
      
         1. Confirm updating the resources.
         1. Wait for the operation to complete.

      All the required resources will be created in the specified folder. You can check resource availability and their settings in the [management console](https://console.yandex.cloud).

   1. Make sure the A record is added:

      ```bash
      host <domain>
      ```

      Result:

      ```text
      <domain> has address <IP_address>
      ```

{% endlist %}

## Create the Ingress and HttpBackendGroup resources {#create-ingress}

Based on the [Ingress](../../managed-kubernetes/alb-ref/ingress.md) and [HttpBackendGroup](../../managed-kubernetes/alb-ref/http-backend-group.md) resources, the ingress controller will deploy an [L7 load balancer](../../application-load-balancer/concepts/application-load-balancer.md) with all the required Application Load Balancer resources.

The `ingress.yaml` and `httpbackendgroup.yaml` configuration files for the specified resources are located in the [yc-mk8s-alb-ingress-health-checks](https://github.com/yandex-cloud-examples/yc-mk8s-alb-ingress-health-checks) repository.

You can specify the settings for custom application health checks in the `HttpBackendGroup` resource in the `spec.backends.healthChecks` parameter.

To create resources:

1. In the `ingress.yaml` file, specify the following values for annotations:

   * `ingress.alb.yc.io/subnets`: One or more subnets to host the Application Load Balancer.
   * `ingress.alb.yc.io/security-groups`: One or more [security groups](../../application-load-balancer/concepts/application-load-balancer.md#security-groups) for the load balancer. If you skip this parameter, the default security group will be used. At least one of the security groups must allow an outgoing TCP connection to port `10501` in the Managed Service for Kubernetes node group subnet or to its security group.
   * `ingress.alb.yc.io/external-ipv4-address`: Public access to the load balancer from the internet. Specify the previously reserved static public IP address.

1. In the same `ingress.yaml` file, specify the delegated domain in the `spec.rules.host` parameter.
1. To create the `Ingress` and `HttpBackendGroup` resources, run the following command from the root of the repository directory:

   ```bash
   kubectl apply -f ingress.yaml --namespace=yc-alb &&
   kubectl apply -f httpbackendgroup.yaml --namespace=yc-alb
   ```

1. Wait until the resources are created and the load balancer is deployed and assigned a public IP address. This may take a few minutes.

   To follow the process and make sure it is error-free, open the logs of the pod it is run in:

   1. In the [management console](https://console.yandex.cloud), navigate to the folder page.
   1. Navigate to **Managed Service for&nbsp;Kubernetes**.
   1. Click the cluster name and select **Workload** in the left-hand panel.
   1. Select the `yc-alb-ingress-controller-*` pod (not `yc-alb-ingress-controller-hc-*`) that is running the resource creation.
   1. Go to the **Logs** tab on the pod page.

      The load balancer's creation logs are generated and displayed in real time. Any errors that occur will also be logged.

   {% note warning %}
   
   Do not modify or delete the network load balancer and its child resources created using Managed Service for Kubernetes via the Yandex Cloud interfaces (the management console, Terraform, CLI, or API). This may cause incorrect operation of the cluster.
   
   {% endnote %}

## Check the result {#check-result}

1. Make sure the load balancer was created. To do this, run the following command and verify that the `ADDRESS` field in the output contains a value:

   ```bash
   kubectl get ingress alb-demo --namespace=yc-alb
   ```

   Result:

   ```bash
   NAME       CLASS    HOSTS     ADDRESS      PORTS   AGE
   alb-demo   <none>   <domain>   <IP_address>   80      15h
   ```

1. Check that the deployed application is available via the L7 load balancer:

   ```bash
   curl --include http://<domain>/test-path
   ```

   Result:

   ```bash
   HTTP/1.1 200 OK
   date: Thu, 18 Jul 2024 12:23:51 GMT
   content-length: 10
   content-type: text/plain; charset=utf-8
   server: ycalb

   /test-path%
   ```

   {% note info %}
   
   If you cannot access the resource at the specified URL, [make sure](../../managed-kubernetes/operations/connect/security-groups.md) the security groups for the Managed Service for Kubernetes cluster and its node groups are configured correctly. If a rule is missing, [add it](../../vpc/operations/security-group-add-rule.md).
   
   {% endnote %}

1. Make sure the app health checks are working correctly:

   {% list tabs group=instructions %}

   - Management console {#console}

      1. In the [management console](https://console.yandex.cloud), navigate to the folder page.
      1. Navigate to **Application Load Balancer**.
      1. Click the load balancer name and select **Health checks** in the left-hand panel.
      1. Check the target health. The `HEALTHY` status indicates the application is up and running.

   {% endlist %}

## Delete the resources you created {#clear-out}

Some resources are not free of charge. Delete the resources you no longer need to avoid paying for them:

1. [Application Load Balancer](../../application-load-balancer/operations/application-load-balancer-delete.md)
1. Application Load Balancer [HTTP router](../../application-load-balancer/operations/http-router-delete.md)
1. Application Load Balancer [backend group](../../application-load-balancer/operations/backend-group-delete.md)
1. Application Load Balancer [target group](../../application-load-balancer/operations/target-group-delete.md)
1. Managed Service for Kubernetes [node group](../../managed-kubernetes/operations/node-group/node-group-delete.md)
1. Managed Service for Kubernetes [cluster](../../managed-kubernetes/operations/kubernetes-cluster/kubernetes-cluster-delete.md)
1. [Container Registry](../../container-registry/operations/registry/registry-delete.md)
1. Cloud DNS [public domain zone](../../dns/operations/zone-delete.md)
1. Virtual Private Cloud [security groups](../../vpc/operations/security-group-delete.md)
1. Virtual Private Cloud [static public IP address](../../vpc/operations/address-delete.md)