[Yandex Cloud documentation](../../index.md) > [Yandex Managed Service for Kubernetes](../index.md) > [Step-by-step guides](index.md) > Network scenarios > Granting access to an application running in a Kubernetes cluster

# Granting access to an application running in a Kubernetes cluster

The example below uses a Kubernetes application that responds to HTTP requests on port 8080. To provide access to the application, use public or internal [services](../concepts/service.md). Their IP addresses do not change, unlike the addresses of pods and cluster nodes.

To publish an application, use a `LoadBalancer` type service. You can set up two types of access:

* Public IP access with an external [Yandex Network Load Balancer](../../network-load-balancer/concepts/index.md).
* Access from internal networks by IP address with an [internal network load balancer](../../network-load-balancer/concepts/nlb-types.md).

  The application will be available:
  * From Yandex Virtual Private Cloud [subnets](../../vpc/concepts/network.md#subnet).
  * From your corporate internal subnets connected to Yandex Cloud via [Yandex Cloud Interconnect](../../interconnect/index.md).
  * Via VPN.

When using an external load balancer, [you can specify](#advanced) a static [public IP address](../../vpc/concepts/address.md#public-addresses) in the `loadBalancerIP` field. You need to [reserve such an address in advance](../../vpc/operations/get-static-ip.md). When reserving a public IP address, you can enable [DDoS protection](../../vpc/ddos-protection/index.md). If you do not specify a static public IP address, the network load balancer will get a dynamic public IP address.

{% note info %}

Unlike an IP address of a pod or node, which may change if node group resources are updated, the static public IP address of a `LoadBalancer` type service does not change.

{% endnote %}

When using an internal load balancer, you can specify an [internal IP address](../../vpc/concepts/address.md#internal-addresses). Make sure the specified internal IP address is not assigned to some other resource in the same cloud network.

{% note warning %}

Once removed from the specification, the internal IP address may be automatically assigned to a different resource in the same cloud network. We recommend selecting the address closer to the upper bound of your subnet's IP address range.

{% endnote %}

To ensure access to the Kubernetes application:
1. [Get ready](#before-you-begin).
1. [Create a Kubernetes app](#create-application).
1. [Create a LoadBalancer type service](#create-lb).
1. [Check application availability](#check-result).
1. [Optionally, create a NetworkPolicy object](#network-policy).

{% cut "How to ensure access to an application via HTTPS" %}

See these guides:

* [Creating a new Kubernetes project in Yandex Cloud](../tutorials/new-kubernetes-project.md)
* [Configuring a Yandex Application Load Balancer using an ingress controller](../tutorials/alb-ingress-controller.md)

{% endcut %}

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

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

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

1. Set up your infrastructure:

    {% list tabs group=instructions %}

    - Manually {#manual}

      1. Create a [cloud network](../../vpc/operations/network-create.md) and [subnet](../../vpc/operations/subnet-create.md).
      1. Create a [service account](../../iam/operations/sa/create.md) with the `k8s.clusters.agent`, `vpc.publicAdmin`, and `load-balancer.admin` [role](../../iam/concepts/access-control/roles.md). It needs the `load-balancer.admin` role to create a [network load balancer](../../network-load-balancer/concepts/index.md).
      1. [Create security groups](connect/security-groups.md) for the Managed Service for Kubernetes cluster and its node groups.

          {% 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](kubernetes-cluster/kubernetes-cluster-create.md) and [node group](node-group/node-group-create.md) with public internet access and preconfigured security groups.

    - Terraform {#tf}

      1. If you do not have Terraform yet, [install it](../../tutorials/infrastructure-management/terraform-quickstart.md#install-terraform).
      1. [Get the authentication credentials](../../tutorials/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](../../tutorials/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](../../tutorials/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-load-balancer.tf](https://github.com/yandex-cloud-examples/yc-mk8s-load-balancer/blob/main/k8s-load-balancer.tf) Managed Service for Kubernetes cluster configuration file to the same working directory. This file describes:
          * [Network](../../vpc/concepts/network.md#network).
          * [Subnet](../../vpc/concepts/network.md#subnet).
          * Managed Service for Kubernetes cluster.
          * [Service account](../../iam/concepts/users/service-accounts.md) for the Managed Service for Kubernetes cluster and [node group](../concepts/index.md#node-group).
          * [Security groups](../../vpc/concepts/security-groups.md) which contain [rules](connect/security-groups.md) required for the Managed Service for Kubernetes cluster and its node groups.

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

      1. Specify the following in the configuration file:
          * [Folder ID](../../resource-manager/operations/folder/get-id.md).
          * [Kubernetes version](../concepts/release-channels-and-updates.md) for the Managed Service for Kubernetes cluster and node groups.
          * Name of the Managed Service for Kubernetes cluster service account.
      1. Validate your Terraform configuration files 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).

          {% note warning "Timeouts" %}
          
          The Terraform provider sets time limits for operations with Managed Service for Kubernetes cluster and node group:
          
          * Creating and editing a cluster: 30 minutes.
          * Creating and updating a node group: 60 minutes.
          * Deleting a node group: 20 minutes.
          
          Operations in excess of this time will be interrupted.
          
          {% cut "How do I modify these limits?" %}
          
          Add the `timeouts` sections (the `yandex_kubernetes_cluster` and `yandex_kubernetes_node_group` resources, respectively) to the cluster and node group description.
          
          Here is an example:
          
          ```hcl
          resource "yandex_kubernetes_node_group" "<node_group_name>" {
            ...
            timeouts {
              create = "1h30m"
              update = "1h30m"
              delete = "30m"
            }
          }
          ```
          
          {% endcut %}
          
          {% endnote %}

    {% endlist %}

## Create a Kubernetes app {#create-application}

1. Create a file named `hello.yaml` and add the [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) resource specification to it to create the application:

   ```yaml
   apiVersion: apps/v1
   kind: Deployment
   metadata:
     name: hello
   spec:
     replicas: 2
     selector:
       matchLabels:
         app: hello
     template:
       metadata:
         labels:
           app: hello
       spec:
         containers:
         - name: hello-app
           image: cr.yandex/crpjd37scfv653nl11i9/hello:1.1
   ```

1. Create an application:

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

1. Make sure the application was created:

   ```bash
   kubectl get deployment 
   ```

   Result:

   ```text
   NAME    READY   UP-TO-DATE   AVAILABLE   AGE
   hello   2/2     2            2           17h
   ```

## Create a LoadBalancer type service {#create-lb}

When you create a `LoadBalancer` type service, the Yandex Cloud controller installs a network load balancer in your folder. It is charged based on the Network Load Balancer [pricing policy](../../network-load-balancer/pricing.md).

{% note warning %}

* You will be charged for the network load balancer you created based on the [pricing policy](../../network-load-balancer/pricing.md).
* Do not modify or delete the network load balancer and target groups automatically created in your folder via the Yandex Cloud interfaces (the management console, Terraform, CLI, or API). This may cause incorrect operation of the cluster.

{% endnote %}

To create a `LoadBalancer` type service:

1. Select and prepare the service specification based on the required load balancer type:

   {% list tabs group=instructions %}

   * External load balancer {#external-balancer}

      1. Create a file named `load-balancer.yaml` and add the following service specification to it:

         ```yaml
         apiVersion: v1
         kind: Service
         metadata:
           name: hello
         spec:
           type: LoadBalancer
           ports:
           - port: <application_port>
             name: plaintext
             targetPort: 8080
           selector:
             <Kubernetes_labels>
         ```

         In the specification, indicate:

         * `spec.ports.port`: Application port.

            The example assumes the Kubernetes application is available over HTTP, so specify `80` as the value. If you need to access the application over HTTPS, set the value to `443`.

         * `spec.selector`: Kubernetes labels specified in the `spec.selector.matchLabels` field of the `Deployment` resource.

            Specify the `app: hello` label as it is used in the `Deployment` resource you created previously.

         For details on the specification, see [this reference](../nlb-ref/service.md).

      1. Optionally, [reserve a static public IP address](../../vpc/operations/get-static-ip.md) and add it to the specification:

         ```yaml
         ...
         spec:
           loadBalancerIP: <static_IP_address>
           ...
         ```

         {% note info %}

         If you do not specify a static IP address, the network load balancer will get a dynamic IP address.

         {% endnote %}

   * Internal load balancer {#internal-balancer}

      1. Create a file named `load-balancer.yaml` and add the following service specification to it:

         ```yaml
         apiVersion: v1
         kind: Service
         metadata:
           name: hello
           annotations:
             yandex.cloud/load-balancer-type: internal
             yandex.cloud/subnet-id: <cluster_subnet_ID>
         spec:
           type: LoadBalancer
           ports:
           - port: <application_port>
             name: plaintext
             targetPort: 8080
           selector:
             <Kubernetes_labels>
         ```

         In the specification, indicate:

         * `yandex.cloud/subnet-id`: ID of the subnet hosting the cluster. You can [get the ID together with the subnet information](../../vpc/operations/subnet-get-info.md).
         * `spec.ports.port`: Application port.

            The example assumes the Kubernetes application is available over HTTP, so specify `80` as the value. If you need to access the application over HTTPS, set the value to `443`.

         * `spec.selector`: Kubernetes labels specified in the `spec.selector.matchLabels` field of the `Deployment` resource.

            Specify the `app: hello` label as it is used in the `Deployment` resource you created previously.

         For details on the specification, see [this reference](../nlb-ref/service.md).

      1. Optionally, [reserve a static private IP address](../../vpc/operations/private-ip-reserve.md) and add it to the specification:

         ```yaml
         ...
         spec:
           loadBalancerIP: <static_IP_address>
           ...
         ```

         {% note info %}

         If you do not specify a static IP address, the network load balancer will get a dynamic IP address.

         {% endnote %}

   {% endlist %}

1. Optionally, add a traffic management policy:

   ```yaml
   ...
   spec:
     externalTrafficPolicy: <Cluster_or_Local>
     ...
   ```

   The possible values are:

   * **Cluster**: Traffic is routed to different Kubernetes nodes (default). As a result, traffic is distributed evenly; however, there are certain drawbacks:
   
      * The packet may come to one node's proxy and get rerouted to another node leading to delays in performing operations and sending packets.
      * The pod that receives the packet sees the IP address of the proxying node rather than the one of the client. As a result, the client IP address is not preserved.
   
   * **Local**: Traffic is proxied and distributed across pods on the same node. The traffic is routed to the node via the port specified in the service of the [LoadBalancer or NodePort type](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types).
   
      The traffic comes to a specific node, so it is distributed unevenly across nodes; however, the client IP address is preserved.
   
   For more information about policies for external traffic management, see [this Kubernetes guide](https://kubernetes.io/docs/reference/networking/virtual-ips/#external-traffic-policy).

1. Optionally, enable [node health checks](../../network-load-balancer/concepts/health-check.md).

   `LoadBalancer` type services in Managed Service for Kubernetes can run health check requests for a [target group](../../network-load-balancer/concepts/target-resources.md). Based on the received metrics, Managed Service for Kubernetes decides if the nodes are available.

   To enable node availability checks, specify the following annotations in the service specification:

   ```yaml
   ...
   metadata:
     ...
     annotations:
       yandex.cloud/load-balancer-healthcheck-healthy-threshold: "2"
       yandex.cloud/load-balancer-healthcheck-interval: "2s"
   ```

   Annotations used:

   * `yandex.cloud/load-balancer-healthcheck-healthy-threshold`: Number of consecutive successful checks to consider a cluster node available.
   * `yandex.cloud/load-balancer-healthcheck-interval`: Check interval in seconds.

1. Create a network load balancer:

   ```bash
   kubectl apply -f load-balancer.yaml
   ```

## Check application availability {#check-result}

1. View information about the network load balancer you created and get its IP address:

   {% list tabs group=instructions %}

   - Management console {#console}

     1. In the [management console](https://console.yandex.cloud), select your default folder.
     1. Navigate to **Network Load Balancer**.
     1. The **Load balancers** tab shows the network load balancer with the `k8s` prefix in the name and the unique ID of your Kubernetes cluster in the description.

        Copy the balancer address in the **IP address** column.

   - kubectl {#kubectl}

     ```bash
     kubectl describe service hello
     ```

     Result:

     ```text
     Name:                     hello
     Namespace:                default
     Labels:                   <none>
     Annotations:              <none>
     Selector:                 app=hello
     Type:                     LoadBalancer
     IP:                       172.20.169.7
     LoadBalancer Ingress:     130.193.50.111
     Port:                     plaintext 80/TCP
     TargetPort:               8080/TCP
     NodePort:                 plaintext 32302/TCP
     Endpoints:                10.1.130.4:8080
     Session Affinity:         None
     External Traffic Policy:  Cluster
     Events:
       Type    Reason                Age    From                Message
       ----    ------                ----   ----                -------
       Normal  EnsuringLoadBalancer  2m43s  service-controller  Ensuring load balancer
       Normal  EnsuredLoadBalancer   2m17s  service-controller  Ensured load balancer
     ```

     Copy the balancer address from the `LoadBalancer Ingress` field.

   {% endlist %}

1. Make sure the application is available. The verification steps depend on your load balancer type:

   {% list tabs group=instructions %}

   * External load balancer {#external-balancer}

      Run this command:

      ```bash
      curl http://<load_balancer_IP_address>
      ```

      Result:

      ```text
      Hello, world!
      Running in 'hello-********'
      ```

   * Internal load balancer {#internal-balancer}

      1. In the Managed Service for Kubernetes cluster subnet, [create a Linux VM](../../compute/operations/vm-create/create-linux-vm.md).

         Since you have deployed an internal network load balancer, you can only test access to the Kubernetes application from the cluster subnet.

      1. [Connect to the VM over SSH](../../compute/operations/vm-connect/ssh.md).
      1. Check availability of the Kubernetes application:

         ```bash
         curl http://<load_balancer_IP_address>
         ```

         Result:

         ```text
         Hello, world!
         Running in 'hello-********'
         ```

   {% endlist %}

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

## Optionally, create a NetworkPolicy object {#network-policy}

To connect to services published via Network Load Balancer from specific IP addresses, enable [network policies](../concepts/network-policy.md) in the cluster. To set up access via the load balancer, create a [NetworkPolicy](https://kubernetes.io/docs/concepts/services-networking/network-policies/#networkpolicy-resource) object with an `Ingress` type policy.

{% cut "NetworkPolicy object configuration example" %}

```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: whitelist-netpol
  namespace: ns-example
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  - Ingress
  ingress:
  - from:
    # Address ranges used by the load balancer to health check nodes.
    - ipBlock:
        cidr: 198.18.235.0/24
    - ipBlock:
        cidr: 198.18.248.0/24
    # Pod address ranges.
    - ipBlock:
        cidr: 172.16.1.0/12
    - ipBlock:
        cidr: 172.16.2.0/12
```

{% endcut %}

For more information, see the `NetworkPolicy` resource [reference](../nlb-ref/networkpolicy.md).

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

Delete the resources you no longer need to avoid paying for them:

1. Delete the resources depending on how you created them:

    {% list tabs group=instructions %}

    - Manually {#manual}

        [Delete the Managed Service for Kubernetes cluster](kubernetes-cluster/kubernetes-cluster-delete.md).

    - Terraform {#tf}

        1. In the terminal window, go to the directory containing the infrastructure plan.
        
            {% note warning %}
        
            Make sure the directory has no Terraform manifests with the resources you want to keep. Terraform deletes all resources that were created using the manifests in the current directory.
        
            {% endnote %}
        
        1. Delete resources:
        
            1. Run this command:
        
                ```bash
                terraform destroy
                ```
        
            1. Confirm deleting the resources and wait for the operation to complete.
        
            All the resources described in the Terraform manifests will be deleted.

    {% endlist %}

1. If you used static [public](../../vpc/concepts/address.md#public-addresses) IP addresses to access your Managed Service for Kubernetes cluster or nodes, release and delete them.