[Yandex Cloud documentation](../../index.md) > [Yandex Managed Service for Kubernetes](../index.md) > [Tutorials](index.md) > Using Cloud Marketplace products > Configuring an L7 Application Load Balancer using an ingress controller

# Configuring a Yandex Application Load Balancer using an ingress controller

[Yandex Application Load Balancer](../../application-load-balancer/index.md) helps balance the load and distribute traffic between your applications. To use it for managing ingress traffic of applications running in a [Managed Service for Kubernetes cluster](../concepts/index.md#kubernetes-cluster), you need an [ingress controller](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/).

{% 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 %}

To set up access to the applications running in your Managed Service for Kubernetes cluster via an Application Load Balancer (L7 load balancer):

1. [Set up the Ingress resource and test applications](#create-ingress-and-apps).
1. [Optionally, configure the Ingress resource group](#configure-group).
1. [Make sure the Managed Service for Kubernetes cluster applications are accessible via Application Load Balancer](#verify-setup).

For full configuration of the resources for the Application Load Balancer ingress controller, see the following sections:

* [Ingress](../alb-ref/ingress.md): Backend traffic distribution and load balancer configuration rules.
* [HttpBackendGroup](../alb-ref/http-backend-group.md), [GrpcBackendGroup](../alb-ref/grpc-backend-group.md): Combining backends into groups.
* [IngressClass](../alb-ref/ingress-class.md): Managing multiple ingress controllers in a Kubernetes cluster.
* [Service](../alb-ref/service-for-ingress.md): Description of Kubernetes services used as backends.


## 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](../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)).
* Object Storage bucket fee covering data storage and data operations (see [Object Storage pricing](../../storage/pricing.md)).


## Getting started {#before-you-begin}

1. [Register a public domain zone and delegate your domain](../../dns/operations/zone-create-public.md).

1. If you already have a certificate for the domain zone, [add its details](../../certificate-manager/operations/import/cert-create.md) to [Yandex Certificate Manager](../../certificate-manager/index.md). If not, issue a new Let's Encrypt® certificate and [add](../../certificate-manager/operations/managed/cert-create.md) it to Certificate Manager.

1. Get the certificate ID:
   
     ```bash
     yc certificate-manager certificate list
     ```
   
     Result:
   
     ```text
     +----------------------+-----------+----------------+---------------------+----------+--------+
     |          ID          |   NAME    |    DOMAINS     |      NOT AFTER      |   TYPE   | STATUS |
     +----------------------+-----------+----------------+---------------------+----------+--------+
     | fpq8diorouhp******** | cert-test |    test.ru     | 2022-01-06 17:19:37 | IMPORTED | ISSUED |
     +----------------------+-----------+----------------+---------------------+----------+--------+
     ```

1. [Create security groups](../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.

    {% 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](../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](../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. [Install the Application Load Balancer ingress controller](../operations/applications/alb-ingress-controller.md).


1. Optionally, [install](../operations/applications/externaldns.md) ExternalDNS with Webhook Yandex Cloud DNS to automatically create a [DNS record](../../dns/concepts/resource-record.md) in [Yandex Cloud DNS](../../dns/index.md) when creating an Ingress controller.


1. [Install kubect](https://kubernetes.io/docs/tasks/tools/install-kubectl) and [configure it to work with the new cluster](../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.

## Set up the Ingress resource and test applications {#create-ingress-and-apps}

The [Ingress resource](../../application-load-balancer/k8s-ref/ingress.md) defines:

* L7 load balancer parameters set using annotations.

    {% 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 %}

* Rules for incoming traffic distribution between [Kubernetes services](../../application-load-balancer/k8s-ref/service-for-ingress.md).

    Services acting as Application Load Balancer backends may be specified in the Ingress resource either directly or as part of [HttpBackendGroup](../../application-load-balancer/k8s-ref/http-backend-group.md) or [GrpcBackendGroup](../../application-load-balancer/k8s-ref/grpc-backend-group.md) backend groups.

Create test applications and Ingress resource:

{% list tabs %}

- Ingress resource for Kubernetes services

  1. In a separate directory, create the `demo-app-1.yaml` and `demo-app-2.yaml` application configuration files:

     {% cut "demo-app-1.yaml" %}

     ```yaml
     apiVersion: v1
     kind: ConfigMap
     metadata:
       name: alb-demo-1
     data:
       nginx.conf: |
         worker_processes auto;
         events {
         }
         http {
           server {
             listen 80 ;
             location = /_healthz {
               add_header Content-Type text/plain;
               return 200 'ok';
             }
             location / {
               add_header Content-Type text/plain;
               return 200 'Index';
             }
             location = /app1 {
               add_header Content-Type text/plain;
               return 200 'This is APP#1';
             }
           }
         }
     ---
     apiVersion: apps/v1
     kind: Deployment
     metadata:
       name: alb-demo-1
       labels:
         app: alb-demo-1
         version: v1
     spec:
       replicas: 2
       selector:
         matchLabels:
           app: alb-demo-1
       strategy:
         type: RollingUpdate
         rollingUpdate:
           maxSurge: 1
           maxUnavailable: 0
       template:
         metadata:
           labels:
             app: alb-demo-1
             version: v1
         spec:
           terminationGracePeriodSeconds: 5
           volumes:
             - name: alb-demo-1
               configMap:
                 name: alb-demo-1
           containers:
             - name: alb-demo-1
               image: nginx:latest
               ports:
                 - name: http
                   containerPort: 80
               livenessProbe:
                 httpGet:
                   path: /_healthz
                   port: 80
                 initialDelaySeconds: 3
                 timeoutSeconds: 2
                 failureThreshold: 2
               volumeMounts:
                 - name: alb-demo-1
                   mountPath: /etc/nginx
                   readOnly: true
               resources:
                 limits:
                   cpu: 250m
                   memory: 128Mi
                 requests:
                   cpu: 100m
                   memory: 64Mi
     ---
     apiVersion: v1
     kind: Service
     metadata:
       name: alb-demo-1
     spec:
       selector:
         app: alb-demo-1
       type: NodePort
       ports:
         - name: http
           port: 80
           targetPort: 80
           protocol: TCP
           nodePort: 30081
     ```

     {% endcut %}

     {% cut "demo-app-2.yaml" %}

     ```yaml
     apiVersion: v1
     kind: ConfigMap
     metadata:
       name: alb-demo-2
     data:
       nginx.conf: |
         worker_processes auto;
         events {
         }
         http {
           server {
             listen 80 ;
             location = /_healthz {
               add_header Content-Type text/plain;
               return 200 'ok';
             }
             location / {
               add_header Content-Type text/plain;
               return 200 'Add app#';
             }
             location = /app2 {
               add_header Content-Type text/plain;
               return 200 'This is APP#2';
             }
           }
         }
     ---
     apiVersion: apps/v1
     kind: Deployment
     metadata:
       name: alb-demo-2
       labels:
         app: alb-demo-2
         version: v1
     spec:
       replicas: 2
       selector:
         matchLabels:
           app: alb-demo-2
       strategy:
         type: RollingUpdate
         rollingUpdate:
           maxSurge: 1
           maxUnavailable: 0
       template:
         metadata:
           labels:
             app: alb-demo-2
             version: v1
         spec:
           terminationGracePeriodSeconds: 5
           volumes:
             - name: alb-demo-2
               configMap:
                 name: alb-demo-2
           containers:
             - name: alb-demo-2
               image: nginx:latest
               ports:
                 - name: http
                   containerPort: 80
               livenessProbe:
                 httpGet:
                   path: /_healthz
                   port: 80
                 initialDelaySeconds: 3
                 timeoutSeconds: 2
                 failureThreshold: 2
               volumeMounts:
                 - name: alb-demo-2
                   mountPath: /etc/nginx
                   readOnly: true
               resources:
                 limits:
                   cpu: 250m
                   memory: 128Mi
                 requests:
                   cpu: 100m
                   memory: 64Mi
     ---
     apiVersion: v1
     kind: Service
     metadata:
       name: alb-demo-2
     spec:
       selector:
         app: alb-demo-2
       type: NodePort
       ports:
         - name: http
           port: 80
           targetPort: 80
           protocol: TCP
           nodePort: 30082
     ```

     {% endcut %}

  1. In the same directory, create a file named `ingress.yaml` and specify in it the [delegated domain name](#before-you-begin), [ID of the certificate](#before-you-begin), and settings for the Application Load Balancer:

     ```yaml
     apiVersion: networking.k8s.io/v1
     kind: Ingress
     metadata:
       name: alb-demo-tls
       annotations:
         ingress.alb.yc.io/subnets: <list_of_subnet_IDs>
         ingress.alb.yc.io/security-groups: <list_of_security_group_IDs>
         ingress.alb.yc.io/external-ipv4-address: <IP_address_assignment_method>
         ingress.alb.yc.io/group-name: my-ingress-group
     spec:
       tls:
         - hosts:
             - <domain_name>
           secretName: yc-certmgr-cert-id-<TLS_certificate_ID>
       rules:
         - host: <domain_name>
           http:
             paths:
               - path: /app1
                 pathType: Prefix
                 backend:
                   service:
                     name: alb-demo-1
                     port:
                       number: 80
               - path: /app2
                 pathType: Prefix
                 backend:
                   service:
                     name: alb-demo-2
                     port:
                       number: 80
               - pathType: Prefix
                 path: "/"
                 backend:
                   service:
                     name: alb-demo-2
                     port:
                       name: http
     ```

     Where:

     * `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. Enter the [IP address you got earlier](../../vpc/operations/get-static-ip.md) or set `auto` to get a new IP address automatically.

       If you set `auto`, deleting the load balancer from the [cloud](../../resource-manager/concepts/resources-hierarchy.md#cloud) removes its [IP address](../../vpc/concepts/address.md). To avoid this, use a reserved IP address.

     * `ingress.alb.yc.io/group-name`: Group name. Ingress resources are grouped so that a separate load balancer serves each group.

       You can use any group name instead of `my-ingress-group`. Make sure it meets the naming [requirements](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/).

     Pre-0.2.0 [ALB Ingress Controller](https://yandex.cloud/en/marketplace/products/yc/alb-ingress-controller) versions map each backend group to a distinct combination of `host`, `http.paths.path`, and `http.paths.pathType` values. ALB Ingress Controller 0.2.0 and later maps backend groups directly to the `backend.service` configuration. This may cause collisions when upgrading the controller. To avoid them, check the [upgrade restrictions](../operations/applications/upgrade-alb-ingress-controller.md) for your infrastructure.

     Optionally, specify the additional settings for the load balancer:

     {% cut "Additional settings" %}

     {% note info %}
     
     The settings listed below will only apply to the [virtual hosts](../../application-load-balancer/tools/k8s-ingress-controller/principles.md#mapping) of the Ingress resource in which the corresponding annotations are configured.
     
     They will not apply to the virtual hosts of the group's other Ingress resources.
     
     {% endnote %}

     Available settings:

     * `ingress.alb.yc.io/group-settings-name`: Name for the Ingress resource group settings to describe in the `IngressGroupSettings` optional resource. For more information, see [Configure the Ingress resource group](#configure-group).
     * `ingress.alb.yc.io/internal-ipv4-address`: Provide internal access to the load balancer. Enter the internal IP address or use `auto` to get the IP address automatically.

       {% note info %}

       You can only use one type of access to the load balancer at a time: `ingress.alb.yc.io/external-ipv4-address` or `ingress.alb.yc.io/internal-ipv4-address`.

       {% endnote %}

     * `ingress.alb.yc.io/internal-alb-subnet`: Subnet to host the load balancer. This parameter is required if you select `ingress.alb.yc.io/internal-ipv4-address`.
     * `ingress.alb.yc.io/protocol`: Protocol for connections between the load balancer and backends:
       * `http`: HTTP/1.1. This is a default value.
       * `http2`: HTTP/2.
       * `grpc`: gRPC.
     * `ingress.alb.yc.io/transport-security`: Encryption protocol for connections between the load balancer and backends.

        {% note warning %}

        For [ALB Ingress Controller](https://yandex.cloud/en/marketplace/products/yc/alb-ingress-controller) 0.2.0 and later, you can only use this annotation in the [Service](../../application-load-balancer/k8s-ref/service-for-ingress.md#metadata) object.

        Annotations specified in `Ingress` resources sharing a single service with the same backend group settings apply correctly. However, this feature is deprecated and will be discontinued.

        {% endnote %}

        The acceptable value is `tls`: TLS without certificate validation.

        If this annotation is not specified, the load balancer will connect to the backends without encryption.
     * `ingress.alb.yc.io/prefix-rewrite`: Replace the path with the specified value.
     * `ingress.alb.yc.io/upgrade-types`: Valid values of the `Upgrade` HTTP header, e.g., `websocket`.
     * `ingress.alb.yc.io/request-timeout`: Maximum connection request timeout.
     * `ingress.alb.yc.io/idle-timeout`: Maximum connection idle time.

       Make sure to provide the `request-timeout` and `idle-timeout` values with units of measurement, e.g., `300ms` or `1.5h`. Acceptable units of measurement include:
       * `ns`, nanoseconds
       * `us`, microseconds
       * `ms`, milliseconds
       * `s`, seconds
       * `m`, minutes
       * `h`, hours

     * `ingress.alb.yc.io/security-profile-id`: Support for [Yandex Smart Web Security](../../smartwebsecurity/concepts/index.md) that ensures protection against DDoS attacks and bots, enables [WAF](../../smartwebsecurity/concepts/waf.md) and [limits the load](../../smartwebsecurity/concepts/arl.md) on the protected resource.

       To enable support for Yandex Smart Web Security, specify the previously created Smart Web Security [profile](../../smartwebsecurity/concepts/profiles.md) in the Ingress annotation:

       ```yaml
       ingress.alb.yc.io/security-profile-id: <security_profile_ID>
       ```

       {% note info %}
       
       To connect your security profile to an Application Load Balancer virtual host, the service account used by the Ingress controller must have the [smart-web-security.editor](../../smartwebsecurity/security/index.md#smart-web-security-editor) role for the folder hosting Application Load Balancer and Smart Web Security resources. For more information, see [Assigning a role to a service account](../../iam/operations/sa/assign-role-for-sa.md).
       
       {% endnote %}

     * `ingress.alb.yc.io/use-regex`: Support for [RE2](https://github.com/google/re2/wiki/Syntax) regular expressions when matching the request path. If set to `true`, the support is enabled. This setting only applies when `pathType` is set to `Exact`.

     * `ingress.alb.yc.io/balancing-panic-threshold`: [Panic mode](../../application-load-balancer/concepts/backend-group.md#panic-mode) threshold. The mode will be activated if the percentage of healthy endpoints drops below the specified threshold. The default value is `0`, which means the panic mode will never be activated.

     * `ingress.alb.yc.io/balancing-locality-aware-routing`: Percentage of incoming traffic the load balancer forwards to backends from its [availability zone](../../overview/concepts/geo-scope.md). The remaining traffic is split equally between the other zones. The default value is `0`. [More on locality-aware routing](../../application-load-balancer/concepts/backend-group.md#locality).

     * `ingress.alb.yc.io/autoscale-max-size`: Maximum total number of resource units. By default, it is unlimited. Make sure this value is no less than the number of load balancer availability zones multiplied by the minimum number of resource units per zone. Learn more about the autoscaling settings [here](../../application-load-balancer/concepts/application-load-balancer.md#lcu-scaling-settings).

     * `ingress.alb.yc.io/modify-header-response-append`: Adds a string to the response header value. To specify the header and string, use this format:

       ```yaml
       ingress.alb.yc.io/modify-header-response-append: <name_of_header_to_edit>=<string>
       ```

     * `ingress.alb.yc.io/modify-header-response-replace`: Replaces the response header value. To specify the header and its new value, use this format:

       ```yaml
       ingress.alb.yc.io/modify-header-response-replace: <name_of_header_to_edit>=<new_header_value>
       ```

     * `ingress.alb.yc.io/modify-header-response-rename`: Renames the response header. To specify the header and its new name, use this format:

       ```yaml
       ingress.alb.yc.io/modify-header-response-rename: <name_of_header_to_edit>=<new_header_name>
       ```

     * `ingress.alb.yc.io/modify-header-response-remove`: Removes the response header. To specify the header to remove, use this format:

       ```yaml
       ingress.alb.yc.io/modify-header-response-remove: <name_of_header_to_remove>=true
       ```

     * `ingress.alb.yc.io/modify-header-request-append`: Adds a string to the request header value. To specify the header and string, use this format:

       ```yaml
       ingress.alb.yc.io/modify-header-request-append: <name_of_header_to_edit>=<string>
       ```

     * `ingress.alb.yc.io/modify-header-request-replace`: Replaces the request header value. To specify the header and its new value, use this format:

       ```yaml
       ingress.alb.yc.io/modify-header-request-replace: <name_of_header_to_edit>=<new_header_value>
       ```

     * `ingress.alb.yc.io/modify-header-request-rename`: Renames the request header. To specify the header and its new name, use this format:

       ```yaml
       ingress.alb.yc.io/modify-header-request-rename: <name_of_header_to_edit>=<new_header_name>
       ```

     * `ingress.alb.yc.io/modify-header-request-remove`: Removes the request header. To specify the header to remove, use this format:

       ```yaml
       ingress.alb.yc.io/modify-header-request-remove: <name_of_header_to_remove>=true
       ```

     * `ingress.alb.yc.io/session-affinity-header`: Sets an HTTP header for [session affinity](../../application-load-balancer/concepts/backend-group.md#session-affinity). To specify the header, use this format:

       ```yaml
       ingress.alb.yc.io/session-affinity-header: name=<header_name>
       ```

     * `ingress.alb.yc.io/session-affinity-cookie`: Sets cookie settings for session affinity. To specify the settings, use this format:

       ```yaml
       ingress.alb.yc.io/session-affinity-cookie: name=<cookie_name>,ttl=<cookie_lifetime>
       ```

       Make sure to provide the `ttl` value with units of measurement, e.g., `300ms` or `1.5h`. Acceptable units of measurement include:
       * `ns`, nanoseconds
       * `us`, microseconds
       * `ms`, milliseconds
       * `s`, seconds
       * `m`, minutes
       * `h`, hours

     * `ingress.alb.yc.io/session-affinity-connection`: Allows using a client IP address for session affinity. To specify this property, use the following format:

       ```yaml
       ingress.alb.yc.io/session-affinity-connection: source-ip=<true_or_false>
       ```

     {% endcut %}

     If you use several ingress controllers, create an [IngressClass](../alb-ref/ingress-class.md) resource for each of them. In the `Ingress` configuration, specify the `IngressClass` you need in the `spec.ingressClassName` field.

     For more information about the `Ingress` resource settings, see [Ingress resource fields and annotations](../alb-ref/ingress.md).

  1. Create Kubernetes applications and Ingress resource:

     ```bash
     kubectl apply -f .
     ```

     The ALB ingress controller will automatically deploy an [L7 load balancer](../../application-load-balancer/concepts/application-load-balancer.md) using the Ingress resource configuration.

  1. Wait until the L7 load balancer is created and assigned a public IP address. This may take several 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 one of the `alb-demo-***` pods the load balancer's creation was run in.
     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.

  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-tls
     ```

     Result:

     ```bash
     NAME          CLASS   HOSTS           ADDRESS     PORTS    AGE
     alb-demo-tls  <none>  <domain_name>  <IP_address>  80, 443  15h
     ```

- Ingress resource for a backend group

  1. Create a [backend group with a bucket](../../application-load-balancer/operations/backend-group-create.md#with-s3-bucket):
     1. Create a [public bucket in Object Storage](../../tutorials/web/static/console.md#create-public-bucket).
     1. [Configure the website home page and error page](../../tutorials/web/static/console.md).
  1. Create a configuration file named `demo-app-1.yaml` for your application:

     {% cut "demo-app-1.yaml" %}

     ```yaml
     apiVersion: v1
     kind: ConfigMap
     metadata:
       name: alb-demo-1
     data:
       nginx.conf: |
         worker_processes auto;
         events {
         }
         http {
           server {
             listen 80 ;
             location = /_healthz {
               add_header Content-Type text/plain;
               return 200 'ok';
             }
             location / {
               add_header Content-Type text/plain;
               return 200 'Index';
             }
             location = /app1 {
               add_header Content-Type text/plain;
               return 200 'This is APP#1';
             }
           }
         }
     ---
     apiVersion: apps/v1
     kind: Deployment
     metadata:
       name: alb-demo-1
       labels:
         app: alb-demo-1
         version: v1
     spec:
       replicas: 2
       selector:
         matchLabels:
           app: alb-demo-1
       strategy:
         type: RollingUpdate
         rollingUpdate:
           maxSurge: 1
           maxUnavailable: 0
       template:
         metadata:
           labels:
             app: alb-demo-1
             version: v1
         spec:
           terminationGracePeriodSeconds: 5
           volumes:
             - name: alb-demo-1
               configMap:
                 name: alb-demo-1
           containers:
             - name: alb-demo-1
               image: nginx:latest
               ports:
                 - name: http
                   containerPort: 80
               livenessProbe:
                 httpGet:
                   path: /_healthz
                   port: 80
                 initialDelaySeconds: 3
                 timeoutSeconds: 2
                 failureThreshold: 2
               volumeMounts:
                 - name: alb-demo-1
                   mountPath: /etc/nginx
                   readOnly: true
               resources:
                 limits:
                   cpu: 250m
                   memory: 128Mi
                 requests:
                   cpu: 100m
                   memory: 64Mi
     ---
     apiVersion: v1
     kind: Service
     metadata:
       name: alb-demo-1
     spec:
       selector:
         app: alb-demo-1
       type: NodePort
       ports:
         - name: http
           port: 80
           targetPort: 80
           protocol: TCP
           nodePort: 30081
     ```

     {% endcut %}

  1. In a separate directory, create a file named `http-group.yaml` with the `HttpBackendGroup` resource settings:

     ```yaml
     apiVersion: alb.yc.io/v1alpha1
     kind: HttpBackendGroup
     metadata:
       name: example-backend-group
     spec:
       backends: # List of backends.
         - name: alb-demo-1
           weight: 70 # Backend relative weight in traffic distribution. Traffic will be distributed in proportion to the weights of other backends in the group. Specify the weight even if the group contains only one backend.
           service:
              name: alb-demo-1
              port:
                number: 80
         - name: bucket-backend
           weight: 30
           storageBucket:
             name: <bucket_name>
     ```

     Optionally, specify the additional settings for the backend group:
     * `spec.backends.useHttp2`: `HTTP/2` mode.
     * `spec.backends.tls`: CA certificate trusted by the load balancer when establishing a secure connection to backend endpoints. Specify the certificate contents in the `trustedCa` field in plain text.

     Learn more in [Backend groups](../../application-load-balancer/concepts/backend-group.md).

  1. In the same directory, create a file named `ingress-http.yaml` and specify in it the [delegated domain name](#before-you-begin), [ID of the certificate](#before-you-begin), and settings for the Application Load Balancer L7 load balancer:

     ```yaml
     apiVersion: networking.k8s.io/v1
     kind: Ingress
     metadata:
       name: alb-demo-tls
       annotations:
         ingress.alb.yc.io/subnets: <list_of_subnet_IDs>
         ingress.alb.yc.io/security-groups: <list_of_security_group_IDs>
         ingress.alb.yc.io/external-ipv4-address: <IP_address_assignment_method>
         ingress.alb.yc.io/group-name: my-ingress-group
     spec:
       tls:
         - hosts:
           - <domain_name>
           secretName: yc-certmgr-cert-id-<TLS_certificate_ID>
       rules:
         - host: <domain_name>
           http:
             paths:
               - path: /app1
                 pathType: Exact
                 backend:
                   resource:
                     apiGroup: alb.yc.io
                     kind: HttpBackendGroup
                     name: example-backend-group
     ```

     Where:
     * `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. Enter the [IP address you got earlier](../../vpc/operations/get-static-ip.md) or set `auto` to get a new IP address automatically.

       If you set `auto`, deleting the load balancer from the [cloud](../../resource-manager/concepts/resources-hierarchy.md#cloud) removes its [IP address](../../vpc/concepts/address.md). To avoid this, use a reserved IP address.

     * `ingress.alb.yc.io/group-name`: Group name. Ingress resources are grouped so that a separate load balancer serves each group.

       You can use any group name instead of `my-ingress-group`. Make sure it meets the naming [requirements](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/).

     Optionally, specify the additional settings for the load balancer.

     {% note info %}
     
     The settings listed below will only apply to the [virtual hosts](../../application-load-balancer/tools/k8s-ingress-controller/principles.md#mapping) of the Ingress resource in which the corresponding annotations are configured.
     
     They will not apply to the virtual hosts of the group's other Ingress resources.
     
     {% endnote %}

     Available settings:

     * `ingress.alb.yc.io/group-settings-name`: Name for the Ingress resource group settings to describe in the `IngressGroupSettings` optional resource. For more information, see [Configure the Ingress resource group](#configure-group).
     * `ingress.alb.yc.io/internal-ipv4-address`: Provide internal access to the load balancer. Enter the internal IP address or use `auto` to get the IP address automatically.

       {% note info %}

       You can only use one type of access to the load balancer at a time: `ingress.alb.yc.io/external-ipv4-address` or `ingress.alb.yc.io/internal-ipv4-address`.

       {% endnote %}

     * `ingress.alb.yc.io/internal-alb-subnet`: Subnet to host the load balancer. This parameter is required if you select `ingress.alb.yc.io/internal-ipv4-address`.
     * `ingress.alb.yc.io/protocol`: Protocol for connections between the load balancer and backends:
       * `http`: HTTP/1.1. This is a default value.
       * `http2`: HTTP/2.
       * `grpc`: gRPC.
     * `ingress.alb.yc.io/prefix-rewrite`: Replace the path with the specified value.
     * `ingress.alb.yc.io/upgrade-types`: Valid values of the `Upgrade` HTTP header, e.g., `websocket`.
     * `ingress.alb.yc.io/request-timeout`: Maximum connection request timeout.
     * `ingress.alb.yc.io/idle-timeout`: Maximum connection idle time.

       Make sure to provide the `request-timeout` and `idle-timeout` values with units of measurement, e.g., `300ms` or `1.5h`. Acceptable units of measurement include:
       * `ns`, nanoseconds
       * `us`, microseconds
       * `ms`, milliseconds
       * `s`, seconds
       * `m`, minutes
       * `h`, hours

     * `ingress.alb.yc.io/security-profile-id`: Support for [Yandex Smart Web Security](../../smartwebsecurity/concepts/index.md) that ensures protection against DDoS attacks and bots, enables [WAF](../../smartwebsecurity/concepts/waf.md) and [limits the load](../../smartwebsecurity/concepts/arl.md) on the protected resource.

       To enable support for Yandex Smart Web Security, specify the previously created Smart Web Security [profile](../../smartwebsecurity/concepts/profiles.md) in the Ingress annotation:

       ```yaml
       ingress.alb.yc.io/security-profile-id: <security_profile_ID>
       ```

       {% note info %}
       
       To connect your security profile to an Application Load Balancer virtual host, the service account used by the Ingress controller must have the [smart-web-security.editor](../../smartwebsecurity/security/index.md#smart-web-security-editor) role for the folder hosting Application Load Balancer and Smart Web Security resources. For more information, see [Assigning a role to a service account](../../iam/operations/sa/assign-role-for-sa.md).
       
       {% endnote %}

     * `ingress.alb.yc.io/use-regex`: Support for [RE2](https://github.com/google/re2/wiki/Syntax) regular expressions when matching the request path. If set to `true`, the support is enabled. This setting only applies when `pathType` is set to `Exact`.

     For more information about the Ingress resource settings, see [Ingress resource fields and annotations](../alb-ref/ingress.md).
  1. Create a Kubernetes app, `HttpBackendGroup` resource, and `Ingress` resource:

     ```bash
     kubectl apply -f .
     ```

    The ALB ingress controller will automatically deploy an [L7 load balancer](../../application-load-balancer/concepts/application-load-balancer.md) using the Ingress resource configuration.

  1. Wait until the L7 load balancer is created and assigned a public IP address. This may take several 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 one of the `alb-demo-***` pods the load balancer's creation was run in.
     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.

  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-tls
     ```

     Result:

     ```bash
     NAME          CLASS   HOSTS           ADDRESS     PORTS    AGE
     alb-demo-tls  <none>  <domain_name>  <IP_address>  80, 443  15h
     ```

{% endlist %}

By default, the Application Load Balancer ingress controller receives application [health check](../../application-load-balancer/concepts/backend-group.md#health-checks) requests from the L7 load balancer on TCP port `10501` and health-checks [kube-proxy](https://kubernetes.io/docs/reference/command-line-tools-reference/kube-proxy/) pods on each cluster node. If `kube-proxy` is healthy, then, even though an application does not respond in a particular pod, Kubernetes will redirect traffic to a different pod running that application or to a different node.

You can use the [HttpBackendGroup](../../application-load-balancer/k8s-ref/http-backend-group.md) or [GrpcBackendGroup](../../application-load-balancer/k8s-ref/grpc-backend-group.md) resource settings to customize health checks. Learn more in [Health checking applications in a Yandex Managed Service for Kubernetes cluster via a Yandex Application Load Balancer](custom-health-checks.md).

## Optionally, configure the Ingress resource group {#configure-group}

If you specified a name for the Ingress resource group settings in the `ingress.alb.yc.io/group-settings-name` annotation when setting up the Ingress resource, you can specify logging settings for the L7 load balancer. To do this, [create a custom log group](../../logging/operations/create-group.md) and specify the Ingress resource group settings in the `IngressGroupSettings` optional resource:

1. Create a file named `settings.yaml` with your logging settings and custom log group ID, such as the following:

    ```yaml
    apiVersion: alb.yc.io/v1alpha1
    kind: IngressGroupSettings
    metadata:
      name: <name_for_Ingress_resource_group_settings>
    logOptions:
      logGroupID: <custom_log_group_ID>
      discardRules:
        - discardPercent: 50
          grpcCodes:
            - OK
            - CANCELLED
            - UNKNOWN
        - discardPercent: 67
          httpCodeIntervals:
            - HTTP_1XX
        - discardPercent: 20
          httpCodes:
            - 200
            - 404
    ```

    Where `name` is the name for the Ingress resource group settings in the `ingress.alb.yc.io/group-settings-name` annotation.

1. Apply the settings for the Ingress resource group:

    ```bash
    kubectl apply -f settings.yaml
    ```

## Make sure the applications are accessible via the L7 load balancer {#verify-setup}

1. If you have no [ExternalDNS with the Cloud DNS plugin](https://yandex.cloud/en/marketplace/products/yc/externaldns) installed, [add an A record to your domain zone](../../dns/operations/resource-record-create.md). In the **Data** field, specify the public IP address of your L7 Application Load Balancer. If you are using ExternalDNS with the Yandex Cloud DNS plugin, this record will be created automatically.
1. Test the load balancer:

   {% list tabs %}

   - Ingress resource for Kubernetes services

     Open the application URIs in your browser:

     ```http
     https://<your_domain>/app1
     https://<your_domain>/app2
     ```

     Make sure the applications are accessible via the Application Load Balancer and return pages showing `This is APP#1` and `This is APP#2`, respectively.

     {% note info %}
     
     If you cannot access the resource at the specified URL, [make sure](../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 %}

   - Ingress resource for a backend group

     Open the application URI in your browser:

     ```http
     https://<your_domain>/app1
     ```

     Make sure the targets are accessible via the Application Load Balancer.

     {% note info %}
     
     If you cannot access the resource at the specified URL, [make sure](../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 %}

   {% 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. [Delete the Managed Service for Kubernetes cluster](../operations/kubernetes-cluster/kubernetes-cluster-delete.md).
1. [Delete the Application Load Balancer target groups](../../application-load-balancer/operations/target-group-delete.md).
1. [Delete the Object Storage bucket](../../storage/operations/buckets/delete.md).